diff --git a/.travis.yml b/.travis.yml index 8231bc68f7..4cf6a09aac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,10 @@ - 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 @@ -14,8 +13,8 @@ deploy: 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" + - "desktop/build/libs/desktop-release.jar" + - "server/build/libs/server-release.jar" on: repo: Anuken/Mindustry tags: true diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 989b5dd893..05700dfe47 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -1,12 +1,11 @@ + package="io.anuke.mindustry"> - - - - - + + + + - + + android:name="io.anuke.mindustry.AndroidLauncher" + android:label="@string/app_name" + android:screenOrientation="user" + android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout"> - - + + @@ -34,7 +33,7 @@ - + @@ -42,28 +41,28 @@ - + - - - + + + - - - + + + + android:theme="@style/GdxTheme"/> diff --git a/android/build.gradle b/android/build.gradle index f218d1876a..d87fbc2d69 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,35 +1,32 @@ -buildscript { - repositories { +buildscript{ + repositories{ mavenLocal() mavenCentral() google() - maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } + maven{ url "https://oss.sonatype.org/content/repositories/snapshots/" } jcenter() } - - dependencies { + + dependencies{ classpath 'com.android.tools.build:gradle:3.3.2' } } apply plugin: "com.android.application" -configurations { natives } +configurations{ natives } -repositories { - mavenCentral() +repositories{ + mavenCentral() jcenter() - maven { - url "https://maven.google.com" + maven{ + url "https://maven.google.com" } } -dependencies { +dependencies{ implementation project(":core") implementation project(":net") - implementation 'com.android.support:support-v4:28.0.0' - implementation 'org.sufficientlysecure:donations:2.5' - implementation 'com.google.android.gms:play-services-auth:16.0.1' implementation arcModule("backends:backend-android") natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi" @@ -47,16 +44,16 @@ dependencies { task deploy(type: Copy){ dependsOn "assembleRelease" - from "build/outputs/apk/google/release/android-google-release.apk" + from "build/outputs/apk/release/android-release.apk" into "../deploy/" - rename ("android-google-release.apk", appName + "-android-" + getVersionString() + ".apk") + rename("android-release.apk", appName + "-android-" + getVersionString() + ".apk") } -android { +android{ buildToolsVersion '28.0.3' compileSdkVersion 28 - sourceSets { - main { + sourceSets{ + main{ manifest.srcFile 'AndroidManifest.xml' java.srcDirs = ['src'] aidl.srcDirs = ['src'] @@ -68,11 +65,11 @@ android { androidTest.setRoot('tests') } - packagingOptions { + packagingOptions{ exclude 'META-INF/robovm/ios/robovm.xml' } - defaultConfig { + defaultConfig{ def vfile = file('../core/assets/version.properties') def code = 0 @@ -96,22 +93,16 @@ android { versionName versionNameResult } - compileOptions { + compileOptions{ sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } flavorDimensions "google" - productFlavors { - google { - buildConfigField "boolean", "DONATIONS_GOOGLE", "true" - } - } - - signingConfigs { - release { - if(project.hasProperty("RELEASE_STORE_FILE")) { + signingConfigs{ + release{ + if(project.hasProperty("RELEASE_STORE_FILE")){ storeFile file(RELEASE_STORE_FILE) storePassword RELEASE_STORE_PASSWORD keyAlias RELEASE_KEY_ALIAS @@ -122,8 +113,8 @@ android { } } - buildTypes { - release { + buildTypes{ + release{ signingConfig signingConfigs.release } } @@ -131,22 +122,22 @@ android { // called every time gradle gets executed, takes the native dependencies of // the natives configuration, and extracts them to the proper libs/ folders // so they get packed with the APK. -task copyAndroidNatives() { +task copyAndroidNatives(){ file("libs/armeabi/").mkdirs() file("libs/armeabi-v7a/").mkdirs() file("libs/arm64-v8a/").mkdirs() file("libs/x86_64/").mkdirs() file("libs/x86/").mkdirs() - configurations.natives.files.each { jar -> + configurations.natives.files.each{ jar -> def outputDir = null - if (jar.name.endsWith("natives-arm64-v8a.jar")) outputDir = file("libs/arm64-v8a") - if (jar.name.endsWith("natives-armeabi-v7a.jar")) outputDir = file("libs/armeabi-v7a") - if (jar.name.endsWith("natives-armeabi.jar")) outputDir = file("libs/armeabi") - if (jar.name.endsWith("natives-x86_64.jar")) outputDir = file("libs/x86_64") - if (jar.name.endsWith("natives-x86.jar")) outputDir = file("libs/x86") - if (outputDir != null) { - copy { + if(jar.name.endsWith("natives-arm64-v8a.jar")) outputDir = file("libs/arm64-v8a") + if(jar.name.endsWith("natives-armeabi-v7a.jar")) outputDir = file("libs/armeabi-v7a") + if(jar.name.endsWith("natives-armeabi.jar")) outputDir = file("libs/armeabi") + if(jar.name.endsWith("natives-x86_64.jar")) outputDir = file("libs/x86_64") + if(jar.name.endsWith("natives-x86.jar")) outputDir = file("libs/x86") + if(outputDir != null){ + copy{ from zipTree(jar) into outputDir include "*.so" @@ -155,21 +146,21 @@ task copyAndroidNatives() { } } -task run(type: Exec) { +task run(type: Exec){ def path def localProperties = project.file("../local.properties") - if (localProperties.exists()) { + if(localProperties.exists()){ Properties properties = new Properties() - localProperties.withInputStream { instr -> + localProperties.withInputStream{ instr -> properties.load(instr) } def sdkDir = properties.getProperty('sdk.dir') - if (sdkDir) { + if(sdkDir){ path = sdkDir - } else { + }else{ path = "$System.env.ANDROID_HOME" } - } else { + }else{ path = "$System.env.ANDROID_HOME" } @@ -178,19 +169,19 @@ task run(type: Exec) { } // sets up the Android Idea project, using the old Ant based build. -idea { - module { +idea{ + module{ sourceDirs += file("src") scopes = [COMPILE: [plus: [project.configurations.compile]]] - iml { - withXml { + iml{ + withXml{ def node = it.asNode() def builder = NodeBuilder.newInstance() builder.current = node - builder.component(name: "FacetManager") { - facet(type: "android", name: "Android") { - configuration { + builder.component(name: "FacetManager"){ + facet(type: "android", name: "Android"){ + configuration{ option(name: "UPDATE_PROPERTY_FILES", value: "true") } } diff --git a/android/ic_launcher-web.png b/android/ic_launcher-web.png index 4ad2ddd445..658c1fd713 100644 Binary files a/android/ic_launcher-web.png and b/android/ic_launcher-web.png differ diff --git a/android/project.properties b/android/project.properties index 4ab125693c..f13bd4b19c 100644 --- a/android/project.properties +++ b/android/project.properties @@ -9,6 +9,5 @@ # # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt - # Project target. target=android-19 diff --git a/android/res/drawable/background.png b/android/res/drawable/background.png deleted file mode 100644 index b02bc10b64..0000000000 Binary files a/android/res/drawable/background.png and /dev/null differ diff --git a/android/res/drawable/ic_launcher_background.png b/android/res/drawable/ic_launcher_background.png index 0674f294a8..8e013ea019 100644 Binary files a/android/res/drawable/ic_launcher_background.png and b/android/res/drawable/ic_launcher_background.png differ diff --git a/android/res/drawable/ic_launcher_foreground.png b/android/res/drawable/ic_launcher_foreground.png index d9ba2d1a9b..7adbf4e2c5 100644 Binary files a/android/res/drawable/ic_launcher_foreground.png and b/android/res/drawable/ic_launcher_foreground.png differ diff --git a/android/res/layout/donations_activity.xml b/android/res/layout/donations_activity.xml deleted file mode 100644 index 15b305760f..0000000000 --- a/android/res/layout/donations_activity.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/android/res/mipmap-hdpi/ic_launcher.png b/android/res/mipmap-hdpi/ic_launcher.png index 2447c3f621..f4d594a423 100644 Binary files a/android/res/mipmap-hdpi/ic_launcher.png and b/android/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/res/mipmap-hdpi/ic_launcher_background.png b/android/res/mipmap-hdpi/ic_launcher_background.png index f9543146b7..4a792ac88c 100644 Binary files a/android/res/mipmap-hdpi/ic_launcher_background.png and b/android/res/mipmap-hdpi/ic_launcher_background.png differ diff --git a/android/res/mipmap-hdpi/ic_launcher_foreground.png b/android/res/mipmap-hdpi/ic_launcher_foreground.png index 5e0ac93602..f4bace551a 100644 Binary files a/android/res/mipmap-hdpi/ic_launcher_foreground.png and b/android/res/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/android/res/mipmap-hdpi/ic_launcher_round.png b/android/res/mipmap-hdpi/ic_launcher_round.png index 686f48cb81..ffd1c7fca6 100644 Binary files a/android/res/mipmap-hdpi/ic_launcher_round.png and b/android/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/android/res/mipmap-mdpi/ic_launcher.png b/android/res/mipmap-mdpi/ic_launcher.png index 8946c07d2a..4071a357a3 100644 Binary files a/android/res/mipmap-mdpi/ic_launcher.png and b/android/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/res/mipmap-mdpi/ic_launcher_background.png b/android/res/mipmap-mdpi/ic_launcher_background.png index 7f784e8f33..50c0775712 100644 Binary files a/android/res/mipmap-mdpi/ic_launcher_background.png and b/android/res/mipmap-mdpi/ic_launcher_background.png differ diff --git a/android/res/mipmap-mdpi/ic_launcher_foreground.png b/android/res/mipmap-mdpi/ic_launcher_foreground.png index 29ee0aca67..10c2324cba 100644 Binary files a/android/res/mipmap-mdpi/ic_launcher_foreground.png and b/android/res/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/android/res/mipmap-mdpi/ic_launcher_round.png b/android/res/mipmap-mdpi/ic_launcher_round.png index 1952f47833..5b314cf65f 100644 Binary files a/android/res/mipmap-mdpi/ic_launcher_round.png and b/android/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/android/res/mipmap-xhdpi/ic_launcher.png b/android/res/mipmap-xhdpi/ic_launcher.png index 7d2b5292be..f76fa1cd09 100644 Binary files a/android/res/mipmap-xhdpi/ic_launcher.png and b/android/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/res/mipmap-xhdpi/ic_launcher_background.png b/android/res/mipmap-xhdpi/ic_launcher_background.png index 17e0f3f893..6b4646a1c2 100644 Binary files a/android/res/mipmap-xhdpi/ic_launcher_background.png and b/android/res/mipmap-xhdpi/ic_launcher_background.png differ diff --git a/android/res/mipmap-xhdpi/ic_launcher_foreground.png b/android/res/mipmap-xhdpi/ic_launcher_foreground.png index b18c416546..34f6137a4d 100644 Binary files a/android/res/mipmap-xhdpi/ic_launcher_foreground.png and b/android/res/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/android/res/mipmap-xhdpi/ic_launcher_round.png b/android/res/mipmap-xhdpi/ic_launcher_round.png index 1d6e1d523c..260458750c 100644 Binary files a/android/res/mipmap-xhdpi/ic_launcher_round.png and b/android/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/android/res/mipmap-xxhdpi/ic_launcher.png b/android/res/mipmap-xxhdpi/ic_launcher.png index 96deec6e8a..cde10344a7 100644 Binary files a/android/res/mipmap-xxhdpi/ic_launcher.png and b/android/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/res/mipmap-xxhdpi/ic_launcher_background.png b/android/res/mipmap-xxhdpi/ic_launcher_background.png index c3458d1cfd..bfda7fa416 100644 Binary files a/android/res/mipmap-xxhdpi/ic_launcher_background.png and b/android/res/mipmap-xxhdpi/ic_launcher_background.png differ diff --git a/android/res/mipmap-xxhdpi/ic_launcher_foreground.png b/android/res/mipmap-xxhdpi/ic_launcher_foreground.png index 7b5c3d24be..637925a18a 100644 Binary files a/android/res/mipmap-xxhdpi/ic_launcher_foreground.png and b/android/res/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/android/res/mipmap-xxhdpi/ic_launcher_round.png b/android/res/mipmap-xxhdpi/ic_launcher_round.png index 375d7b0634..8d00a8c395 100644 Binary files a/android/res/mipmap-xxhdpi/ic_launcher_round.png and b/android/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/android/res/mipmap-xxxhdpi/ic_launcher.png b/android/res/mipmap-xxxhdpi/ic_launcher.png index 12f7a9e6ee..db23766b64 100644 Binary files a/android/res/mipmap-xxxhdpi/ic_launcher.png and b/android/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/res/mipmap-xxxhdpi/ic_launcher_background.png b/android/res/mipmap-xxxhdpi/ic_launcher_background.png index e3f671b50f..96b6c95fbd 100644 Binary files a/android/res/mipmap-xxxhdpi/ic_launcher_background.png and b/android/res/mipmap-xxxhdpi/ic_launcher_background.png differ diff --git a/android/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/android/res/mipmap-xxxhdpi/ic_launcher_foreground.png index 3cb7d5ad21..e8739f65cf 100644 Binary files a/android/res/mipmap-xxxhdpi/ic_launcher_foreground.png and b/android/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/android/res/mipmap-xxxhdpi/ic_launcher_round.png b/android/res/mipmap-xxxhdpi/ic_launcher_round.png index 3ce9bec872..f3f3aaa547 100644 Binary files a/android/res/mipmap-xxxhdpi/ic_launcher_round.png and b/android/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/android/res/values-ko/strings.xml b/android/res/values-ko/strings.xml deleted file mode 100644 index e239363d3f..0000000000 --- a/android/res/values-ko/strings.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - Mindustry - - 1 달러 - 2 달러 - 5 달러 - 10 달러 - 15 달러 - 25 달러 - 50 달러 - - - diff --git a/android/res/values-ru/strings.xml b/android/res/values-ru/strings.xml deleted file mode 100644 index 6eb672b67a..0000000000 --- a/android/res/values-ru/strings.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - Mindustry - - 1 Доллар - 2 Доллара - 5 Долларов - 10 Долларов - 15 Долларов - 25 Долларов - 50 Долларов - - - diff --git a/android/res/values-uk/strings.xml b/android/res/values-uk/strings.xml deleted file mode 100644 index f1303715ff..0000000000 --- a/android/res/values-uk/strings.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - Mindustry - - 1 Доллар - 2 Доллара - 5 Долларів - 10 Долларів - 15 Долларів - 25 Долларів - 50 Долларів - - - diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml index 5bc3a457fa..b77280e581 100644 --- a/android/res/values/strings.xml +++ b/android/res/values/strings.xml @@ -2,14 +2,5 @@ Mindustry - - 1 Dollar - 2 Dollars - 5 Dollars - 10 Dollars - 15 Dollars - 25 Dollars - 50 Dollars - - + \ No newline at end of file diff --git a/android/src/io/anuke/mindustry/AndroidLauncher.java b/android/src/io/anuke/mindustry/AndroidLauncher.java index a7bb47034b..087f392f7d 100644 --- a/android/src/io/anuke/mindustry/AndroidLauncher.java +++ b/android/src/io/anuke/mindustry/AndroidLauncher.java @@ -10,11 +10,6 @@ import android.os.Build; import android.os.Bundle; import android.provider.Settings.Secure; import android.telephony.TelephonyManager; -import android.util.Log; -import com.google.android.gms.common.GoogleApiAvailability; -import com.google.android.gms.common.GooglePlayServicesNotAvailableException; -import com.google.android.gms.common.GooglePlayServicesRepairableException; -import com.google.android.gms.security.ProviderInstaller; import io.anuke.arc.Core; import io.anuke.arc.backends.android.surfaceview.AndroidApplication; import io.anuke.arc.backends.android.surfaceview.AndroidApplicationConfiguration; @@ -23,18 +18,15 @@ import io.anuke.arc.function.Consumer; import io.anuke.arc.scene.ui.layout.Unit; import io.anuke.arc.util.Strings; import io.anuke.arc.util.serialization.Base64Coder; -import io.anuke.net.KryoClient; -import io.anuke.net.KryoServer; import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.game.Saves.SaveSlot; import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.ui.dialogs.FileChooser; +import io.anuke.net.KryoClient; +import io.anuke.net.KryoServer; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.util.ArrayList; import static io.anuke.mindustry.Vars.*; @@ -53,8 +45,8 @@ public class AndroidLauncher extends AndroidApplication{ Platform.instance = new Platform(){ @Override - public void openDonations(){ - showDonations(); + public void hide(){ + moveTaskToBack(true); } @Override @@ -64,7 +56,7 @@ public class AndroidLauncher extends AndroidApplication{ int len = s.length(); byte[] data = new byte[len / 2]; for(int i = 0; i < len; i += 2){ - data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + data[i / 2] = (byte)((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16)); } String result = new String(Base64Coder.encode(data)); @@ -94,7 +86,7 @@ public class AndroidLauncher extends AndroidApplication{ if(checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){ perms.add(Manifest.permission.READ_EXTERNAL_STORAGE); } - requestPermissions(perms.toArray(new String[perms.size()]), PERMISSION_REQUEST_CODE); + requestPermissions(perms.toArray(new String[0]), PERMISSION_REQUEST_CODE); } } @@ -114,17 +106,10 @@ public class AndroidLauncher extends AndroidApplication{ } }; - try{ - ProviderInstaller.installIfNeeded(this); - }catch(GooglePlayServicesRepairableException e){ - GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance(); - apiAvailability.getErrorDialog(this, e.getConnectionStatusCode(), 0).show(); - }catch(GooglePlayServicesNotAvailableException e){ - Log.e("SecurityException", "Google Play Services not available."); - } if(doubleScaleTablets && isTablet(this.getContext())){ Unit.dp.addition = 0.5f; } + config.hideStatusBar = true; Net.setClientProvider(new KryoClient()); Net.setServerProvider(new KryoServer()); @@ -133,7 +118,7 @@ public class AndroidLauncher extends AndroidApplication{ } @Override - public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults){ + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults){ if(requestCode == PERMISSION_REQUEST_CODE){ for(int i : grantResults){ if(i != PackageManager.PERMISSION_GRANTED) return; @@ -195,22 +180,8 @@ public class AndroidLauncher extends AndroidApplication{ } } - private boolean isPackageInstalled(String packagename){ - try{ - getPackageManager().getPackageInfo(packagename, 0); - return true; - }catch(Exception e){ - return false; - } - } - private boolean isTablet(Context context){ - TelephonyManager manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); - return manager.getPhoneType() == TelephonyManager.PHONE_TYPE_NONE; - } - - private void showDonations(){ - Intent intent = new Intent(this, DonationsActivity.class); - startActivity(intent); + TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); + return manager != null && manager.getPhoneType() == TelephonyManager.PHONE_TYPE_NONE; } } diff --git a/android/src/io/anuke/mindustry/DonationsActivity.java b/android/src/io/anuke/mindustry/DonationsActivity.java deleted file mode 100644 index 09b6a6b12f..0000000000 --- a/android/src/io/anuke/mindustry/DonationsActivity.java +++ /dev/null @@ -1,73 +0,0 @@ -package io.anuke.mindustry; - -import android.content.Intent; -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentActivity; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentTransaction; -import android.view.View; -import android.widget.Button; -import org.sufficientlysecure.donations.DonationsFragment; - -public class DonationsActivity extends FragmentActivity{ - /** - * Google - */ - private static final String GOOGLE_PUBKEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzG93KhpfBPKTo2jF0yxbWkkmMKwsPNM4SsMj1aDq7vv6n3R+mqJVfprOJxFfJh7JchXTflLIgiaKXFAiU70gJbMTniEWnEaFSxAeF09a7U0RjOwN+7rFwjCG91c2CpYxPanBTQP4zasc1ODPVzq4q6/4ByjhenN71V4WmR08NFIAodcfFPrOkDPil7i8y7cgcd1Ky53U0TS+LLYJttAK3XdTK4s7VE3I5IKoeNa4uwCmIM59R67q2k3cXjLk/nP6MP+y++EzHN/PTiR1sVg4dMP8K31RPw/1QNLPQwJz6Wc872oWwb7xo5gkoXbDc5WPPydsi8F3SyKNaYwzN6CDFQIDAQAB"; - private static final String[] GOOGLE_CATALOG = new String[]{ - "mindustry.donation.1", "mindustry.donation.2", "mindustry.donation.5", - "mindustry.donation.10", "mindustry.donation.15", - "mindustry.donation.25", "mindustry.donation.50"}; - DonationsFragment donationsFragment; - - /** - * Called when the activity is first created. - */ - @Override - public void onCreate(Bundle savedInstanceState){ - super.onCreate(savedInstanceState); - - setTheme(R.style.GdxTheme); - - setContentView(R.layout.donations_activity); - - FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); - if(BuildConfig.DONATIONS_GOOGLE){ - donationsFragment = DonationsFragment.newInstance(BuildConfig.DEBUG, true, GOOGLE_PUBKEY, GOOGLE_CATALOG, - getResources().getStringArray(R.array.donation_google_catalog_values), false, null, null, - null, false, null, null, false, null); - } - - - ft.replace(R.id.donations_activity_container, donationsFragment, "donationsFragment"); - ft.commit(); - } - - public void onStart(){ - super.onStart(); - Button b = findViewById(org.sufficientlysecure.donations.R.id.donations__google_android_market_donate_button); - b.setOnClickListener(view -> { - donationsFragment.donateGoogleOnClick(donationsFragment.getView()); - b.setEnabled(false); - }); - } - - - /** - * Needed for Google Play In-app Billing. It uses startIntentSenderForResult(). The result is not propagated to - * the Fragment like in startActivityForResult(). Thus we need to propagate manually to our Fragment. - */ - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data){ - super.onActivityResult(requestCode, resultCode, data); - Button b = findViewById(org.sufficientlysecure.donations.R.id.donations__google_android_market_donate_button); - b.setEnabled(true); - - FragmentManager fragmentManager = getSupportFragmentManager(); - Fragment fragment = fragmentManager.findFragmentByTag("donationsFragment"); - if(fragment != null){ - fragment.onActivityResult(requestCode, resultCode, data); - } - } -} diff --git a/annotations/build.gradle b/annotations/build.gradle index edc88bfb58..d894ed0abf 100644 --- a/annotations/build.gradle +++ b/annotations/build.gradle @@ -1,6 +1,6 @@ apply plugin: "java" sourceCompatibility = 1.8 -sourceSets.main.java.srcDirs = [ "src/main/java/" ] -sourceSets.main.resources.srcDirs = [ "src/main/resources/" ] +sourceSets.main.java.srcDirs = ["src/main/java/"] +sourceSets.main.resources.srcDirs = ["src/main/resources/"] diff --git a/annotations/src/main/java/io/anuke/annotations/Annotations.java b/annotations/src/main/java/io/anuke/annotations/Annotations.java index ce7832f76d..7961a57b89 100644 --- a/annotations/src/main/java/io/anuke/annotations/Annotations.java +++ b/annotations/src/main/java/io/anuke/annotations/Annotations.java @@ -1,31 +1,40 @@ package io.anuke.annotations; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; +import java.lang.annotation.*; public class Annotations{ - /** Marks a class as serializable.*/ + @Target({ElementType.METHOD, ElementType.FIELD}) + @Retention(RetentionPolicy.SOURCE) + public @interface Nullable{ + + } + + @Target({ElementType.METHOD, ElementType.FIELD}) + @Retention(RetentionPolicy.SOURCE) + public @interface NonNull{ + + } + + /** Marks a class as serializable. */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.SOURCE) public @interface Serialize{ } - /** Marks a class as a special value type struct. Class name must end in 'Struct'.*/ + /** Marks a class as a special value type struct. Class name must end in 'Struct'. */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.SOURCE) public @interface Struct{ } - /**Marks a field of a struct. Optional.*/ + /** Marks a field of a struct. Optional. */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.SOURCE) public @interface StructField{ - /**Size of a struct field in bits. Not valid on booleans or floating point numbers.*/ + /** Size of a struct field in bits. Not valid on booleans or floating point numbers. */ int value(); } diff --git a/annotations/src/main/java/io/anuke/annotations/ClassEntry.java b/annotations/src/main/java/io/anuke/annotations/ClassEntry.java index 3da814be88..a9be2ec134 100644 --- a/annotations/src/main/java/io/anuke/annotations/ClassEntry.java +++ b/annotations/src/main/java/io/anuke/annotations/ClassEntry.java @@ -1,7 +1,5 @@ package io.anuke.annotations; -import io.anuke.annotations.MethodEntry; - import java.util.ArrayList; /** Represents a class witha list method entries to include in it. */ diff --git a/annotations/src/main/java/io/anuke/annotations/MethodEntry.java b/annotations/src/main/java/io/anuke/annotations/MethodEntry.java index 3566516372..d642671641 100644 --- a/annotations/src/main/java/io/anuke/annotations/MethodEntry.java +++ b/annotations/src/main/java/io/anuke/annotations/MethodEntry.java @@ -1,8 +1,6 @@ package io.anuke.annotations; -import io.anuke.annotations.Annotations.Loc; -import io.anuke.annotations.Annotations.PacketPriority; -import io.anuke.annotations.Annotations.Variant; +import io.anuke.annotations.Annotations.*; import javax.lang.model.element.ExecutableElement; diff --git a/annotations/src/main/java/io/anuke/annotations/RemoteMethodAnnotationProcessor.java b/annotations/src/main/java/io/anuke/annotations/RemoteMethodAnnotationProcessor.java index 1c5bb5301d..b9fbba57a8 100644 --- a/annotations/src/main/java/io/anuke/annotations/RemoteMethodAnnotationProcessor.java +++ b/annotations/src/main/java/io/anuke/annotations/RemoteMethodAnnotationProcessor.java @@ -1,18 +1,13 @@ package io.anuke.annotations; -import com.squareup.javapoet.FieldSpec; -import com.squareup.javapoet.JavaFile; -import com.squareup.javapoet.TypeSpec; +import com.squareup.javapoet.*; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.annotations.IOFinder.ClassSerializer; import javax.annotation.processing.*; import javax.lang.model.SourceVersion; -import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.TypeElement; +import javax.lang.model.element.*; import javax.tools.Diagnostic.Kind; import java.util.*; import java.util.stream.Collectors; @@ -21,14 +16,14 @@ import java.util.stream.Collectors; /** The annotation processor for generating remote method call code. */ @SupportedSourceVersion(SourceVersion.RELEASE_8) @SupportedAnnotationTypes({ - "io.anuke.annotations.Annotations.Remote", - "io.anuke.annotations.Annotations.WriteClass", - "io.anuke.annotations.Annotations.ReadClass", +"io.anuke.annotations.Annotations.Remote", +"io.anuke.annotations.Annotations.WriteClass", +"io.anuke.annotations.Annotations.ReadClass", }) public class RemoteMethodAnnotationProcessor extends AbstractProcessor{ /** Maximum size of each event packet. */ public static final int maxPacketSize = 4096; - /** Warning on top of each autogenerated file.*/ + /** Warning on top of each autogenerated file. */ public static final String autogenWarning = "Autogenerated file. Do not modify!\n"; /** Name of the base package to put all the generated classes. */ private static final String packageName = "io.anuke.mindustry.gen"; @@ -37,7 +32,7 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor{ private static final String readServerName = "RemoteReadServer"; /** Name of class that handles reading and invoking packets on the client. */ private static final String readClientName = "RemoteReadClient"; - /**Simple class name of generated class name.*/ + /** Simple class name of generated class name. */ private static final String callLocation = "Call"; /** Processing round number. */ @@ -115,7 +110,7 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor{ //create and add entry MethodEntry method = new MethodEntry(entry.name, Utils.getMethodName(element), annotation.targets(), annotation.variants(), - annotation.called(), annotation.unreliable(), annotation.forward(), lastMethodID++, (ExecutableElement) element, annotation.priority()); + annotation.called(), annotation.unreliable(), annotation.forward(), lastMethodID++, (ExecutableElement)element, annotation.priority()); entry.methods.add(method); methods.add(method); @@ -140,7 +135,7 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor{ TypeSpec.Builder hashBuilder = TypeSpec.classBuilder("MethodHash").addModifiers(Modifier.PUBLIC); hashBuilder.addJavadoc(autogenWarning); hashBuilder.addField(FieldSpec.builder(int.class, "HASH", Modifier.STATIC, Modifier.PUBLIC, Modifier.FINAL) - .initializer("$1L", Objects.hash(methods)).build()); + .initializer("$1L", Objects.hash(methods)).build()); //build and write resulting hash class TypeSpec spec = hashBuilder.build(); diff --git a/annotations/src/main/java/io/anuke/annotations/RemoteReadGenerator.java b/annotations/src/main/java/io/anuke/annotations/RemoteReadGenerator.java index 69dbe29f8b..d23bd592c9 100644 --- a/annotations/src/main/java/io/anuke/annotations/RemoteReadGenerator.java +++ b/annotations/src/main/java/io/anuke/annotations/RemoteReadGenerator.java @@ -3,9 +3,7 @@ package io.anuke.annotations; import com.squareup.javapoet.*; import io.anuke.annotations.IOFinder.ClassSerializer; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; +import javax.lang.model.element.*; import javax.tools.Diagnostic.Kind; import java.io.IOException; import java.lang.reflect.Constructor; @@ -25,24 +23,23 @@ public class RemoteReadGenerator{ /** * Generates a class for reading remote invoke packets. - * * @param entries List of methods to use. * @param className Simple target class name. * @param packageName Full target package name. * @param needsPlayer Whether this read method requires a reference to the player sender. */ public void generateFor(List entries, String className, String packageName, boolean needsPlayer) - throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException, IOException{ + throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException, IOException{ TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC); classBuilder.addJavadoc(RemoteMethodAnnotationProcessor.autogenWarning); //create main method builder MethodSpec.Builder readMethod = MethodSpec.methodBuilder("readPacket") - .addModifiers(Modifier.PUBLIC, Modifier.STATIC) - .addParameter(ByteBuffer.class, "buffer") //buffer to read form - .addParameter(int.class, "id") //ID of method type to read - .returns(void.class); + .addModifiers(Modifier.PUBLIC, Modifier.STATIC) + .addParameter(ByteBuffer.class, "buffer") //buffer to read form + .addParameter(int.class, "id") //ID of method type to read + .returns(void.class); if(needsPlayer){ //since the player type isn't loaded yet, creating a type def is necessary @@ -115,13 +112,13 @@ public class RemoteReadGenerator{ //execute the relevant method before the forward //if it throws a ValidateException, the method won't be forwarded - readBlock.addStatement("$N." + entry.element.getSimpleName() + "(" + varResult.toString() + ")", ((TypeElement) entry.element.getEnclosingElement()).getQualifiedName().toString()); + readBlock.addStatement("$N." + entry.element.getSimpleName() + "(" + varResult.toString() + ")", ((TypeElement)entry.element.getEnclosingElement()).getQualifiedName().toString()); //call forwarded method, don't forward on the client reader if(entry.forward && entry.where.isServer && needsPlayer){ //call forwarded method readBlock.addStatement(packageName + "." + entry.className + "." + entry.element.getSimpleName() + - "__forward(player.con.id" + (varResult.length() == 0 ? "" : ", ") + varResult.toString() + ")"); + "__forward(player.con.id" + (varResult.length() == 0 ? "" : ", ") + varResult.toString() + ")"); } readBlock.nextControlFlow("catch (java.lang.Exception e)"); diff --git a/annotations/src/main/java/io/anuke/annotations/RemoteWriteGenerator.java b/annotations/src/main/java/io/anuke/annotations/RemoteWriteGenerator.java index 2f195aa896..411f8ead86 100644 --- a/annotations/src/main/java/io/anuke/annotations/RemoteWriteGenerator.java +++ b/annotations/src/main/java/io/anuke/annotations/RemoteWriteGenerator.java @@ -4,10 +4,7 @@ import com.squareup.javapoet.*; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.IOFinder.ClassSerializer; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; +import javax.lang.model.element.*; import javax.tools.Diagnostic.Kind; import java.io.IOException; import java.nio.ByteBuffer; @@ -33,7 +30,7 @@ public class RemoteWriteGenerator{ //add temporary write buffer classBuilder.addField(FieldSpec.builder(ByteBuffer.class, "TEMP_BUFFER", Modifier.STATIC, Modifier.PRIVATE, Modifier.FINAL) - .initializer("ByteBuffer.allocate($1L)", RemoteMethodAnnotationProcessor.maxPacketSize).build()); + .initializer("ByteBuffer.allocate($1L)", RemoteMethodAnnotationProcessor.maxPacketSize).build()); //go through each method entry in this class for(MethodEntry methodEntry : entry.methods){ @@ -65,8 +62,8 @@ public class RemoteWriteGenerator{ //create builder MethodSpec.Builder method = MethodSpec.methodBuilder(elem.getSimpleName().toString() + (forwarded ? "__forward" : "")) //add except suffix when forwarding - .addModifiers(Modifier.STATIC, Modifier.SYNCHRONIZED) - .returns(void.class); + .addModifiers(Modifier.STATIC, Modifier.SYNCHRONIZED) + .returns(void.class); //forwarded methods aren't intended for use, and are not public if(!forwarded){ @@ -109,7 +106,7 @@ public class RemoteWriteGenerator{ for(VariableElement var : elem.getParameters()){ //special case: calling local-only methods uses the local player if(index == 0 && methodEntry.where == Loc.client){ - results.append("io.anuke.mindustry.Vars.players[0]"); + results.append("io.anuke.mindustry.Vars.player"); }else{ results.append(var.getSimpleName()); } @@ -119,7 +116,7 @@ public class RemoteWriteGenerator{ //add the statement to call it method.addStatement("$N." + elem.getSimpleName() + "(" + results.toString() + ")", - ((TypeElement) elem.getEnclosingElement()).getQualifiedName().toString()); + ((TypeElement)elem.getEnclosingElement()).getQualifiedName().toString()); if(methodEntry.local != Loc.both){ method.endControlFlow(); @@ -170,7 +167,7 @@ public class RemoteWriteGenerator{ method.addStatement("TEMP_BUFFER.put(" + varName + " ? (byte)1 : 0)"); }else{ method.addStatement("TEMP_BUFFER.put" + - capName + "(" + varName + ")"); + capName + "(" + varName + ")"); } }else{ //else, try and find a serializer @@ -209,7 +206,7 @@ public class RemoteWriteGenerator{ //send the actual packet method.addStatement("io.anuke.mindustry.net.Net." + sendString + "packet, " + - (methodEntry.unreliable ? "io.anuke.mindustry.net.Net.SendMode.udp" : "io.anuke.mindustry.net.Net.SendMode.tcp") + ")"); + (methodEntry.unreliable ? "io.anuke.mindustry.net.Net.SendMode.udp" : "io.anuke.mindustry.net.Net.SendMode.tcp") + ")"); //end check for server/client @@ -221,7 +218,7 @@ public class RemoteWriteGenerator{ private String getCheckString(Loc loc){ return loc.isClient && loc.isServer ? "io.anuke.mindustry.net.Net.server() || io.anuke.mindustry.net.Net.client()" : - loc.isClient ? "io.anuke.mindustry.net.Net.client()" : - loc.isServer ? "io.anuke.mindustry.net.Net.server()" : "false"; + loc.isClient ? "io.anuke.mindustry.net.Net.client()" : + loc.isServer ? "io.anuke.mindustry.net.Net.server()" : "false"; } } diff --git a/annotations/src/main/java/io/anuke/annotations/SerializeAnnotationProcessor.java b/annotations/src/main/java/io/anuke/annotations/SerializeAnnotationProcessor.java index 1f8450cd13..358a52bbbf 100644 --- a/annotations/src/main/java/io/anuke/annotations/SerializeAnnotationProcessor.java +++ b/annotations/src/main/java/io/anuke/annotations/SerializeAnnotationProcessor.java @@ -5,13 +5,9 @@ import io.anuke.annotations.Annotations.Serialize; import javax.annotation.processing.*; import javax.lang.model.SourceVersion; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; +import javax.lang.model.element.*; import javax.lang.model.util.ElementFilter; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import java.lang.reflect.Field; import java.util.List; import java.util.Set; @@ -21,7 +17,7 @@ import java.util.Set; "io.anuke.annotations.Annotations.Serialize" }) public class SerializeAnnotationProcessor extends AbstractProcessor{ - /**Target class name.*/ + /** Target class name. */ private static final String className = "Serialization"; /** Name of the base package to put all the generated classes. */ private static final String packageName = "io.anuke.mindustry.gen"; @@ -50,8 +46,21 @@ public class SerializeAnnotationProcessor extends AbstractProcessor{ classBuilder.addJavadoc(RemoteMethodAnnotationProcessor.autogenWarning); MethodSpec.Builder method = MethodSpec.methodBuilder("init").addModifiers(Modifier.PUBLIC, Modifier.STATIC); + TypeName jsonType = ClassName.bestGuess("io.anuke.arc.util.serialization.Json"); + TypeName jsonValueType = ClassName.bestGuess("io.anuke.arc.util.serialization.JsonValue"); + TypeName ubJsonWriterType = ClassName.bestGuess("io.anuke.arc.util.serialization.UBJsonWriter"); + TypeName ubJsonReaderType = ClassName.bestGuess("io.anuke.arc.util.serialization.UBJsonReader"); + + classBuilder.addField(jsonType, "bjson", Modifier.STATIC, Modifier.PRIVATE); + classBuilder.addField(ubJsonReaderType, "bjsonReader", Modifier.STATIC, Modifier.PRIVATE); + classBuilder.addStaticBlock(CodeBlock.builder() + .addStatement("bjson = new " + jsonType + "()") + .addStatement("bjsonReader = new " + ubJsonReaderType + "()") + .build()); + for(TypeElement elem : elements){ TypeName type = TypeName.get(elem.asType()); + String simpleTypeName = type.toString().substring(type.toString().lastIndexOf('.') + 1); TypeSpec.Builder serializer = TypeSpec.anonymousClassBuilder("") .addSuperinterface(ParameterizedTypeName.get( @@ -70,11 +79,24 @@ public class SerializeAnnotationProcessor extends AbstractProcessor{ .addException(IOException.class) .addModifiers(Modifier.PUBLIC); + MethodSpec.Builder jsonWriteMethod = MethodSpec.methodBuilder("write" + simpleTypeName + "Json") + .returns(void.class) + .addParameter(jsonType, "json") + .addParameter(type, "object") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC); + + MethodSpec.Builder jsonReadMethod = MethodSpec.methodBuilder("read" + simpleTypeName + "Json") + .returns(type) + .addParameter(jsonValueType, "value") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC); + readMethod.addStatement("$L object = new $L()", type, type); + jsonReadMethod.addStatement("$L object = new $L()", type, type); List fields = ElementFilter.fieldsIn(Utils.elementUtils.getAllMembers(elem)); for(VariableElement field : fields){ - if(field.getModifiers().contains(Modifier.STATIC) || field.getModifiers().contains(Modifier.TRANSIENT) || field.getModifiers().contains(Modifier.PRIVATE)) continue; + if(field.getModifiers().contains(Modifier.STATIC) || field.getModifiers().contains(Modifier.TRANSIENT) || field.getModifiers().contains(Modifier.PRIVATE)) + continue; String name = field.getSimpleName().toString(); String typeName = Utils.typeUtils.erasure(field.asType()).toString().replace('$', '.'); @@ -83,29 +105,57 @@ public class SerializeAnnotationProcessor extends AbstractProcessor{ if(field.asType().getKind().isPrimitive()){ writeMethod.addStatement("stream.write" + capName + "(object." + name + ")"); readMethod.addStatement("object." + name + "= stream.read" + capName + "()"); + + jsonWriteMethod.addStatement("json.writeValue(\"" + name + "\", object." + name + ")"); + jsonReadMethod.addStatement("if(value.has(\"" + name + "\")) object." + name + "= value.get" + capName + "(\"" + name + "\")"); }else{ - writeMethod.addStatement("io.anuke.arc.Core.settings.getSerializer(" + typeName+ ".class).write(stream, object." + name + ")"); - readMethod.addStatement("object." + name + " = (" +typeName+")io.anuke.arc.Core.settings.getSerializer(" + typeName+ ".class).read(stream)"); + writeMethod.addStatement("io.anuke.arc.Core.settings.getSerializer(" + typeName + ".class).write(stream, object." + name + ")"); + readMethod.addStatement("object." + name + " = (" + typeName + ")io.anuke.arc.Core.settings.getSerializer(" + typeName + ".class).read(stream)"); } } readMethod.addStatement("return object"); + jsonReadMethod.addStatement("return object"); serializer.addMethod(writeMethod.build()); serializer.addMethod(readMethod.build()); - method.addStatement("io.anuke.arc.Core.settings.setSerializer($N, $L)", Utils.elementUtils.getBinaryName(elem).toString().replace('$', '.') + ".class", serializer.build()); + method.addStatement("io.anuke.arc.Core.settings.setSerializer($N, $L)", Utils.elementUtils.getBinaryName(elem).toString().replace('$', '.') + ".class", serializer.build()); - String sname = type.toString().substring(type.toString().lastIndexOf('.') + 1); - - name(writeMethod, "write" + sname); - name(readMethod, "read" + sname); + name(writeMethod, "write" + simpleTypeName); + name(readMethod, "read" + simpleTypeName); writeMethod.addModifiers(Modifier.STATIC); readMethod.addModifiers(Modifier.STATIC); classBuilder.addMethod(writeMethod.build()); classBuilder.addMethod(readMethod.build()); + + classBuilder.addMethod(jsonWriteMethod.build()); + classBuilder.addMethod(jsonReadMethod.build()); + + MethodSpec.Builder binaryJsonWriteMethod = MethodSpec.methodBuilder("write" + simpleTypeName + "StreamJson") + .returns(void.class) + .addParameter(DataOutput.class, "stream") + .addParameter(type, "object") + .addException(IOException.class) + .addModifiers(Modifier.PUBLIC, Modifier.STATIC) + .addStatement("java.io.StringWriter output = new java.io.StringWriter()") + .addStatement("bjson.setWriter(output)") + .addStatement("bjson.writeObjectStart(" + type + ".class, " + type + ".class)") + .addStatement("write" + simpleTypeName + "Json(bjson, object)") + .addStatement("bjson.writeObjectEnd()") + .addStatement("stream.writeUTF(output.toString())"); + + MethodSpec.Builder binaryJsonReadMethod = MethodSpec.methodBuilder("read" + simpleTypeName + "StreamJson") + .returns(type) + .addParameter(DataInput.class, "stream") + .addException(IOException.class) + .addModifiers(Modifier.PUBLIC, Modifier.STATIC) + .addStatement("return read" + simpleTypeName + "Json(bjson.fromJson(null, stream.readUTF()))"); + + classBuilder.addMethod(binaryJsonWriteMethod.build()); + classBuilder.addMethod(binaryJsonReadMethod.build()); } classBuilder.addMethod(method.build()); diff --git a/annotations/src/main/java/io/anuke/annotations/StructAnnotationProcessor.java b/annotations/src/main/java/io/anuke/annotations/StructAnnotationProcessor.java index dca27b6fa1..fa89b6e132 100644 --- a/annotations/src/main/java/io/anuke/annotations/StructAnnotationProcessor.java +++ b/annotations/src/main/java/io/anuke/annotations/StructAnnotationProcessor.java @@ -1,28 +1,25 @@ package io.anuke.annotations; -import com.squareup.javapoet.JavaFile; -import com.squareup.javapoet.MethodSpec; -import com.squareup.javapoet.TypeName; -import com.squareup.javapoet.TypeSpec; +import com.squareup.javapoet.*; import io.anuke.annotations.Annotations.Struct; import io.anuke.annotations.Annotations.StructField; import javax.annotation.processing.*; import javax.lang.model.SourceVersion; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; +import javax.lang.model.element.*; import javax.lang.model.type.TypeKind; import javax.lang.model.util.ElementFilter; import javax.tools.Diagnostic.Kind; import java.util.List; import java.util.Set; -/**Generates ""value types"" classes that are packed into integer primitives of the most aproppriate size. - * It would be nice if Java didn't make crazy hacks like this necessary.*/ +/** + * Generates ""value types"" classes that are packed into integer primitives of the most aproppriate size. + * It would be nice if Java didn't make crazy hacks like this necessary. + */ @SupportedSourceVersion(SourceVersion.RELEASE_8) @SupportedAnnotationTypes({ - "io.anuke.annotations.Annotations.Struct" +"io.anuke.annotations.Annotations.Struct" }) public class StructAnnotationProcessor extends AbstractProcessor{ /** Name of the base package to put all the generated classes. */ @@ -57,7 +54,7 @@ public class StructAnnotationProcessor extends AbstractProcessor{ String structParam = structName.toLowerCase(); TypeSpec.Builder classBuilder = TypeSpec.classBuilder(structName) - .addModifiers(Modifier.FINAL, Modifier.PUBLIC); + .addModifiers(Modifier.FINAL, Modifier.PUBLIC); try{ List variables = ElementFilter.fieldsIn(elem.getEnclosedElements()); @@ -92,14 +89,14 @@ public class StructAnnotationProcessor extends AbstractProcessor{ //[get] field(structType) : fieldType MethodSpec.Builder getter = MethodSpec.methodBuilder(var.getSimpleName().toString()) - .addModifiers(Modifier.STATIC, Modifier.PUBLIC) - .returns(varType) - .addParameter(structType, structParam); + .addModifiers(Modifier.STATIC, Modifier.PUBLIC) + .returns(varType) + .addParameter(structType, structParam); //[set] field(structType, fieldType) : structType MethodSpec.Builder setter = MethodSpec.methodBuilder(var.getSimpleName().toString()) - .addModifiers(Modifier.STATIC, Modifier.PUBLIC) - .returns(structType) - .addParameter(structType, structParam).addParameter(varType, "value"); + .addModifiers(Modifier.STATIC, Modifier.PUBLIC) + .returns(structType) + .addParameter(structType, structParam).addParameter(varType, "value"); //[getter] if(varType == TypeName.BOOLEAN){ @@ -129,7 +126,7 @@ public class StructAnnotationProcessor extends AbstractProcessor{ //floats: need conversion setter.addStatement("return ($T)(($L & $L) | (($T)Float.floatToIntBits(value) << $LL))", structType, structParam, bitString(offset, size, structTotalSize), structType, offset); }else{ - cons.append(" | (").append("(").append(structType).append(")").append(varName).append(" << ").append(offset).append("L)"); + cons.append(" | (((").append(structType).append(")").append(varName).append(" << ").append(offset).append("L)").append(" & ").append(bitString(offset, size, structTotalSize)).append(")"); //bytes, shorts, chars, ints setter.addStatement("return ($T)(($L & $L) | (($T)value << $LL))", structType, structParam, bitString(offset, size, structTotalSize), structType, offset); @@ -209,7 +206,7 @@ public class StructAnnotationProcessor extends AbstractProcessor{ throw new IllegalArgumentException("Too many fields, must fit in 64 bits. Curent size: " + size); } - /**returns a type's element size in bits.*/ + /** returns a type's element size in bits. */ static int typeSize(TypeKind kind) throws IllegalArgumentException{ switch(kind){ case BOOLEAN: diff --git a/annotations/src/main/java/io/anuke/annotations/Utils.java b/annotations/src/main/java/io/anuke/annotations/Utils.java index 551d953bc4..fa54f4c12d 100644 --- a/annotations/src/main/java/io/anuke/annotations/Utils.java +++ b/annotations/src/main/java/io/anuke/annotations/Utils.java @@ -14,11 +14,11 @@ public class Utils{ public static Messager messager; public static String getMethodName(Element element){ - return ((TypeElement) element.getEnclosingElement()).getQualifiedName().toString() + "." + element.getSimpleName(); + return ((TypeElement)element.getEnclosingElement()).getQualifiedName().toString() + "." + element.getSimpleName(); } public static boolean isPrimitive(String type){ return type.equals("boolean") || type.equals("byte") || type.equals("short") || type.equals("int") - || type.equals("long") || type.equals("float") || type.equals("double") || type.equals("char"); + || type.equals("long") || type.equals("float") || type.equals("double") || type.equals("char"); } } diff --git a/build.gradle b/build.gradle index 74fb990a22..1b5a1b72e7 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ buildscript{ } dependencies{ - classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.5' + classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.6' classpath "com.badlogicgames.gdx:gdx-tools:1.9.9" classpath "com.badlogicgames.packr:packr:2.1-SNAPSHOT" } @@ -25,15 +25,15 @@ allprojects{ if(!project.hasProperty("versionType")) versionType = 'official' appName = 'Mindustry' gdxVersion = '1.9.9' - roboVMVersion = '2.3.0' + roboVMVersion = '2.3.6' arcHash = null - + debugged = { - return new File(projectDir.parent, '../debug').exists() && System.properties["release"] == null + return new File(projectDir.parent, '../debug').exists() && !project.hasProperty("release") } localArc = { - return (System.properties["release"] == null || System.properties["release"] == "false") && new File(projectDir.parent, '../Arc').exists() + return (!project.hasProperty("release")) && new File(projectDir.parent, '../Arc').exists() } getArcHash = { @@ -43,7 +43,7 @@ allprojects{ arcHash = 'git ls-remote https://github.com/Anuken/Arc.git'.execute().text.split("\t")[0] }catch(e){ e.printStackTrace() - arcHash = "-SNAPSHOT"; + arcHash = "-SNAPSHOT" } } return arcHash @@ -89,7 +89,8 @@ allprojects{ try{ pfile.createNewFile() - }catch(Exception ignored){} + }catch(Exception ignored){ + } if(pfile.exists()){ props.load(new FileInputStream(pfile)) @@ -112,6 +113,7 @@ allprojects{ maven{ url "https://oss.sonatype.org/content/repositories/snapshots/" } maven{ url "https://oss.sonatype.org/content/repositories/releases/" } maven{ url 'https://jitpack.io' } + jcenter() } } @@ -121,14 +123,14 @@ project(":desktop"){ 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-lwjgl3") - compile 'com.github.MinnDevelopment:java-discord-rpc:v2.0.0' + compile 'com.github.MinnDevelopment:java-discord-rpc:v2.0.2' } } @@ -156,9 +158,10 @@ project(":ios"){ dependencies{ compile project(":core") compile project(":net") + compileOnly project(":annotations") compile arcModule("backends:backend-robovm") - + compile "com.mobidevelop.robovm:robovm-rt:$roboVMVersion" compile "com.mobidevelop.robovm:robovm-cocoatouch:$roboVMVersion" compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-ios" @@ -199,6 +202,7 @@ project(":core"){ compile arcModule("arc-core") compile arcModule("extensions:freetype") + //compile arcModule("extensions:postprocessing") if(localArc() && debugged()) compile arcModule("extensions:recorder") compileOnly project(":annotations") diff --git a/core/assets-raw/sprites/blocks/defense/mender-top.png b/core/assets-raw/sprites/blocks/defense/mender-top.png new file mode 100644 index 0000000000..424c81c793 Binary files /dev/null and b/core/assets-raw/sprites/blocks/defense/mender-top.png differ diff --git a/core/assets-raw/sprites/blocks/defense/mender.png b/core/assets-raw/sprites/blocks/defense/mender.png new file mode 100644 index 0000000000..34c765afcd Binary files /dev/null and b/core/assets-raw/sprites/blocks/defense/mender.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 22ffe595a5..a9c0f5adad 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-rotator.png b/core/assets-raw/sprites/blocks/drills/laser-drill-rotator.png index f58528f84f..fe87720d61 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 46d9519881..106df26337 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 97e620dfb3..1cf4fb002b 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/oil-extractor-top.png b/core/assets-raw/sprites/blocks/drills/oil-extractor-top.png index ba07cbb184..ab6dbb8f03 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 8d363c44cb..b67aa00eb5 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/environment/creeptree.png b/core/assets-raw/sprites/blocks/environment/creeptree.png new file mode 100644 index 0000000000..7f50d064fc Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/creeptree.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 new file mode 100644 index 0000000000..1d3f1286e3 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/dark-metal-large.png differ diff --git a/core/assets-raw/sprites/blocks/environment/dark-metal1.png b/core/assets-raw/sprites/blocks/environment/dark-metal1.png new file mode 100644 index 0000000000..628ab6f6a3 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/dark-metal1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/dark-metal2.png b/core/assets-raw/sprites/blocks/environment/dark-metal2.png new file mode 100644 index 0000000000..048f1f88ff Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/dark-metal2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/dark-panel-1.png b/core/assets-raw/sprites/blocks/environment/dark-panel-1.png new file mode 100644 index 0000000000..5127bcd8ae Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/dark-panel-1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/dark-panel-2.png b/core/assets-raw/sprites/blocks/environment/dark-panel-2.png new file mode 100644 index 0000000000..58bfca2b27 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/dark-panel-2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/dark-panel-3.png b/core/assets-raw/sprites/blocks/environment/dark-panel-3.png new file mode 100644 index 0000000000..098dfbf429 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/dark-panel-3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/dark-panel-4.png b/core/assets-raw/sprites/blocks/environment/dark-panel-4.png new file mode 100644 index 0000000000..4d15be6b8d Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/dark-panel-4.png differ diff --git a/core/assets-raw/sprites/blocks/environment/dark-panel-5.png b/core/assets-raw/sprites/blocks/environment/dark-panel-5.png new file mode 100644 index 0000000000..7b52b05aa7 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/dark-panel-5.png differ diff --git a/core/assets-raw/sprites/blocks/environment/dark-panel-6.png b/core/assets-raw/sprites/blocks/environment/dark-panel-6.png new file mode 100644 index 0000000000..1fdc58d411 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/dark-panel-6.png differ diff --git a/core/assets-raw/sprites/blocks/environment/darksand1.png b/core/assets-raw/sprites/blocks/environment/darksand1.png new file mode 100644 index 0000000000..aa70565c08 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/darksand1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/darksand2.png b/core/assets-raw/sprites/blocks/environment/darksand2.png new file mode 100644 index 0000000000..82c0b9e074 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/darksand2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/darksand3.png b/core/assets-raw/sprites/blocks/environment/darksand3.png new file mode 100644 index 0000000000..942a1b2574 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/darksand3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/dunerocks-large.png b/core/assets-raw/sprites/blocks/environment/dunerocks-large.png index 44f6a2f372..7139941920 100644 Binary files a/core/assets-raw/sprites/blocks/environment/dunerocks-large.png and b/core/assets-raw/sprites/blocks/environment/dunerocks-large.png differ diff --git a/core/assets-raw/sprites/blocks/environment/dunerocks1.png b/core/assets-raw/sprites/blocks/environment/dunerocks1.png index 384904fa48..c13f3b73f2 100644 Binary files a/core/assets-raw/sprites/blocks/environment/dunerocks1.png and b/core/assets-raw/sprites/blocks/environment/dunerocks1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/dunerocks2.png b/core/assets-raw/sprites/blocks/environment/dunerocks2.png index 0409649b3f..11d9c15cba 100644 Binary files a/core/assets-raw/sprites/blocks/environment/dunerocks2.png and b/core/assets-raw/sprites/blocks/environment/dunerocks2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/edge-stencil-blocky.png b/core/assets-raw/sprites/blocks/environment/edge-stencil-blocky.png deleted file mode 100644 index e9e15f64bb..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/edge-stencil-blocky.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/hotrock1.png b/core/assets-raw/sprites/blocks/environment/hotrock1.png index f7c566bf06..5cb74267f6 100644 Binary files a/core/assets-raw/sprites/blocks/environment/hotrock1.png and b/core/assets-raw/sprites/blocks/environment/hotrock1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/hotrock2.png b/core/assets-raw/sprites/blocks/environment/hotrock2.png index 41586d523b..b26e6dddd7 100644 Binary files a/core/assets-raw/sprites/blocks/environment/hotrock2.png and b/core/assets-raw/sprites/blocks/environment/hotrock2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/hotrock3.png b/core/assets-raw/sprites/blocks/environment/hotrock3.png index cc72227234..b2bb2e1a47 100644 Binary files a/core/assets-raw/sprites/blocks/environment/hotrock3.png and b/core/assets-raw/sprites/blocks/environment/hotrock3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/ice-edge.png b/core/assets-raw/sprites/blocks/environment/ice-edge.png deleted file mode 100644 index 0355b50f3a..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/ice-edge.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/ignarock1.png b/core/assets-raw/sprites/blocks/environment/ignarock1.png index c329cb2f15..cde4186e52 100644 Binary files a/core/assets-raw/sprites/blocks/environment/ignarock1.png and b/core/assets-raw/sprites/blocks/environment/ignarock1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/ignarock2.png b/core/assets-raw/sprites/blocks/environment/ignarock2.png index 08834e87af..536e8d995b 100644 Binary files a/core/assets-raw/sprites/blocks/environment/ignarock2.png and b/core/assets-raw/sprites/blocks/environment/ignarock2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/ignarock3.png b/core/assets-raw/sprites/blocks/environment/ignarock3.png index eb0af3a572..6ba51e5957 100644 Binary files a/core/assets-raw/sprites/blocks/environment/ignarock3.png and b/core/assets-raw/sprites/blocks/environment/ignarock3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/magmarock1.png b/core/assets-raw/sprites/blocks/environment/magmarock1.png index 05d62c8859..68ef3a28e7 100644 Binary files a/core/assets-raw/sprites/blocks/environment/magmarock1.png and b/core/assets-raw/sprites/blocks/environment/magmarock1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/magmarock2.png b/core/assets-raw/sprites/blocks/environment/magmarock2.png index 65640ff22c..dfab8e2f30 100644 Binary files a/core/assets-raw/sprites/blocks/environment/magmarock2.png and b/core/assets-raw/sprites/blocks/environment/magmarock2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/magmarock3.png b/core/assets-raw/sprites/blocks/environment/magmarock3.png index 07dbf8366d..66f3080629 100644 Binary files a/core/assets-raw/sprites/blocks/environment/magmarock3.png and b/core/assets-raw/sprites/blocks/environment/magmarock3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/metal-floor-2.png b/core/assets-raw/sprites/blocks/environment/metal-floor-2.png index 8d3b818096..d4930278d5 100644 Binary files a/core/assets-raw/sprites/blocks/environment/metal-floor-2.png and b/core/assets-raw/sprites/blocks/environment/metal-floor-2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/metal-floor-3.png b/core/assets-raw/sprites/blocks/environment/metal-floor-3.png index eb6b15d03b..f16fde60bb 100644 Binary files a/core/assets-raw/sprites/blocks/environment/metal-floor-3.png and b/core/assets-raw/sprites/blocks/environment/metal-floor-3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/metal-floor-5.png b/core/assets-raw/sprites/blocks/environment/metal-floor-5.png index e9d39b3db2..b2fe8c279d 100644 Binary files a/core/assets-raw/sprites/blocks/environment/metal-floor-5.png and b/core/assets-raw/sprites/blocks/environment/metal-floor-5.png differ diff --git a/core/assets-raw/sprites/blocks/environment/metal-floor-damaged1.png b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged1.png index e4220e9adc..f4eb327e07 100644 Binary files a/core/assets-raw/sprites/blocks/environment/metal-floor-damaged1.png and b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/metal-floor-damaged2.png b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged2.png index a74ac3897d..a8bcd4755d 100644 Binary files a/core/assets-raw/sprites/blocks/environment/metal-floor-damaged2.png and b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/metal-floor-damaged3.png b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged3.png index 2f07315bc5..3bf985f177 100644 Binary files a/core/assets-raw/sprites/blocks/environment/metal-floor-damaged3.png and b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/metal-floor-damaged4.png b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged4.png index 64027a66f1..2ce2d2786c 100644 Binary files a/core/assets-raw/sprites/blocks/environment/metal-floor-damaged4.png and b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged4.png differ diff --git a/core/assets-raw/sprites/blocks/environment/metal-floor-damaged5.png b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged5.png index 9c9b48708b..c030a04fa1 100644 Binary files a/core/assets-raw/sprites/blocks/environment/metal-floor-damaged5.png and b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged5.png differ diff --git a/core/assets-raw/sprites/blocks/environment/metal-floor-damaged6.png b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged6.png index f2b7f15be5..8b9b4d3fe8 100644 Binary files a/core/assets-raw/sprites/blocks/environment/metal-floor-damaged6.png and b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged6.png differ diff --git a/core/assets-raw/sprites/blocks/environment/metal-floor.png b/core/assets-raw/sprites/blocks/environment/metal-floor.png index 049e13a3ae..c030a04fa1 100644 Binary files a/core/assets-raw/sprites/blocks/environment/metal-floor.png and b/core/assets-raw/sprites/blocks/environment/metal-floor.png differ diff --git a/core/assets-raw/sprites/blocks/environment/moss1.png b/core/assets-raw/sprites/blocks/environment/moss1.png index 8344698387..924b902506 100644 Binary files a/core/assets-raw/sprites/blocks/environment/moss1.png and b/core/assets-raw/sprites/blocks/environment/moss1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/moss2.png b/core/assets-raw/sprites/blocks/environment/moss2.png index ed1a8981fb..3719205bea 100644 Binary files a/core/assets-raw/sprites/blocks/environment/moss2.png and b/core/assets-raw/sprites/blocks/environment/moss2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/moss3.png b/core/assets-raw/sprites/blocks/environment/moss3.png index ea5072a8dd..65ca4ca767 100644 Binary files a/core/assets-raw/sprites/blocks/environment/moss3.png and b/core/assets-raw/sprites/blocks/environment/moss3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/pack.json b/core/assets-raw/sprites/blocks/environment/pack.json index 91480ffa76..2612f17acc 100644 --- a/core/assets-raw/sprites/blocks/environment/pack.json +++ b/core/assets-raw/sprites/blocks/environment/pack.json @@ -1,8 +1,8 @@ { - duplicatePadding: true, - combineSubdirectories: true, - flattenPaths: true, - maxWidth: 2048, - maxHeight: 2048, - fast: true, + duplicatePadding: true, + combineSubdirectories: true, + flattenPaths: true, + maxWidth: 2048, + maxHeight: 2048, + fast: true } diff --git a/core/assets-raw/sprites/blocks/environment/pack_fallback.json b/core/assets-raw/sprites/blocks/environment/pack_fallback.json new file mode 100644 index 0000000000..853c7fc32f --- /dev/null +++ b/core/assets-raw/sprites/blocks/environment/pack_fallback.json @@ -0,0 +1,8 @@ +{ + duplicatePadding: true, + combineSubdirectories: true, + flattenPaths: true, + maxWidth: 1024, + maxHeight: 1024, + fast: true +} diff --git a/core/assets-raw/sprites/blocks/environment/pebbles1.png b/core/assets-raw/sprites/blocks/environment/pebbles1.png new file mode 100644 index 0000000000..28d2e8fe26 Binary files /dev/null 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 new file mode 100644 index 0000000000..e1f1679a9b Binary files /dev/null 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 new file mode 100644 index 0000000000..74c2388174 Binary files /dev/null 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 13eee73aaa..643932c15b 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/saltrocks-large.png b/core/assets-raw/sprites/blocks/environment/saltrocks-large.png new file mode 100644 index 0000000000..93c9d32da7 Binary files /dev/null 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 new file mode 100644 index 0000000000..0c5f64d1b6 Binary files /dev/null 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 new file mode 100644 index 0000000000..fa9643f794 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/saltrocks2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/sand1.png b/core/assets-raw/sprites/blocks/environment/sand1.png index 73e2c6d635..348aa527c2 100644 Binary files a/core/assets-raw/sprites/blocks/environment/sand1.png and b/core/assets-raw/sprites/blocks/environment/sand1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/sand2.png b/core/assets-raw/sprites/blocks/environment/sand2.png index 4429bb584b..47a14cdb84 100644 Binary files a/core/assets-raw/sprites/blocks/environment/sand2.png and b/core/assets-raw/sprites/blocks/environment/sand2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/sand3.png b/core/assets-raw/sprites/blocks/environment/sand3.png index c358be019b..f66cb0f33d 100644 Binary files a/core/assets-raw/sprites/blocks/environment/sand3.png and b/core/assets-raw/sprites/blocks/environment/sand3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/sandrocks-large.png b/core/assets-raw/sprites/blocks/environment/sandrocks-large.png index d91729fb22..968b6ce405 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 5df0ef7fe1..a9a76d7a83 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 70a4cea724..a795170808 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/shale1.png b/core/assets-raw/sprites/blocks/environment/shale1.png index 5b44a22c0b..81110df96b 100644 Binary files a/core/assets-raw/sprites/blocks/environment/shale1.png and b/core/assets-raw/sprites/blocks/environment/shale1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/shale2.png b/core/assets-raw/sprites/blocks/environment/shale2.png index bd6746d7a7..2ae6234529 100644 Binary files a/core/assets-raw/sprites/blocks/environment/shale2.png and b/core/assets-raw/sprites/blocks/environment/shale2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/shale3.png b/core/assets-raw/sprites/blocks/environment/shale3.png index f8678bd05f..dde6687dea 100644 Binary files a/core/assets-raw/sprites/blocks/environment/shale3.png and b/core/assets-raw/sprites/blocks/environment/shale3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/shrubs-large.png b/core/assets-raw/sprites/blocks/environment/shrubs-large.png new file mode 100644 index 0000000000..b155b297cd Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/shrubs-large.png differ diff --git a/core/assets-raw/sprites/blocks/environment/shrubs1.png b/core/assets-raw/sprites/blocks/environment/shrubs1.png new file mode 100644 index 0000000000..38e9848fc8 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/shrubs1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/shrubs2.png b/core/assets-raw/sprites/blocks/environment/shrubs2.png new file mode 100644 index 0000000000..6989198ea6 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/shrubs2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/snowrock1.png b/core/assets-raw/sprites/blocks/environment/snowrock1.png index 2a4cc7fca6..4b588fd1ca 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 fe78b97576..ee3ec6ad9c 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 75017dbee1..2e5047e702 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 5a18216caa..0f91b13def 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 d3f14dc536..24a26a54fe 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-moss1.png b/core/assets-raw/sprites/blocks/environment/spore-moss1.png index 270349168a..140e0023c6 100644 Binary files a/core/assets-raw/sprites/blocks/environment/spore-moss1.png and b/core/assets-raw/sprites/blocks/environment/spore-moss1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/spore-moss2.png b/core/assets-raw/sprites/blocks/environment/spore-moss2.png index 0546666a22..03b6b94fef 100644 Binary files a/core/assets-raw/sprites/blocks/environment/spore-moss2.png and b/core/assets-raw/sprites/blocks/environment/spore-moss2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/spore-moss3.png b/core/assets-raw/sprites/blocks/environment/spore-moss3.png index 4cfbe3ed3c..d1349bebe6 100644 Binary files a/core/assets-raw/sprites/blocks/environment/spore-moss3.png and b/core/assets-raw/sprites/blocks/environment/spore-moss3.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 9b0cf4712e..43f842fbca 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 8d9fbecd7a..8567468ec4 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 c50be4bb96..a3ce58c7ae 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/extra/rubble-4-0.png b/core/assets-raw/sprites/blocks/extra/rubble-4-0.png index 0a23d121b1..91c1fc9749 100644 Binary files a/core/assets-raw/sprites/blocks/extra/rubble-4-0.png and b/core/assets-raw/sprites/blocks/extra/rubble-4-0.png differ diff --git a/core/assets-raw/sprites/blocks/extra/rubble-4-1.png b/core/assets-raw/sprites/blocks/extra/rubble-4-1.png index 0bc32c92a7..91c1fc9749 100644 Binary files a/core/assets-raw/sprites/blocks/extra/rubble-4-1.png and b/core/assets-raw/sprites/blocks/extra/rubble-4-1.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/mechanical-pump.png b/core/assets-raw/sprites/blocks/liquid/mechanical-pump.png index b92420f1c3..f7d2ebe4cb 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/mechanical-pump.png and b/core/assets-raw/sprites/blocks/liquid/mechanical-pump.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/thermal-pump.png b/core/assets-raw/sprites/blocks/liquid/thermal-pump.png index c89ff8890d..a62d3d2418 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/thermal-pump.png and b/core/assets-raw/sprites/blocks/liquid/thermal-pump.png differ diff --git a/core/assets-raw/sprites/blocks/power/differential-generator-top.png b/core/assets-raw/sprites/blocks/power/differential-generator-top.png index a540f2b93c..ae0c4cc026 100644 Binary files a/core/assets-raw/sprites/blocks/power/differential-generator-top.png and b/core/assets-raw/sprites/blocks/power/differential-generator-top.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 adf332a1e9..95ff31b79b 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-top.png b/core/assets-raw/sprites/blocks/power/impact-reactor-top.png index b564994c56..05e799b15f 100644 Binary files a/core/assets-raw/sprites/blocks/power/impact-reactor-top.png and b/core/assets-raw/sprites/blocks/power/impact-reactor-top.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 50ad5a1852..dfb3ad5eaf 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/production/alloy-smelter-top.png b/core/assets-raw/sprites/blocks/production/alloy-smelter-top.png index 52616bf864..bef438ec0e 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/coal-centrifuge.png b/core/assets-raw/sprites/blocks/production/coal-centrifuge.png new file mode 100644 index 0000000000..31258cfb90 Binary files /dev/null and b/core/assets-raw/sprites/blocks/production/coal-centrifuge.png differ diff --git a/core/assets-raw/sprites/blocks/production/cultivator-top.png b/core/assets-raw/sprites/blocks/production/cultivator-top.png index c665608609..dc29af6e09 100644 Binary files a/core/assets-raw/sprites/blocks/production/cultivator-top.png and b/core/assets-raw/sprites/blocks/production/cultivator-top.png differ diff --git a/core/assets-raw/sprites/blocks/production/multi-press.png b/core/assets-raw/sprites/blocks/production/multi-press.png index 3adb9c84f1..effe30d689 100644 Binary files a/core/assets-raw/sprites/blocks/production/multi-press.png and b/core/assets-raw/sprites/blocks/production/multi-press.png differ diff --git a/core/assets-raw/sprites/blocks/production/plastanium-compressor.png b/core/assets-raw/sprites/blocks/production/plastanium-compressor.png index 8bcbc2c911..afdcb7006c 100644 Binary files a/core/assets-raw/sprites/blocks/production/plastanium-compressor.png and b/core/assets-raw/sprites/blocks/production/plastanium-compressor.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 18897e6b0f..e5ff06ade7 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/separator.png b/core/assets-raw/sprites/blocks/production/separator.png index 623bc76bba..6f628f9255 100644 Binary files a/core/assets-raw/sprites/blocks/production/separator.png and b/core/assets-raw/sprites/blocks/production/separator.png differ diff --git a/core/assets-raw/sprites/blocks/production/spore-press-frame0.png b/core/assets-raw/sprites/blocks/production/spore-press-frame0.png index 58a7284a74..4b646157a2 100644 Binary files a/core/assets-raw/sprites/blocks/production/spore-press-frame0.png and b/core/assets-raw/sprites/blocks/production/spore-press-frame0.png differ diff --git a/core/assets-raw/sprites/blocks/production/spore-press-frame1.png b/core/assets-raw/sprites/blocks/production/spore-press-frame1.png index 9d6b5fba03..1b8efd7534 100644 Binary files a/core/assets-raw/sprites/blocks/production/spore-press-frame1.png and b/core/assets-raw/sprites/blocks/production/spore-press-frame1.png differ diff --git a/core/assets-raw/sprites/blocks/production/spore-press-frame2.png b/core/assets-raw/sprites/blocks/production/spore-press-frame2.png index 8899a23501..404487235d 100644 Binary files a/core/assets-raw/sprites/blocks/production/spore-press-frame2.png and b/core/assets-raw/sprites/blocks/production/spore-press-frame2.png differ diff --git a/core/assets-raw/sprites/blocks/production/spore-press.png b/core/assets-raw/sprites/blocks/production/spore-press.png index def84f6512..4b06633f50 100644 Binary files a/core/assets-raw/sprites/blocks/production/spore-press.png and b/core/assets-raw/sprites/blocks/production/spore-press.png differ diff --git a/core/assets-raw/sprites/blocks/storage/launch-pad-large.png b/core/assets-raw/sprites/blocks/storage/launch-pad-large.png new file mode 100644 index 0000000000..10148c4853 Binary files /dev/null and b/core/assets-raw/sprites/blocks/storage/launch-pad-large.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/duo.png b/core/assets-raw/sprites/blocks/turrets/duo.png index 40d21d0fb0..68873f34e0 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/duo.png and b/core/assets-raw/sprites/blocks/turrets/duo.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/fuse.png b/core/assets-raw/sprites/blocks/turrets/fuse.png index c03bad9cba..a8875a7664 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 e679043a66..7f74cc57d8 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 9864ac6ad9..cb4a837ebb 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/salvo.png b/core/assets-raw/sprites/blocks/turrets/salvo.png index bfa377509f..9527912c07 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 f6e1d7ff61..d1b98c75bc 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-heat.png b/core/assets-raw/sprites/blocks/turrets/scorch-heat.png new file mode 100644 index 0000000000..ba5b47935e Binary files /dev/null and b/core/assets-raw/sprites/blocks/turrets/scorch-heat.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/scorch.png b/core/assets-raw/sprites/blocks/turrets/scorch.png new file mode 100644 index 0000000000..a1fb61f657 Binary files /dev/null and b/core/assets-raw/sprites/blocks/turrets/scorch.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/wave.png b/core/assets-raw/sprites/blocks/turrets/wave.png index ff132fbd74..05a115eb68 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/wave.png and b/core/assets-raw/sprites/blocks/turrets/wave.png differ diff --git a/core/assets-raw/sprites/blocks/units/crawler-factory-top-open.png b/core/assets-raw/sprites/blocks/units/crawler-factory-top-open.png index 290db9d373..8a41754b19 100644 Binary files a/core/assets-raw/sprites/blocks/units/crawler-factory-top-open.png and b/core/assets-raw/sprites/blocks/units/crawler-factory-top-open.png differ diff --git a/core/assets-raw/sprites/blocks/units/crawler-factory-top.png b/core/assets-raw/sprites/blocks/units/crawler-factory-top.png index f7cad4dbf6..79816238f7 100644 Binary files a/core/assets-raw/sprites/blocks/units/crawler-factory-top.png and b/core/assets-raw/sprites/blocks/units/crawler-factory-top.png differ diff --git a/core/assets-raw/sprites/blocks/walls/scrap-wall-gigantic.png b/core/assets-raw/sprites/blocks/walls/scrap-wall-gigantic.png index ffdc63ffcc..3146c493f8 100644 Binary files a/core/assets-raw/sprites/blocks/walls/scrap-wall-gigantic.png and b/core/assets-raw/sprites/blocks/walls/scrap-wall-gigantic.png differ diff --git a/core/assets-raw/sprites/blocks/walls/scrap-wall-huge1.png b/core/assets-raw/sprites/blocks/walls/scrap-wall-huge1.png index c03322d55d..b2b3c57b51 100644 Binary files a/core/assets-raw/sprites/blocks/walls/scrap-wall-huge1.png and b/core/assets-raw/sprites/blocks/walls/scrap-wall-huge1.png differ diff --git a/core/assets-raw/sprites/blocks/walls/scrap-wall-huge2.png b/core/assets-raw/sprites/blocks/walls/scrap-wall-huge2.png index bdf6d1344c..982649f167 100644 Binary files a/core/assets-raw/sprites/blocks/walls/scrap-wall-huge2.png and b/core/assets-raw/sprites/blocks/walls/scrap-wall-huge2.png differ diff --git a/core/assets-raw/sprites/blocks/walls/scrap-wall-huge3.png b/core/assets-raw/sprites/blocks/walls/scrap-wall-huge3.png index fa12bc5e02..02e2cd0a7a 100644 Binary files a/core/assets-raw/sprites/blocks/walls/scrap-wall-huge3.png and b/core/assets-raw/sprites/blocks/walls/scrap-wall-huge3.png differ diff --git a/core/assets-raw/sprites/blocks/walls/scrap-wall-large2.png b/core/assets-raw/sprites/blocks/walls/scrap-wall-large2.png index 804d7749e4..0b0c955246 100644 Binary files a/core/assets-raw/sprites/blocks/walls/scrap-wall-large2.png and b/core/assets-raw/sprites/blocks/walls/scrap-wall-large2.png differ diff --git a/core/assets-raw/sprites/blocks/walls/scrap-wall-large3.png b/core/assets-raw/sprites/blocks/walls/scrap-wall-large3.png index d7279d6b32..e3ae01cb89 100644 Binary files a/core/assets-raw/sprites/blocks/walls/scrap-wall-large3.png and b/core/assets-raw/sprites/blocks/walls/scrap-wall-large3.png differ diff --git a/core/assets-raw/sprites/blocks/walls/scrap-wall-large4.png b/core/assets-raw/sprites/blocks/walls/scrap-wall-large4.png index 3ea4802427..59002328c8 100644 Binary files a/core/assets-raw/sprites/blocks/walls/scrap-wall-large4.png and b/core/assets-raw/sprites/blocks/walls/scrap-wall-large4.png differ diff --git a/core/assets-raw/sprites/blocks/walls/scrap-wall4.png b/core/assets-raw/sprites/blocks/walls/scrap-wall4.png index df86f16cc2..0c709a1049 100644 Binary files a/core/assets-raw/sprites/blocks/walls/scrap-wall4.png and b/core/assets-raw/sprites/blocks/walls/scrap-wall4.png differ diff --git a/core/assets-raw/sprites/blocks/walls/scrap-wall5.png b/core/assets-raw/sprites/blocks/walls/scrap-wall5.png index 1f75829f3a..0c709a1049 100644 Binary files a/core/assets-raw/sprites/blocks/walls/scrap-wall5.png and b/core/assets-raw/sprites/blocks/walls/scrap-wall5.png differ diff --git a/core/assets-raw/sprites/blocks/walls/thruster.png b/core/assets-raw/sprites/blocks/walls/thruster.png index 82ec7622f6..8531ab06b7 100644 Binary files a/core/assets-raw/sprites/blocks/walls/thruster.png and b/core/assets-raw/sprites/blocks/walls/thruster.png differ diff --git a/core/assets-raw/sprites/mechs/mechs/omega-mech-armor.png b/core/assets-raw/sprites/mechs/mechs/omega-mech-armor.png index 943895deab..c2688c825e 100644 Binary files a/core/assets-raw/sprites/mechs/mechs/omega-mech-armor.png and b/core/assets-raw/sprites/mechs/mechs/omega-mech-armor.png differ diff --git a/core/assets-raw/sprites/pack.json b/core/assets-raw/sprites/pack.json index 91480ffa76..2612f17acc 100644 --- a/core/assets-raw/sprites/pack.json +++ b/core/assets-raw/sprites/pack.json @@ -1,8 +1,8 @@ { - duplicatePadding: true, - combineSubdirectories: true, - flattenPaths: true, - maxWidth: 2048, - maxHeight: 2048, - fast: true, + duplicatePadding: true, + combineSubdirectories: true, + flattenPaths: true, + maxWidth: 2048, + maxHeight: 2048, + fast: true } diff --git a/core/assets-raw/sprites/pack_fallback.json b/core/assets-raw/sprites/pack_fallback.json new file mode 100644 index 0000000000..853c7fc32f --- /dev/null +++ b/core/assets-raw/sprites/pack_fallback.json @@ -0,0 +1,8 @@ +{ + duplicatePadding: true, + combineSubdirectories: true, + flattenPaths: true, + maxWidth: 1024, + maxHeight: 1024, + fast: true +} diff --git a/core/assets-raw/sprites/ui/button-disabled.9.png b/core/assets-raw/sprites/ui/button-disabled.9.png index 2f57455034..b2e4d7eb25 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-right-down.9.png b/core/assets-raw/sprites/ui/button-right-down.9.png index 475f255934..efbabad92d 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 c764c18dab..1f6d0fa234 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 2c8c4bb1e0..cd3d8d52e1 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/check-off.png b/core/assets-raw/sprites/ui/check-off.png index 4ab1f7fae8..79b86aabc1 100644 Binary files a/core/assets-raw/sprites/ui/check-off.png and b/core/assets-raw/sprites/ui/check-off.png differ diff --git a/core/assets-raw/sprites/ui/check-on-over.png b/core/assets-raw/sprites/ui/check-on-over.png index 80f373a89f..716e6fffb7 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 57cc8a7484..e4a8d11538 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 2501a9daa9..5f618e5c86 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-noitems.9.png b/core/assets-raw/sprites/ui/content-background-noitems.9.png new file mode 100644 index 0000000000..f612ec98d4 Binary files /dev/null and b/core/assets-raw/sprites/ui/content-background-noitems.9.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-add.png b/core/assets-raw/sprites/ui/icons/icon-add.png index 50c7a2c330..328c8ca469 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-add.png and b/core/assets-raw/sprites/ui/icons/icon-add.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-database-small.png b/core/assets-raw/sprites/ui/icons/icon-database-small.png index dc105e3f67..059fd6f219 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-database-small.png and b/core/assets-raw/sprites/ui/icons/icon-database-small.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-database.png b/core/assets-raw/sprites/ui/icons/icon-database.png index f5bc48c80d..41e4b672f2 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-file-image.png b/core/assets-raw/sprites/ui/icons/icon-file-image.png index 5b0d2adbe5..254ea95f3d 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-file-image.png and b/core/assets-raw/sprites/ui/icons/icon-file-image.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-fill.png b/core/assets-raw/sprites/ui/icons/icon-fill.png index 25d439a830..79bc8b2c39 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-fill.png and b/core/assets-raw/sprites/ui/icons/icon-fill.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-power-requirement.png b/core/assets-raw/sprites/ui/icons/icon-power-requirement.png index dc82f5942e..a6deaa19bc 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-power-requirement.png and b/core/assets-raw/sprites/ui/icons/icon-power-requirement.png differ diff --git a/core/assets-raw/sprites/ui/logotext.png b/core/assets-raw/sprites/ui/logotext.png index 4305683321..64976a6c47 100644 Binary files a/core/assets-raw/sprites/ui/logotext.png and b/core/assets-raw/sprites/ui/logotext.png differ diff --git a/core/assets-raw/sprites/ui/underline-red.9.png b/core/assets-raw/sprites/ui/underline-red.9.png new file mode 100644 index 0000000000..5a6bc60651 Binary files /dev/null and b/core/assets-raw/sprites/ui/underline-red.9.png differ diff --git a/core/assets-raw/sprites/units/chaos-array-base.png b/core/assets-raw/sprites/units/chaos-array-base.png index b1174913d6..e80d4a1b53 100644 Binary files a/core/assets-raw/sprites/units/chaos-array-base.png and b/core/assets-raw/sprites/units/chaos-array-base.png differ diff --git a/core/assets-raw/sprites/units/chaos-array-leg.png b/core/assets-raw/sprites/units/chaos-array-leg.png index 7269601fcf..8d0aba139b 100644 Binary files a/core/assets-raw/sprites/units/chaos-array-leg.png and b/core/assets-raw/sprites/units/chaos-array-leg.png differ diff --git a/core/assets-raw/sprites/units/chaos-array.png b/core/assets-raw/sprites/units/chaos-array.png index afd96f43dc..9c0ff7d661 100644 Binary files a/core/assets-raw/sprites/units/chaos-array.png and b/core/assets-raw/sprites/units/chaos-array.png differ diff --git a/core/assets-raw/sprites/units/eradicator-base.png b/core/assets-raw/sprites/units/eradicator-base.png index 24b5cdb446..750e78bf41 100644 Binary files a/core/assets-raw/sprites/units/eradicator-base.png and b/core/assets-raw/sprites/units/eradicator-base.png differ diff --git a/core/assets-raw/sprites/units/eradicator-leg.png b/core/assets-raw/sprites/units/eradicator-leg.png index 3a503a2e6a..82ade466da 100644 Binary files a/core/assets-raw/sprites/units/eradicator-leg.png and b/core/assets-raw/sprites/units/eradicator-leg.png differ diff --git a/core/assets-raw/sprites/units/eradicator.png b/core/assets-raw/sprites/units/eradicator.png index c620aa3d0f..e4d3b0fe67 100644 Binary files a/core/assets-raw/sprites/units/eradicator.png and b/core/assets-raw/sprites/units/eradicator.png differ diff --git a/core/assets-raw/sprites/units/eruptor-base.png b/core/assets-raw/sprites/units/eruptor-base.png index 0b1e55dbb9..6efea6d508 100644 Binary files a/core/assets-raw/sprites/units/eruptor-base.png and b/core/assets-raw/sprites/units/eruptor-base.png differ diff --git a/core/assets-raw/sprites/units/eruptor-leg.png b/core/assets-raw/sprites/units/eruptor-leg.png index c3d622340a..9725454262 100644 Binary files a/core/assets-raw/sprites/units/eruptor-leg.png and b/core/assets-raw/sprites/units/eruptor-leg.png differ diff --git a/core/assets-raw/sprites/units/eruptor.png b/core/assets-raw/sprites/units/eruptor.png index 992fc9ea2d..ea76a8b29b 100644 Binary files a/core/assets-raw/sprites/units/eruptor.png and b/core/assets-raw/sprites/units/eruptor.png differ diff --git a/core/assets-raw/sprites/units/lich.png b/core/assets-raw/sprites/units/lich.png index 9f34958af8..ab440f96d8 100644 Binary files a/core/assets-raw/sprites/units/lich.png and b/core/assets-raw/sprites/units/lich.png differ diff --git a/core/assets-raw/sprites/units/reaper.png b/core/assets-raw/sprites/units/reaper.png index 2d70f5d179..5094cbae27 100644 Binary files a/core/assets-raw/sprites/units/reaper.png and b/core/assets-raw/sprites/units/reaper.png differ diff --git a/core/assets-raw/sprites/units/revenant.png b/core/assets-raw/sprites/units/revenant.png index 2c9616b93e..645ec6a995 100644 Binary files a/core/assets-raw/sprites/units/revenant.png and b/core/assets-raw/sprites/units/revenant.png differ diff --git a/core/assets-raw/sprites/weapons/artillery-equip.png b/core/assets-raw/sprites/weapons/artillery-equip.png index 843da3adbc..7572b98c95 100644 Binary files a/core/assets-raw/sprites/weapons/artillery-equip.png and b/core/assets-raw/sprites/weapons/artillery-equip.png differ diff --git a/core/assets-raw/sprites/weapons/chain-blaster-equip.png b/core/assets-raw/sprites/weapons/chain-blaster-equip.png index d2bc4331f4..b3c37d50a2 100644 Binary files a/core/assets-raw/sprites/weapons/chain-blaster-equip.png and b/core/assets-raw/sprites/weapons/chain-blaster-equip.png differ diff --git a/core/assets-raw/sprites/weapons/chaos-equip.png b/core/assets-raw/sprites/weapons/chaos-equip.png index 0a83fcc8a1..3254c70c88 100644 Binary files a/core/assets-raw/sprites/weapons/chaos-equip.png and b/core/assets-raw/sprites/weapons/chaos-equip.png differ diff --git a/core/assets-raw/sprites/weapons/eradication-equip.png b/core/assets-raw/sprites/weapons/eradication-equip.png index 16befb33e1..c3fbf46416 100644 Binary files a/core/assets-raw/sprites/weapons/eradication-equip.png and b/core/assets-raw/sprites/weapons/eradication-equip.png differ diff --git a/core/assets-raw/sprites/weapons/eruption-equip.png b/core/assets-raw/sprites/weapons/eruption-equip.png index 7758d622a5..11dc406fb0 100644 Binary files a/core/assets-raw/sprites/weapons/eruption-equip.png and b/core/assets-raw/sprites/weapons/eruption-equip.png differ diff --git a/core/assets-raw/sprites/weapons/flamethrower-equip.png b/core/assets-raw/sprites/weapons/flamethrower-equip.png index 40b085ac43..6c11713a5e 100644 Binary files a/core/assets-raw/sprites/weapons/flamethrower-equip.png and b/core/assets-raw/sprites/weapons/flamethrower-equip.png differ diff --git a/core/assets-raw/sprites/weapons/lich-missiles-equip.png b/core/assets-raw/sprites/weapons/lich-missiles-equip.png index 8deeb5416a..b5118bbf4e 100644 Binary files a/core/assets-raw/sprites/weapons/lich-missiles-equip.png and b/core/assets-raw/sprites/weapons/lich-missiles-equip.png differ diff --git a/core/assets-raw/sprites/weapons/reaper-gun-equip.png b/core/assets-raw/sprites/weapons/reaper-gun-equip.png index 1eb3cb64ba..f4addc0634 100644 Binary files a/core/assets-raw/sprites/weapons/reaper-gun-equip.png and b/core/assets-raw/sprites/weapons/reaper-gun-equip.png differ diff --git a/core/assets-raw/sprites/weapons/revenant-missiles-equip.png b/core/assets-raw/sprites/weapons/revenant-missiles-equip.png index e8ebc4be08..7e23b71b4e 100644 Binary files a/core/assets-raw/sprites/weapons/revenant-missiles-equip.png and b/core/assets-raw/sprites/weapons/revenant-missiles-equip.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/craters1.png b/core/assets-raw/sprites_replacement/blocks/environment/craters1.png new file mode 100644 index 0000000000..4b2172bc61 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/craters1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/craters2.png b/core/assets-raw/sprites_replacement/blocks/environment/craters2.png new file mode 100644 index 0000000000..1170ab3c4f Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/craters2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/craters3.png b/core/assets-raw/sprites_replacement/blocks/environment/craters3.png new file mode 100644 index 0000000000..9a23d383f7 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/craters3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/craters4.png b/core/assets-raw/sprites_replacement/blocks/environment/craters4.png new file mode 100644 index 0000000000..3d77e3080f Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/craters4.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/dark-metal-large.png b/core/assets-raw/sprites_replacement/blocks/environment/dark-metal-large.png new file mode 100644 index 0000000000..2b30255f53 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/dark-metal-large.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/dark-metal1.png b/core/assets-raw/sprites_replacement/blocks/environment/dark-metal1.png new file mode 100644 index 0000000000..907b253157 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/dark-metal1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/dark-metal2.png b/core/assets-raw/sprites_replacement/blocks/environment/dark-metal2.png new file mode 100644 index 0000000000..3eb3558f6c Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/dark-metal2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/dark-panel-1.png b/core/assets-raw/sprites_replacement/blocks/environment/dark-panel-1.png new file mode 100644 index 0000000000..3035832574 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/dark-panel-1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/dark-panel-2.png b/core/assets-raw/sprites_replacement/blocks/environment/dark-panel-2.png new file mode 100644 index 0000000000..cead3de9bc Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/dark-panel-2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/dark-panel-3.png b/core/assets-raw/sprites_replacement/blocks/environment/dark-panel-3.png new file mode 100644 index 0000000000..bf321e76a6 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/dark-panel-3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/dark-panel-4.png b/core/assets-raw/sprites_replacement/blocks/environment/dark-panel-4.png new file mode 100644 index 0000000000..0a76f30595 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/dark-panel-4.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/dark-panel-5.png b/core/assets-raw/sprites_replacement/blocks/environment/dark-panel-5.png new file mode 100644 index 0000000000..3f3c511fe4 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/dark-panel-5.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/dark-panel-6.png b/core/assets-raw/sprites_replacement/blocks/environment/dark-panel-6.png new file mode 100644 index 0000000000..6ff46b0373 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/dark-panel-6.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/darksand-tainted-water.png b/core/assets-raw/sprites_replacement/blocks/environment/darksand-tainted-water.png new file mode 100644 index 0000000000..fce4fce352 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/darksand-tainted-water.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/darksand-water.png b/core/assets-raw/sprites_replacement/blocks/environment/darksand-water.png new file mode 100644 index 0000000000..9074571f83 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/darksand-water.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/darksand1.png b/core/assets-raw/sprites_replacement/blocks/environment/darksand1.png new file mode 100644 index 0000000000..0478f5a78d Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/darksand1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/darksand2.png b/core/assets-raw/sprites_replacement/blocks/environment/darksand2.png new file mode 100644 index 0000000000..2ee445aba9 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/darksand2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/darksand3.png b/core/assets-raw/sprites_replacement/blocks/environment/darksand3.png new file mode 100644 index 0000000000..f6e829199b Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/darksand3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/edge-stencil-blocky.png b/core/assets-raw/sprites_replacement/blocks/environment/edge-stencil-blocky.png new file mode 100644 index 0000000000..7dd02ca754 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/edge-stencil-blocky.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/edge-stencil-smooth.png b/core/assets-raw/sprites_replacement/blocks/environment/edge-stencil-smooth.png index 55f4b9fb03..c05f1f7b08 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/environment/edge-stencil-smooth.png and b/core/assets-raw/sprites_replacement/blocks/environment/edge-stencil-smooth.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/grass1.png b/core/assets-raw/sprites_replacement/blocks/environment/grass1.png new file mode 100644 index 0000000000..adf810314d Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/grass1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/grass2.png b/core/assets-raw/sprites_replacement/blocks/environment/grass2.png new file mode 100644 index 0000000000..2f37e91369 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/grass2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/grass3.png b/core/assets-raw/sprites_replacement/blocks/environment/grass3.png new file mode 100644 index 0000000000..704219e7f9 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/grass3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/holostone1.png b/core/assets-raw/sprites_replacement/blocks/environment/holostone1.png new file mode 100644 index 0000000000..cc68b49c90 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/holostone1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/holostone2.png b/core/assets-raw/sprites_replacement/blocks/environment/holostone2.png new file mode 100644 index 0000000000..1c74d19a1b Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/holostone2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/holostone3.png b/core/assets-raw/sprites_replacement/blocks/environment/holostone3.png new file mode 100644 index 0000000000..008f5a85f1 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/holostone3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/hotrock1.png b/core/assets-raw/sprites_replacement/blocks/environment/hotrock1.png new file mode 100644 index 0000000000..d331a9b07c Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/hotrock1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/hotrock2.png b/core/assets-raw/sprites_replacement/blocks/environment/hotrock2.png new file mode 100644 index 0000000000..5bfe3110eb Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/hotrock2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/hotrock3.png b/core/assets-raw/sprites_replacement/blocks/environment/hotrock3.png new file mode 100644 index 0000000000..1d37b221a3 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/hotrock3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/ice1.png b/core/assets-raw/sprites_replacement/blocks/environment/ice1.png new file mode 100644 index 0000000000..7e3bfcedfa Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/ice1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/ice2.png b/core/assets-raw/sprites_replacement/blocks/environment/ice2.png new file mode 100644 index 0000000000..9a2643a694 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/ice2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/ice3.png b/core/assets-raw/sprites_replacement/blocks/environment/ice3.png new file mode 100644 index 0000000000..08821cc029 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/ice3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/ignarock1.png b/core/assets-raw/sprites_replacement/blocks/environment/ignarock1.png new file mode 100644 index 0000000000..fff2086d21 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/ignarock1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/ignarock2.png b/core/assets-raw/sprites_replacement/blocks/environment/ignarock2.png new file mode 100644 index 0000000000..da2c7412b7 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/ignarock2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/ignarock3.png b/core/assets-raw/sprites_replacement/blocks/environment/ignarock3.png new file mode 100644 index 0000000000..e303b57082 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/ignarock3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/magmarock1.png b/core/assets-raw/sprites_replacement/blocks/environment/magmarock1.png new file mode 100644 index 0000000000..a25af14de1 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/magmarock1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/magmarock2.png b/core/assets-raw/sprites_replacement/blocks/environment/magmarock2.png new file mode 100644 index 0000000000..7360fb1690 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/magmarock2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/magmarock3.png b/core/assets-raw/sprites_replacement/blocks/environment/magmarock3.png new file mode 100644 index 0000000000..7516823fc6 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/magmarock3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/moss1.png b/core/assets-raw/sprites_replacement/blocks/environment/moss1.png new file mode 100644 index 0000000000..800bb05170 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/moss1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/moss2.png b/core/assets-raw/sprites_replacement/blocks/environment/moss2.png new file mode 100644 index 0000000000..2d338650e1 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/moss2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/moss3.png b/core/assets-raw/sprites_replacement/blocks/environment/moss3.png new file mode 100644 index 0000000000..e840a1936a Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/moss3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/pine.png b/core/assets-raw/sprites_replacement/blocks/environment/pine.png index fcdc3e71fc..1642bbbfd0 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/environment/pine.png and b/core/assets-raw/sprites_replacement/blocks/environment/pine.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/sand1.png b/core/assets-raw/sprites_replacement/blocks/environment/sand1.png new file mode 100644 index 0000000000..ae4fe3c363 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/sand1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/sand2.png b/core/assets-raw/sprites_replacement/blocks/environment/sand2.png new file mode 100644 index 0000000000..2d6b23f129 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/sand2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/sand3.png b/core/assets-raw/sprites_replacement/blocks/environment/sand3.png new file mode 100644 index 0000000000..b03562c494 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/sand3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/shale1.png b/core/assets-raw/sprites_replacement/blocks/environment/shale1.png new file mode 100644 index 0000000000..6f242df279 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/shale1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/shale2.png b/core/assets-raw/sprites_replacement/blocks/environment/shale2.png new file mode 100644 index 0000000000..2edf629f90 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/shale2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/shale3.png b/core/assets-raw/sprites_replacement/blocks/environment/shale3.png new file mode 100644 index 0000000000..95382a191c Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/shale3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/shrubs-large.png b/core/assets-raw/sprites_replacement/blocks/environment/shrubs-large.png new file mode 100644 index 0000000000..17ec22101d Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/shrubs-large.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/shrubs1.png b/core/assets-raw/sprites_replacement/blocks/environment/shrubs1.png new file mode 100644 index 0000000000..dd09a62fec Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/shrubs1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/shrubs2.png b/core/assets-raw/sprites_replacement/blocks/environment/shrubs2.png new file mode 100644 index 0000000000..d211c517a5 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/shrubs2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/snow1.png b/core/assets-raw/sprites_replacement/blocks/environment/snow1.png new file mode 100644 index 0000000000..39f893df24 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/snow1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/snow2.png b/core/assets-raw/sprites_replacement/blocks/environment/snow2.png new file mode 100644 index 0000000000..3d1a76608d Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/snow2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/snow3.png b/core/assets-raw/sprites_replacement/blocks/environment/snow3.png new file mode 100644 index 0000000000..c52f98cdae Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/snow3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/spore-moss1.png b/core/assets-raw/sprites_replacement/blocks/environment/spore-moss1.png new file mode 100644 index 0000000000..b1e7fbbf34 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/spore-moss1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/spore-moss2.png b/core/assets-raw/sprites_replacement/blocks/environment/spore-moss2.png new file mode 100644 index 0000000000..cf05c4279e Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/spore-moss2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/spore-moss3.png b/core/assets-raw/sprites_replacement/blocks/environment/spore-moss3.png new file mode 100644 index 0000000000..8b519681f9 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/spore-moss3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/stone1.png b/core/assets-raw/sprites_replacement/blocks/environment/stone1.png new file mode 100644 index 0000000000..e9f42a172d Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/stone1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/stone2.png b/core/assets-raw/sprites_replacement/blocks/environment/stone2.png new file mode 100644 index 0000000000..09bc9f3e5a Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/stone2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/stone3.png b/core/assets-raw/sprites_replacement/blocks/environment/stone3.png new file mode 100644 index 0000000000..ca2487d441 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/stone3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/tainted-water.png b/core/assets-raw/sprites_replacement/blocks/environment/tainted-water.png new file mode 100644 index 0000000000..1618a1b0e1 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/tainted-water.png differ diff --git a/core/assets-raw/sprites_replacement/editor/pack.json b/core/assets-raw/sprites_replacement/editor/pack.json index 91480ffa76..2612f17acc 100644 --- a/core/assets-raw/sprites_replacement/editor/pack.json +++ b/core/assets-raw/sprites_replacement/editor/pack.json @@ -1,8 +1,8 @@ { - duplicatePadding: true, - combineSubdirectories: true, - flattenPaths: true, - maxWidth: 2048, - maxHeight: 2048, - fast: true, + duplicatePadding: true, + combineSubdirectories: true, + flattenPaths: true, + maxWidth: 2048, + maxHeight: 2048, + fast: true } diff --git a/core/assets-raw/sprites_replacement/effects/circle-shadow.png b/core/assets-raw/sprites_replacement/effects/circle-shadow.png new file mode 100644 index 0000000000..2e9aaec802 Binary files /dev/null and b/core/assets-raw/sprites_replacement/effects/circle-shadow.png differ diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 80b94476fb..56c4861dd0 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -11,6 +11,7 @@ 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. screenshot = Screenshot saved to {0} +screenshot.invalid = Map too large, potentially not enough memory for screenshot. gameover = Game Over gameover.pvp = The[accent] {0}[] team is victorious! highscore = [accent]New highscore! @@ -23,9 +24,10 @@ 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.\n\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.\n\nTry it. +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.\n\n[scarlet]DO 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.\n\n[scarlet]DO IT. +launcheditems = [accent]Launched Items map.delete = Are you sure you want to delete the map "[accent]{0}[]"? level.highscore = High Score: [accent]{0} level.select = Level Select @@ -42,6 +44,7 @@ addplayers = Add/Remove Players customgame = Custom Game newgame = New Game none = +minimap = Minimap close = Close quit = Quit maps = Maps @@ -183,7 +186,8 @@ 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.pvp = This map does not have any enemy cores for player to spawn into! Add[SCARLET] non-blue[] 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 @@ -285,7 +289,8 @@ donate = Donate abandon = Abandon abandon.text = This zone and all its resources will be lost to the enemy. locked = Locked -complete = [LIGHT_GRAY]Complete: +complete = [LIGHT_GRAY]Reach: +zone.requirement = Wave {0} in zone {1} resume = Resume Zone:\n[LIGHT_GRAY]{0} bestwave = [LIGHT_GRAY]Best Wave: {0} launch = < LAUNCH > @@ -297,7 +302,7 @@ uncover = Uncover configure = Configure Loadout configure.locked = [LIGHT_GRAY]Unlock configuring loadout:\nWave {0}. zone.unlocked = [LIGHT_GRAY]{0} unlocked. -zone.complete = Wave {0} reached:\nNext zone requirements met. +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... @@ -314,6 +319,7 @@ error.io = Network I/O error. error.any = Unknown 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 @@ -339,63 +345,62 @@ no = No info.title = Info error.title = [crimson]An error has occured error.crashtitle = An error has occured -blocks.outputspeed = Drill Speed: {0}/ -blocks.efficiency = Efficiency: {0}% -blocks.unknown = [LIGHT_GRAY]??? -blocks.blockinfo = Block Info -blocks.powerbalance = Power: {0} -blocks.poweroutput = Power Output: {0} +blocks.input = Input +blocks.output = Output +blocks.booster = Booster +block.unknown = [LIGHT_GRAY]??? blocks.powercapacity = Power Capacity blocks.powershot = Power/Shot blocks.targetsair = Targets Air blocks.targetsground = Targets Ground -blocks.items = Items: {0} blocks.itemsmoved = Move Speed +blocks.launchtime = Time Between Launches blocks.shootrange = Range blocks.size = Size blocks.liquidcapacity = Liquid Capacity -blocks.maxitemssecond = Max Items blocks.powerrange = Power Range blocks.poweruse = Power Use blocks.powerdamage = Power/Damage -blocks.inputitemcapacity = Input Item Capacity -blocks.outputitemcapacity = Output Item Capacity blocks.itemcapacity = Item Capacity blocks.basepowergeneration = Base Power Generation -blocks.powertransferspeed = Power Transfer -blocks.craftspeed = Production Speed -blocks.inputliquid = Input Liquid -blocks.inputliquidaux = Aux Liquid -blocks.inputitem = Input Item -blocks.inputitems = Input Items -blocks.outputitem = Output Item +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.liquidoutput = Liquid Output -blocks.liquidoutputspeed = Liquid Output Speed -blocks.liquiduse = Liquid Use -blocks.coolant = Coolant -blocks.liquid = Liquid -blocks.coolantuse = Coolant Use -blocks.inputliquidfuel = Fuel Liquid -blocks.liquidfueluse = Liquid Fuel Use -blocks.boostitem = Boost Item -blocks.boostliquid = Boost Liquid blocks.health = Health -blocks.heat = Heat -blocks.power = Power -blocks.progress = Build Progress -blocks.spawned = Units: {0}/{1} -blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = Inaccuracy blocks.shots = Shots blocks.reload = Shots/Second -blocks.inputfuel = Fuel -blocks.fuelburntime = Fuel Burn Time -blocks.inputcapacity = Input capacity -blocks.outputcapacity = Output capacity blocks.ammo = Ammo + +bar.drillspeed = Drill Speed: {0}/s +bar.efficiency = Efficiency: {0}% +bar.powerbalance = Power: {0}/s +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] damage +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 fire rate + unit.blocks = blocks unit.powersecond = power units/second unit.liquidsecond = liquid units/second @@ -404,6 +409,9 @@ unit.liquidunits = liquid units unit.powerunits = power units unit.degrees = degrees unit.seconds = seconds +unit.persecond = /sec +unit.timesspeed = x speed +unit.percent = % unit.items = items category.general = General category.power = Power @@ -412,7 +420,11 @@ category.items = Items category.crafting = Input/Output category.shooting = Shooting category.optional = Optional Enhancements +setting.landscape.name = Lock Landscape +setting.shadows.name = Shadows setting.animatedwater.name = Animated Water +setting.animatedshields.name = Animated Shields +setting.antialias.name = Antialias[LIGHT_GRAY] (requires restart)[] setting.indicators.name = Enemy/Ally Indicators setting.autotarget.name = Auto-Target setting.fpscap.name = Max FPS @@ -431,15 +443,19 @@ setting.sensitivity.name = Controller Sensitivity setting.saveinterval.name = Autosave Interval setting.seconds = {0} Seconds setting.fullscreen.name = Fullscreen +setting.borderless.name = Borderless Window setting.fps.name = Show FPS setting.vsync.name = VSync setting.lasers.name = Show Power Lasers +setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance, disables animations) setting.minimap.name = Show Minimap setting.musicvol.name = Music Volume setting.mutemusic.name = Mute Music setting.sfxvol.name = SFX Volume setting.mutesound.name = Mute Sound 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 @@ -486,6 +502,25 @@ 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 (Red Team) Resources +rules.pvp = PvP +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 + content.item.name = Items content.liquid.name = Liquids content.unit.name = Units @@ -528,7 +563,7 @@ liquid.oil.name = Oil liquid.cryofluid.name = Cryofluid mech.alpha-mech.name = Alpha mech.alpha-mech.weapon = Heavy Repeater -mech.alpha-mech.ability = None +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 @@ -563,15 +598,18 @@ 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.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.sandrocks.name = Sand Rocks block.spore-pine.name = Spore Pine block.sporerocks.name = Spore Rocks @@ -583,8 +621,8 @@ block.moss.name = Moss block.spore-moss.name = Spore Moss block.shalerocks.name = Shale Rocks block.scrap-wall.name = Scrap Wall -block.scrap-wall-large.name = Large Scrap Wall -block.scrap-wall-huge.name = Huge Scrap Wall +block.scrap-wall-large.name = Large Scrap Wall +block.scrap-wall-huge.name = Huge Scrap Wall block.scrap-wall-gigantic.name = Gigantic Scrap Wall block.thruster.name = Thruster block.kiln.name = Kiln @@ -598,13 +636,17 @@ block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus block.deepwater.name = Deep Water 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 = Dark Sand +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 @@ -616,11 +658,19 @@ 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.name = Metal Floor 1 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-5.name = Metal Floor 4 block.metal-floor-damaged.name = Metal Floor Damaged +block.creeptree.name = Creeptree +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 @@ -636,6 +686,7 @@ block.thorium-wall-large.name = Large Thorium Wall block.door.name = Door block.door-large.name = Large Door block.duo.name = Duo +block.scorch.name = Scorch block.scatter.name = Scatter block.hail.name = Hail block.lancer.name = Lancer @@ -656,6 +707,7 @@ 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 @@ -721,6 +773,7 @@ block.blast-drill.name = Airblast Drill block.thermal-pump.name = Thermal Pump block.thermal-generator.name = Thermal Generator block.alloy-smelter.name = Alloy Smelter +block.mender.name = Mender block.mend-projector.name = Mend Projector block.surge-wall.name = Surge Wall block.surge-wall-large.name = Large Surge Wall @@ -736,6 +789,7 @@ 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 @@ -820,7 +874,7 @@ block.silicon-smelter.description = Reduces sand with highly pure coal in order 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.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. @@ -885,4 +939,4 @@ block.power-source.description = Infinitely outputs power. Sandbox only. block.power-void.description = Voids all power inputted into it. Sandbox only. liquid.water.description = Commonly used for cooling machines and waste processing. liquid.oil.description = Can be burnt, exploded or used as a coolant. -liquid.cryofluid.description = The most efficient liquid for cooling things down. \ No newline at end of file +liquid.cryofluid.description = The most efficient liquid for cooling things down. diff --git a/core/assets/bundles/bundle_cs.properties b/core/assets/bundles/bundle_cs.properties index 83949f0ad5..e6ae1ad361 100644 --- a/core/assets/bundles/bundle_cs.properties +++ b/core/assets/bundles/bundle_cs.properties @@ -23,6 +23,7 @@ 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 = Jsi si jistý že chceš smazat mapu "[accent]{0}[]"? level.highscore = Nejvyšší skóre: [accent]{0} level.select = Výběr levelu @@ -39,6 +40,7 @@ addplayers = Přidat/Odebrat hráče customgame = Vlastní hra newgame = New Game none = +minimap = Minimap close = Zavřít quit = Ukončit maps = Mapy @@ -181,6 +183,7 @@ map.delete.confirm = Jsi si jistý žechceš tuto mapu smazat? tato akce je nevr map.random = [accent]Náhodná mapa map.nospawn = Tato mapa nemá žádná jádra pro hráče ke spawnutí! přidej[ROYAL] blue[] jádro na tuto mapu v editoru. map.nospawn.pvp = Tato mapa nemá žádné nepřátelské jádra pro hráče ke spawnutí! přidej[SCARLET] red[] jádro na tuto mapu v editoru. +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 = Chyba v načítání mapy: poškozený nebo neplatný soubor mapy. editor.brush = Štětec editor.openin = Otevřít v editoru. @@ -282,6 +285,7 @@ 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 @@ -293,7 +297,7 @@ uncover = Uncover configure = Configure Loadout configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. zone.unlocked = [LIGHT_GRAY]{0} unlocked. -zone.complete = Zone conditions met. +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... @@ -332,63 +336,59 @@ no = Ne info.title = Informace error.title = [crimson]Objevila se chyba error.crashtitle = Objevila se chyba -blocks.outputspeed = Drill Speed: {0}/s -blocks.efficiency = Efficiency: {0}% -blocks.unknown = [LIGHT_GRAY]??? -blocks.blockinfo = Informace o bloku -blocks.powerbalance = Power: {0} -blocks.poweroutput = Power Output: {0} +blocks.input = Input +blocks.output = Output +blocks.booster = Booster +block.unknown = [LIGHT_GRAY]??? blocks.powercapacity = Kapacita energie blocks.powershot = Energie na výstřel blocks.targetsair = Zaměřuje vzdušné jednotky blocks.targetsground = Targets Ground -blocks.items = Items: {0} blocks.itemsmoved = Move Speed +blocks.launchtime = Time Between Launches blocks.shootrange = Dostřel blocks.size = velikost blocks.liquidcapacity = Kapacita tekutin -blocks.maxitemssecond = Max předmětů blocks.powerrange = Rozsah energie blocks.poweruse = Spotřebuje energie blocks.powerdamage = Energie na poškození -blocks.inputitemcapacity = Kapacita vstupních předmětů -blocks.outputitemcapacity = Kapacita výstupních předmětů blocks.itemcapacity = kapacita předmětů blocks.basepowergeneration = Základní generování energie -blocks.powertransferspeed = Přenos energie -blocks.craftspeed = Rychlost produkce -blocks.inputliquid = Vstupní tekutiny -blocks.inputliquidaux = Aux tekutina -blocks.inputitem = Vstupní předmět -blocks.inputitems = Vstupní předměty -blocks.outputitem = Výstupní předmět +blocks.productiontime = Production Time +blocks.repairtime = Block Full Repair Time +blocks.speedincrease = Speed Increase +blocks.range = Range blocks.drilltier = Vrtatelné blocks.drillspeed = Základní rychlost vrtu +blocks.boosteffect = Boost Effect blocks.maxunits = Max Active Units -blocks.liquidoutput = Výstup tekutin -blocks.liquidoutputspeed = Rychlost výstupu tekutin -blocks.liquiduse = Spotřebuje tekutin -blocks.coolant = Chlazení -blocks.liquid = Liquid -blocks.coolantuse = Spotřeba chlazení -blocks.inputliquidfuel = Palivo-tekutina -blocks.liquidfueluse = Spotřeba Paliva-tekutiny -blocks.boostitem = Předmět pro zrychlení -blocks.boostliquid = Tekutina pro zrychlení blocks.health = Životy -blocks.heat = Heat -blocks.power = Power -blocks.progress = Build Progress -blocks.spawned = Units: {0}/{1} -blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = Nepřesnost/výchylka blocks.shots = Střely blocks.reload = Střely za sekundu -blocks.inputfuel = Palivo -blocks.fuelburntime = Čas spalování paliva -blocks.inputcapacity = Vstupní kapacita -blocks.outputcapacity = Výstupní kapacita 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 +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 = Bloky unit.powersecond = jednotek energie/sekunda unit.liquidsecond = jednotek tekutin/sekundu @@ -397,6 +397,9 @@ unit.liquidunits = jednotek tekutin unit.powerunits = jednotek energie unit.degrees = úhly unit.seconds = sekundy +unit.persecond = /sec +unit.timesspeed = x speed +unit.percent = % unit.items = předměty category.general = Všeobecné category.power = Energie @@ -405,7 +408,11 @@ category.items = Předměty category.crafting = Vyžaduje category.shooting = Střílí category.optional = Volitelné vylepšení +setting.landscape.name = Lock Landscape +setting.shadows.name = Shadows setting.animatedwater.name = Animated Water +setting.animatedshields.name = Animated Shields +setting.antialias.name = Antialias[LIGHT_GRAY] (requires restart)[] setting.indicators.name = Indikátor pro spojence setting.autotarget.name = Automaticky zaměřuje setting.fpscap.name = Max FPS @@ -424,9 +431,11 @@ setting.sensitivity.name = Citlivost ovladače setting.saveinterval.name = Interval automatického ukládání setting.seconds = {0} Sekund setting.fullscreen.name = Celá obrazovka +setting.borderless.name = Borderless Window setting.fps.name = Ukázat snímky/sekundu setting.vsync.name = Vertikální synchronizace setting.lasers.name = Ukázat laser energie +setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance) setting.minimap.name = Ukázat minimapu setting.musicvol.name = Hlasitost hudby setting.mutemusic.name = Ztišit hudbu @@ -479,6 +488,21 @@ mode.pvp.name = PvP mode.pvp.description = Bojuj proti ostatním hráčům v lokální síti. mode.attack.name = Útok 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.pvp = PvP +rules.unitdrops = Unit Drops +rules.unitbuildspeedmultiplier = Unit Creation Speed Multiplier +rules.unithealthmultiplier = Unit Health Multiplier +rules.playerdamagemultiplier = Player 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 content.item.name = Předměty content.liquid.name = Tekutiny content.unit.name = jednotky @@ -559,6 +583,7 @@ mech.itemcapacity = [LIGHT_GRAY]Kapacita předmětů: {0} mech.minespeed = [LIGHT_GRAY]Rychlost těžení: {0} mech.minepower = [LIGHT_GRAY]Síla těžení: {0} mech.ability = [LIGHT_GRAY]Schopnost: {0} +mech.buildspeed = [LIGHT_GRAY]Building Speed: {0}% liquid.heatcapacity = [LIGHT_GRAY]Kapacita teploty: {0} liquid.viscosity = [LIGHT_GRAY]Viskozita: {0} liquid.temperature = [LIGHT_GRAY]Teplota: {0} @@ -590,13 +615,17 @@ block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus block.deepwater.name = Hluboká voda block.water.name = Voda +block.tainted-water.name = Tainted Water +block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Tar block.stone.name = Kámen block.sand.name = Písek +block.darksand.name = Dark Sand block.ice.name = Led block.snow.name = Sníh 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 @@ -628,6 +657,7 @@ block.thorium-wall-large.name = Velká thoriová stěna block.door.name = Dveře block.door-large.name = Velké dveře block.duo.name = Duo +block.scorch.name = Scorch block.scatter.name = Scatter block.hail.name = Hail block.lancer.name = Lancer @@ -713,6 +743,7 @@ block.blast-drill.name = Tlakovzdušný vrt block.thermal-pump.name = Termální pumpa block.thermal-generator.name = Termální Generátor block.alloy-smelter.name = Slitinová pec +block.mender.name = Mender block.mend-projector.name = Opravný projektor block.surge-wall.name = Impulzní stěna block.surge-wall-large.name = Velká Impulzní stěna @@ -728,6 +759,7 @@ block.meltdown.name = Meltdown block.container.name = Kontejnér 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 = modrá team.red.name = červená team.orange.name = oranžová diff --git a/core/assets/bundles/bundle_de.properties b/core/assets/bundles/bundle_de.properties index a30bbafe2a..10d3657902 100644 --- a/core/assets/bundles/bundle_de.properties +++ b/core/assets/bundles/bundle_de.properties @@ -23,6 +23,7 @@ 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 = Bist du sicher, dass du die Karte "[accent]{0}[]" löschen möchtest? level.highscore = High Score: [accent]{0} level.select = Level Auswahl @@ -39,6 +40,7 @@ addplayers = Hinzufügen/Entfernen von Spielern customgame = Benutzerdefiniertes Spiel newgame = New Game none = +minimap = Minimap close = Schließen quit = Verlassen maps = Karten @@ -181,6 +183,7 @@ map.delete.confirm = Bist du sicher, dass du diese Karte löschen willst? Die Ak map.random = [accent]Zufällige Karte map.nospawn = Diese Karte hat keine Kerne in denen die Spieler beginnen können! Füge einen [ROYAL]blue[] Kern zu dieser Karte im Editor hinzu. map.nospawn.pvp = Diese Karte hat keine gegnerischen Kerne wo Gegner starten könnten! Füge über den Editor [SCARLET] rote[] Kerne zu dieser Karte hinzu. +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 = Fehler beim Laden der Karte: Beschädigtes oder invalide Karten Datei. editor.brush = Pinsel editor.openin = Öffne im Editor @@ -282,6 +285,7 @@ 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 @@ -293,7 +297,7 @@ uncover = Uncover configure = Configure Loadout configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. zone.unlocked = [LIGHT_GRAY]{0} unlocked. -zone.complete = Zone conditions met. +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... @@ -332,63 +336,59 @@ no = Nein info.title = [accent]Info error.title = [crimson] Ein Fehler ist aufgetreten error.crashtitle = Ein Fehler ist aufgetreten! -blocks.outputspeed = Drill Speed: {0}/s -blocks.efficiency = Efficiency: {0}% -blocks.unknown = [LIGHT_GRAY]??? -blocks.blockinfo = Blockinfo: -blocks.powerbalance = Power: {0} -blocks.poweroutput = Power Output: {0} +blocks.input = Input +blocks.output = Output +blocks.booster = Booster +block.unknown = [LIGHT_GRAY]??? blocks.powercapacity = Kapazität blocks.powershot = Stromverbrauch/Schuss blocks.targetsair = Visiert Luft Einheiten an blocks.targetsground = Targets Ground -blocks.items = Items: {0} blocks.itemsmoved = Move Speed +blocks.launchtime = Time Between Launches blocks.shootrange = Reichweite blocks.size = Größe blocks.liquidcapacity = Flüssigkeitskapazität -blocks.maxitemssecond = Max Materialien blocks.powerrange = Stromreichweite blocks.poweruse = Stromverbrauch blocks.powerdamage = Stromverbrauch/Schadenspunkt -blocks.inputitemcapacity = Annahmekapazität -blocks.outputitemcapacity = Ausgabekapazität blocks.itemcapacity = Materialkapazität blocks.basepowergeneration = Basis-Stromerzeugung -blocks.powertransferspeed = Stromübertragung -blocks.craftspeed = Produktionsgeschwindigkeit -blocks.inputliquid = Benötigte Flüssigkeit -blocks.inputliquidaux = Optionale Flüssigkeit -blocks.inputitem = Akzeptiertes Material -blocks.inputitems = Akzeptierte Materialien -blocks.outputitem = Erzeugtes Material +blocks.productiontime = Production Time +blocks.repairtime = Block Full Repair Time +blocks.speedincrease = Speed Increase +blocks.range = Range blocks.drilltier = Abbaubare Erze blocks.drillspeed = Bohrgeschwindigkeit +blocks.boosteffect = Boost Effect blocks.maxunits = Max Active Units -blocks.liquidoutput = Erzeugte Flüssigkeit -blocks.liquidoutputspeed = Ausgabegeschwindigkeit -blocks.liquiduse = Flüssigkeitsverbrauch -blocks.coolant = Kühlmittel -blocks.liquid = Liquid -blocks.coolantuse = Kühlmittelverbrauch -blocks.inputliquidfuel = Kraftstoff -blocks.liquidfueluse = Kraftstoffverbrauch -blocks.boostitem = Boost Item -blocks.boostliquid = Boost Liquid blocks.health = Lebenspunkte -blocks.heat = Heat -blocks.power = Power -blocks.progress = Build Progress -blocks.spawned = Units: {0}/{1} -blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = Ungenauigkeit blocks.shots = Schüsse blocks.reload = Schüsse/Sekunde -blocks.inputfuel = Kraftstoff -blocks.fuelburntime = Kraftstoff Verbrennungs-Zeit -blocks.inputcapacity = Annahmekapazität -blocks.outputcapacity = Ausgabekapazität 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 +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 = Blöcke unit.powersecond = Stromeinheiten/Sekunde unit.liquidsecond = Flüssigkeitseinheiten/Sekunde @@ -397,6 +397,9 @@ unit.liquidunits = Flüssigkeitseinheiten unit.powerunits = Stromeinheiten unit.degrees = Grad unit.seconds = Sekunden +unit.persecond = /sec +unit.timesspeed = x speed +unit.percent = % unit.items = Materialeinheiten category.general = Generell category.power = Strom @@ -405,7 +408,11 @@ category.items = Materialien category.crafting = Erzeugung category.shooting = Schießen category.optional = Optional Enhancements +setting.landscape.name = Lock Landscape +setting.shadows.name = Shadows setting.animatedwater.name = Animated Water +setting.animatedshields.name = Animated Shields +setting.antialias.name = Antialias[LIGHT_GRAY] (requires restart)[] setting.indicators.name = Ally Indicators setting.autotarget.name = Auto-Zielauswahl setting.fpscap.name = Max FPS @@ -424,9 +431,11 @@ setting.sensitivity.name = Controller-Empfindlichkeit setting.saveinterval.name = Autosave Häufigkeit setting.seconds = {0} Sekunden setting.fullscreen.name = Vollbild +setting.borderless.name = Borderless Window setting.fps.name = Zeige FPS setting.vsync.name = VSync setting.lasers.name = Zeige Stromlaser +setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance) setting.minimap.name = Zeige die Minimap setting.musicvol.name = Musiklautstärke setting.mutemusic.name = Musik stummschalten @@ -479,6 +488,21 @@ mode.pvp.name = PvP mode.pvp.description = Kämpfe gegen andere Spieler local. 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.pvp = PvP +rules.unitdrops = Unit Drops +rules.unitbuildspeedmultiplier = Unit Creation Speed Multiplier +rules.unithealthmultiplier = Unit Health Multiplier +rules.playerdamagemultiplier = Player 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 content.item.name = Materialien content.liquid.name = Flüssigkeiten content.unit.name = Einheiten @@ -559,6 +583,7 @@ mech.itemcapacity = [LIGHT_GRAY]Materialkapazität: {0} mech.minespeed = [LIGHT_GRAY]Erzabbaugeschwindigkeit: {0} mech.minepower = [LIGHT_GRAY]Erzabbaukraft: {0} mech.ability = [LIGHT_GRAY]Fähigkeit: {0} +mech.buildspeed = [LIGHT_GRAY]Building Speed: {0}% liquid.heatcapacity = [LIGHT_GRAY]Wärmekapazität: {0} liquid.viscosity = [LIGHT_GRAY]Viskosität: {0} liquid.temperature = [LIGHT_GRAY]Temperatur: {0} @@ -590,13 +615,17 @@ block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus block.deepwater.name = Tiefes Wasser block.water.name = Wasser +block.tainted-water.name = Tainted Water +block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Teer block.stone.name = Stein block.sand.name = Sand +block.darksand.name = Dark Sand block.ice.name = Eis block.snow.name = Schnee 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 @@ -628,6 +657,7 @@ block.thorium-wall-large.name = Große Thorium-Mauer block.door.name = Tür block.door-large.name = Große Tür block.duo.name = Duo +block.scorch.name = Scorch block.scatter.name = Scatter block.hail.name = Hail block.lancer.name = Lancer @@ -713,6 +743,7 @@ block.blast-drill.name = Sprengbohrer block.thermal-pump.name = Thermische Pumpe block.thermal-generator.name = Thermischer Generator block.alloy-smelter.name = Legierungsschmeltzer +block.mender.name = Mender block.mend-projector.name = Reparaturprojektor block.surge-wall.name = Spannungsstoß-Mauer block.surge-wall-large.name = Große Spannungsstoß-Mauer @@ -728,6 +759,7 @@ 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 = Blau team.red.name = Rot team.orange.name = Orange diff --git a/core/assets/bundles/bundle_es.properties b/core/assets/bundles/bundle_es.properties index 1c69a9654b..017f90e397 100644 --- a/core/assets/bundles/bundle_es.properties +++ b/core/assets/bundles/bundle_es.properties @@ -23,6 +23,7 @@ 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 = ¿Estás seguro que quieres borrar el mapa "[accent]{0}[]"? level.highscore = Puntuación más alta: [accent]{0} level.select = Selección de nivel @@ -39,6 +40,7 @@ addplayers = Agregar/Quitar Jugadores customgame = Partida personalizada newgame = New Game none = +minimap = Minimap close = Cerrar quit = Salir maps = Mapas @@ -181,6 +183,7 @@ map.delete.confirm = ¿Estás seguro de querer borrar este mapa? ¡Recuerda que map.random = [accent]Mapa Aleatorio map.nospawn = ¡Este mapa no tiene ningún núcleo en el cual pueda aparecer el jugador! Agrega un núcleo[ROYAL] blue[] al mapa con el editor. map.nospawn.pvp = ¡Este mapa no tiene ningún núcleo enemigo para que aparezca el jugador! Añade un núcleo[SCARLET] red[] a este mapa en el 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 cargando el mapa: archivo corrupto o inválido. editor.brush = Pincel editor.openin = Abrir en el Editor @@ -282,6 +285,7 @@ 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 @@ -293,7 +297,7 @@ uncover = Uncover configure = Configure Loadout configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. zone.unlocked = [LIGHT_GRAY]{0} unlocked. -zone.complete = Zone conditions met. +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... @@ -332,63 +336,59 @@ no = No info.title = [accent]Información error.title = [crimson]Un error ha ocurrido. error.crashtitle = Un error ha ocurrido. -blocks.outputspeed = Drill Speed: {0}/s -blocks.efficiency = Efficiency: {0}% -blocks.unknown = [LIGHT_GRAY]??? -blocks.blockinfo = Información del Bloque -blocks.powerbalance = Power: {0} -blocks.poweroutput = Power Output: {0} +blocks.input = Input +blocks.output = Output +blocks.booster = Booster +block.unknown = [LIGHT_GRAY]??? blocks.powercapacity = Capacidad de Energía blocks.powershot = Energía/Disparo blocks.targetsair = Apunta al Aire blocks.targetsground = Targets Ground -blocks.items = Items: {0} blocks.itemsmoved = Move Speed +blocks.launchtime = Time Between Launches blocks.shootrange = Rango blocks.size = Tamaño blocks.liquidcapacity = Capacidad de Líquidos -blocks.maxitemssecond = Máximo de Objetos blocks.powerrange = Rango de Energía blocks.poweruse = Consumo de Energía blocks.powerdamage = Energía/Daño -blocks.inputitemcapacity = Capacidad de Entrada de los Objetos -blocks.outputitemcapacity = Capacidad de Salida de los Objetos blocks.itemcapacity = Capacidad de Objetos blocks.basepowergeneration = Generación de energía base -blocks.powertransferspeed = Transferencia de Energía -blocks.craftspeed = Velocidad de Producción -blocks.inputliquid = Líquidos de Entrada -blocks.inputliquidaux = Líquido Auxiliar -blocks.inputitem = Objeto de Entrada -blocks.inputitems = Objetos de Entrada -blocks.outputitem = Objeto de Salida +blocks.productiontime = Production Time +blocks.repairtime = Block Full Repair Time +blocks.speedincrease = Speed Increase +blocks.range = Range blocks.drilltier = Taladrables blocks.drillspeed = Velocidad Base del Taladro +blocks.boosteffect = Boost Effect blocks.maxunits = Max Active Units -blocks.liquidoutput = Líquido de Salida -blocks.liquidoutputspeed = Velocidad de Salida del Líquido -blocks.liquiduse = Uso de Líquido -blocks.coolant = Refrigerante -blocks.liquid = Liquid -blocks.coolantuse = Uso del Refrigerante -blocks.inputliquidfuel = Combustible Líquido -blocks.liquidfueluse = Uso del Combustible Líquido -blocks.boostitem = Boost Item -blocks.boostliquid = Boost Liquid blocks.health = Vida -blocks.heat = Heat -blocks.power = Power -blocks.progress = Build Progress -blocks.spawned = Units: {0}/{1} -blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = Imprecisión blocks.shots = Disparos blocks.reload = Recarga -blocks.inputfuel = Combustible -blocks.fuelburntime = Tiempo de Quemado del Combustible -blocks.inputcapacity = Capacidad de entrada -blocks.outputcapacity = Capacidad de salida 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 +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 = bloques unit.powersecond = unidades de energía/segundo unit.liquidsecond = unidades de líquido/segundo @@ -397,6 +397,9 @@ unit.liquidunits = unidades de líquido unit.powerunits = unidades de energía unit.degrees = grados unit.seconds = segundos +unit.persecond = /sec +unit.timesspeed = x speed +unit.percent = % unit.items = objetos category.general = General category.power = Energía @@ -405,7 +408,11 @@ category.items = Objetos category.crafting = Fabricación category.shooting = Disparo category.optional = Mejoras Opcionales +setting.landscape.name = Lock Landscape +setting.shadows.name = Shadows setting.animatedwater.name = Animated Water +setting.animatedshields.name = Animated Shields +setting.antialias.name = Antialias[LIGHT_GRAY] (requires restart)[] setting.indicators.name = Ally Indicators setting.autotarget.name = Auto apuntado setting.fpscap.name = Máx FPS @@ -424,9 +431,11 @@ setting.sensitivity.name = Sensibilidad del Control setting.saveinterval.name = Intervalo del Auto-guardado setting.seconds = {0} Segundos setting.fullscreen.name = Pantalla Completa +setting.borderless.name = Borderless Window setting.fps.name = Mostrar FPS setting.vsync.name = VSync setting.lasers.name = Mostrar Energía de los Láseres +setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance) setting.minimap.name = Mostrar Minimapa setting.musicvol.name = Volumen de la Música setting.mutemusic.name = Silenciar Musica @@ -479,6 +488,21 @@ mode.pvp.name = PvP mode.pvp.description = Pelea contra otros jugadores localmente. 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.pvp = PvP +rules.unitdrops = Unit Drops +rules.unitbuildspeedmultiplier = Unit Creation Speed Multiplier +rules.unithealthmultiplier = Unit Health Multiplier +rules.playerdamagemultiplier = Player 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 content.item.name = Objetos content.liquid.name = Líquidos content.unit.name = Unidades @@ -559,6 +583,7 @@ mech.itemcapacity = [LIGHT_GRAY]Capacidad de objetos: {0} mech.minespeed = [LIGHT_GRAY]Velocidad de minado: {0} mech.minepower = [LIGHT_GRAY]Potencia de minado: {0} mech.ability = [LIGHT_GRAY]Hablidad: {0} +mech.buildspeed = [LIGHT_GRAY]Building Speed: {0}% liquid.heatcapacity = [LIGHT_GRAY]Capacidad Térmica: {0} liquid.viscosity = [LIGHT_GRAY]Viscosidad: {0} liquid.temperature = [LIGHT_GRAY]Temperatura: {0} @@ -590,13 +615,17 @@ block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus block.deepwater.name = Aguas profundas block.water.name = Agua +block.tainted-water.name = Tainted Water +block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Alquitrán block.stone.name = Piedra block.sand.name = Arena +block.darksand.name = Dark Sand block.ice.name = Hielo block.snow.name = Nieve 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 @@ -628,6 +657,7 @@ block.thorium-wall-large.name = Pared de Torio grande block.door.name = Puerta block.door-large.name = Puerta Larga block.duo.name = Dúo +block.scorch.name = Scorch block.scatter.name = Scatter block.hail.name = Granizo block.lancer.name = Lancero @@ -713,6 +743,7 @@ block.blast-drill.name = Taladro de explosión block.thermal-pump.name = Bomba Térmica block.thermal-generator.name = Generador Térmico block.alloy-smelter.name = Alloy Smelter +block.mender.name = Mender block.mend-projector.name = Proyector de reparación block.surge-wall.name = Surge Wall block.surge-wall-large.name = Large Surge Wall @@ -728,6 +759,7 @@ block.meltdown.name = Meltdown block.container.name = Contenedor 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 = Azul team.red.name = Rojo team.orange.name = Naranja diff --git a/core/assets/bundles/bundle_fr.properties b/core/assets/bundles/bundle_fr.properties index b9605355b1..c442e6fbe1 100644 --- a/core/assets/bundles/bundle_fr.properties +++ b/core/assets/bundles/bundle_fr.properties @@ -1,44 +1,46 @@ 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 = Crédits -contributors = Translators and Contributors +contributors = Traducteurs et contributeurs discord = Rejoignez le discord de Mindustry -link.discord.description = Le discord officiel de mindustry -link.github.description = Code source du jeu -link.dev-builds.description = Versions instables du jeu +link.discord.description = Le discord officiel de Mindustry! +link.github.description = Code source du jeu. +link.dev-builds.description = Versions instables du jeu. link.trello.description = Trello officiel pour les futurs ajouts . link.itch.io.description = Page itch.io avec le lien du téléchargement pour PC et la version web . -link.google-play.description = Listing par le Google Play Store +link.google-play.description = Accès à la version android du Google Play Store. link.wiki.description = Wiki officiel de mindustry . linkfail = Erreur lors de l'ouverture du lien !\nL'URL a été copié avec succès. -screenshot = Screenshot saved to {0} +screenshot = Capture d'écran sauvegardée à {0} gameover = Partie terminée. gameover.pvp = L'équipe [accent] {0}[] a gagnée ! highscore = [YELLOW]Nouveau meilleur score! -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. +stat.wave = Vagues vaincues:[accent] {0} +stat.enemiesDestroyed = Ennemies détruits:[accent] {0} +stat.built = Bâtiments construits:[accent] {0} +stat.destroyed = Bâtiments détruits:[accent] {0} +stat.deconstructed = Bâtiments déconstruits:[accent] {0} +stat.delivered = Ressources transférées: +stat.rank = Rang Final: [accent]{0} +placeline = Tu as sélectionné un bloc.\nTu peux les[accent] placer en rangée[] en[accent] maintenant ton doigt sur l'écran pendant quelques secondes[] et en le glissant vers n'importe qu'elle direction.\nEssaye! +removearea = Tu as sélectionné le mode de suppression.\nTu peux[accent] supprimer les blocs en rectangle[] en[accent] maintenant ton doigt sur l'écran pendant quelques secondes[] et en le glissant.\nEssaye! +launcheditems = [accent]ressources transférées map.delete = Êtes-vous sûr de supprimer cette carte"[accent]{0}[]"? level.highscore = Meilleur score: [accent]{0} level.select = Sélection de niveau level.mode = Mode de jeu : showagain = Ne pas montrer la prochaine fois coreattack = [scarlet] -nearpoint = [[ [scarlet]LEAVE DROP POINT IMMEDIATELY[] ]\nannihilation imminent -outofbounds = [[ OUT OF BOUNDS ]\n[]self-destruct in {0} -database = Core Database +nearpoint = [[ [scarlet]QUITTEZ LE POINT D'APPARITION ENNEMI IMMÉDIATEMENT[] ]\nannihilation imminente +outofbounds = [[ HORS LIMITES ]\n[]auto-destruction dans {0} +database = Base de données savegame = Sauvegarder la partie loadgame = Charger la partie joingame = Rejoindre une partie addplayers = Ajouter/Enlever des joueurs -customgame = Partie personnalisée -newgame = New Game +customgame = Partie customisée +newgame = Nouvelle partie none = +minimap = Minimap close = Fermer quit = Quitter maps = Cartes @@ -46,16 +48,16 @@ continue = Continuer maps.none = [LIGHT_GRAY]Aucune carte trouvée! about.button = À propos name = Nom: -noname = Pick a[accent] player name[] first. +noname = Commencer par choisir un[accent] nom de joueur[]. filename = Nom du fichier: unlocked = Nouveau bloc débloqué! -completed = [accent]Completed -techtree = Tech Tree -research.list = [LIGHT_GRAY]Research: -research = Research -researched = [LIGHT_GRAY]{0} researched. +completed = [accent]Complété +techtree = Arbre technologique +research.list = [LIGHT_GRAY]Recherche: +research = Rechercher +researched = [LIGHT_GRAY]{0} recherché(e). players = {0} joueurs en ligne -players.single = {0} joueur en ligne +players.single = {0} joueurs en ligne server.closing = [accent]Fermeture du serveur... server.kicked.kick = Vous avez été expulsé du serveur! server.kicked.serverClose = Serveur fermé. @@ -147,7 +149,7 @@ save.wave = Vague {0} save.difficulty = Difficulté: {0} save.date = Dernière sauvegarde: {0} save.playtime = Temps de jeu: {0} -warning = Warning. +warning = Avertissement. confirm = Confirmer delete = Supprimer ok = OK @@ -181,6 +183,7 @@ map.delete.confirm = Êtes-vous sûr de supprimer cette carte? Cette action ne p map.random = [accent]Carte aléatoire map.nospawn = Cette carte n'a pas de base pour que le joueur y apparaisse! Ajouter une [ROYAL]base bleue[] sur cette carte dans l'éditeur. map.nospawn.pvp = Cette carte n'a pas de base ennemies pour qu'un joueur ennemi y apparaisse! Ajouter au moins une [SCARLET]Base rouge[] sur cette carte dans l'éditeur. +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 = Erreur lors du chargement de la carte: carte corrompue ou invalide. editor.brush = Pinceau editor.openin = Ouvrir dans l'éditeur @@ -189,32 +192,32 @@ editor.oregen.info = Génération de minerais: editor.mapinfo = Infos sur la carte editor.author = Auteur: editor.description = Description: -editor.waves = Waves: -waves.title = Waves +editor.waves = Vagues: +waves.title = Vagues waves.remove = Remove -waves.never = -waves.every = every -waves.waves = wave(s) -waves.perspawn = per spawn -waves.to = to +waves.never = jamais +waves.every = tous les +waves.waves = vague(s) +waves.perspawn = par apparition +waves.to = à 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... +waves.preview = Prévisualiser +waves.edit = Modifier... +waves.copy = Copier dans le Presse-papiers +waves.load = Coller depuis le Presse-papiers +waves.invalid = Vagues invalides dans le Presse-papiers. +waves.copied = Vagues copiées +editor.default = [LIGHT_GRAY] +edit = Modifier... editor.name = Nom: editor.teams = Équipe editor.elevation = Élevation -editor.errorload = Error loading file:\n[accent]{0} -editor.errorsave = Error saving file:\n[accent]{0} -editor.errorname = Map has no name defined. -editor.update = Update -editor.randomize = Randomize -editor.apply = Apply +editor.errorload = Erreur lors du chargement du fichier:\n[accent]{0} +editor.errorsave = Erreur lors de la sauvegarde du fichier:\n[accent]{0} +editor.errorname = La carte n'a pas de nom! +editor.update = Mettre à jour +editor.randomize = Randomiser +editor.apply = Appliquer editor.generate = Générer editor.resize = Redimensionner editor.loadmap = Charger une carte @@ -243,26 +246,26 @@ editor.mapname = Nom de la carte²: editor.overwrite = [accent]Attention !\nCeci réécrit une carte existante . editor.overwrite.confirm = [scarlet]Attention ![] Une carte avec ce nom existe déjà. Êtes-vous sûr de vouloir la réécrire? editor.selectmap = Séléctionnez une carte: -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 +filters.empty = [LIGHT_GRAY]Aucun filtre! Ajoutez-en un avec les boutons ci-dessous. +filter.distort = Déformation +filter.noise = Bruit +filter.ore = Minerai +filter.rivernoise = Bruit des rivières +filter.scatter = Dispersement filter.terrain = Terrain -filter.option.scale = Scale +filter.option.scale = Gamme filter.option.chance = Chance filter.option.mag = Magnitude -filter.option.threshold = Threshold -filter.option.circle-scale = Circle Scale +filter.option.threshold = Seuil +filter.option.circle-scale = Gamme du cercle 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 +filter.option.falloff = Diminution +filter.option.block = Bloc +filter.option.floor = Sol +filter.option.wall = Mur +filter.option.ore = Minerai +filter.option.floor2 = Sol secondaire +filter.option.threshold2 = Seuil secondaire width = Largeur: height = Hauteur: menu = Menu @@ -279,48 +282,49 @@ editor = Éditeur mapeditor = Éditeur de carte donate = Faire un\ndon abandon = Abandon -abandon.text = This zone and all its resources will be lost to the enemy. -locked = Locked -complete = [LIGHT_GRAY]Complete: -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.complete = Zone conditions met. -zone.config.complete = Wave {0} reached:\nLoadout config unlocked. -zone.resources = Resources Detected: -add = Add... -boss.health = Boss Health +abandon.text = Cette zone et tous ses ressources vont être perdues. +locked = Verrouillé +complete = [LIGHT_GRAY]Compléter: +zone.requirement = Vague {0} dans la zone {1} +resume = Reprendre la partie en cours:\n[LIGHT_GRAY]{0} +bestwave = [LIGHT_GRAY]Meilleur: {0} +launch = Lancement +launch.title = Lancement réussi +launch.next = [LIGHT_GRAY] Prochaine opportunité à la vague {0} +launch.unable = [scarlet]Impossible d'effectuer le lancement.[] Ennemis. +launch.confirm = Cela va transférer tous tes ressources dans votre coeur.\nTu ne vas pas pouvoir retourner à cette base. +uncover = Découvrir +configure = Configurer le transfert des ressources. +configure.locked = [LIGHT_GRAY]Atteigner la vague {0}\npour configurer le transfert des ressources +zone.unlocked = [LIGHT_GRAY]{0} Débloquée. +zone.requirement.complete = Vague {0} atteinte:\n{1} Exigences de la zone complétées +zone.config.complete = Vague {0} atteinte:\nConfiguration du transfert débloquée. +zone.resources = Ressources détectées: +add = Ajouter... +boss.health = Vie du BOSS connectfail = [crimson]Échec de la connexion au serveur : [accent]{0} -error.unreachable = Server injoignable. +error.unreachable = Serveur injoignable. error.invalidaddress = Adresse invalide. error.timedout = Délai de connexion dépassé!\nAssurez-vous que l'hôte a autorisé l'accès au port, et que l'adresse soit correcte! error.mismatch = Erreur de paquet:\nPossible différence de verison entre le client et le serveur .\nVérifiez que vous et l'hôte avez la plus récente version de Mindustry ! error.alreadyconnected = Déjà connecté. error.mapnotfound = Fichier de la carte introuvable! -error.io = Network I/O error. +error.io = Erreur de Réseau (I/O) error.any = Erreur réseau inconnue. -zone.groundZero.name = Ground Zero -zone.craters.name = The Craters -zone.frozenForest.name = Frozen Forest -zone.ruinousShores.name = Ruinous Shores -zone.stainedMountains.name = Stained Mountains -zone.desolateRift.name = Desolate Rift -zone.nuclearComplex.name = Nuclear Production Complex +zone.groundZero.name = Première Bataille +zone.craters.name = Les Cratères +zone.frozenForest.name = Forêt Glaciale +zone.ruinousShores.name = Rives en Ruine +zone.stainedMountains.name = Montagnes Tâchetées +zone.desolateRift.name = Fissure abandonnée +zone.nuclearComplex.name = Complexe nucléaire settings.language = Langage settings.reset = Valeur par défaut. settings.rebind = Réatttribuer settings.controls = Contrôles settings.game = Jeu settings.sound = Son -settings.graphics = Graphiques +settings.graphics = Graphismes settings.cleardata = Effacer les données du jeu... settings.clear.confirm = Êtes-vous sûr d'effacer ces données ?\nCe qui est fait ne peut être défait ! settings.clearall.confirm = [scarlet]ATTENTION![]\nCet action effacera toutes les données , incluant les sauvegarges, les cartes, les déblocages et la configuration des touches.\nUne fois que vous aurez pressé 'ok' le jeu effacera toutes les données et se fermera. @@ -332,31 +336,31 @@ no = Non info.title = Info error.title = [crimson]Une erreur s'est produite error.crashtitle = Une erreur s'est produite -blocks.outputspeed = Drill Speed: {0}/s -blocks.efficiency = Efficiency: {0}% -blocks.unknown = [LIGHT_GRAY]??? +bar.drillspeed = Vitesse de forage: {0}/s +bar.efficiency = Efficacité: {0}% +block.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Info sur le bloc -blocks.powerbalance = Power: {0} -blocks.poweroutput = Power Output: {0} -blocks.powercapacity = capacité d'énergie +bar.powerbalance = Énergie: {0} +bar.poweroutput = Énergie en sortie: {0} +blocks.powercapacity = Capacité d'énergie blocks.powershot = Énergie/Tir blocks.targetsair = Cible les unités aériennes -blocks.targetsground = Targets Ground -blocks.items = Items: {0} -blocks.itemsmoved = Move Speed +blocks.targetsground = Cible les unités terrestres +bar.items = Objets: {0} +blocks.itemsmoved = Vitesse de Déplacement +blocks.launchtime = Temps entre chaque lancement blocks.shootrange = Portée blocks.size = Taille blocks.liquidcapacity = Capacité en liquide -blocks.maxitemssecond = Production maximale blocks.powerrange = Distance de transmission blocks.poweruse = Énergie utilisée blocks.powerdamage = Énergie/Dégâts -blocks.inputitemcapacity = Capacité d'entrée -blocks.outputitemcapacity = Capacité de sortie blocks.itemcapacity = Stockage -blocks.basepowergeneration = Generation d'énergie minimale +blocks.basepowergeneration = Génération d'énergie minimale blocks.powertransferspeed = Vitesse de transfert d'énergie blocks.craftspeed = Vitesse de production +blocks.repairtime = Temps pour la Réparation Totale du Bloc +blocks.range = Portée blocks.inputliquid = Liquide requis blocks.inputliquidaux = Liquide optionnel blocks.inputitem = Objets en entrée @@ -364,23 +368,23 @@ blocks.inputitems = Objets utilisés blocks.outputitem = Objet produit blocks.drilltier = Forable blocks.drillspeed = Vitesse de forage de base -blocks.maxunits = Max Active Units +blocks.maxunits = Nombre d'unité actives maximal blocks.liquidoutput = Liquide en sortie blocks.liquidoutputspeed = Vitesse de production de liquide blocks.liquiduse = Quantité de liquide utilisée blocks.coolant = Liquide de refroidissement -blocks.liquid = Liquid +bar.liquid = Liquide blocks.coolantuse = Quantité de liquide de refroidissement utilisée blocks.inputliquidfuel = Carburant liquide blocks.liquidfueluse = Quantité de carburant liquide utilisé -blocks.boostitem = Boost Item -blocks.boostliquid = Boost Liquid +blocks.boostitem = Objets boosters +blocks.boostliquid = Liquides boosters blocks.health = Santé -blocks.heat = Heat -blocks.power = Power -blocks.progress = Build Progress -blocks.spawned = Units: {0}/{1} -blocks.power.satisfaction = Power Satisfaction +bar.heat = Chaleur +bar.power = Énergie +bar.progress = Progression de la construction +bar.spawned = Unités: {0}/{1} +blocks.power.satisfaction = Énergie minimum nécessaire blocks.inaccuracy = Précision blocks.shots = Tir blocks.reload = Tirs/Seconde @@ -388,7 +392,18 @@ blocks.inputfuel = Carburant blocks.fuelburntime = Durée du carburant blocks.inputcapacity = Capacité d'entrée blocks.outputcapacity = Capacité de production -blocks.ammo = Ammo +blocks.ammo = Munitions +bullet.damage = [stat]{0}[lightgray] dmg +bullet.splashdamage = [stat]{0}[lightgray] dmg de zone ~[stat] {1}[lightgray] tuiles +bullet.incendiary = [stat]incendiaire +bullet.homing = [stat]autoguidage +bullet.shock = [stat]choc +bullet.frag = [stat]frag +bullet.knockback = [stat]{0}[lightgray] recul +bullet.freezing = [stat]gel +bullet.tarred = [stat]tarred +bullet.multiplier = [stat]{0}[lightgray]x multiplicateur de munitions +bullet.reload = [stat]{0}[lightgray]x rechargement unit.blocks = blocs unit.powersecond = Énergie/seconde unit.liquidsecond = Liquides/seconde @@ -397,6 +412,9 @@ unit.liquidunits = Unité de liquide unit.powerunits = Unité d'énergie unit.degrees = degrés unit.seconds = secondes +unit.persecond = /sec +unit.timesspeed = x speed +unit.percent = % unit.items = Objets category.general = Général category.power = Énergie @@ -404,19 +422,22 @@ category.liquids = Liquides category.items = Objets category.crafting = Fabrication category.shooting = Défense -category.optional = Optional Enhancements -setting.animatedwater.name = Animated Water -setting.indicators.name = Ally Indicators +category.optional = Améliorations optionnelles +setting.landscape.name = Verrouiller la rotation en mode paysage +setting.shadows.name = Ombres +setting.animatedwater.name = Eau animée +setting.antialias.name = Antialias[LIGHT_GRAY] (demande le redémarrage de l'appareil)[] +setting.indicators.name = Indicateurs pour les alliés setting.autotarget.name = Visée automatique setting.fpscap.name = Max FPS setting.fpscap.none = None setting.fpscap.text = {0} FPS -setting.swapdiagonal.name = Always Diagonal Placement +setting.swapdiagonal.name = Autoriser le placement des blocs en diagonal setting.difficulty.training = entraînement -setting.difficulty.easy = facile -setting.difficulty.normal = normal -setting.difficulty.hard = difficile -setting.difficulty.insane = Extreme +setting.difficulty.easy = Facile +setting.difficulty.normal = Normal +setting.difficulty.hard = Difficile +setting.difficulty.insane = Extrème setting.difficulty.name = Difficulté: setting.screenshake.name = Tremblement de l'écran setting.effects.name = Montrer les effets @@ -424,36 +445,37 @@ setting.sensitivity.name = Sensibilité de la manette setting.saveinterval.name = Intervalle des sauvegardes auto setting.seconds = {0} secondes setting.fullscreen.name = Plein écran +setting.borderless.name = Fenêtre sans contour setting.fps.name = Afficher FPS setting.vsync.name = VSync setting.lasers.name = Afficher les rayons des lasers -setting.minimap.name = montrer la minimap -setting.musicvol.name = volume de la musique +setting.minimap.name = Montrer la minimap +setting.musicvol.name = Volume de la musique setting.mutemusic.name = Couper la musique setting.sfxvol.name = Volume des SFX setting.mutesound.name = Couper les SFX -setting.crashreport.name = Send Anonymous Crash Reports +setting.crashreport.name = Envoyer un rapport de crash anonyme keybind.title = Paramétrer les touches -category.general.name = General +category.general.name = Général category.view.name = Voir category.multiplayer.name = Multijoueur command.attack = Attaque command.retreat = Retraite command.patrol = Patrouille -keybind.gridMode.name = Block Select -keybind.gridModeShift.name = Category Select +keybind.gridMode.name = Sélection des blocs +keybind.gridModeShift.name = Sélection des catégories keybind.press = Appuyer sur une touche... keybind.press.axis = Appuyer sur un axe ou une touche... -keybind.screenshot.name = Map Screenshot +keybind.screenshot.name = Capture d'écran keybind.move_x.name = mouvement x keybind.move_y.name = mouvement y keybind.select.name = sélectionner -keybind.diagonal_placement.name = Diagonal Placement -keybind.pick.name = Pick Block -keybind.break_block.name = Break Block -keybind.deselect.name = Déselectionner +keybind.diagonal_placement.name = Placement en diagonal +keybind.pick.name = Choisir un bloc +keybind.break_block.name = Suppprimer un bloc +keybind.deselect.name = Désélectionner keybind.shoot.name = tirer -keybind.zoom_hold.name = tenir le zoom +keybind.zoom_hold.name = maintenir le zoom keybind.zoom.name = zoom keybind.menu.name = menu keybind.pause.name = Pause @@ -479,6 +501,21 @@ mode.pvp.name = JcJ mode.pvp.description = Battez-vous contre d'autres joueurs en local. 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.pvp = PvP +rules.unitdrops = Unit Drops +rules.unitbuildspeedmultiplier = Unit Creation Speed Multiplier +rules.unithealthmultiplier = Unit Health Multiplier +rules.playerdamagemultiplier = Player 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 content.item.name = Objets content.liquid.name = Liquides content.unit.name = Unités @@ -559,6 +596,7 @@ mech.itemcapacity = [LIGHT_GRAY]Capacité de stockage: {0} mech.minespeed = [LIGHT_GRAY]Vitesse de minage: {0} mech.minepower = [LIGHT_GRAY]Puissance du minage: {0} mech.ability = [LIGHT_GRAY]Compétence: {0} +mech.buildspeed = [LIGHT_GRAY]Building Speed: {0}% liquid.heatcapacity = [LIGHT_GRAY]Capacité Thermique: {0} liquid.viscosity = [LIGHT_GRAY]Viscosité: {0} liquid.temperature = [LIGHT_GRAY]Température: {0} @@ -590,13 +628,17 @@ block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus block.deepwater.name = Eau profonde block.water.name = Eau +block.tainted-water.name = Tainted Water +block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Pétrole block.stone.name = Roche block.sand.name = Sable +block.darksand.name = Dark Sand block.ice.name = glace block.snow.name = Neige 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 @@ -628,6 +670,7 @@ block.thorium-wall-large.name = Mur en Thorium large block.door.name = Porte block.door-large.name = Grande porte block.duo.name = Duo +block.scorch.name = Scorch block.scatter.name = Scatter block.hail.name = Hail block.lancer.name = Lancier @@ -713,6 +756,7 @@ block.blast-drill.name = Foreuse à explosion block.thermal-pump.name = Pompe thermique block.thermal-generator.name = Générateur thermique block.alloy-smelter.name = Fonderie d'alliage superchargé +block.mender.name = Mender block.mend-projector.name = Projecteur soignant block.surge-wall.name = mur superchargé block.surge-wall-large.name = Grand mur superchargé @@ -728,6 +772,7 @@ block.meltdown.name = Meltdown block.container.name = Conteneur 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 = Bleu team.red.name = Rouge team.orange.name = Orange diff --git a/core/assets/bundles/bundle_fr_BE.properties b/core/assets/bundles/bundle_fr_BE.properties index 390b766f2f..8713ecbf89 100644 --- a/core/assets/bundles/bundle_fr_BE.properties +++ b/core/assets/bundles/bundle_fr_BE.properties @@ -23,6 +23,7 @@ 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 = Êtes-vous sûr de vouloir supprimer cette carte ?"[accent]{0}[]"? level.highscore = Meilleur score: [accent]{0} level.select = Sélection de niveau @@ -39,6 +40,7 @@ addplayers = Ajouter/Enlever des joueurs customgame = Partie personnalisée newgame = New Game none = +minimap = Minimap close = Fermer quit = Quitter maps = Cartes @@ -181,6 +183,7 @@ map.delete.confirm = Êtes-vous sûr de vouloir effacer cette carte ? Cette acti map.random = [accent]Carte aléatoire map.nospawn = Cette carte ne possède pas de base pour que le joueur puisse apparaître !Ajouter un [ROYAL]base bleue[] sur cette carte dans l'éditeur. map.nospawn.pvp = Cette carte ne contient aucune base ennemi dans lequel le joueur apparaît!\nAjoutez des bases[SCARLET] rouge[] à cette carte dans l'éditeur. +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 = Erreur lors du chargement de la carte: carte corrompue ou invalide. editor.brush = Pinceau editor.openin = Ouvrir dans l'éditeur @@ -282,6 +285,7 @@ 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 @@ -293,7 +297,7 @@ uncover = Uncover configure = Configure Loadout configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. zone.unlocked = [LIGHT_GRAY]{0} unlocked. -zone.complete = Zone conditions met. +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... @@ -332,63 +336,59 @@ no = Non info.title = Info error.title = [crimson]Une erreur s'est produite error.crashtitle = Une erreur s'est produite -blocks.outputspeed = Drill Speed: {0}/s -blocks.efficiency = Efficiency: {0}% -blocks.unknown = [LIGHT_GRAY]??? -blocks.blockinfo = Info sur le bloc -blocks.powerbalance = Power: {0} -blocks.poweroutput = Power Output: {0} +blocks.input = Input +blocks.output = Output +blocks.booster = Booster +block.unknown = [LIGHT_GRAY]??? blocks.powercapacity = Capacité d'énergie blocks.powershot = Énergie/Tir blocks.targetsair = Cible les unités aériennes blocks.targetsground = Targets Ground -blocks.items = Items: {0} blocks.itemsmoved = Move Speed +blocks.launchtime = Time Between Launches blocks.shootrange = Portée blocks.size = Taille blocks.liquidcapacity = Capacité en liquide -blocks.maxitemssecond = Production maximale blocks.powerrange = Distance de transmission blocks.poweruse = Énergie utilisée blocks.powerdamage = Énergie/Dégâts -blocks.inputitemcapacity = Capacité d'entrée -blocks.outputitemcapacity = Capacité de sortie blocks.itemcapacity = Stockage blocks.basepowergeneration = Production d'énergie de base -blocks.powertransferspeed = Vitesse de transfert d'énergie -blocks.craftspeed = Vitesse de production -blocks.inputliquid = Liquide requis -blocks.inputliquidaux = Liquide optionnel -blocks.inputitem = Objet utilisé -blocks.inputitems = Objets utilisés -blocks.outputitem = Objet produit +blocks.productiontime = Production Time +blocks.repairtime = Block Full Repair Time +blocks.speedincrease = Speed Increase +blocks.range = Range blocks.drilltier = Forable blocks.drillspeed = Vitesse de forage de base +blocks.boosteffect = Boost Effect blocks.maxunits = Max Active Units -blocks.liquidoutput = Liquide en sortie -blocks.liquidoutputspeed = Vitesse de sortie du liquide -blocks.liquiduse = Quantité de liquide utilisé -blocks.coolant = Liquide de refroidissement -blocks.liquid = Liquid -blocks.coolantuse = Quantité de liquide de refroidissement utilisé -blocks.inputliquidfuel = Carburant liquide -blocks.liquidfueluse = Quantité de carburant liquide utilisé -blocks.boostitem = Objet boostant la production -blocks.boostliquid = Liquide boostant la production blocks.health = Santé -blocks.heat = Heat -blocks.power = Power -blocks.progress = Build Progress -blocks.spawned = Units: {0}/{1} -blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = Précision blocks.shots = Tirs blocks.reload = Tirs/Seconde -blocks.inputfuel = Carburant -blocks.fuelburntime = Durée du carburant -blocks.inputcapacity = Capacité d'entrée -blocks.outputcapacity = Capacité de sortie 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 +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 = Blocs unit.powersecond = Énergie/seconde unit.liquidsecond = Liquides/seconde @@ -397,6 +397,9 @@ unit.liquidunits = Unité de liquide unit.powerunits = Unité d'énergie unit.degrees = degrés unit.seconds = secondes +unit.persecond = /sec +unit.timesspeed = x speed +unit.percent = % unit.items = Objets category.general = Général category.power = Énergie @@ -405,7 +408,11 @@ category.items = Objets category.crafting = Fabrication category.shooting = Défense category.optional = Améliorations facultatives +setting.landscape.name = Lock Landscape +setting.shadows.name = Shadows setting.animatedwater.name = Animated Water +setting.animatedshields.name = Animated Shields +setting.antialias.name = Antialias[LIGHT_GRAY] (requires restart)[] setting.indicators.name = Indicateurs d'alliés setting.autotarget.name = Visée automatique setting.fpscap.name = Max FPS @@ -424,9 +431,11 @@ 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.borderless.name = Borderless Window setting.fps.name = Afficher FPS setting.vsync.name = VSync setting.lasers.name = Afficher les rayons des lasers +setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance) setting.minimap.name = Montrer la minimap setting.musicvol.name = Volume de la musique setting.mutemusic.name = Couper la musique @@ -479,6 +488,21 @@ mode.pvp.name = PvP mode.pvp.description = Lutter contre d'autres joueurs pour gagner ! mode.attack.name = Attaque 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.pvp = PvP +rules.unitdrops = Unit Drops +rules.unitbuildspeedmultiplier = Unit Creation Speed Multiplier +rules.unithealthmultiplier = Unit Health Multiplier +rules.playerdamagemultiplier = Player 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 content.item.name = Objets content.liquid.name = Liquides content.unit.name = Unités @@ -559,6 +583,7 @@ mech.itemcapacity = [LIGHT_GRAY]Capacité de stockage: {0} mech.minespeed = [LIGHT_GRAY]Vitesse de minage: {0} mech.minepower = [LIGHT_GRAY]Puissance du minage: {0} mech.ability = [LIGHT_GRAY]Compétence: {0} +mech.buildspeed = [LIGHT_GRAY]Building Speed: {0}% liquid.heatcapacity = [LIGHT_GRAY]Capacité Thermique {0} liquid.viscosity = [LIGHT_GRAY]Viscosité: {0} liquid.temperature = [LIGHT_GRAY]Température: {0} @@ -590,13 +615,17 @@ block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus block.deepwater.name = Eau profonde block.water.name = Eau +block.tainted-water.name = Tainted Water +block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Pétrole block.stone.name = Roche block.sand.name = Sable +block.darksand.name = Dark Sand block.ice.name = Glace block.snow.name = Neige 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 @@ -628,6 +657,7 @@ block.thorium-wall-large.name = Mur en Thorium large block.door.name = Porte block.door-large.name = Grande porte block.duo.name = Duo +block.scorch.name = Scorch block.scatter.name = Scatter block.hail.name = Hail block.lancer.name = Lancer @@ -713,6 +743,7 @@ block.blast-drill.name = Foreuse à explosion block.thermal-pump.name = Pompe thermique block.thermal-generator.name = Générateur thermique block.alloy-smelter.name = Fonderie d'alliage superchargé +block.mender.name = Mender block.mend-projector.name = Projecteur soignant block.surge-wall.name = Mur superchargé block.surge-wall-large.name = Grand mur superchargé @@ -728,6 +759,7 @@ block.meltdown.name = Meltdown block.container.name = Conteneur 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 = Bleu team.red.name = Rouge team.orange.name = Orange diff --git a/core/assets/bundles/bundle_in_ID.properties b/core/assets/bundles/bundle_in_ID.properties index 75b8abdf17..edc7221b4c 100644 --- a/core/assets/bundles/bundle_in_ID.properties +++ b/core/assets/bundles/bundle_in_ID.properties @@ -23,6 +23,7 @@ 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} level.select = Pilih Level @@ -39,6 +40,7 @@ addplayers = Tambah/Hapus Pemain customgame = Game Bebas newgame = New Game none = +minimap = Minimap close = Tutup quit = Keluar maps = Peta @@ -181,6 +183,7 @@ map.delete.confirm = Are you sure you want to delete this map? This action canno 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 @@ -282,6 +285,7 @@ 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 @@ -293,7 +297,7 @@ uncover = Uncover configure = Configure Loadout configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. zone.unlocked = [LIGHT_GRAY]{0} unlocked. -zone.complete = Zone conditions met. +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... @@ -332,63 +336,59 @@ no = No info.title = [accent]Info error.title = [crimson]Telah terjadi kesalahan error.crashtitle = Telah terjadi kesalahan -blocks.outputspeed = Drill Speed: {0}/s -blocks.efficiency = Efficiency: {0}% -blocks.unknown = [LIGHT_GRAY]??? -blocks.blockinfo = Info Blok -blocks.powerbalance = Power: {0} -blocks.poweroutput = Power Output: {0} +blocks.input = Input +blocks.output = Output +blocks.booster = Booster +block.unknown = [LIGHT_GRAY]??? blocks.powercapacity = Kapasitas Tenaga blocks.powershot = Tenaga/tembakan blocks.targetsair = Targets Air blocks.targetsground = Targets Ground -blocks.items = Items: {0} blocks.itemsmoved = Move Speed +blocks.launchtime = Time Between Launches blocks.shootrange = Range blocks.size = Ukuran blocks.liquidcapacity = Kapasitas cairan -blocks.maxitemssecond = Batas barang/detik blocks.powerrange = Jangkauan tenaga blocks.poweruse = Power Use blocks.powerdamage = Power/Damage -blocks.inputitemcapacity = Input Item Capacity -blocks.outputitemcapacity = Input Item Capacity blocks.itemcapacity = Kapasitas Barang blocks.basepowergeneration = Base Power Generation -blocks.powertransferspeed = Power Transfer -blocks.craftspeed = Production Speed -blocks.inputliquid = Cairan yang Masuk -blocks.inputliquidaux = Aux Liquid -blocks.inputitem = Barang yang Masuk -blocks.inputitems = Input Items -blocks.outputitem = Output Item +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.liquidoutput = Liquid Output -blocks.liquidoutputspeed = Liquid Output Speed -blocks.liquiduse = Liquid Use -blocks.coolant = Coolant -blocks.liquid = Liquid -blocks.coolantuse = Coolant Use -blocks.inputliquidfuel = Fuel Liquid -blocks.liquidfueluse = Liquid Fuel Use -blocks.boostitem = Boost Item -blocks.boostliquid = Boost Liquid blocks.health = Darah -blocks.heat = Heat -blocks.power = Power -blocks.progress = Build Progress -blocks.spawned = Units: {0}/{1} -blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = Ketidaktelitian blocks.shots = Tembakan blocks.reload = Reload -blocks.inputfuel = Fuel -blocks.fuelburntime = Fuel Burn Time -blocks.inputcapacity = Kapasitas masuk -blocks.outputcapacity = Kapasitas keluar 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 +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 @@ -397,6 +397,9 @@ unit.liquidunits = liquid units unit.powerunits = power units unit.degrees = degrees unit.seconds = seconds +unit.persecond = /sec +unit.timesspeed = x speed +unit.percent = % unit.items = items category.general = General category.power = Power @@ -405,7 +408,11 @@ category.items = Items category.crafting = Crafting category.shooting = Shooting category.optional = Optional Enhancements +setting.landscape.name = Lock Landscape +setting.shadows.name = Shadows setting.animatedwater.name = Animated Water +setting.animatedshields.name = Animated Shields +setting.antialias.name = Antialias[LIGHT_GRAY] (requires restart)[] setting.indicators.name = Ally Indicators setting.autotarget.name = Auto-Target setting.fpscap.name = Max FPS @@ -424,9 +431,11 @@ setting.sensitivity.name = Sensitivitas Pengendali setting.saveinterval.name = Waktu Simpan Otomatis setting.seconds = {0} Detik setting.fullscreen.name = Layar Penuh +setting.borderless.name = Borderless Window 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.musicvol.name = Volume Musik setting.mutemusic.name = Bisukan Musik @@ -479,6 +488,21 @@ 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.pvp = PvP +rules.unitdrops = Unit Drops +rules.unitbuildspeedmultiplier = Unit Creation Speed Multiplier +rules.unithealthmultiplier = Unit Health Multiplier +rules.playerdamagemultiplier = Player 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 content.item.name = Items content.liquid.name = Liquids content.unit.name = Units @@ -559,6 +583,7 @@ 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} @@ -590,13 +615,17 @@ 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 @@ -628,6 +657,7 @@ block.thorium-wall-large.name = Large Thorium Wall block.door.name = pintu block.door-large.name = pintu besar block.duo.name = Duo +block.scorch.name = Scorch block.scatter.name = Scatter block.hail.name = Hail block.lancer.name = Lancer @@ -713,6 +743,7 @@ 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 @@ -728,6 +759,7 @@ 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 diff --git a/core/assets/bundles/bundle_it.properties b/core/assets/bundles/bundle_it.properties index 0851eedc72..50ce00f123 100644 --- a/core/assets/bundles/bundle_it.properties +++ b/core/assets/bundles/bundle_it.properties @@ -23,6 +23,7 @@ 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 = Sei sicuro di voler eliminare questa mappa"[accent]{0}[]"? level.highscore = Miglior punteggio: [accent]{0} level.select = Selezione del livello @@ -39,6 +40,7 @@ addplayers = Aggiungi/rimuovi giocatori customgame = Gioco personalizzato newgame = New Game none = +minimap = Minimap close = Chiuso quit = Esci maps = Mappe @@ -181,6 +183,7 @@ map.delete.confirm = Sei sicuro di voler eliminare questa mappa? Non potrai torn map.random = [accent]Mappa casuale map.nospawn = Questa mappa non possiede un nucleo dove spawnare! Aggiungine uno nell'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 = Errore nel caricamento della mappa: file mappa corrotto o non valido. editor.brush = Pennello editor.openin = Apri nell'editor @@ -282,6 +285,7 @@ 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 @@ -293,7 +297,7 @@ uncover = Uncover configure = Configure Loadout configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. zone.unlocked = [LIGHT_GRAY]{0} unlocked. -zone.complete = Zone conditions met. +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... @@ -332,63 +336,59 @@ no = No info.title = [accent] Info error.title = [crimson]Si è verificato un errore error.crashtitle = Si è verificato un errore -blocks.outputspeed = Drill Speed: {0}/s -blocks.efficiency = Efficiency: {0}% -blocks.unknown = [LIGHT_GRAY]??? -blocks.blockinfo = info sul blocco -blocks.powerbalance = Power: {0} -blocks.poweroutput = Power Output: {0} +blocks.input = Input +blocks.output = Output +blocks.booster = Booster +block.unknown = [LIGHT_GRAY]??? blocks.powercapacity = Capacità Energetica blocks.powershot = Danno/Colpo blocks.targetsair = Attacca nemici aerei blocks.targetsground = Targets Ground -blocks.items = Items: {0} blocks.itemsmoved = Move Speed +blocks.launchtime = Time Between Launches blocks.shootrange = Raggio blocks.size = Grandezza blocks.liquidcapacity = Capacità del liquido -blocks.maxitemssecond = Oggetti massimi/secondo blocks.powerrange = Raggio Energia blocks.poweruse = Utilizzo energia blocks.powerdamage = Power/Damage -blocks.inputitemcapacity = Capacità oggetti in entrata -blocks.outputitemcapacity = Capacità oggetti in uscità blocks.itemcapacity = Capacità blocks.basepowergeneration = Base Power Generation -blocks.powertransferspeed = Velocità trasferimento energia -blocks.craftspeed = Velocità produzione -blocks.inputliquid = Input del liquido -blocks.inputliquidaux = Liquidi extra -blocks.inputitem = Input Oggetto -blocks.inputitems = Oggetti in entrata -blocks.outputitem = Oggetti in uscita +blocks.productiontime = Production Time +blocks.repairtime = Block Full Repair Time +blocks.speedincrease = Speed Increase +blocks.range = Range blocks.drilltier = Scavabili blocks.drillspeed = Velocità scavo stbile +blocks.boosteffect = Boost Effect blocks.maxunits = Max Active Units -blocks.liquidoutput = Uscita liquidi -blocks.liquidoutputspeed = Liquid Output Speed -blocks.liquiduse = Uso liquidi -blocks.coolant = Refrigerante -blocks.liquid = Liquid -blocks.coolantuse = uso refrigerante -blocks.inputliquidfuel = carburante liquido -blocks.liquidfueluse = Utilizzo carburante liquido -blocks.boostitem = Boost Item -blocks.boostliquid = Boost Liquid blocks.health = Salute -blocks.heat = Heat -blocks.power = Power -blocks.progress = Build Progress -blocks.spawned = Units: {0}/{1} -blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = Inaccuratezza blocks.shots = Colpi blocks.reload = Ricarica -blocks.inputfuel = Carburante -blocks.fuelburntime = Tempo combustione carburante -blocks.inputcapacity = Capacità di ingresso -blocks.outputcapacity = Capacità di uscita 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 +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 = blocchi unit.powersecond = unità energia/secondo unit.liquidsecond = unità liquide/secondo @@ -397,6 +397,9 @@ unit.liquidunits = unità liquidi unit.powerunits = unità energia unit.degrees = gradi unit.seconds = secondi +unit.persecond = /sec +unit.timesspeed = x speed +unit.percent = % unit.items = oggetti category.general = Generali category.power = Energia @@ -405,7 +408,11 @@ category.items = Oggetti category.crafting = Produzione category.shooting = Potenza di fuoco category.optional = Optional Enhancements +setting.landscape.name = Lock Landscape +setting.shadows.name = Shadows setting.animatedwater.name = Animated Water +setting.animatedshields.name = Animated Shields +setting.antialias.name = Antialias[LIGHT_GRAY] (requires restart)[] setting.indicators.name = Ally Indicators setting.autotarget.name = Auto-Target setting.fpscap.name = Limite FPS @@ -424,9 +431,11 @@ setting.sensitivity.name = Sensibilità del controller setting.saveinterval.name = Intervallo di salvataggio automatico setting.seconds = {0} Secondi setting.fullscreen.name = Schermo Intero +setting.borderless.name = Borderless Window setting.fps.name = Mostra FPS setting.vsync.name = VSync setting.lasers.name = Mostra Laser Energetici +setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance) setting.minimap.name = Mostra minimappa setting.musicvol.name = Volume Musica setting.mutemusic.name = Silenzia musica @@ -479,6 +488,21 @@ 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.pvp = PvP +rules.unitdrops = Unit Drops +rules.unitbuildspeedmultiplier = Unit Creation Speed Multiplier +rules.unithealthmultiplier = Unit Health Multiplier +rules.playerdamagemultiplier = Player 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 content.item.name = Oggetti content.liquid.name = Liquidi content.unit.name = Units @@ -559,6 +583,7 @@ mech.itemcapacity = [LIGHT_GRAY]Capacità oggetti: {0} mech.minespeed = [LIGHT_GRAY]Velocità di scavo: {0} mech.minepower = [LIGHT_GRAY]Potenza di scavo: {0} mech.ability = [LIGHT_GRAY]Abilità: {0} +mech.buildspeed = [LIGHT_GRAY]Building Speed: {0}% liquid.heatcapacity = [LIGHT_GRAY]Capacità calorifica: {0} liquid.viscosity = [LIGHT_GRAY]Viscosità: {0} liquid.temperature = [LIGHT_GRAY]Temperatura: {0} @@ -590,13 +615,17 @@ block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus block.deepwater.name = acqua profonda block.water.name = acqua +block.tainted-water.name = Tainted Water +block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Tar block.stone.name = pietra block.sand.name = sabbia +block.darksand.name = Dark Sand block.ice.name = ghiaccio block.snow.name = neve 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 @@ -628,6 +657,7 @@ block.thorium-wall-large.name = Muro grande di torio block.door.name = porta block.door-large.name = Porta grande block.duo.name = Duo +block.scorch.name = Scorch block.scatter.name = Scatter block.hail.name = Bombardiere block.lancer.name = Idrogetto @@ -713,6 +743,7 @@ block.blast-drill.name = Blast Drill block.thermal-pump.name = Pompa termica block.thermal-generator.name = Generatore termico block.alloy-smelter.name = Altoforno +block.mender.name = Mender block.mend-projector.name = Riparatore block.surge-wall.name = Surge Wall block.surge-wall-large.name = Large Surge Wall @@ -728,6 +759,7 @@ 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 diff --git a/core/assets/bundles/bundle_ja.properties b/core/assets/bundles/bundle_ja.properties index d58f9d1d50..10dfada1dd 100644 --- a/core/assets/bundles/bundle_ja.properties +++ b/core/assets/bundles/bundle_ja.properties @@ -14,7 +14,6 @@ screenshot = スクリーンショットを {0} に保存しました。 gameover = ゲームオーバー gameover.pvp = [accent] {0}[] チームの勝利! highscore = [accent]ハイスコアを記録! - stat.wave = 防衛したウェーブ:[accent] {0} stat.enemiesDestroyed = 敵による破壊数:[accent] {0} stat.built = 建設した建造物数:[accent] {0} @@ -22,10 +21,9 @@ stat.destroyed = 破壊した建造物数:[accent] {0} stat.deconstructed = 解体した建造物数:[accent] {0} stat.delivered = 獲得した資源: stat.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 = マップ "[accent]{0}[]" を削除してもよろしいですか? level.highscore = ハイスコア: [accent]{0} level.select = レベル選択 @@ -42,6 +40,7 @@ addplayers = プレイヤーを追加/削除 customgame = カスタムゲーム newgame = 新しいゲーム none = <なし> +minimap = Minimap close = 閉じる quit = 終了 maps = マップ @@ -184,6 +183,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.invalid = マップの読み込みエラー: ファイルが無効、または破損しています。 editor.brush = ブラシ editor.openin = エディターで開く @@ -196,7 +196,7 @@ editor.waves = ウェーブ: waves.title = ウェーブ waves.remove = 削除 waves.never = <永久> -waves.every = +waves.every = every waves.waves = ウェーブごとに出現 waves.perspawn = スポーン waves.to = から @@ -285,6 +285,7 @@ abandon = 撤退 abandon.text = このゾーンとすべての資源が敵に奪われます。 locked = ロック complete = [LIGHT_GRAY]完了: +zone.requirement = Wave {0} in zone {1} resume = 再開ゾーン:\n[LIGHT_GRAY]{0} bestwave = [LIGHT_GRAY]最高ウェーブ: {0} launch = 出撃 @@ -296,7 +297,7 @@ uncover = 開拓 configure = 積荷の設定 configure.locked = [LIGHT_GRAY]ウェーブ {0} を達成すると積荷を設定できるようになります。 zone.unlocked = [LIGHT_GRAY]{0} がアンロックされました. -zone.complete = ゾーンの条件が達成されました。 +zone.requirement.complete = Wave {0} reached:\n{1} zone requirements met. zone.config.complete = ウェーブ {0} を達成:\n積荷の設定が解除されました。 zone.resources = 発見した資源: add = 追加... @@ -335,63 +336,59 @@ no = いいえ info.title = 情報 error.title = [crimson]エラーが発生しました error.crashtitle = エラーが発生しました -blocks.outputspeed = 採掘速度: {0}/秒 -blocks.efficiency = 効率: {0}% -blocks.unknown = [LIGHT_GRAY]??? -blocks.blockinfo = ブロック情報 -blocks.powerbalance = 電力: {0} -blocks.poweroutput = 電力発電量: {0} +blocks.input = Input +blocks.output = Output +blocks.booster = Booster +block.unknown = [LIGHT_GRAY]??? blocks.powercapacity = 電力容量 blocks.powershot = 電力/ショット blocks.targetsair = 対空攻撃 blocks.targetsground = 対地攻撃 -blocks.items = アイテム: {0} blocks.itemsmoved = 輸送速度 +blocks.launchtime = Time Between Launches blocks.shootrange = 範囲 blocks.size = 大きさ blocks.liquidcapacity = 液体容量 -blocks.maxitemssecond = 最大アイテム量 blocks.powerrange = 電力範囲 blocks.poweruse = 電力使用量 blocks.powerdamage = 電力/ダメージ -blocks.inputitemcapacity = 搬入アイテム容量 -blocks.outputitemcapacity = 搬出アイテム容量 blocks.itemcapacity = アイテム容量 blocks.basepowergeneration = 基本発電量 -blocks.powertransferspeed = 電力伝送量 -blocks.craftspeed = 生産速度 -blocks.inputliquid = 必要な液体 -blocks.inputliquidaux = 補助液 -blocks.inputitem = 必要なアイテム -blocks.inputitems = 必要なアイテム -blocks.outputitem = 搬出アイテム +blocks.productiontime = Production Time +blocks.repairtime = Block Full Repair Time +blocks.speedincrease = Speed Increase +blocks.range = Range blocks.drilltier = ドリル blocks.drillspeed = 基本採掘速度 +blocks.boosteffect = Boost Effect blocks.maxunits = 最大ユニット数 -blocks.liquidoutput = 搬出液体 -blocks.liquidoutputspeed = 液体搬出速度 -blocks.liquiduse = 液体使用量 -blocks.coolant = 冷却 -blocks.liquid = 液体 -blocks.coolantuse = 冷却使用量 -blocks.inputliquidfuel = 液体燃料 -blocks.liquidfueluse = 液体燃料使用量 -blocks.boostitem = 加速アイテム -blocks.boostliquid = 加速液体 blocks.health = 耐久値 -blocks.heat = 熱 -blocks.power = 電力 -blocks.progress = 建設状況 -blocks.spawned = ユニット数: {0}/{1} -blocks.power.satisfaction = 電力需要 blocks.inaccuracy = 精度のずれ blocks.shots = ショット blocks.reload = ショット/秒 -blocks.inputfuel = 燃料 -blocks.fuelburntime = 燃焼時間 -blocks.inputcapacity = 搬入容量 -blocks.outputcapacity = 搬出容量 blocks.ammo = 弾薬 +bar.drillspeed = 採掘速度: {0}/秒 +bar.efficiency = 効率: {0}% +bar.powerbalance = 電力: {0} +bar.poweramount = Power: {0} +bar.poweroutput = 電力発電量: {0} +bar.items = アイテム: {0} +bar.liquid = 液体 +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 unit.blocks = ブロック unit.powersecond = 電力/秒 unit.liquidsecond = 液体/秒 @@ -400,6 +397,9 @@ unit.liquidunits = 液体 unit.powerunits = 電力 unit.degrees = 度 unit.seconds = 秒 +unit.persecond = /sec +unit.timesspeed = x speed +unit.percent = % unit.items = アイテム category.general = 一般 category.power = 電力 @@ -408,7 +408,11 @@ category.items = アイテム category.crafting = 製作速度 category.shooting = 攻撃速度 category.optional = 機能強化オプション +setting.landscape.name = Lock Landscape +setting.shadows.name = Shadows setting.animatedwater.name = 水のアニメーション +setting.animatedshields.name = Animated Shields +setting.antialias.name = Antialias[LIGHT_GRAY] (requires restart)[] setting.indicators.name = 味方の方角表示 setting.autotarget.name = 自動ターゲット setting.fpscap.name = 最大FPS @@ -427,9 +431,11 @@ setting.sensitivity.name = 操作感度 setting.saveinterval.name = 自動保存間隔 setting.seconds = {0} 秒 setting.fullscreen.name = フルスクリーン +setting.borderless.name = Borderless Window setting.fps.name = FPSを表示 setting.vsync.name = VSync setting.lasers.name = 電力レーザーを表示 +setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance) setting.minimap.name = ミニマップを表示 setting.musicvol.name = 音楽 音量 setting.mutemusic.name = 音楽をミュート @@ -482,6 +488,21 @@ mode.pvp.name = PvP 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.pvp = PvP +rules.unitdrops = Unit Drops +rules.unitbuildspeedmultiplier = Unit Creation Speed Multiplier +rules.unithealthmultiplier = Unit Health Multiplier +rules.playerdamagemultiplier = Player 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 content.item.name = アイテム content.liquid.name = 液体 content.unit.name = ユニット @@ -562,6 +583,7 @@ mech.itemcapacity = [LIGHT_GRAY]アイテム容量: {0} mech.minespeed = [LIGHT_GRAY]採掘速度: {0} mech.minepower = [LIGHT_GRAY]採掘性能: {0} mech.ability = [LIGHT_GRAY]能力: {0} +mech.buildspeed = [LIGHT_GRAY]Building Speed: {0}% liquid.heatcapacity = [LIGHT_GRAY]熱容量: {0} liquid.viscosity = [LIGHT_GRAY]粘度: {0} liquid.temperature = [LIGHT_GRAY]温度: {0} @@ -570,8 +592,8 @@ block.salt.name = 岩塩氷河 block.sandrocks.name = 砂岩 block.spore-pine.name = 胞子の松の木 block.sporerocks.name = 胞子の岩 -block.snowrock.name = Snow Rock block.rock.name = 岩 +block.snowrock.name = Snow Rock block.shale.name = 泥板岩 block.shale-boulder.name = 泥板岩の丸石 block.moss.name = コケ @@ -593,13 +615,17 @@ block.core-foundation.name = コア: ファンデーション block.core-nucleus.name = コア: ニュークリアス block.deepwater.name = 深層水 block.water.name = 水 +block.tainted-water.name = Tainted Water +block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = タール block.stone.name = 石 block.sand.name = 砂 +block.darksand.name = Dark Sand block.ice.name = 氷 block.snow.name = 雪 block.craters.name = クレーター block.sand-water.name = 濁った水 +block.darksand-water.name = Dark Sand Water block.char.name = 焦げ跡 block.holostone.name = ホロストーン block.ice-snow.name = 雪氷 @@ -631,6 +657,7 @@ block.thorium-wall-large.name = 大きなトリウムの壁 block.door.name = ドア block.door-large.name = 大きなドア block.duo.name = デュオ +block.scorch.name = Scorch block.scatter.name = スキャッター block.hail.name = ヘイル block.lancer.name = ランサー @@ -716,6 +743,7 @@ block.blast-drill.name = エアブラストドリル block.thermal-pump.name = サーマルポンプ block.thermal-generator.name = サーマル発電機 block.alloy-smelter.name = 合金溶鉱炉 +block.mender.name = Mender block.mend-projector.name = 修復プロジェクター block.surge-wall.name = サージの壁 block.surge-wall-large.name = 大きなサージの壁 @@ -731,6 +759,7 @@ block.meltdown.name = メルトダウン block.container.name = コンテナー block.launch-pad.name = 出撃パッド block.launch-pad.description = コアの出撃不要で多くのアイテムを脱出します。これは未完成です。 +block.launch-pad-large.name = Large Launch Pad team.blue.name = ブルー team.red.name = レッド team.orange.name = オレンジ @@ -856,7 +885,6 @@ block.wraith-factory.description = 高速で突撃攻撃が可能な迎撃ユニ block.ghoul-factory.description = 大型の爆撃機のグールを製造します。 block.dagger-factory.description = 基本的な地上ユニットのダガーを製造します。 block.titan-factory.description = 改良された武装地上ユニットのタイタンを製造します。 - block.fortress-factory.description = 大型の砲撃地上ユニットのフォートレスを製造します。 block.revenant-factory.description = 大型のレーザー航空ユニットのレベナントを製造します。 block.repair-point.description = 近くの負傷したユニットを修復します。 diff --git a/core/assets/bundles/bundle_ko.properties b/core/assets/bundles/bundle_ko.properties index 44ff43c869..c1224e5c51 100644 --- a/core/assets/bundles/bundle_ko.properties +++ b/core/assets/bundles/bundle_ko.properties @@ -18,19 +18,20 @@ stat.wave = 웨이브 성공:[accent]{0} stat.enemiesDestroyed = 파괴한 적 수:[accent]{0} stat.built = 건설한 건물 수:[accent]{0} stat.destroyed = 파괴된 건물 수:[accent]{0} -stat.deconstructed = 해체한 건물 수:[accent]{0} +stat.deconstructed = 파괴한 건물 수:[accent]{0} stat.delivered = 획득한 자원: stat.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. +placeline = 블록을 선택하셨습니다.\n][accent]몇초간 설치 시작지점을 누르고[] 원하는 방향을 향해 드래그 하면 [accent]일렬로[] 설치할 수 있습니다.\n한번 해 보세요. +removearea = 블록 제거모드를 선택하셨습니다.\n[accent]몇초간 제거 시작지점을 누르고[] 원하는 구역 끝을 향해 드래그 하면 [accent]직사각형[] 안에 있는 모든 건물을 제거할 수 있습니다.\n한번 해 보세요. +launcheditems = [accent]출격 아이템 map.delete = 정말로 "[accent]{0}[]" 맵을 삭제하시겠습니까?\n level.highscore = 최고 점수: [accent]{0} level.select = 맵 선택 level.mode = 게임 모드 : showagain = 다음 세션에서 이 메세지를 표시하지 않습니다 coreattack = < 코어가 공격받고 있습니다! > -nearpoint = [[ [scarlet]드롭 지점에서 나가세요[] ]\n모든 유닛 및 건물 파괴 임박 -outofbounds = [[ 출입 금지 구역 ]\n[]{0}초후 건물이 해체됩니다. +nearpoint = [[ [scarlet]드롭 지점에서 나가세요[] ]\n적 스폰시 건물 및 유닛 파괴 +outofbounds = [[ 출입 금지 구역 ]\n[]{0}초후 유닛이 파괴됩니다. database = 코어 데이터베이스 savegame = 게임 저장 loadgame = 게임 불러오기 @@ -39,6 +40,7 @@ addplayers = 플레이어 추가/제거 customgame = 커스텀 게임 newgame = 새 게임 none = <없음> +minimap = 미니맵 close = 닫기 quit = 나가기 maps = 맵 @@ -180,7 +182,8 @@ builtin = 기본맵 map.delete.confirm = 이 맵을 삭제하시겠습니까? 이 명령은 취소할 수 없습니다! map.random = [accent]랜덤 맵 map.nospawn = 이 맵에 플레이어가 스폰 할 코어가 없습니다! 맵 편집기에서 [ROYAL]파란색[]코어를 맵에 추가하세요. -map.nospawn.pvp = 이 맵에는 적팀 코어가 없습니다! 에디터에서 [SCARLET]빨간팀[] 코어를 추가하세요. +map.nospawn.pvp = 이 맵에는 적팀 코어가 없습니다! 에디터에서 [SCARLET]파란색 팀이 아닌[] 코어를 추가하세요. +map.nospawn.attack = 이 맵에는 플레이어가 공격할 수 있는 적의 코어가 없습니다! 에디터에서 [SCARLET] 빨간팀[] 코어를 맵에 추가하세요. map.invalid = 파일이 잘못되었거나 손상되어 맵을 열 수 없습니다. editor.brush = 브러쉬 editor.openin = 편집기 열기 @@ -189,32 +192,32 @@ editor.oregen.info = 광물 무작위 생성: editor.mapinfo = 맵 정보 editor.author = 만든이: editor.description = 설명: -editor.waves = Waves: -waves.title = Waves -waves.remove = Remove -waves.never = -waves.every = every -waves.waves = wave(s) -waves.perspawn = per spawn -waves.to = to -waves.boss = Boss -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.waves = 웨이브: +waves.title = 웨이브 +waves.remove = 삭제 +waves.never = <절대> +waves.every = 매 +waves.waves = 웨이브마다 +waves.perspawn = 스폰. +waves.to = 부터 +waves.boss = 이 몹은 보스임. +waves.preview = 미리보기 +waves.edit = 편집... +waves.copy = 클립보드로 복사 +waves.load = 클립보드에서 불러오기 +waves.invalid = 클립보드의 잘못된 웨이브 데이터 +waves.copied = 웨이브 복사됨 +editor.default = [LIGHT_GRAY]<기본값> +edit = 편집... editor.name = 이름: editor.teams = 팀 editor.elevation = 지형 높이 -editor.errorload = Error loading file:\n[accent]{0} -editor.errorsave = Error saving file:\n[accent]{0} -editor.errorname = Map has no name defined. -editor.update = Update -editor.randomize = Randomize -editor.apply = Apply +editor.errorload = [accent]{0} 파일을 불러오는데 실패했습니다. +editor.errorsave = [accent]{0} 파일을 저장하는데 실패했습니다. +editor.errorname = 맵에 이름이 지정되어 있지 않습니다. +editor.update = 업데이트 +editor.randomize = 랜덤 +editor.apply = 적용 editor.generate = 생성 editor.resize = 맵 크기조정 editor.loadmap = 맵 불러오기 @@ -243,26 +246,26 @@ editor.mapname = 맵 이름: editor.overwrite = [accept]경고!이 명령은 기존 맵을 덮어씌우게 됩니다. editor.overwrite.confirm = [scarlet]경고![] 이 이름을 가진 맵이 이미 있습니다. 덮어 쓰시겠습니까? editor.selectmap = 불러올 맵 선택: -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 +filters.empty = [LIGHT_GRAY]필터가 없습니다!! 아래 버튼을 눌러 추가하세요. +filter.distort = 비틀기 +filter.noise = 노이즈 +filter.ore = 자원 +filter.rivernoise = 협곡 노이즈 +filter.scatter = 뿌리기 +filter.terrain = 지형 +filter.option.scale = 스케일 +filter.option.chance = 기회 +filter.option.mag = 규모 +filter.option.threshold = 문지방 +filter.option.circle-scale = 둥근 크기 +filter.option.octaves = 옥타보스 +filter.option.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 +filter.option.floor = 바닥 +filter.option.wall = 벽 +filter.option.ore = 자원 +filter.option.floor2 = 2번째 바닥 +filter.option.threshold2 = 2번째 문지방 width = 넓이: height = 높이: menu = 메뉴 @@ -278,10 +281,11 @@ tutorial = 게임 방법 editor = 편집기 mapeditor = 맵 편집기 donate = 기부 -abandon = 버리기 +abandon = 포기 abandon.text = 이 구역과 모든 자원이 적에게 빼앗길 것입니다. locked = 잠김 complete = [LIGHT_GRAY]완료: +zone.requirement = 지역 {1} 에서 웨이브 {0} 달성 resume = 지역 계속 플레이:\n[LIGHT_GRAY]{0} bestwave = [LIGHT_GRAY]최고 점수: {0} launch = < 출격 > @@ -293,7 +297,7 @@ uncover = 털어넣기 configure = 로드아웃 설정 configure.locked = {0} 단계에서 로드아웃을 설정할 수 있음. zone.unlocked = [LIGHT_GRAY] 잠금 해제됨. -zone.complete = 지역 조건이 충족됨. +zone.requirement.complete = 웨이브 {0} 달성:\n{1} 지역 요구사항이 충족됨. zone.config.complete = 웨이브 {0} 달성:\n로드아웃 설정 잠금 해제됨. zone.resources = 자원 감지됨: add = 추가... @@ -332,63 +336,58 @@ no = 아니오 info.title = [accent]정보 error.title = [crimson]오류가 발생했습니다. error.crashtitle = 오류가 발생했습니다. -blocks.outputspeed = 채광 속도: {0}/s -blocks.efficiency = Efficiency: {0}% -blocks.unknown = [LIGHT_GRAY]??? -blocks.blockinfo = 블록 정보 -blocks.powerbalance = 전력: {0} -blocks.poweroutput = 전력 출력: {0} +blocks.input = 입력 +blocks.output = 출력 +blocks.booster = 가속 +block.unknown = [LIGHT_GRAY]??? blocks.powercapacity = 전력 용량 blocks.powershot = 1발당 전력 소모량 blocks.targetsair = 공중공격 가능 -blocks.targetsground = Targets Ground -blocks.items = Items: {0} +blocks.targetsground = 지상공격 가능 blocks.itemsmoved = 이동 속도 +blocks.launchtime = 출격 시간 blocks.shootrange = 사거리 blocks.size = 크기 blocks.liquidcapacity = 액체 용량 -blocks.maxitemssecond = 아이템 보관량 blocks.powerrange = 전력 범위 blocks.poweruse = 전력 사용 blocks.powerdamage = 전력/데미지 -blocks.inputitemcapacity = 입력 아이템 용량 -blocks.outputitemcapacity = 출력 아이템 용량 blocks.itemcapacity = 저장 용량 -blocks.basepowergeneration = 기지 전력 생성기 -blocks.powertransferspeed = 전력 전송량 -blocks.craftspeed = 생산 속도 -blocks.inputliquid = 사용되는 액체 -blocks.inputliquidaux = 보조 액체 -blocks.inputitem = 사용되는 아이템 -blocks.inputitems = 사용되는 아이템들 -blocks.outputitem = 출력 아이템 +blocks.basepowergeneration = 기본 전력 생성량 +blocks.productiontime = 제작 시간 +blocks.repairtime = 전체 블록 수리시간 +blocks.speedincrease = 속도 증가 +blocks.range = 사거리 blocks.drilltier = 드릴 blocks.drillspeed = 기본 드릴 속도 +blocks.boosteffect = 가속 효과 blocks.maxunits = 최대 활성유닛 -blocks.liquidoutput = 액체 출력 -blocks.liquidoutputspeed = 액체 출력속도 -blocks.liquiduse = 액체 사용량 -blocks.coolant = 냉각제 -blocks.liquid = 액체 -blocks.coolantuse = 냉각제 사용 -blocks.inputliquidfuel = 연료 액 -blocks.liquidfueluse = 액체 연료 사용 -blocks.boostitem = 가속 아이템 -blocks.boostliquid = 가속 액체 blocks.health = 체력 -blocks.heat = 발열 -blocks.power = 전력 -blocks.progress = 건설 진행 -blocks.spawned = 유닛: {0}/{1} -blocks.power.satisfaction = 전력 만족도 blocks.inaccuracy = 오차각 blocks.shots = 발포 횟수 blocks.reload = 재장전 -blocks.inputfuel = 연료 -blocks.fuelburntime = 연료 연소 시간 -blocks.inputcapacity = 입력 용량 -blocks.outputcapacity = 출력 용량 blocks.ammo = 탄약 +bar.outputspeed = 채광 속도: {0}/s +bar.efficiency = 효율성: {0}% +bar.powerbalance = 전력: {0}/s +bar.poweroutput = 전력 출력: {0} +bar.items = 아이템: {0} +bar.liquid = 액체 +bar.heat = 발열 +bar.power = 전력 +bar.progress = 건설 진행 +bar.spawned = 유닛: {0}/{1} +bullet.damage = [stat]{0}[lightgray] 데미지 +bullet.splashdamage = [stat]{0}[lightgray] area 데미지 ~[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]x 탄약 배율 +bullet.reload = [stat]{0}[lightgray]x 사격 속도 unit.blocks = 블록 unit.powersecond = 전력/초 unit.liquidsecond = 액체/초 @@ -397,6 +396,9 @@ unit.liquidunits = 액체 unit.powerunits = 전력 unit.degrees = 도 unit.seconds = 초 +unit.persecond = /초 +unit.timesspeed = x 배 +unit.percent = % unit.items = 아이템 category.general = 일반 category.power = 전력 @@ -405,13 +407,17 @@ category.items = 아이템 category.crafting = 제작 category.shooting = 사격 category.optional = 보조 아이템 +setting.landscape.name = 가로화면으로 고정 +setting.shadows.name = 그림자 setting.animatedwater.name = 움직이는 물 -setting.indicators.name = 인디게이터 표시 +setting.animatedshields.name = 움직이는 보호막 +setting.antialias.name = 안티 에일리어싱[LIGHT_GRAY] (재시작 필요)[] +setting.indicators.name = 아군/적 인디게이터 표시 setting.autotarget.name = 자동 조준 setting.fpscap.name = 최대 FPS setting.fpscap.none = 없음 -setting.fpscap.text = FPS -setting.swapdiagonal.name = Always Diagonal Placement +setting.fpscap.text = {0}FPS +setting.swapdiagonal.name = 항상 대각선 설치 setting.difficulty.training = 훈련 setting.difficulty.easy = 쉬움 setting.difficulty.normal = 보통 @@ -424,9 +430,11 @@ setting.sensitivity.name = 컨트롤러 감도 setting.saveinterval.name = 자동저장 간격 setting.seconds = 초 setting.fullscreen.name = 전체 화면 +setting.borderless.name = 테두리 없는 창모드 setting.fps.name = FPS 표시 setting.vsync.name = VSync 활성화 setting.lasers.name = 전력 노드 레이저 표시 +setting.pixelate.name = 픽셀화 [LIGHT_GRAY](게임 성능이 감소할 수 있습니다) setting.minimap.name = 미니맵 보기 setting.musicvol.name = 음악 크기 setting.mutemusic.name = 음소거 @@ -448,7 +456,7 @@ keybind.screenshot.name = 맵 스크린샷 keybind.move_x.name = 오른쪽/왼쪽 이동 keybind.move_y.name = 위 / 아래 중간 keybind.select.name = 선택 -keybind.diagonal_placement.name = Diagonal Placement +keybind.diagonal_placement.name = 대각선 설치 keybind.pick.name = 블록 선택 keybind.break_block.name = 블록 파괴 keybind.deselect.name = 선택해제 @@ -479,6 +487,21 @@ mode.pvp.name = PvP mode.pvp.description = 실제 플레이어와 PvP를 합니다. mode.attack.name = 공격 mode.attack.description = 일정 시간마다 적이 오는 단계가 없으며, 적의 기지를 파괴하는 것을 목표로 합니다. +mode.custom = 커스텀 규칙 +rules.infiniteresources = 무한 자원 +rules.wavetimer = 웨이브 타이머 +rules.waves = 웨이브 +rules.enemyCheat = 무한 AI 자원 +rules.pvp = PvP +rules.unitdrops = 유닛 드롭 +rules.unitbuildspeedmultiplier = 유닛 생산속도 배수 +rules.unithealthmultiplier = 유닛 체력 배수 +rules.playerdamagemultiplier = 플레이어 공격력 배수 +rules.enemycorebuildradius = 적 코어 건설 금지구역:[LIGHT_GRAY] (타일) +rules.respawntime = 리스폰 시간:[LIGHT_GRAY] (초) +rules.wavespacing = 웨이브 간격:[LIGHT_GRAY] (초) +rules.buildcostmultiplier = 건설 소모 배율 +rules.buildspeedmultiplier = 건설 속도 배율 content.item.name = 아이템 content.liquid.name = 액체 content.unit.name = 유닛 @@ -521,8 +544,8 @@ liquid.oil.name = 석유 liquid.cryofluid.name = 냉각유체 mech.alpha-mech.name = 알파 mech.alpha-mech.weapon = 중무장 소총 -mech.alpha-mech.ability = 드론 소환 -mech.alpha-mech.description = 표준 기체.\n적절한 속도와 공격력을 갖추고 있으며, 공격 능력을 높이기 위해 최대 3대의 드론을 만들 수 있습니다. +mech.alpha-mech.ability = 회복 +mech.alpha-mech.description = 표준 기체.\n적절한 속도와 공격력을 갖추고 있습니다. mech.delta-mech.name = 델타 mech.delta-mech.weapon = 전격 생산기 mech.delta-mech.ability = 충전 @@ -556,24 +579,25 @@ unit.speed = [LIGHT_GRAY]속도: {0} mech.weapon = [LIGHT_GRAY]무기: {0} mech.health = [LIGHT_GRAY]체력: {0} mech.itemcapacity = [LIGHT_GRAY]아이템 수용 용량: {0} -mech.minespeed = [LIGHT_GRAY]채광 속도: {0} +mech.minespeed = [LIGHT_GRAY]채광 속도: {0}% mech.minepower = [LIGHT_GRAY]채광 레벨: {0} mech.ability = [LIGHT_GRAY]능력: {0} +mech.buildspeed = [LIGHT_GRAY]건설 속도: {0}% liquid.heatcapacity = [LIGHT_GRAY]발열 용량: {0} liquid.viscosity = [LIGHT_GRAY]점도: {0} liquid.temperature = [LIGHT_GRAY]온도: {0} -block.grass.name = Grass -block.salt.name = Salt -block.sandrocks.name = Sand Rocks -block.spore-pine.name = Spore Pine -block.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.spore-moss.name = Spore Moss -block.shalerocks.name = Shale Rocks +block.grass.name = 잔디 +block.salt.name = 소금 +block.sandrocks.name = 모래 바위 +block.spore-pine.name = 포자 소나무 +block.sporerocks.name = 포자 바위 +block.rock.name = 바위 +block.snowrock.name = 눈바위 +block.shale.name = 이판암 +block.shale-boulder.name = 둥근 이판암 +block.moss.name = 이끼 +block.spore-moss.name = 포자 이끼 +block.shalerocks.name = 이판암 바위 block.scrap-wall.name = 조각벽 block.scrap-wall-large.name = 큰 조각벽 block.scrap-wall-huge.name = 거대한 조각 벽 @@ -585,18 +609,22 @@ block.graphite-press.name = 흑연 압축기 block.multi-press.name = 다중 압축기 block.constructing = {0} [LIGHT_GRAY](만드는중) block.spawn.name = 적 스폰지점 -block.core-shard.name = 코어: 공유 -block.core-foundation.name = 코어: 기초 -block.core-nucleus.name = 코어: 핵 +block.core-shard.name = 코어-공유 +block.core-foundation.name = 코어-기초 +block.core-nucleus.name = 코어-핵 block.deepwater.name = 깊은물 block.water.name = 물 +block.tainted-water.name = 도색된 물 +block.darksand-tainted-water.name = 검은 모래로 도색된 물 block.tar.name = 타르 block.stone.name = 돌 block.sand.name = 모래 +block.darksand.name = 검은 모래 block.ice.name = 얼음 block.snow.name = 눈 block.craters.name = 크레이터 block.sand-water.name = 젖은모래 +block.darksand-water.name = 검은모래물 block.char.name = 숯 block.holostone.name = 홀로스톤 block.ice-snow.name = 얼음눈 @@ -628,7 +656,8 @@ block.thorium-wall-large.name = 대형 토륨벽 block.door.name = 문 block.door-large.name = 대형문 block.duo.name = 듀오 -block.scatter.name = Scatter +block.scorch.name = 스코어치 +block.scatter.name = 스캐터 block.hail.name = 헤일 block.lancer.name = 랜서 block.conveyor.name = 컨베이어 @@ -656,7 +685,7 @@ block.battery-large.name = 대형 배터리 block.combustion-generator.name = 화력 발전기 block.turbine-generator.name = 터빈 발전기 block.differential-generator.name = 차동 발전기 -block.impact-reactor.name = 충격 반응기 +block.impact-reactor.name = 핵융합로 block.mechanical-drill.name = 기계 드릴 block.pneumatic-drill.name = 강철 드릴 block.laser-drill.name = 레이저 드릴 @@ -713,6 +742,7 @@ block.blast-drill.name = 압축 공기분사 드릴 block.thermal-pump.name = 화력 펌프 block.thermal-generator.name = 열발전기 block.alloy-smelter.name = 서지 합금 제련소 +block.mender.name = 멘더 block.mend-projector.name = 수리 프로젝터 block.surge-wall.name = 서지 합금벽 block.surge-wall-large.name = 큰 서지 합금벽 @@ -728,6 +758,7 @@ block.meltdown.name = 멜트다운 block.container.name = 컨테이너 block.launch-pad.name = 발사대 block.launch-pad.description = 출격할 필요 없이 아이템을 수송시킵시다. 미완성. +block.launch-pad-large.name = 큰 출격 패드 team.blue.name = 블루팀 team.red.name = 레드팀 team.orange.name = 오렌지팀 @@ -812,7 +843,7 @@ block.silicon-smelter.description = 고순도 석탄으로 모래를 줄여 실 block.plastanium-compressor.description = 석유와 티타늄으로 플라스타늄을 생산합니다. block.phase-weaver.description = 방사능 토륨과 많은 량의 모래에서 상직물을 생산합니다. block.alloy-smelter.description = 티타늄, 납, 실리콘, 구리로부터 서지 합금을 생산합니다. -block.pulverizer.description = 모래로 돌을 부숩니다. 천연 모래가 부족할 때 유용합니다. +block.pulverizer.description = 모래로 을 부숩니다. 천연 모래가 부족할 때 유용합니다. block.pyratite-mixer.description = 석탄, 납, 모래를 가연성이 높은 피라타이트로 만듭니다. block.blast-mixer.description = 기름을 사용하여 피라타이트를 인화성은 떨어지지만 폭발성은 높은 폭발성 화합물로 변환시킵니다. block.cryofluidmixer.description = 물과 티타늄을 냉각에 훨씬 더 효과적인 냉동액으로 결합시킵니다. @@ -832,7 +863,7 @@ block.solar-panel-large.description = 일반 태양 전지판보다 훨씬 나 block.thorium-reactor.description = 고방사능 토륨으로부터 막대한 양의 전력을 발생시킵니다. 지속적인 냉각이 필요하며 냉각제의 양이 부족하면 크게 폭발합니다. 전력 출력은 최대 용량에서 기본 전력을 발생시키는 완전성에 따라 결정됩니다. block.rtg-generator.description = 냉각은 필요 없지만 토륨 원자로에 비해 전력을 적게 공급하는 방사성 동위원소 열전 발생기. block.unloader.description = 컨테이너, 금고 또는 코어에서 인접한 블록으로 아이템을 출하합니다. 출하시킬 아이템의 종류는 언로더를 눌러 지정할 수 있습니다. -block.container.description = 각종 소량의 자원을 저장할 수 있습니다.[LIGHT_GRAY언로더[]를 사용하여 컨테이너에서 물건을 회수할 수 있습니다. +block.container.description = 각종 소량의 자원을 저장할 수 있습니다.[LIGHT_GRAY]언로더[]를 사용하여 컨테이너에서 물건을 회수할 수 있습니다. block.vault.description = 각종 대량의 자원을 저장할 수 있습니다.[LIGHT_GRAY]언로더[]를 사용하여 금고에서 물건을 회수할 수 있습니다. block.mechanical-drill.description = 싸구려 드릴. 적절한 타일 위에 놓였을때 매우 느린 속도로 계속 출력합니다. block.pneumatic-drill.description = 기압을 이용하여 보다 빠르고 단단한 물질을 채광할 수 있는 향상된 드릴. diff --git a/core/assets/bundles/bundle_nl.properties b/core/assets/bundles/bundle_nl.properties index 81b2d5d1bc..7c0a5e8176 100644 --- a/core/assets/bundles/bundle_nl.properties +++ b/core/assets/bundles/bundle_nl.properties @@ -23,6 +23,7 @@ stat.delivered = Middelen Gelanceerd: stat.rank = Eindrang: [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 = Weet je zeker dat je de map wilt verwijderen? "[accent]{0}[]"? level.highscore = Topscore: [accent]{0} level.select = Selecteer Level @@ -39,6 +40,7 @@ addplayers = Add/Remove Players customgame = Custom Game newgame = New Game none = +minimap = Minimap close = Close quit = Quit maps = Maps @@ -181,6 +183,7 @@ map.delete.confirm = Are you sure you want to delete this map? This action canno 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 @@ -282,6 +285,7 @@ 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 Wave: {0} launch = < LAUNCH > @@ -293,7 +297,7 @@ uncover = Uncover configure = Configure Loadout configure.locked = [LIGHT_GRAY]Unlock configuring loadout:\nWave {0}. zone.unlocked = [LIGHT_GRAY]{0} unlocked. -zone.complete = Wave {0} reached:\nNew zone requirements met. +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... @@ -332,63 +336,59 @@ no = No info.title = Info error.title = [crimson]An error has occured error.crashtitle = An error has occured -blocks.outputspeed = Drill Speed: {0}/s -blocks.efficiency = Efficiency: {0}% -blocks.unknown = [LIGHT_GRAY]??? -blocks.blockinfo = Block Info -blocks.powerbalance = Power: {0} -blocks.poweroutput = Power Output: {0} +blocks.input = Input +blocks.output = Output +blocks.booster = Booster +block.unknown = [LIGHT_GRAY]??? blocks.powercapacity = Power Capacity blocks.powershot = Power/Shot blocks.targetsair = Targets Air blocks.targetsground = Targets Ground -blocks.items = Items: {0} blocks.itemsmoved = Move Speed +blocks.launchtime = Time Between Launches blocks.shootrange = Range blocks.size = Size blocks.liquidcapacity = Liquid Capacity -blocks.maxitemssecond = Max Items blocks.powerrange = Power Range blocks.poweruse = Power Use blocks.powerdamage = Power/Damage -blocks.inputitemcapacity = Input Item Capacity -blocks.outputitemcapacity = Output Item Capacity blocks.itemcapacity = Item Capacity blocks.basepowergeneration = Base Power Generation -blocks.powertransferspeed = Power Transfer -blocks.craftspeed = Production Speed -blocks.inputliquid = Input Liquid -blocks.inputliquidaux = Aux Liquid -blocks.inputitem = Input Item -blocks.inputitems = Input Items -blocks.outputitem = Output Item +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.liquidoutput = Liquid Output -blocks.liquidoutputspeed = Liquid Output Speed -blocks.liquiduse = Liquid Use -blocks.coolant = Coolant -blocks.liquid = Liquid -blocks.coolantuse = Coolant Use -blocks.inputliquidfuel = Fuel Liquid -blocks.liquidfueluse = Liquid Fuel Use -blocks.boostitem = Boost Item -blocks.boostliquid = Boost Liquid blocks.health = Health -blocks.heat = Heat -blocks.power = Power -blocks.progress = Build Progress -blocks.spawned = Units: {0}/{1} -blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = Inaccuracy blocks.shots = Shots blocks.reload = Shots/Second -blocks.inputfuel = Fuel -blocks.fuelburntime = Fuel Burn Time -blocks.inputcapacity = Input capacity -blocks.outputcapacity = Output capacity 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 +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 @@ -397,6 +397,9 @@ unit.liquidunits = liquid units unit.powerunits = power units unit.degrees = degrees unit.seconds = seconds +unit.persecond = /sec +unit.timesspeed = x speed +unit.percent = % unit.items = items category.general = General category.power = Power @@ -405,7 +408,11 @@ category.items = Items category.crafting = Crafting category.shooting = Shooting category.optional = Optional Enhancements +setting.landscape.name = Lock Landscape +setting.shadows.name = Shadows setting.animatedwater.name = Animated Water +setting.animatedshields.name = Animated Shields +setting.antialias.name = Antialias[LIGHT_GRAY] (requires restart)[] setting.indicators.name = Ally Indicators setting.autotarget.name = Auto-Target setting.fpscap.name = Max FPS @@ -424,9 +431,11 @@ setting.sensitivity.name = Controller Sensitivity setting.saveinterval.name = Autosave Interval setting.seconds = {0} Seconds setting.fullscreen.name = Fullscreen +setting.borderless.name = Borderless Window setting.fps.name = Show FPS setting.vsync.name = VSync setting.lasers.name = Show Power Lasers +setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance) setting.minimap.name = Show Minimap setting.musicvol.name = Music Volume setting.mutemusic.name = Mute Music @@ -479,6 +488,21 @@ 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.pvp = PvP +rules.unitdrops = Unit Drops +rules.unitbuildspeedmultiplier = Unit Creation Speed Multiplier +rules.unithealthmultiplier = Unit Health Multiplier +rules.playerdamagemultiplier = Player 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 content.item.name = Items content.liquid.name = Liquids content.unit.name = Units @@ -559,6 +583,7 @@ 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} @@ -590,13 +615,17 @@ block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus block.deepwater.name = Deep Water 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 = Dark 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 @@ -628,6 +657,7 @@ block.thorium-wall-large.name = Large Thorium Wall block.door.name = Door block.door-large.name = Large Door block.duo.name = Duo +block.scorch.name = Scorch block.scatter.name = Scatter block.hail.name = Hail block.lancer.name = Lancer @@ -713,6 +743,7 @@ block.blast-drill.name = Airblast Drill block.thermal-pump.name = Thermal Pump block.thermal-generator.name = Thermal Generator block.alloy-smelter.name = Alloy Smelter +block.mender.name = Mender block.mend-projector.name = Mend Projector block.surge-wall.name = Surge Wall block.surge-wall-large.name = Large Surge Wall @@ -728,6 +759,7 @@ 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 diff --git a/core/assets/bundles/bundle_pl.properties b/core/assets/bundles/bundle_pl.properties index 4e7e8e798f..716ac5c50a 100644 --- a/core/assets/bundles/bundle_pl.properties +++ b/core/assets/bundles/bundle_pl.properties @@ -23,6 +23,7 @@ stat.delivered = Surowce wystrzelone: 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 = Jesteś pewny, że chcesz usunąć "[accent]{0}[]"? level.highscore = Rekord: [accent]{0} level.select = Wybrany poziom @@ -39,6 +40,7 @@ addplayers = Dodaj/Usuń graczy customgame = Własna Gra newgame = Nowa Gra none = <żadne> +minimap = Minimap close = Zamknij quit = Wyjdź maps = Mapy @@ -181,6 +183,7 @@ map.delete.confirm = Jesteś pewny, że chcesz usunąć tę mapę? Nie będzie m map.random = [accent]Losowa mapa map.nospawn = Ta mapa nie zawiera żadnego rdzenia! Musisz dodać [ROYAL]niebieski[] rdzeń do tej mapy. map.nospawn.pvp = Ta mapa nie ma żadnego rdzenia przeciwnika, aby mogli się zrespić przeciwnicy! Dodaj[SCARLET] czerwony[] rdzeń do mapy w edytorze. +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 podczas ładowania mapy: uszkodzony lub niepoprawny plik mapy. editor.brush = Pędzel editor.openin = Otwórz w edytorze @@ -282,6 +285,7 @@ abandon = Opuść abandon.text = Ta strefa i wszystkie jej surowce będą przejęte przez przeciwników. locked = Zablokowane complete = [LIGHT_GRAY]Ukończone: +zone.requirement = Wave {0} in zone {1} resume = Kontynuuj Strefę:\n[LIGHT_GRAY]{0} bestwave = [LIGHT_GRAY]Najwyższa fala: {0} launch = Wystrzel @@ -293,7 +297,7 @@ uncover = Uncover configure = Configure Loadout configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. zone.unlocked = [LIGHT_GRAY] Strefa {0} odblokowana! -zone.complete = Zone conditions met. +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... @@ -332,63 +336,59 @@ no = Nie ma mowy! info.title = [accent]Informacje error.title = [crimson]Wystąpił błąd error.crashtitle = Wystąpił błąd -blocks.outputspeed = Drill Speed: {0}/s -blocks.efficiency = Efficiency: {0}% -blocks.unknown = [LIGHT_GRAY]??? -blocks.blockinfo = Informacje o bloku -blocks.powerbalance = Power: {0} -blocks.poweroutput = Power Output: {0} +blocks.input = Input +blocks.output = Output +blocks.booster = Booster +block.unknown = [LIGHT_GRAY]??? blocks.powercapacity = Pojemność mocy blocks.powershot = moc/strzał blocks.targetsair = Może namierzać wrogów powietrznych blocks.targetsground = Targets Ground -blocks.items = Items: {0} blocks.itemsmoved = Move Speed +blocks.launchtime = Time Between Launches blocks.shootrange = Zasięg blocks.size = Rozmiar blocks.liquidcapacity = Pojemność cieczy -blocks.maxitemssecond = Maksymalna liczba przedmiotów/sekundę blocks.powerrange = Zakres mocy blocks.poweruse = Zużycie prądu blocks.powerdamage = Moc/Zniszczenia -blocks.inputitemcapacity = Pojemność materiałów -blocks.outputitemcapacity = Pojemność produktów blocks.itemcapacity = Pojemność przedmiotów blocks.basepowergeneration = Base Power Generation -blocks.powertransferspeed = Szybość przesyłu prądu -blocks.craftspeed = Szybkość produkcji -blocks.inputliquid = Potrzebna ciecz -blocks.inputliquidaux = Płyny do produkcji -blocks.inputitem = Potrzebne przedmioty -blocks.inputitems = Materiały do produkcji -blocks.outputitem = Produkty +blocks.productiontime = Production Time +blocks.repairtime = Block Full Repair Time +blocks.speedincrease = Speed Increase +blocks.range = Range blocks.drilltier = Co może wykopać blocks.drillspeed = Postawowa szybkość kopania +blocks.boosteffect = Boost Effect blocks.maxunits = Max Active Units -blocks.liquidoutput = Wyprodukowany płyn -blocks.liquidoutputspeed = Prędkość odpływu cieczy -blocks.liquiduse = Zużycie płynów -blocks.coolant = Płyn chłodzący -blocks.liquid = Płyn -blocks.coolantuse = Zużycie płynu chłodzącego -blocks.inputliquidfuel = Paliwo -blocks.liquidfueluse = Zużycie paliwa -blocks.boostitem = Boost Item -blocks.boostliquid = Boost Liquid blocks.health = Zdrowie -blocks.heat = Heat -blocks.power = Prąd -blocks.progress = Build Progress -blocks.spawned = Units: {0}/{1} -blocks.power.satisfaction = Zapotrzebowanie Prądu blocks.inaccuracy = Niedokładność blocks.shots = Strzały blocks.reload = Przeładowanie -blocks.inputfuel = Paliwo -blocks.fuelburntime = Płonięcie paliwa -blocks.inputcapacity = Pojemność wejściowa -blocks.outputcapacity = Wydajność wyjściowa 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 = Płyn +bar.heat = Heat +bar.power = Prąd +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 +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 = Klocki unit.powersecond = jednostek prądu na sekundę unit.liquidsecond = jednostek płynów na sekundę @@ -397,6 +397,9 @@ unit.liquidunits = jednostek płynów unit.powerunits = jednostek prądu unit.degrees = stopnie unit.seconds = sekundy +unit.persecond = /sec +unit.timesspeed = x speed +unit.percent = % unit.items = Przedmioty category.general = Główne category.power = Prąd @@ -405,7 +408,11 @@ category.items = Przedmioty category.crafting = Przetwórstwo category.shooting = Strzelanie category.optional = Ulepszenia Nieobowiąskowe +setting.landscape.name = Lock Landscape +setting.shadows.name = Shadows setting.animatedwater.name = Animated Water +setting.animatedshields.name = Animated Shields +setting.antialias.name = Antialias[LIGHT_GRAY] (requires restart)[] setting.indicators.name = Wskaźniki Przyjaciół setting.autotarget.name = Automatyczne Celowanie setting.fpscap.name = Maksymalny FPS @@ -424,9 +431,11 @@ setting.sensitivity.name = Czułość kontrolera setting.saveinterval.name = Interwał automatycznego zapisywania setting.seconds = Sekundy setting.fullscreen.name = Pełny ekran +setting.borderless.name = Borderless Window setting.fps.name = Widoczny licznik FPS setting.vsync.name = Synchronizacja pionowa setting.lasers.name = Pokaż lasery zasilające +setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance) setting.minimap.name = Pokaż Minimapę setting.musicvol.name = Głośność muzyki setting.mutemusic.name = Wycisz muzykę @@ -479,6 +488,21 @@ mode.pvp.name = PvP mode.pvp.description = Walcz przeciwko innym graczom. mode.attack.name = Atak 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.pvp = PvP +rules.unitdrops = Unit Drops +rules.unitbuildspeedmultiplier = Unit Creation Speed Multiplier +rules.unithealthmultiplier = Unit Health Multiplier +rules.playerdamagemultiplier = Player 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 content.item.name = Przedmioty content.liquid.name = Płyny content.unit.name = Jednostki @@ -559,6 +583,7 @@ mech.itemcapacity = [LIGHT_GRAY]Pojemność przedmiotów: {0} mech.minespeed = [LIGHT_GRAY]Prędkość kopania: {0} mech.minepower = [LIGHT_GRAY]Moc kopania: {0} mech.ability = [LIGHT_GRAY]Umiejętność: {0} +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} @@ -590,13 +615,17 @@ block.core-foundation.name = Rdzeń: Podstawa block.core-nucleus.name = Core: Nucleus block.deepwater.name = Głęboka Woda block.water.name = Woda +block.tainted-water.name = Tainted Water +block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Smoła block.stone.name = Kamień block.sand.name = Piasek +block.darksand.name = Dark Sand block.ice.name = Lód block.snow.name = Śnieg 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 @@ -628,6 +657,7 @@ block.thorium-wall-large.name = Duża Torowa Ściana block.door.name = Drzwi block.door-large.name = Duże drzwi block.duo.name = Podwójne działko +block.scorch.name = Scorch block.scatter.name = Scatter block.hail.name = Święte działko block.lancer.name = Lancer @@ -713,6 +743,7 @@ block.blast-drill.name = Wiertło Wybuchowe block.thermal-pump.name = Pompa Termalna block.thermal-generator.name = Generator Termalny block.alloy-smelter.name = Piec Mieszający +block.mender.name = Mender block.mend-projector.name = Projektor Napraw block.surge-wall.name = Ściana Stopu Energetycznego block.surge-wall-large.name = Duża Ściana Stopu Energetycznego @@ -728,6 +759,7 @@ block.meltdown.name = Meltdown block.container.name = Kontener block.launch-pad.name = Skocznia 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 = niebieski team.red.name = czerwony team.orange.name = pomarańczowy diff --git a/core/assets/bundles/bundle_pt_BR.properties b/core/assets/bundles/bundle_pt_BR.properties index 49da1b3a45..a36696def4 100644 --- a/core/assets/bundles/bundle_pt_BR.properties +++ b/core/assets/bundles/bundle_pt_BR.properties @@ -10,28 +10,29 @@ link.itch.io.description = Pagina da Itch.io com os Downloads 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 saved to {0} +screenshot = Screenshot salvo para {0} gameover = O núcleo foi destruído. gameover.pvp = O time[accent] {0}[] É vitorioso! highscore = [YELLOW]Novo recorde! -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. +stat.wave = Ondas 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} +stat.deconstructed = Construções desconstruídas:[accent] {0} +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 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]LEAVE DROP POINT IMMEDIATELY[] ]\nannihilation imminent -outofbounds = [[ OUT OF BOUNDS ]\n[]self-destruct in {0} -database = Core Database +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 loadgame = Carregar Jogo joingame = Entrar no Jogo @@ -39,21 +40,22 @@ addplayers = Adicionar/Remover Jogador customgame = Jogo Customizado newgame = Novo Jogo none = +minimap = Minimap close = Fechar quit = Sair maps = Mapas -continue = Continue +continue = Continuar maps.none = [LIGHT_GRAY]Nenhum Mapa Encontrado! about.button = Sobre name = Nome: -noname = Pick a[accent] player name[] first. +noname = Pegue[accent] um nome[] primeiro. filename = Nome do arquivo: unlocked = Novo bloco Desbloqueado! -completed = [accent]Completed -techtree = Tech Tree -research.list = [LIGHT_GRAY]Research: -research = Research -researched = [LIGHT_GRAY]{0} researched. +completed = [accent]Completado +techtree = Árvore de tecnologia +research.list = [LIGHT_GRAY]Pesquise: +research = Pesquisa +researched = [LIGHT_GRAY]{0} pesquisado. players = {0} Jogadores Ativos players.single = {0} Jogador Ativo server.closing = [accent]Fechando servidor... @@ -67,7 +69,7 @@ server.kicked.nameInUse = Este nome ja esta sendo usado\nneste servidor. server.kicked.nameEmpty = Voce deve ter pelo menos uma letra ou numero. server.kicked.idInUse = Voce ja esta neste servidor! Conectar com duas contas não é permitido. server.kicked.customClient = Este servidor não suporta construções customizadas. Baixe a versão original. -server.kicked.gameover = Game over! +server.kicked.gameover = Fim de jogo! host.info = The [accent]Hospedar[]Botão Hopeda um servidor no Host[scarlet]6567[] e [scarlet]6568.[]\nQualquer um no [LIGHT_GRAY]Wi-fi Ou Internet local[] Pode ver este servidor na lista de servidores.\n\nSe voce quer poder entrar em qualquer servidor em seu ip, [accent]port forwarding[] é requerido.\n\n[LIGHT_GRAY]Note: Se alguem esta com problemas em conectar no seu servidor lan, Tenha certeza que deixou mindustry Acessar sua internet local nas configurações de firewall join.info = Aqui, Você pode entar em um [accent]IP De servidor[] Para conectar, Ou descobrir [accent]Servidores[] Da rede local.\nAmbos os servidores LAN e WAN São suportados.\n\n[LIGHT_GRAY]Note: Não tem uma lista de servidores automaticos; Se você quer conectar ao IP de alguem, Você precisa pedir o IP Ao Rosteador. hostserver = Hospedar servidor @@ -157,11 +159,11 @@ openlink = Abrir Link copylink = Copiar link back = Voltar quit.confirm = Você tem certeza que quer sair? -changelog.title = Changelog -changelog.loading = Coletando changelog... -changelog.error.android = [accent]Note que a Changelog as vezes Funciona no android 4.4 e abaixo!\nIsso é por causa de um erro interno no sistema android. -changelog.error.ios = [accent]A changelog não é suportada no IOS. -changelog.error = [scarlet]Erro ao coletar Changelog!\nCheque a Conexão com a internet. +changelog.title = registro de Mudanças +changelog.loading = Coletando o registro... +changelog.error.android = [accent]Note que o registro as vezes Funciona no android 4.4 e abaixo!\nIsso é por causa de um erro interno no sistema android. +changelog.error.ios = [accent]A registro não é suportada no IOS. +changelog.error = [scarlet]Erro ao coletar o registro!\nCheque a Conexão com a internet. changelog.current = [yellow][[Primeira versão] changelog.latest = [accent][[Ultima versão] loading = [accent]Carregando... @@ -169,9 +171,9 @@ saving = [accent]Salvando... wave = [accent]Horda {0} wave.waiting = Horda em {0} waiting = Aguardando... -waiting.players = Waiting for players... -wave.enemies = [LIGHT_GRAY]{0} Enemies Remaining -wave.enemy = [LIGHT_GRAY]{0} Enemy Remaining +waiting.players = Esperando por jogadores... +wave.enemies = [LIGHT_GRAY]{0} Enimigos Restantes +wave.enemy = [LIGHT_GRAY]{0} Enimigo Restante loadimage = Carregar\nImagem saveimage = Salvar\nImagem unknown = Desconhecido @@ -181,6 +183,7 @@ map.delete.confirm = Certeza que quer deletar este mapa? Isto não pode ser desf map.random = [accent]Mapa aleatório map.nospawn = Esse mapa não contém um [yellow]núcleo[] para o jogador Nascer! [ROYAL]blue[] Coloque um [yellow]núcleo[] no editor de mapa. map.nospawn.pvp = Esse mapa não tem núcleos inimigos para os jogadores nascerem! Adicione[SCARLET] Núcleos vermelhos[] no mapa no 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 = Erro ao carregar o mapa: Arquivo de mapa invalido ou corrupto. editor.brush = Pincel editor.openin = Abrir no Editor @@ -189,32 +192,32 @@ editor.oregen.info = Geração de minério: editor.mapinfo = Informação do mapa editor.author = Autor: editor.description = Descrição: -editor.waves = Waves: -waves.title = Waves -waves.remove = Remove -waves.never = -waves.every = every -waves.waves = wave(s) -waves.perspawn = per spawn -waves.to = to +editor.waves = Ondas: +waves.title = Ondas +waves.remove = Remover +waves.never = +waves.every = a casa +waves.waves = ondas(s) +waves.perspawn = por spawn +waves.to = para 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... +waves.preview = Prever +waves.edit = Editar... +waves.copy = Copiar para área de transferência +waves.load = carregar da área de transferência +waves.invalid = Ondas inválidas na área de transferência. +waves.copied = Ondas copiadas. +editor.default = [LIGHT_GRAY] +edit = Editar... editor.name = Nome: editor.teams = Time editor.elevation = Elevação -editor.errorload = Error loading file:\n[accent]{0} -editor.errorsave = Error saving file:\n[accent]{0} -editor.errorname = Map has no name defined. -editor.update = Update -editor.randomize = Randomize -editor.apply = Apply +editor.errorload = Erro carregando arquivo:\n[accent]{0} +editor.errorsave = Erro salvando arquivo:\n[accent]{0} +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 @@ -243,26 +246,26 @@ editor.mapname = Nome do Mapa: editor.overwrite = [accent]Aviso!\nIsso Subistitui um mapa existente. editor.overwrite.confirm = [scarlet]Aviso![] Um mapa com esse nome já existe. Tem certeza que deseja substituir? editor.selectmap = Selecione uma mapa para carregar: -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 +filters.empty = [LIGHT_GRAY]Sem filtro! Adicione um usando o botão abaixo. +filter.distort = Distorcer +filter.noise = Ruído +filter.ore = Minério +filter.rivernoise = Ruído para rios filter.scatter = Scatter -filter.terrain = Terrain -filter.option.scale = Scale +filter.terrain = Terreno +filter.option.scale = Escala filter.option.chance = Chance filter.option.mag = Magnitude -filter.option.threshold = Threshold -filter.option.circle-scale = Circle Scale -filter.option.octaves = Octaves +filter.option.threshold = Margem +filter.option.circle-scale = Escala de círculo +filter.option.octaves = Oitavas 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 +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.threshold2 = Margem secundária width = Largura: height = Altura: menu = Menu @@ -279,21 +282,22 @@ editor = Editor mapeditor = Editor de mapa donate = Doar abandon = Abandonar -abandon.text = This zone and all its resources will be lost to the enemy. +abandon.text = Esta zona e todos os seus recursos serão perdidos para o enimigo. locked = Trancado complete = [LIGHT_GRAY]Complete: -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. +zone.requirement = Wave {0} in zone {1} +resume = Resumir Zona:\n[LIGHT_GRAY]{0} +bestwave = [LIGHT_GRAY]Melhor: {0} +launch = Lançar +launch.title = Lançamento feito com sucesso +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 = Uncover configure = Configure Loadout configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. zone.unlocked = [LIGHT_GRAY]{0} unlocked. -zone.complete = Zone conditions met. +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... @@ -332,63 +336,59 @@ no = Não info.title = [accent]Informação error.title = [crimson]Ocorreu um Erro. error.crashtitle = Ocorreu um Erro -blocks.outputspeed = Drill Speed: {0}/s -blocks.efficiency = Efficiency: {0}% -blocks.unknown = [LIGHT_GRAY]??? -blocks.blockinfo = Informação do Bloco -blocks.powerbalance = Power: {0} -blocks.poweroutput = Power Output: {0} +blocks.input = Input +blocks.output = Output +blocks.booster = Booster +block.unknown = [LIGHT_GRAY]??? blocks.powercapacity = Capacidade de Energia blocks.powershot = Energia/tiro blocks.targetsair = Mirar no ar blocks.targetsground = Targets Ground -blocks.items = Items: {0} blocks.itemsmoved = Move Speed +blocks.launchtime = Time Between Launches blocks.shootrange = Alcance blocks.size = Tamanho blocks.liquidcapacity = Capacidade de Líquido -blocks.maxitemssecond = Máximo de itens/segundo blocks.powerrange = Alcance da Energia blocks.poweruse = Uso de energia blocks.powerdamage = Dano/Poder -blocks.inputitemcapacity = Configurar capacidade de itens -blocks.outputitemcapacity = Configurar capacidade de itens blocks.itemcapacity = Capacidade de Itens blocks.basepowergeneration = Geração de poder base -blocks.powertransferspeed = Transferência de energia -blocks.craftspeed = Velocidade de produção -blocks.inputliquid = Líquido de entrada -blocks.inputliquidaux = Líquido auxiliar -blocks.inputitem = Item de entrada -blocks.inputitems = Itens de entrada -blocks.outputitem = Itens de saida +blocks.productiontime = Production Time +blocks.repairtime = Block Full Repair Time +blocks.speedincrease = Speed Increase +blocks.range = Range blocks.drilltier = Furaveis blocks.drillspeed = Velocidade da furadeira base +blocks.boosteffect = Boost Effect blocks.maxunits = Max Active Units -blocks.liquidoutput = Saida de liquido -blocks.liquidoutputspeed = Velocidade da saida de líquido -blocks.liquiduse = Uso de liquido -blocks.coolant = Esfriador -blocks.liquid = Liquid -blocks.coolantuse = Uso do esfriador -blocks.inputliquidfuel = Liquido de combustivel -blocks.liquidfueluse = Uso do liquido de combustivel -blocks.boostitem = Acelerar item -blocks.boostliquid = Acelerar líquido blocks.health = Saúde -blocks.heat = Heat -blocks.power = Poder -blocks.progress = Build Progress -blocks.spawned = Units: {0}/{1} -blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = Imprecisão blocks.shots = Tiros blocks.reload = Recarregar -blocks.inputfuel = Combustivel -blocks.fuelburntime = Tempo de queima de combustivel -blocks.inputcapacity = Capacidade de entrada -blocks.outputcapacity = Capacidade de saída 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 = Poder +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 +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 = blocos unit.powersecond = Unidades de energia/segundo unit.liquidsecond = Unidades de líquido/segundo @@ -397,6 +397,9 @@ unit.liquidunits = Unidades de liquido unit.powerunits = Unidades de energia unit.degrees = Graus unit.seconds = segundos +unit.persecond = /sec +unit.timesspeed = x speed +unit.percent = % unit.items = itens category.general = Geral category.power = Poder @@ -405,7 +408,11 @@ category.items = Itens category.crafting = Construindo category.shooting = Atirando category.optional = Melhoras opcionais +setting.landscape.name = Lock Landscape +setting.shadows.name = Shadows setting.animatedwater.name = Animated Water +setting.animatedshields.name = Animated Shields +setting.antialias.name = Antialias[LIGHT_GRAY] (requires restart)[] setting.indicators.name = Ally Indicators setting.autotarget.name = Alvo automatico setting.fpscap.name = FPS Maximo @@ -424,9 +431,11 @@ setting.sensitivity.name = Sensibilidade do Controle setting.saveinterval.name = Intervalo de autosalvamento setting.seconds = {0} Segundos setting.fullscreen.name = Tela Cheia +setting.borderless.name = Borderless Window setting.fps.name = Mostrar FPS setting.vsync.name = VSync setting.lasers.name = Mostrar lasers +setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance) setting.minimap.name = Mostrar minimapa setting.musicvol.name = Volume da Música setting.mutemusic.name = Desligar Música @@ -479,6 +488,21 @@ mode.pvp.name = PvP mode.pvp.description = Lutar contra outros jogadores locais. mode.attack.name = Ataque 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.pvp = PvP +rules.unitdrops = Unit Drops +rules.unitbuildspeedmultiplier = Unit Creation Speed Multiplier +rules.unithealthmultiplier = Unit Health Multiplier +rules.playerdamagemultiplier = Player 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 content.item.name = Itens content.liquid.name = Liquidos content.unit.name = Units @@ -559,6 +583,7 @@ 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} mech.ability = [LIGHT_GRAY]Habilidade: {0} +mech.buildspeed = [LIGHT_GRAY]Building Speed: {0}% liquid.heatcapacity = [LIGHT_GRAY]Capacidade de aquecimento: {0} liquid.viscosity = [LIGHT_GRAY]Viscosidade: {0} liquid.temperature = [LIGHT_GRAY]Temperatura: {0} @@ -590,13 +615,17 @@ block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus block.deepwater.name = água funda block.water.name = Água +block.tainted-water.name = Tainted Water +block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Tar block.stone.name = Pedra block.sand.name = Areia +block.darksand.name = Dark Sand block.ice.name = Gelo block.snow.name = Neve 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 @@ -628,6 +657,7 @@ block.thorium-wall-large.name = Parede larga de tório block.door.name = Porta block.door-large.name = Porta Grande block.duo.name = Dupla +block.scorch.name = Scorch block.scatter.name = Scatter block.hail.name = Hail block.lancer.name = Lancador @@ -713,6 +743,7 @@ block.blast-drill.name = Mineradora de Explosão block.thermal-pump.name = Cano termico block.thermal-generator.name = Gerador Térmico block.alloy-smelter.name = Fundidora de Liga +block.mender.name = Mender block.mend-projector.name = Projetor Mend block.surge-wall.name = Parede de Surge block.surge-wall-large.name = Parede de Surge grande @@ -728,6 +759,7 @@ 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 team.blue.name = Azul team.red.name = Vermelho team.orange.name = Laranja diff --git a/core/assets/bundles/bundle_ru.properties b/core/assets/bundles/bundle_ru.properties index 7d7e362293..52c7140c4f 100644 --- a/core/assets/bundles/bundle_ru.properties +++ b/core/assets/bundles/bundle_ru.properties @@ -21,8 +21,9 @@ stat.destroyed = Строений уничтожено:[accent] {0} stat.deconstructed = Строений деконструировано:[accent] {0} stat.delivered = Ресурсов добыто: stat.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. +placeline = Вы выбрали блок.\nВы можете[accent] строить в линию[], сначала[accent] удерживая палец в течение нескольких секунд[] и потом перетаскивая его.\n\n[scarlet]СДЕЛАЙ ЭТО. +removearea = Вы выбрали режим удаления.\nВы можете[accent] удалять блоки в выбранной области[], [accent]удерживая палец несколько секунд[] и потом перетаскивая его.\n\n[scarlet]СДЕЛАЙ ЭТО +launcheditems = [accent]Запущенные предметы map.delete = Вы действительно хотите удалить карту "[accent]{0}[]"? level.highscore = Рекорд: [accent]{0} level.select = Выбор карты @@ -39,6 +40,7 @@ addplayers = Доб/удалить игроков customgame = Пользовательская игра newgame = Новая игра none = <нет> +minimap = Minimap close = Закрыть quit = Выход maps = Карты @@ -181,6 +183,7 @@ map.delete.confirm = Вы действительно хотите удалить map.random = [accent]Случайная карта map.nospawn = Эта карта не имеет ядер, в которых игрок может появиться! Добавьте[ROYAL] синее[] ядро на эту карту в редакторе карт. map.nospawn.pvp = У этой карты нет вражеских ядер, в которых игрок может появиться! Добавьте[SCARLET] красные[] ядра к этой карте в редакторе. +map.nospawn.attack = У этой карты нету вражеских ядер! Добавьте [scarlet] красные[] ядра в эту карте в редакторе. map.invalid = Ошибка загрузки карты: повреждённый или недопустимый файл карты. editor.brush = Кисть editor.openin = Открыть в редакторе @@ -189,33 +192,33 @@ editor.oregen.info = Генерация Руд: editor.mapinfo = Информация о карте editor.author = Автор: editor.description = Описание: -editor.waves = Waves: -waves.title = Waves -waves.remove = Remove -waves.never = -waves.every = every -waves.waves = wave(s) -waves.perspawn = per spawn -waves.to = to -waves.boss = Boss -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.waves = Волны: +waves.title = Волны +waves.remove = Удалить +waves.never = <никогда> +waves.every = Каждый +waves.waves = волна(ы) +waves.perspawn = за появление +waves.to = к +waves.boss = Босс +waves.preview = Предварительный просмотр +waves.edit = Редактировать ... +waves.copy = Копировать в буфер обмена +waves.load = Загрузить из буфера обмена +waves.invalid = Неверные волны в буфере обмена. +waves.copied = Волны скопированы. +editor.default = [LIGHT_GRAY]<По умолчанию> +edit = Редактировать... editor.name = Название: editor.teams = Команды editor.elevation = Возвышенность -editor.errorload = Error loading file:\n[accent]{0} -editor.errorsave = Error saving file:\n[accent]{0} -editor.errorname = Map has no name defined. -editor.update = Update -editor.randomize = Randomize -editor.apply = Apply -editor.generate = Создать +editor.errorload = Ошибка загрузки изображения: [accent] {0} +editor.errorsave = Ошибка сохранения изображения: [accent] {0} +editor.errorname = Карта не имеет определенного имени. +editor.update = Обновить +editor.randomize = Случайно +editor.apply = Применить +editor.generate = Сгенерировать editor.resize = Изменить \nразмер editor.loadmap = Загрузить\nкарту editor.savemap = Сохранить\nкарту @@ -243,26 +246,26 @@ editor.mapname = Название карты: editor.overwrite = [accent]Внимание! \nЭто перезапишет уже существующую карту. editor.overwrite.confirm = [scarlet]Осторожно![] Карта с таким названием уже существует. Вы действительно хотите её перезаписать? editor.selectmap = Выберите карту для загрузки: -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 +filters.empty = [LIGHT_GRAY]Нет фильтров. Добавьте один при помощи кнопки ниже +filter.distort = Искажение +filter.noise = Шум +filter.ore = Руда +filter.rivernoise = Речной Шум +filter.scatter = Распылитель +filter.terrain = Ландшафт +filter.option.scale = Масштаб +filter.option.chance = Шанс +filter.option.mag = Величина +filter.option.threshold = Спад +filter.option.circle-scale = Круговая шкала +filter.option.octaves = Октавы +filter.option.falloff = Спад +filter.option.block = Блок +filter.option.floor = Поверхность +filter.option.wall = Стена +filter.option.ore = Руда +filter.option.floor2 = Вторая поверхность +filter.option.threshold2 = Вторичный спад width = Ширина: height = Высота: menu = Меню @@ -282,6 +285,7 @@ abandon = Покинуть abandon.text = Эта зона и все ресурсы будут потеряны. locked = Заблокировано complete = [LIGHT_GRAY]Завершено: +zone.requirement = Wave {0} in zone {1} resume = Возобновить зону:\n[LIGHT_GRAY]{0} bestwave = [LIGHT_GRAY]Наилучшая волна: {0} launch = < ЗАПУСК > @@ -293,7 +297,7 @@ uncover = Раскрыть configure = Выгрузить конфигурацию configure.locked = [LIGHT_GRAY]Разблокировать настройки выгрузки:\nВолна {0}. zone.unlocked = [LIGHT_GRAY]{0} разблокировано. -zone.complete = {0} волн достигнуто:\nНовые требования зоны выполнены. +zone.requirement.complete = Wave {0} reached:\n{1} zone requirements met. zone.config.complete = {0} волн достигнуто:\nВыгружаемая конфигурация разблокирована zone.resources = Обнаруженные ресурсы: add = Добавить... @@ -332,63 +336,61 @@ no = Нет info.title = Информация error.title = [crimson]Произошла ошибка error.crashtitle = Произошла ошибка -blocks.outputspeed = Drill Speed: {0}/s -blocks.efficiency = Efficiency: {0}% -blocks.unknown = [LIGHT_GRAY]??? -blocks.blockinfo = Информация о блоке -blocks.powerbalance = Энергия: {0} -blocks.poweroutput = Выходная энергия: {0} +blocks.input = Вход +blocks.output = Выход +blocks.booster = Ускоритель +block.unknown = [LIGHT_GRAY]??? blocks.powercapacity = Вместимость энергии blocks.powershot = Энергия/выстрел -blocks.targetsair = Атакует воздуш. юнитов -blocks.targetsground = Targets Ground -blocks.items = Items: {0} +blocks.targetsair = Воздушные цели +blocks.targetsground = Наземные цели blocks.itemsmoved = Скорость перемещения +blocks.launchtime = Интервал запусков blocks.shootrange = Радиус действия blocks.size = Размер blocks.liquidcapacity = Вместимость жидкости -blocks.maxitemssecond = Макс. количество предметов/секунду blocks.powerrange = Диапазон передачи энергии blocks.poweruse = Потребляет энергии blocks.powerdamage = Энергия/урон -blocks.inputitemcapacity = Вместимость входящих предметов -blocks.outputitemcapacity = Вместимость выходящих предметов blocks.itemcapacity = Вместимость предметов blocks.basepowergeneration = Базовая генерация энергии -blocks.powertransferspeed = Скорость передачи энергии +blocks.productiontime = Время производства blocks.craftspeed = Скорость производства +blocks.repairtime = Время полной регенерации +blocks.speedincrease = Увеличение скорости +blocks.range = Радиус действия blocks.inputliquid = Прием жидкости -blocks.inputliquidaux = Вспом. жидкость -blocks.inputitem = Входящий предмет -blocks.inputitems = Входящие предметы -blocks.outputitem = Выходящий предмет blocks.drilltier = Добывает blocks.drillspeed = Базовая скорость сверления -blocks.maxunits = Max Active Units -blocks.liquidoutput = Выходящая жидкость -blocks.liquidoutputspeed = Выходная скорость жидкости -blocks.liquiduse = Используется жидкости -blocks.coolant = Охлаждающая жидкость -blocks.liquid = Жидкость -blocks.coolantuse = Охлажд. жидкости используется -blocks.inputliquidfuel = Жидкое топливо -blocks.liquidfueluse = Жидкого топлива используется -blocks.boostitem = Ускоряющий предмет -blocks.boostliquid = Ускоряющая жидкость +blocks.boosteffect = Ускоряющий эффект +blocks.maxunits = Максимальное количество активных единиц blocks.health = Здоровье -blocks.heat = Heat -blocks.power = Энергия -blocks.progress = Build Progress -blocks.spawned = Units: {0}/{1} -blocks.power.satisfaction = Энергии хватает blocks.inaccuracy = Разброс blocks.shots = Выстрелы blocks.reload = Выстрелы/секунду -blocks.inputfuel = Входящее топливо -blocks.fuelburntime = Время горения топлива -blocks.inputcapacity = Макс. вместимость входящих предметов -blocks.outputcapacity = Макс. вместимость выходящих предметов blocks.ammo = Боеприпасы +bar.drillspeed = Скорость свердления: {0}/s +bar.efficiency = Эффективность: {0}% +bar.powerbalance = Энергия: {0}/с +bar.poweramount = Энергия: {0} +bar.poweroutput = Выходная энергия: {0} +bar.items = Предметы: {0} +bar.liquid = Жидкости +bar.heat = Нагревание +bar.power = Энергия +bar.progress = Прогресс Строительство +bar.spawned = Боев. ед. : {0}/{1} +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]x снарядов +bullet.reload = [stat]{0}[lightgray]x скорость перезарядки unit.blocks = блоки unit.powersecond = единиц энергии/секунду unit.liquidsecond = жидкостных единиц/секунду @@ -397,21 +399,29 @@ unit.liquidunits = жидкостных единиц unit.powerunits = энерг. единиц unit.degrees = град. unit.seconds = сек. +unit.persecond = /сек +unit.timesspeed = x скорость +unit.percent = % unit.items = единиц category.general = Основные category.power = Энергия category.liquids = Жидкости category.items = Предметы -category.crafting = Создание +category.crafting = Ввод/вывод category.shooting = Cтрельба category.optional = Дополнительные улучшения -setting.animatedwater.name = Animated Water -setting.indicators.name = Показывать в сторону союзников -setting.autotarget.name = Авто-цель +setting.landscape.name = Сохранить ландшафт +setting.shadows.name = Тени +setting.animatedwater.name = Анимированная вода +setting.animatedshields.name = Анимированные щиты +setting.antialias.name = Сглаживание[LIGHT_GRAY] (требует перезапуска)[] +setting.indicators.name = Показывать в сторону союзников и врагов +setting.autotarget.name = Авто-стрельба setting.fpscap.name = Макс. FPS setting.fpscap.none = Неограниченный +minimap = Мини-карта setting.fpscap.text = {0} FPS -setting.swapdiagonal.name = Always Diagonal Placement +setting.swapdiagonal.name = Всегда Диагональное Размещение setting.difficulty.training = обучение setting.difficulty.easy = легко setting.difficulty.normal = нормально @@ -424,6 +434,7 @@ setting.sensitivity.name = Чувствительность контроллер setting.saveinterval.name = Интервал автосохранения setting.seconds = {0} Секунд setting.fullscreen.name = Полноэкранный режим +setting.borderless.name = Окно без границ setting.fps.name = Показывать FPS setting.vsync.name = Верт. синхронизация setting.lasers.name = Показывать энергию лазеров @@ -448,7 +459,7 @@ keybind.screenshot.name = Скриншот карты keybind.move_x.name = Движение по оси x keybind.move_y.name = Движение по оси y keybind.select.name = Выбор/Выстрел -keybind.diagonal_placement.name = Diagonal Placement +keybind.diagonal_placement.name = Диагональное Размещение keybind.pick.name = Выбрать блок keybind.break_block.name = Разрушить блок keybind.deselect.name = Отмена @@ -475,10 +486,25 @@ mode.sandbox.name = Песочница mode.sandbox.description = Бесконечные ресурсы и нет таймера для волн, но можно самим вызвать волну. mode.freebuild.name = Cвободная\nстройка mode.freebuild.description = Ограниченные ресурсы и нет таймера для волн. -mode.pvp.name = Противо-\nстояние +mode.pvp.name = PvP mode.pvp.description = боритесь против других игроков. mode.attack.name = Атака mode.attack.description = Нет волн, цель - уничтожить базу противника. +mode.custom = Настройки правил +rules.infiniteresources = Бескон. Ресурсы (Игрок) +rules.wavetimer = Интервал волн +rules.waves = Волны +rules.enemyCheat = Бескон. Ресурсы (ИИ) +rules.pvp = PvP +rules.unitdrops = Ресурсы Боев. Ед. +rules.unitbuildspeedmultiplier = Множитель Скорости Создания Боев. Ед. +rules.unithealthmultiplier = Множитель Здоровья Боев. Ед. +rules.playerdamagemultiplier = Множитель Урона Игрока +rules.enemycorebuildradius = Радиус защиты враж. ядер: [LIGHT_GRAY] {0} (блоков) +rules.respawntime = Интервал возрождения: [LIGHT_GRAY] (сек) +rules.wavespacing = Интервал волн: [LIGHT_GRAY] (sec) +rules.buildcostmultiplier = Множитель затрат на строительство +rules.buildspeedmultiplier = Множитель скорости строительства content.item.name = Предметы content.liquid.name = Жидкости content.unit.name = Боевые единицы @@ -503,11 +529,11 @@ item.phase-fabric.name = Фазовая ткань item.phase-fabric.description = Невесомое вещество, используемое в современной электронике и технологии самовосстановления. Не для вышивания. item.surge-alloy.name = Кинетический сплав item.surge-alloy.description = Передовой сплав с уникальными электрическими свойствами. -item.spore-pod.name = Spore Pod -item.spore-pod.description = Used for conversion into oil, explosives and fuel. +item.spore-pod.name = Споровой стручок +item.spore-pod.description = Используется для превращения в нефть, взрывчатые вещества и топливо. item.sand.name = Песок item.sand.description = Обычный материал, который широко используется при плавке как в сплаве, так и в виде шлака. -item.blast-compound.name = Взрывоопасное соединение +item.blast-compound.name = Взрывная смесь item.blast-compound.description = Летучее соединение, используемое в бомбах и взрывчатых веществах. Также может гореть в качестве топлива, но не рекомендуется этого делать. item.pyratite.name = Пиротит item.pyratite.description = Очень огнеопасное вещество, используемое в зажигательном оружии. @@ -521,8 +547,8 @@ liquid.oil.name = Нефть liquid.cryofluid.name = Криогенная жидкость mech.alpha-mech.name = Альфа mech.alpha-mech.weapon = Тяжёлый пулемёт -mech.alpha-mech.ability = Призыв дронов -mech.alpha-mech.description = Стандартный мех для настольных устройств. Имеет приличную скорость и урон; может создать до 3-х дронов для увеличения возможности победы. +mech.alpha-mech.ability = Регенерация +mech.alpha-mech.description = Стандартный мех для настольных устройств. Имеет приличную скорость и урон. mech.delta-mech.name = Дельта mech.delta-mech.weapon = Дуговой генератор mech.delta-mech.ability = Разряд @@ -554,26 +580,27 @@ item.radioactivity = [LIGHT_GRAY]Радиоактивность: {0}% unit.health = [LIGHT_GRAY]Здоровье: {0} unit.speed = [LIGHT_GRAY]Скорость: {0} mech.weapon = [LIGHT_GRAY]Оружие: {0} -mech.health = [LIGHT_GRAY]Health: {0} +mech.health = [LIGHT_GRAY]Здоровье: {0} mech.itemcapacity = [LIGHT_GRAY]Вместимость предметов: {0} -mech.minespeed = [LIGHT_GRAY]Скорость добычи: {0} +mech.minespeed = [LIGHT_GRAY]Скорость добычи: {0}% mech.minepower = [LIGHT_GRAY]Мощность добычи: {0} mech.ability = [LIGHT_GRAY]Способность: {0} +mech.buildspeed = [LIGHT_GRAY]Скорость строительства: {0}% liquid.heatcapacity = [LIGHT_GRAY]Теплоёмкость: {0} liquid.viscosity = [LIGHT_GRAY]Вязкость: {0} liquid.temperature = [LIGHT_GRAY]Температура: {0} -block.grass.name = Grass -block.salt.name = Salt -block.sandrocks.name = Sand Rocks -block.spore-pine.name = Spore Pine -block.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.spore-moss.name = Spore Moss -block.shalerocks.name = Shale Rocks +block.grass.name = Трава +block.salt.name = Соль +block.sandrocks.name = Песчаные Скалы +block.spore-pine.name = Споровая сосна +block.sporerocks.name = Споровые камни +block.rock.name = Камень +block.snowrock.name = Снежный камень +block.shale.name = Сланец +block.shale-boulder.name = Сланцевый валун +block.moss.name = Мох +block.spore-moss.name = Споровый Мох +block.shalerocks.name = Сланцевые Породы block.scrap-wall.name = Стена из металлолома block.scrap-wall-large.name = Великая стена из металлолома block.scrap-wall-huge.name = Огромная стена из металлолома @@ -590,13 +617,17 @@ block.core-foundation.name = Ядро: Штаб block.core-nucleus.name = Ядро: Атом block.deepwater.name = Глубоководье block.water.name = Вода +block.tainted-water.name = Tainted Water +block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Дёготь block.stone.name = Камень -block.sand.name = Тёмный песок +block.sand.name = Песок +block.darksand.name = Тёмный песок block.ice.name = Лёд block.snow.name = Снег block.craters.name = Кратеры block.sand-water.name = Песок с водой +block.darksand-water.name = Тёмный песок с водой block.char.name = Выжженная Земля block.holostone.name = Голографический камень block.ice-snow.name = Ледяной Снег @@ -628,7 +659,8 @@ block.thorium-wall-large.name = Большая ториевая стена block.door.name = Дверь block.door-large.name = Большая дверь block.duo.name = Двойная турель -block.scatter.name = Scatter +block.scorch.name = Обжигатель +block.scatter.name = Рассеиватель block.hail.name = Град block.lancer.name = Копейщик block.conveyor.name = Конвейер @@ -646,7 +678,7 @@ block.pulverizer.name = Измельчитель block.cryofluidmixer.name = Мешалка для криогенной жидкости block.melter.name = Плавильня block.incinerator.name = Мусоросжигатель -block.spore-press.name = Spore Press +block.spore-press.name = Споровой Пресс block.separator.name = Отделитель block.power-node.name = Силовой узел block.power-node-large.name = Большой силовой узел @@ -660,15 +692,15 @@ block.impact-reactor.name = Импульсный реактор block.mechanical-drill.name = Механический бур block.pneumatic-drill.name = Пневматический бур block.laser-drill.name = Лазерный бур -block.water-extractor.name = Экстрактор воды +block.water-extractor.name = Гидроконденсатор block.cultivator.name = Культиватор block.alpha-dart-mech-pad.name = Реконструктор мехов "Альфа-Дротик" -block.delta-mech-pad.name = Delta Mech Pad -block.javelin-ship-pad.name = Реконструктор кораблей "Джавелин" -block.trident-ship-pad.name = Реконструктор кораблей "Трезубeц" -block.glaive-ship-pad.name = Реконструктор кораблей "Копьё" -block.omega-mech-pad.name = Реконструктор мехов "Омега" -block.tau-mech-pad.name = Реконструктор мехов "Тау" +block.delta-mech-pad.name = Реконструктор "Дельта" +block.javelin-ship-pad.name = Реконструктор "Джавелин" +block.trident-ship-pad.name = Реконструктор "Трезубeц" +block.glaive-ship-pad.name = Реконструктор "Копьё" +block.omega-mech-pad.name = Реконструктор "Омега" +block.tau-mech-pad.name = Реконструктор "Тау" block.conduit.name = Трубопровод block.mechanical-pump.name = Механическая помпа block.item-source.name = Источник предметов @@ -689,13 +721,13 @@ block.pyratite-mixer.name = Мешалка пиротита block.blast-mixer.name = Мешалка взрывоопасного соединения block.solar-panel.name = Солнечная панель block.solar-panel-large.name = Большая солнечная панель -block.oil-extractor.name = Нефтяной экстрактор +block.oil-extractor.name = Нефтяная вышка block.spirit-factory.name = Завод дронов "Призрак" block.phantom-factory.name = Завод дронов "Фантом" block.wraith-factory.name = Завод призрачных истребителей block.ghoul-factory.name = Завод бомбардировщиков "Гуль" block.dagger-factory.name = Завод мехов "Кинджал" -block.crawler-factory.name = Crawler Mech Factory +block.crawler-factory.name = Завод мехов "Камикадзе" block.titan-factory.name = Завод мехов "Титан" block.fortress-factory.name = Завод мехов "Крепость" block.revenant-factory.name = Завод бомбардировщиков "Потусторонний убийца" @@ -713,6 +745,7 @@ block.blast-drill.name = Воздушная буровая установка block.thermal-pump.name = Термальный насос block.thermal-generator.name = Термальный генератор block.alloy-smelter.name = Плавильня кинетического сплава +block.mender.name = Mender block.mend-projector.name = Ремонтирующий гранатомёт block.surge-wall.name = Стена из кинетического сплава block.surge-wall-large.name = Большая стена из кинетического сплава @@ -727,7 +760,8 @@ block.spectre.name = Призрак block.meltdown.name = Катастрофа block.container.name = Склад block.launch-pad.name = Стартовая площадка -block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. +block.launch-pad.description = Запускает партии предметов без необходимости запуска ядра. Незавершённое. +block.launch-pad-large.name = Большая Стартовая площадка team.blue.name = Синяя team.red.name = Красная team.orange.name = Оранжевая @@ -740,7 +774,7 @@ unit.phantom.name = Фантомный дрон unit.phantom.description = Продвинутый дрон. Автоматически добывает руды, собирает предметы, ремонтирует блоки. Значительнее эффективней нежели обычный дрон unit.dagger.name = Кинджал unit.dagger.description = Основная наземная боевая единица. Может быть полезен в группах. -unit.crawler.name = Crawler +unit.crawler.name = Камикадзе unit.titan.name = Титан unit.titan.description = Улучшенная бронированная наземная боевая единица. Атакует наземные и воздушные цели. unit.ghoul.name = Бомбардировщик "Гуль" @@ -763,8 +797,8 @@ tutorial.turret = Оборонительные сооружения должны tutorial.drillturret = Двойные турели требуют[accent] патронов из меди[] для стрельбы.\nРазместите бур рядом с турелью, чтобы снабдить её добытой медью. tutorial.waves = [LIGHT_GRAY]Враг[] приближается.\n\nЗащитите своё ядро от двух волн. Вам может понадобится больше турелей. tutorial.lead = Осмотритесь! Магическим образом появились новые руды. Добудьте [accent] свинец[].\n\nПеретащите ресурс из своего устройства(юнита) в ядро для переноса ресурсов. -tutorial.smelter = Медь и свинец являются мягкими металлами.\nПревосходный[accent] плотный сплав[] может быть создан в плавильном заводе.\n\nПостройте один плавильный завод. -tutorial.densealloy = Теперь плавильный завод производит плотный сплав.\nСоздайте немного.\nУлучшите производство, если это необходимо. +tutorial.smelter = Медь и свинец являются мягкими металлами.\nПревосходный[accent] графит[] может быть создан в плавильном заводе.\n\nПостройте один плавильный завод. +tutorial.densealloy = Теперь плавильный завод производит графит.\nСоздайте немного.\nУлучшите производство, если это необходимо. tutorial.siliconsmelter = Сейчас ядро создаст[accent] дрона[] для добычи и ремонта блоков. \n\nЗаводы для других единиц могут быть созданы с помощью кремния.\nСоздайте [accent]кремниевый завод[]. tutorial.silicondrill = Для производства кремния требуется[accent] уголь[] и[accent] песок[].\nНачните их добычу, сделав буры. tutorial.generator = Эта технология требует энергии.\nПостройте [accent] генератор внутреннего сгорания[] для того, чтобы запитать устройство энергией. @@ -790,18 +824,18 @@ block.mend-projector.description = Ремонтирует строения в н block.overdrive-projector.description = Ускоряет в небольшом радиусе все ваши действия. block.force-projector.description = Создаёт в небольшом радиусе силовое поле, которое защищает от атак противника. block.shock-mine.description = Поставьте её на землю. Она бьётся ЭЛЕКТРИЧЕСТВОМ О_О -block.duo.description = Маленькая и дешёвая турель. -block.scatter.description = A medium-sized anti-air turret. Sprays clumps of lead or scrap flak at enemy units. -block.arc.description = Турель с малым радиусом атаки. В качестве патронов требует воду или криогенную жидкость. Также нужна энергия. -block.hail.description = Дальнобойная начальная турель.\nИспользует в качестве снарядов плотный сплав, кремний и пиротит.\nДля ускорения стрельбы можно подвести воду и криогенную жидкость. +block.duo.description = Маленькая и дешёвая турель. Полезно против наземных юнитов. +block.scatter.description = Противовоздушная турель среднего размера. Распыляет глыбы свинца или металлолома на вражеских боевых единиц. +block.arc.description = Маленькая турель ближнего радиуса действия, которая стреляет электричеством по случайной дуге в направлении врага. +block.hail.description = Дальнобойная начальная турель.\nИспользует в качестве снарядов кремний и пиротит.\nДля ускорения стрельбы можно подвести воду и криогенную жидкость. block.lancer.description = Турель, которая стреляет лазером на среднее расстояние.\nИспользует в качестве снарядов энергию.\nДля ускорения стрельбы можно подвести воду или криогенную жидкость. block.wave.description = Турель с средним радиусом атаки, которая отталкивает противников в стороны. Использует в качестве снарядов воду, нефть, лаву или криогенную жидкость. -block.salvo.description = Турель с средним радиусом атаки. Использует в качестве снарядов медь, плотный сплав, торий, кремний и пиротит.\nТакже нужна какая-то жидкость: вода или криогенная. +block.salvo.description = Турель с средним радиусом атаки. Использует в качестве снарядов медь, торий, кремний и пиротит.\nТакже нужна какая-то жидкость: вода или криогенная. block.swarmer.description = Турель с большим радиусом атаки. Использует в качестве снарядов кинетический сплав, пиротит и взрывоопасное соединение.\n Также нужна какая-то жидкость: вода или криогенная. -block.ripple.description = Первая турель 3х3.\nИспользует в качестве снарядов плотный сплав, кремний, взрывоопасное соединение и пиротит. \nТакже нужна какая-то жидкость: вода или криогенная. +block.ripple.description = Первая турель 3х3.\nИспользует в качестве снарядов кремний, взрывоопасное соединение и пиротит. \nТакже нужна какая-то жидкость: вода или криогенная. block.cyclone.description = Турель с большой дальностью атаки. Использует в качестве снарядов пластиний, взрывоопасное соединение и кинетический сплав.\nТакже нужна какая-то жидкость:вода или криогенная. -block.fuse.description = Турель с малой дальностью атаки. Использует в качестве снарядов плотный сплав. \nТакже нужна какая-то жидкость: вода или криогенная. -block.spectre.description = Первая турель 4х4 с средним радиусом атаки. Использует в качестве снарядов плотный сплав, торий или пиротит. +block.fuse.description = Турель с малой дальностью атаки. Использует в качестве снарядов графит. \nТакже нужна какая-то жидкость: вода или криогенная. +block.spectre.description = Первая турель 4х4 с средним радиусом атаки. Использует в качестве снарядов торий или пиротит. block.meltdown.description = Турель с средним радиусом атаки. Для патронов требует воду или криогенную жидкость. Также нужна энергия. block.conveyor.description = Перемещает ресурсы с маленькой скоростью. block.titanium-conveyor.description = Конвейер второго поколения. Увеличена скорость перемещения предметов и прочность конвейера. @@ -812,13 +846,13 @@ block.silicon-smelter.description = С помощью песка, угля и э block.plastanium-compressor.description = Создаёт пластиний из титана и нефти. Требует энергии. Для ускорения производства можно добавить в компрессор песок. block.phase-weaver.description = Производит фазовую материю из тория и песка. Требует большего количества энергии. block.alloy-smelter.description = Создаёт кинетический сплав из титана, кремния, меди и свинца. Требует энергию. -block.pulverizer.description = Измельчает камень в песок. Требует энергию. +block.pulverizer.description = Измельчает металлолом в песок. Требует энергию. block.pyratite-mixer.description = Создаёт пиротит из угля, свинца и песка. Требует энергии. block.blast-mixer.description = Создаёт взрывоопасное соединение из нефти и пиротита. Для ускорения производства можно добавить в мешалку песок. block.cryofluidmixer.description = Производит криогенную жидкость из воды и титана. Требует энергии. block.melter.description = Расплавляет металлолом в шлак для дальнейшей обработки или использования в турелях. block.incinerator.description = Если есть ненужные ресурсы, можно просто их сжечь.\n Требует энергии. -block.spore-press.description = Compresses spore pods into oil. +block.spore-press.description = Сжимает капсулы со спорами в нефть. block.separator.description = Извлекает полезные минералы из шлака. block.power-node.description = Максимум допустимо 4 подключения.\n Чтобы соединить с каким-то блоком нужно следующее:\n1. Чтобы он находился в радиусе действия\n2.Нажать на нужный силовой узел, а затем на другой силовой узел или блок. block.power-node-large.description = Силовой узел второго поколения. Увеличен радиус действия и количество максимально допустимых подключений. @@ -829,7 +863,7 @@ block.turbine-generator.description = Для производства энерг block.thermal-generator.description = Генерирует энергию, когда помещается в жаркие места. block.solar-panel.description = Зелёная энергия. Бесконечный источник энергии. block.solar-panel-large.description = Зелёная энергия. Большой и бесконечный источник энергии. -block.thorium-reactor.description = Производит энергию в большом количестве. Может взорваться. Требуется торий и жидкость для охлаждения (вода или криогенная). +block.thorium-reactor.description = Вырабатывает огромное количество энергии из высокорадиоактивного тория. Требует постоянного охлаждения. Взорвётся при недостаточном количестве охлаждающей жидкости. Выходная мощность зависит от наполненности, при этом базовая мощность генерируется на полную мощность. block.rtg-generator.description = Радиоизотопный термоэлектрический генератор, который не требует охлаждения, но обеспечивает меньшую мощность, чем ториевый реактор. block.unloader.description = Выгружает из ядра или хранилища верхний левый предмет. block.container.description = Хранит небольшое количество предметов. Используйте его для создания буферов, когда существует непостоянная потребность в материалах. [LIGHT_GRAY] Разгрузчик[] можно использовать для извлечения элементов из хранилища. @@ -839,7 +873,7 @@ block.pneumatic-drill.description = Улучшенная версия механ block.laser-drill.description = Улучшенная версия пневматического бура.\n\nДобывает тоже самое, что и пневматический бур. Также может добывать торий.\n\nМожно подвести к нему[BLUE] воду[] для увеличения скорости сверления. block.blast-drill.description = Самый мощный бур.\n\nДобывает тоже самое, что и лазерный бур. Сверлит быстрей всех буров, но требует ещё больше энергии.\n\nМожно подвести к нему [BLUE]воду[] для увеличения скорости сверления. block.water-extractor.description = Извлекает воду из земли. Используйте его, когда поблизости нет озера. -block.cultivator.description = Культирует споры водой для получения биоматерии. +block.cultivator.description = Выращивает крошечные скопления спор в готовых к промышленности стручках. block.oil-extractor.description = Использует большое количество энергии для добычи нефти из песка, динозавров(зачёркнуто). Используйте его, когда поблизости нет прямого источника нефти. block.trident-ship-pad.description = Оставьте свой текущий корабль и перейдите в достаточно хорошо бронированный тяжёлый бомбардировщик.\nИспользуйте двойное нажатие, стоя на реконструкторе, чтобы превратиться в этот мех. block.javelin-ship-pad.description = Оставьте свой текущий корабль и перейдите в сильный и быстрый перехватчик с молниеносным оружием.\nИспользуйте двойное нажатие, стоя на реконструкторе, чтобы превратиться в этот мех. @@ -856,7 +890,7 @@ block.titan-factory.description = Производит продвинутые з block.fortress-factory.description = Производит тяжёлые артиллерийские боевые единицы. block.revenant-factory.description = Производит тяжёлые летающие боевые единицы. block.repair-point.description = Может ремонтировать вас и ваши боевые единицы -block.conduit.description = Основной блок транспортировки жидкости. Работает как конвейер, но с жидкостями. Лучше всего использовать экстракторы, насосы или т.п.. +block.conduit.description = Основной блок транспортировки жидкости. Работает как конвейер, но с жидкостями. block.pulse-conduit.description = Улучшенный блок транспортировки жидкости. Транспортирует жидкости быстрее и хранит больше, чем стандартные. block.phase-conduit.description = Улучшенный блок транспортировки жидкости. Использует энергию для передачи жидкостей на подключенный фазовый канал на несколько плиток. block.liquid-router.description = Принимает жидкости с одного направления и равномерно выводит их до трех других направлений. Может также хранить определенное количество жидкости. Полезно для разделения жидкостей из одного источника на несколько целей. @@ -865,15 +899,15 @@ block.liquid-junction.description = Действует как мост для д block.bridge-conduit.description = Расширенный блок транспортировки жидкости. Позволяет транспортировать жидкости до 3 блоков любого ландшафта или здания. Лучше всего подключать последовательно и в линию. block.mechanical-pump.description = Дешевый насос с медленным выкачиванием, но без потребления энергии. Качает только воду. block.rotary-pump.description = Передовой насос, который удваивает скорость, используя энергию. -block.thermal-pump.description = Конечный насос. В три раза быстрее, чем механический насос и единственный насос, который способен извлекать лаву. +block.thermal-pump.description = Последний насос. block.router.description = Принимает предметы из одного направления и равномерно выводит их до трёх других направлений. Полезно для разделения материалов из одного источника на несколько целей. block.distributor.description = Передовой маршрутизатор, который равномерно разбивает элементы до 7 других направлений. block.bridge-conveyor.description = Улучшенный транспортный блок элементов. Позволяет транспортировать предметы до 3-х блоков над любым ландшафтом или зданием. -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. +block.item-source.description = Бесконечно выводит предметы. +block.liquid-source.description = Бесконечно выводит жидкости. +block.item-void.description = Уничтожает любые предметы, которые входят в него, не используя енергію. +block.power-source.description = Бесконечно выводит энергию. +block.power-void.description = Аннулирует всю энергию, введённую в него. liquid.water.description = Эту жидкость можно подвести к бурам для ускорения скорости добычи или к турелям для ускорения стрельбы. liquid.oil.description = Может гореть, взрывоопасна и используется для охлаждения. liquid.cryofluid.description = Может быть использована для ускорения стрельбы турелей или для охлаждения чего-то. diff --git a/core/assets/bundles/bundle_tk.properties b/core/assets/bundles/bundle_tk.properties index 983cf1d71d..7dfd3d76e3 100644 --- a/core/assets/bundles/bundle_tk.properties +++ b/core/assets/bundles/bundle_tk.properties @@ -23,6 +23,7 @@ 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 = Su haritayi silmek istediginden emin misin? "[accent]{0}[]"? level.highscore = Yuksek Skor: [accent]{0} level.select = Seviye secimi @@ -39,6 +40,7 @@ addplayers = Oyuncu ekle/cikar customgame = Ozel oyun newgame = New Game none = +minimap = Minimap close = Kapat quit = Cik maps = Haritalar @@ -181,6 +183,7 @@ map.delete.confirm = Haritayi silmek istedigine emin misin? Bu geri alinamaz! map.random = [accent]Rasgele harita map.nospawn = Haritada Oyncularin cikmasi icin cekirdek yok! Haritaya[ROYAL]Mavi[] cekirdek ekle. 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 = Harita yuklenemedi. Gecersiz yada bozuk dosya. editor.brush = Firca editor.openin = Editorde ac @@ -282,6 +285,7 @@ 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 @@ -293,7 +297,7 @@ uncover = Uncover configure = Configure Loadout configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. zone.unlocked = [LIGHT_GRAY]{0} unlocked. -zone.complete = Zone conditions met. +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... @@ -332,63 +336,59 @@ no = Hayir info.title = [accent]Bilgi error.title = [crimson]Bir hata olustu error.crashtitle = Bir hata olustu -blocks.outputspeed = Drill Speed: {0}/s -blocks.efficiency = Efficiency: {0}% -blocks.unknown = [LIGHT_GRAY]??? -blocks.blockinfo = Yapi bilgisi -blocks.powerbalance = Power: {0} -blocks.poweroutput = Power Output: {0} +blocks.input = Input +blocks.output = Output +blocks.booster = Booster +block.unknown = [LIGHT_GRAY]??? blocks.powercapacity = Guc kapasitesi blocks.powershot = Guc/Saldiri hizi blocks.targetsair = Havayi hedef alir mi? blocks.targetsground = Targets Ground -blocks.items = Items: {0} blocks.itemsmoved = Move Speed +blocks.launchtime = Time Between Launches blocks.shootrange = Menzil blocks.size = Buyukluk blocks.liquidcapacity = Sivi kapasitesi -blocks.maxitemssecond = Esya limiti blocks.powerrange = Menzil blocks.poweruse = Guc kullanimi blocks.powerdamage = Power/Damage -blocks.inputitemcapacity = Giris esya kapasitesi -blocks.outputitemcapacity = Cikis esya kapasitesi blocks.itemcapacity = Esya kapasitesi blocks.basepowergeneration = Base Power Generation -blocks.powertransferspeed = Guc transfer hizi -blocks.craftspeed = Yapilma hizi -blocks.inputliquid = Giris sivi -blocks.inputliquidaux = Yardimci sivi -blocks.inputitem = Giris esyasi -blocks.inputitems = Giris esyalari -blocks.outputitem = Sonuc +blocks.productiontime = Production Time +blocks.repairtime = Block Full Repair Time +blocks.speedincrease = Speed Increase +blocks.range = Range blocks.drilltier = Kazilabilirler blocks.drillspeed = Ana kazma hizi +blocks.boosteffect = Boost Effect blocks.maxunits = Max Active Units -blocks.liquidoutput = Sivi cikisi -blocks.liquidoutputspeed = Liquid Output Speed -blocks.liquiduse = Sivi kullanimi -blocks.coolant = Sogutma sivisi -blocks.liquid = Liquid -blocks.coolantuse = Sogutma sivi kullanimi -blocks.inputliquidfuel = Yakit sivisi -blocks.liquidfueluse = Sivi yakit kullanimi -blocks.boostitem = Boost Item -blocks.boostliquid = Boost Liquid blocks.health = Can -blocks.heat = Heat -blocks.power = Power -blocks.progress = Build Progress -blocks.spawned = Units: {0}/{1} -blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = sekme blocks.shots = vuruslar blocks.reload = Yeniden doldurma -blocks.inputfuel = Yakit -blocks.fuelburntime = Yakit yakilma suresi -blocks.inputcapacity = Giris kapasitesi -blocks.outputcapacity = Cikis kapasitesi 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 +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 = Yapilar unit.powersecond = saniyede bir unit.liquidsecond = Saniyede bir @@ -397,6 +397,9 @@ unit.liquidunits = Litre unit.powerunits = Volt unit.degrees = derece unit.seconds = saniye +unit.persecond = /sec +unit.timesspeed = x speed +unit.percent = % unit.items = esya category.general = General category.power = Guc @@ -405,7 +408,11 @@ category.items = esyalar category.crafting = uretim category.shooting = sikma category.optional = Optional Enhancements +setting.landscape.name = Lock Landscape +setting.shadows.name = Shadows setting.animatedwater.name = Animated Water +setting.animatedshields.name = Animated Shields +setting.antialias.name = Antialias[LIGHT_GRAY] (requires restart)[] setting.indicators.name = Ally Indicators setting.autotarget.name = Auto-Target setting.fpscap.name = Max FPS @@ -424,9 +431,11 @@ setting.sensitivity.name = Kumanda hassasligi setting.saveinterval.name = Otomatik kaydetme suresi setting.seconds = {0} Saniye setting.fullscreen.name = Tam ekran +setting.borderless.name = Borderless Window setting.fps.name = FPS'i goster setting.vsync.name = VSync setting.lasers.name = Guc lazerlerini goster +setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance) setting.minimap.name = Haritayi goster setting.musicvol.name = Ses yuksekligi setting.mutemusic.name = Sesi kapat @@ -479,6 +488,21 @@ 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.pvp = PvP +rules.unitdrops = Unit Drops +rules.unitbuildspeedmultiplier = Unit Creation Speed Multiplier +rules.unithealthmultiplier = Unit Health Multiplier +rules.playerdamagemultiplier = Player 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 content.item.name = Esyalar content.liquid.name = Sivilar content.unit.name = Units @@ -559,6 +583,7 @@ mech.itemcapacity = [LIGHT_GRAY]esya kapasitesi: {0} mech.minespeed = [LIGHT_GRAY]kazma hizi: {0} mech.minepower = [LIGHT_GRAY]kazma gucu: {0} mech.ability = [LIGHT_GRAY]yetenek gucu: {0} +mech.buildspeed = [LIGHT_GRAY]Building Speed: {0}% liquid.heatcapacity = [LIGHT_GRAY]isinma kapasitesi: {0} liquid.viscosity = [LIGHT_GRAY]Yari sivilik: {0} liquid.temperature = [LIGHT_GRAY]isi: {0} @@ -590,13 +615,17 @@ block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus block.deepwater.name = su alti block.water.name = su +block.tainted-water.name = Tainted Water +block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Tar block.stone.name = tas block.sand.name = kum +block.darksand.name = Dark Sand block.ice.name = buz block.snow.name = kar 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 @@ -628,6 +657,7 @@ block.thorium-wall-large.name = genis toryum duvari block.door.name = kapi block.door-large.name = genis kapi block.duo.name = ikili +block.scorch.name = Scorch block.scatter.name = Scatter block.hail.name = yagdirici block.lancer.name = Lazer topu @@ -713,6 +743,7 @@ block.blast-drill.name = Patlatici kazici block.thermal-pump.name = Termal pompa block.thermal-generator.name = Magma jeneratoru block.alloy-smelter.name = Alloy eritici +block.mender.name = Mender block.mend-projector.name = Mend koruyucu block.surge-wall.name = kabarma duvari block.surge-wall-large.name = genis kabarma duvari @@ -728,6 +759,7 @@ 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 diff --git a/core/assets/bundles/bundle_tr.properties b/core/assets/bundles/bundle_tr.properties index 9ca17622f7..802f6cfe7a 100644 --- a/core/assets/bundles/bundle_tr.properties +++ b/core/assets/bundles/bundle_tr.properties @@ -23,6 +23,7 @@ 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 = Su haritayi silmek istedigine emin misin? "[orange]{0}[]"? level.highscore = Yüksek Puan: [accent] {0} level.select = Seviye Seç @@ -39,6 +40,7 @@ addplayers = Oyuncu ekle/cikar customgame = Ozel oyun newgame = New Game none = +minimap = Minimap close = Kapat quit = Çık maps = Haritalar @@ -181,6 +183,7 @@ map.delete.confirm = Are you sure you want to delete this map? This action canno 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 @@ -282,6 +285,7 @@ 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 @@ -293,7 +297,7 @@ uncover = Uncover configure = Configure Loadout configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. zone.unlocked = [LIGHT_GRAY]{0} unlocked. -zone.complete = Zone conditions met. +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... @@ -332,63 +336,59 @@ no = No info.title = [Vurgu] Bilgi error.title = [crimson] Bir hata oluştu error.crashtitle = Bir hata oluştu -blocks.outputspeed = Drill Speed: {0}/s -blocks.efficiency = Efficiency: {0}% -blocks.unknown = [LIGHT_GRAY]??? -blocks.blockinfo = Blok Bilgisi -blocks.powerbalance = Power: {0} -blocks.poweroutput = Power Output: {0} +blocks.input = Input +blocks.output = Output +blocks.booster = Booster +block.unknown = [LIGHT_GRAY]??? blocks.powercapacity = Güç kapasitesi blocks.powershot = Güç / atış blocks.targetsair = Targets Air blocks.targetsground = Targets Ground -blocks.items = Items: {0} blocks.itemsmoved = Move Speed +blocks.launchtime = Time Between Launches blocks.shootrange = Range blocks.size = Boyut blocks.liquidcapacity = Sıvı kapasitesi -blocks.maxitemssecond = Maksimum öğe / saniye blocks.powerrange = Güç aralığı blocks.poweruse = Power Use blocks.powerdamage = Power/Damage -blocks.inputitemcapacity = Input Item Capacity -blocks.outputitemcapacity = Input Item Capacity blocks.itemcapacity = Ürün kapasitesi blocks.basepowergeneration = Base Power Generation -blocks.powertransferspeed = Power Transfer -blocks.craftspeed = Production Speed -blocks.inputliquid = Giriş sıvı -blocks.inputliquidaux = Aux Liquid -blocks.inputitem = Giriş öğesi -blocks.inputitems = Input Items -blocks.outputitem = Output Item +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.liquidoutput = Liquid Output -blocks.liquidoutputspeed = Liquid Output Speed -blocks.liquiduse = Liquid Use -blocks.coolant = Coolant -blocks.liquid = Liquid -blocks.coolantuse = Coolant Use -blocks.inputliquidfuel = Fuel Liquid -blocks.liquidfueluse = Liquid Fuel Use -blocks.boostitem = Boost Item -blocks.boostliquid = Boost Liquid blocks.health = Can -blocks.heat = Heat -blocks.power = Power -blocks.progress = Build Progress -blocks.spawned = Units: {0}/{1} -blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = yanlışlık blocks.shots = atışlar blocks.reload = Reload -blocks.inputfuel = Fuel -blocks.fuelburntime = Fuel Burn Time -blocks.inputcapacity = Giriş kapasitesi -blocks.outputcapacity = Çıkış kapasitesi 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 +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 @@ -397,6 +397,9 @@ unit.liquidunits = liquid units unit.powerunits = power units unit.degrees = degrees unit.seconds = seconds +unit.persecond = /sec +unit.timesspeed = x speed +unit.percent = % unit.items = items category.general = General category.power = Power @@ -405,7 +408,11 @@ category.items = Items category.crafting = Crafting category.shooting = Shooting category.optional = Optional Enhancements +setting.landscape.name = Lock Landscape +setting.shadows.name = Shadows setting.animatedwater.name = Animated Water +setting.animatedshields.name = Animated Shields +setting.antialias.name = Antialias[LIGHT_GRAY] (requires restart)[] setting.indicators.name = Ally Indicators setting.autotarget.name = Auto-Target setting.fpscap.name = Max FPS @@ -424,9 +431,11 @@ setting.sensitivity.name = Denetleyici hassasiyeti setting.saveinterval.name = Otomatik Kaydetme Aralığı setting.seconds = saniye setting.fullscreen.name = Tam ekran +setting.borderless.name = Borderless Window setting.fps.name = Saniyede ... Kare göstermek setting.vsync.name = VSync setting.lasers.name = Güç Lazerleri Göster +setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance) setting.minimap.name = Show Minimap setting.musicvol.name = Müzik sesi setting.mutemusic.name = Müziği Kapat @@ -479,6 +488,21 @@ 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.pvp = PvP +rules.unitdrops = Unit Drops +rules.unitbuildspeedmultiplier = Unit Creation Speed Multiplier +rules.unithealthmultiplier = Unit Health Multiplier +rules.playerdamagemultiplier = Player 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 content.item.name = Items content.liquid.name = Liquids content.unit.name = Units @@ -559,6 +583,7 @@ 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} @@ -590,13 +615,17 @@ 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 @@ -628,6 +657,7 @@ block.thorium-wall-large.name = Large Thorium Wall block.door.name = kapı block.door-large.name = büyük kapı block.duo.name = Duo +block.scorch.name = Scorch block.scatter.name = Scatter block.hail.name = Hail block.lancer.name = Lancer @@ -713,6 +743,7 @@ 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 @@ -728,6 +759,7 @@ 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 diff --git a/core/assets/bundles/bundle_uk_UA.properties b/core/assets/bundles/bundle_uk_UA.properties index dc9b549e9d..ad0eaeecbf 100644 --- a/core/assets/bundles/bundle_uk_UA.properties +++ b/core/assets/bundles/bundle_uk_UA.properties @@ -1,4 +1,4 @@ -credits.text = Створив [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[]\n\nЄ питання по грі або проблеми с перекладом? Іди в офіційний сервер discord Mindustry в канал #український. +credits.text = Створив [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[]\n\nЄ питання по грі або проблеми с перекладом?\nЙди в офіційний сервер discord Mindustry в канал #український.\nПерекладач:Prosta4ok_ua credits = Автори contributors = Перекладачі та Помічники discord = Приєднуйтесь до нашого Discord! @@ -21,9 +21,10 @@ stat.destroyed = Будівель знищено:[accent] {0} stat.deconstructed = Будівель декоструйовано[accent] {0} stat.delivered = Ресурсів здобуто: stat.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. -map.delete = Ви впевнені, що хочете видалити карту "[accent]{0}[]"? +placeline = Ви вибрали блок.\nВи можете[accent] будувати в лінію[] [accent] утримуючи палець протягом декількох секунд[] і потім перетягуючи його.\n\n[scarlet]ЗРОБИ ЦЕ. +removearea = Ви вибрали режим видалення.\nВи можете[accent] видаляти блоки в обраній області[],[accent] утримуючи палець кілька секунд [] і потім перетягуючи його.\n\n[scarlet]ЗРОБИ ЦЕ. +launcheditems = [accent]Запущені предмети +map.delete = Ви впевнені, що хочете видалити мапу "[accent]{0}[]"? level.highscore = Рекорд: [accent]{0} level.select = Вибір мапи level.mode = Режим гри: @@ -39,11 +40,12 @@ addplayers = Дод/Видалити гравців customgame = Користувальницька гра newgame = Нова гра none = <нічого> +minimap = Minimap close = Закрити quit = Вийти maps = Мапи continue = Продовжити -maps.none = [LIGHT_GRAY]Карт не знайдено! +maps.none = [LIGHT_GRAY]Мап не знайдено! about.button = Про гру name = Нік: noname = Спочатку придумайте[accent] собі нікнейм[]. @@ -71,7 +73,7 @@ server.kicked.gameover = Гра завершена! host.info = Кнопка [accent]Сервер[] розміщує сервер на порті [scarlet]6567[]. \nКористувачі, які знаходяться у тій же [LIGHT_GRAY] WiFi або локальній мережі[] повинні бачити ваш сервер у своєму списку серверів.\n\nЯкщо ви хочете, щоб люди могли приєднуватися з будь-якої точки через IP, то [accent] переадресація порту [] обов'язкова.\n\n[LIGHT_GRAY] Примітка. Якщо у вас виникли проблеми з підключенням до вашої локальної гри, переконайтеся, що ви дозволили Mindustry доступ до вашої локальної мережі в налаштуваннях брандмауера. join.info = Тут ви можете ввести [accent]IP серверу[] для підключення або знайти сервери у [accent]локальній мережі[] для підключення до них.\nПідтримується локальна мережа(LAN) і широкосмугова мережа(WAN).\n\n[LIGHT_GRAY] Примітка. Тут немає автоматичного глобального списку серверів; якщо ви хочете підключитися до когось через IP, вам доведеться попросити створювача серверу дати свій ip. hostserver = Запустити сервер -hostserver.mobile = Запустити\nсерверу +hostserver.mobile = Запустити\nсервер host = Сервер hosting = [accent]Відкриття серверу... hosts.refresh = Оновити @@ -177,11 +179,12 @@ saveimage = Зберегти зображення unknown = Невідомо custom = Користувальницька builtin = Bбудована -map.delete.confirm = Ви впевнені, що хочете видалити цю карту? Цю дію не можна скасувати! +map.delete.confirm = Ви впевнені, що хочете видалити цю мапу? Цю дію не можна скасувати! map.random = [accent]Випадкова мапа map.nospawn = Ця мапа не має жодного ядра для спавну гравця! Додайте[ROYAL] сине[] ядро в цю мапу редакторі. -map.nospawn.pvp = У цій карти немає ворожих ядер, в яких гравець може з'явитися! Додайте[SCARLET] червоні[] ядра до цієї карті в редакторі. -map.invalid = Помилка завантаження карти: пошкоджений або невірний файл карти. +map.nospawn.pvp = У цієї мапи немає ворожих ядер, в яких гравець може з'явитися! Додайте[SCARLET] не сине[] ядро до цієї мапи в редакторі. +map.nospawn.attack = У цієї мапи немає ворожих ядер,які гравець може атакувати! Додайте[SCARLET] червоне[] ядро до цієї мапи в редакторі. +map.invalid = Помилка завантаження мапи: пошкоджений або невірний файл мапи. editor.brush = Пензлик editor.openin = Відкрити в редакторі editor.oregen = Генерація руд @@ -189,80 +192,80 @@ editor.oregen.info = Генерація руд: editor.mapinfo = Інформація про мапу editor.author = Автор: editor.description = Опис: -editor.waves = Waves: -waves.title = Waves -waves.remove = Remove -waves.never = -waves.every = every -waves.waves = wave(s) -waves.perspawn = per spawn -waves.to = to -waves.boss = Boss -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.waves = Хвилі: +waves.title = Хвилі +waves.remove = Видалити +waves.never = <ніколи> +waves.every = Кожен +waves.waves = хвиля(і) +waves.perspawn = за появу +waves.to = до +waves.boss = Босс +waves.preview = Попередній перегляд +waves.edit = Редагувати ... +waves.copy = Копіювати в буфер обміну +waves.load = Завантаження з буфера обміну +waves.invalid = Недійсні хвилі в буфері обміну. +waves.copied = Хвилі скопіювані. +editor.default = [LIGHT_GRAY]<За замовчуванням> +edit = Редагувати... editor.name = Назва: editor.teams = Команди editor.elevation = Висота -editor.errorload = Error loading file:\n[accent]{0} -editor.errorsave = Error saving file:\n[accent]{0} -editor.errorname = Map has no name defined. -editor.update = Update -editor.randomize = Randomize -editor.apply = Apply -editor.generate = Створити +editor.errorload = Помилка завантаження зображення:[accent] {0} +editor.errorsave = Помилка збереження зображення:\n[accent]{0} +editor.errorname = Мапа не має визначеного імені. +editor.update = Оновити +editor.randomize = Випадково +editor.apply = Застосувати +editor.generate = Згенерувати editor.resize = Змінити \nрозмір editor.loadmap = Завантажити мапу -editor.savemap = Зберегти карту +editor.savemap = Зберегти мапи editor.saved = Збережено! -editor.save.noname = Ваша карта не має назви! Встановіть його в меню «Інформація про карту». -editor.save.overwrite = Ваша карта перезаписує вбудовану карту! Виберіть інше ім'я в меню «Інформація про карту». -editor.import.exists = [scarlet]Неможливо імпортувати: [] вбудована карта з назвою "{0}" вже існує! +editor.save.noname = Ваша мапа не має назви! Встановіть його в меню «Інформація про мапу». +editor.save.overwrite = Ваша мапа перезаписує вбудовану мапу! Виберіть інше ім'я в меню «Інформація про мапу». +editor.import.exists = [scarlet]Неможливо імпортувати: [] вбудована мапа з назвою "{0}" вже існує! editor.import = Імпорт... -editor.importmap = Імпортувати карту -editor.importmap.description = Імпортувати вже існуючу карту +editor.importmap = Імпортувати мапу +editor.importmap.description = Імпортувати вже існуючу мапу editor.importfile = Імпортувати файл -editor.importfile.description = Імпортувати зовнішній файл карти -editor.importimage = Імпорт зовнішнього файла зображення карти +editor.importfile.description = Імпортувати зовнішній файл мапи +editor.importimage = Імпорт зовнішнього файла зображення мапи editor.importimage.description = Імпорт зображення місцевості editor.export = Експорт... editor.exportfile = Експорт файлу -editor.exportfile.description = Експортувати файл карти +editor.exportfile.description = Експортувати файл мапи editor.exportimage = Експорт зображення місцевості -editor.exportimage.description = Експорт файла з зображенням карти +editor.exportimage.description = Експорт файла з зображенням мапи editor.loadimage = Завантажити\nзображення editor.saveimage = Зберегти\nзображення editor.unsaved = [scarlet]У вас є незбережені зміни![]\nВи впевнені, що хочете вийти? -editor.resizemap = Змінити розмір карти -editor.mapname = Название карты: -editor.overwrite = [accent]Попередження!\nЦе перезаписує існуючу карту. -editor.overwrite.confirm = [scarlet]Попередження![] Карта з такою назвою вже існує. Ви впевнені, що хочете переписати її? +editor.resizemap = Змінити розмір мапи +editor.mapname = Назва мапи: +editor.overwrite = [accent]Попередження!\nЦе перезаписує існуючу мапу. +editor.overwrite.confirm = [scarlet]Попередження![] Мапа з такою назвою вже існує. Ви впевнені, що хочете переписати її? editor.selectmap = Виберіть мапу для завантаження: -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 +filters.empty = [LIGHT_GRAY]Нема фільтрів! Додайте хоча б один за допомогою кнопки, що знаходиться нижче. +filter.distort = Спотворення +filter.noise = Шум +filter.ore = Руда +filter.rivernoise = Річковий Шум +filter.scatter = Розпилювач +filter.terrain = Ландшафт +filter.option.scale = Масштаб +filter.option.chance = Шанс +filter.option.mag = Величина +filter.option.threshold = Спад +filter.option.circle-scale = Кругова шкала +filter.option.octaves = Октави +filter.option.falloff = Спад +filter.option.block = Блок +filter.option.floor = Поверхня +filter.option.wall = Стіна +filter.option.ore = Руда +filter.option.floor2 = Друга поверхня +filter.option.threshold2 = Вторинний спад width = Ширина: height = Висота: menu = Меню @@ -282,6 +285,7 @@ abandon = Покинути abandon.text = Ця зона і всі її ресурси будуть втрачені для ворога. locked = Заблоковано complete = [LIGHT_GRAY]Завершено: +zone.requirement = Wave {0} in zone {1} resume = Відновити зону:\n[LIGHT_GRAY]{0} bestwave = [LIGHT_GRAY]Найкраща хвиля: {0} launch = < ЗАПУСК > @@ -293,7 +297,7 @@ uncover = Розкрити configure = Вивантаження configure.locked = [LIGHT_GRAY]Розблокувати можливість вивантаження ресурсів:\nWave {0}. zone.unlocked = [LIGHT_GRAY]{0} розблоковано -zone.complete = {0} хвиль досясгнено:\nНові вимоги до зони виконані. +zone.requirement.complete = Wave {0} reached:\n{1} zone requirements met. zone.config.complete = {0} хвиль досягнено. reached:\nРозблоковано можливість вивантаження. zone.resources = Виявлені ресурси: add = Додати... @@ -323,7 +327,7 @@ settings.sound = Звук settings.graphics = Графіка settings.cleardata = Очистити дані... settings.clear.confirm = Ви впевнені, що хочете очистити ці дані?\nЦя дія не може бути скасовано! -settings.clearall.confirm = [scarlet]УВАГА![]\nЦе очистить всі дані, включаючи збереження, карти, розблокуване та призначенні клавіші.\nПісля того, як ви натиснете ОК, гра видалить усі дані та автоматично вийде. +settings.clearall.confirm = [scarlet]УВАГА![]\nЦе очистить всі дані, включаючи збереження, мапи, розблокуване та призначені клавіші.\nПісля того, як ви натиснете ОК, гра видалить усі дані та автоматично вийде. settings.clearunlocks = Очистити розблоковане settings.clearall = Очистити все paused = Пауза @@ -332,63 +336,61 @@ no = Ні info.title = Інформація error.title = [crimson]Виникла помилка error.crashtitle = Виникла помилка -blocks.outputspeed = Drill Speed: {0}/s -blocks.efficiency = Efficiency: {0}% -blocks.unknown = [LIGHT_GRAY]??? -blocks.blockinfo = Інформація про блок -blocks.powerbalance = Енергія: {0} -blocks.poweroutput = Вихідна енергія: {0} +blocks.input = Вхід +blocks.output = Вихід +blocks.booster = Прискорювач +block.unknown = [LIGHT_GRAY]??? blocks.powercapacity = Місткість енергії blocks.powershot = Енергія/постріл -blocks.targetsair = Атакуе повітряних ворогів -blocks.targetsground = Targets Ground -blocks.items = Items: {0} +blocks.targetsair = Повітряні мішені +blocks.targetsground = Наземні мішені blocks.itemsmoved = Швидкість переміщення +blocks.launchtime = Час між запусками blocks.shootrange = Діапазон дії blocks.size = Розмір blocks.liquidcapacity = Місткість рідини -blocks.maxitemssecond = Макс. кількість предметів/секунду blocks.powerrange = Діапазон передачі енергії blocks.poweruse = Енергії використовує blocks.powerdamage = Енергія/урон -blocks.inputitemcapacity = Ємність вхідних елементів -blocks.outputitemcapacity = Ємність вихідних елементів blocks.itemcapacity = Місткість предметів blocks.basepowergeneration = Базова генерація енергії -blocks.powertransferspeed = Швидкість передачі енергії blocks.craftspeed = Швидкість виробництва +blocks.productiontime = Час виробництва +blocks.repairtime = Час повного відновлення блоку +blocks.speedincrease = Збільшення швидкості +blocks.range = Радіус дії blocks.inputliquid = Прийом рідини -blocks.inputliquidaux = Допоміжна рідина -blocks.inputitem = Вхідний предмет -blocks.inputitems = Вхідні предмети -blocks.outputitem = Вихідний предмет blocks.drilltier = Видобуває blocks.drillspeed = Базова швидкість свердління -blocks.maxunits = Max Active Units -blocks.liquidoutput = Вихідна рідина -blocks.liquidoutputspeed = Швидкість вихідної рідини -blocks.liquiduse = Використовуеться рідин -blocks.coolant = Охолоджуюча рідина -blocks.liquid = Рідина -blocks.coolantuse = Охолодж. рідини використовуеться -blocks.inputliquidfuel = Рідке паливо -blocks.liquidfueluse = Рідкого палива використовуеться -blocks.boostitem = Прискорюючий предмет -blocks.boostliquid = Прискорююча рідина +blocks.boosteffect = Прискорювальний ефект +blocks.maxunits = Максимальна кількість активних одиниць blocks.health = Здоров'я -blocks.heat = Heat -blocks.power = Енергія -blocks.progress = Build Progress -blocks.spawned = Units: {0}/{1} -blocks.power.satisfaction = Енергії вистачає blocks.inaccuracy = Розкид blocks.shots = Постріли blocks.reload = Постріли/секунду -blocks.inputfuel = Паливо -blocks.fuelburntime = Час горіння топлива -blocks.inputcapacity = Макс. місткість вхідних предметів -blocks.outputcapacity = Макс. місткість вихідних предметів blocks.ammo = Боєприпаси +bar.drillspeed = Швидкість сверрдління: {0}/s +bar.efficiency = Ефективність: {0}% +bar.powerbalance = Енергія: {0}/с +bar.poweramount = Енергія: {0} +bar.poweroutput = Вихідна енергія: {0} +bar.items = Предмети: {0} +bar.liquid = Рідина +bar.heat = Нагрівання +bar.power = Енергія +bar.progress = Хід Будівництва +bar.spawned = Бойов. од. : {0}/{1} +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]x патронів +bullet.reload = [stat]{0}[lightgray]x швидкість перезаряджання unit.blocks = блоки unit.powersecond = одиниць енергії/секунду unit.liquidsecond = рідких одиниць/секунду @@ -397,21 +399,29 @@ unit.liquidunits = рідинних одиниць unit.powerunits = енергетичних одиниць unit.degrees = град. unit.seconds = сек. +unit.persecond = /сек +unit.timesspeed = x швидкість +unit.percent = % unit.items = предм. category.general = Загальні category.power = Енергетичні category.liquids = Рідини category.items = Предмети -category.crafting = Створення +category.crafting = Введення/виведення category.shooting = Стрільба category.optional = Додаткові поліпшення -setting.animatedwater.name = Animated Water -setting.indicators.name = Показувати у сторону союзників -setting.autotarget.name = Авто-ціль +setting.landscape.name = Зберегти пейхаж +setting.shadows.name = Тіні +setting.animatedwater.name = Анімована вода +setting.animatedshields.name = Анімовані щити +setting.antialias.name = Згладжування[LIGHT_GRAY] (потребує перезапуску)[] +setting.indicators.name = Показувати у сторону ворогів та союзників +setting.autotarget.name = Авто-стрільба setting.fpscap.name = Макс. FPS setting.fpscap.none = Необмежений +minimap = Міні-мапа setting.fpscap.text = {0} FPS -setting.swapdiagonal.name = Always Diagonal Placement +setting.swapdiagonal.name = Завжди Діагональне Розміщення setting.difficulty.training = навчання setting.difficulty.easy = легка setting.difficulty.normal = нормальна @@ -424,10 +434,12 @@ setting.sensitivity.name = Чутливість контролера setting.saveinterval.name = Інтервал автозбереження setting.seconds = {0} сек. setting.fullscreen.name = Повноекранний режим +setting.borderless.name = Вікно без полів setting.fps.name = Показувати FPS setting.vsync.name = Вертикальна синхронізація setting.lasers.name = Показувати енергію лазерів -setting.minimap.name = Показати мінікарту +setting.pixelate.name = Пікселізація [LIGHT_GRAY](може знизити продуктивність) +setting.minimap.name = Показати міні-мапу setting.musicvol.name = Гучність музики setting.mutemusic.name = Заглушити музику setting.sfxvol.name = Гучність звукових ефектів @@ -448,7 +460,7 @@ keybind.screenshot.name = Скріншот мапи keybind.move_x.name = Рух по осі x keybind.move_y.name = Рух по осі x keybind.select.name = Вибір/Постріл -keybind.diagonal_placement.name = Diagonal Placement +keybind.diagonal_placement.name = Діагональне Розміщення keybind.pick.name = Вибрати блок keybind.break_block.name = Зламати блок keybind.deselect.name = Скасувати @@ -467,18 +479,33 @@ keybind.chat_history_prev.name = Попередня історія чату keybind.chat_history_next.name = Наступна історія чату keybind.chat_scroll.name = Прокрутка чату keybind.drop_unit.name = Скинути бой. од. -keybind.zoom_minimap.name = Збільшити мінікарту +keybind.zoom_minimap.name = Збільшити мінімапу mode.help.title = Опис режимів mode.survival.name = Хвилі mode.survival.description = Звичайний режим. В цьому режимі треба самим добувати ресурси та хвилі йдуть беззупинно. mode.sandbox.name = Пісочниця -mode.sandbox.description = В режимі "Пісочниця" бескінечні ресурси(але їх все одно можно добувати) та хвилі йдуть за вашим бажанням. +mode.sandbox.description = В режимі "Пісочниця" незкінченні ресурси(але їх все одно можно добувати) та хвилі йдуть за вашим бажанням. mode.freebuild.name = Вільне\nбудівництво mode.freebuild.description = В режимі "Пісочниця" треба самим добувати ресурси та хвилі йдуть за вашим бажанням. mode.pvp.name = PVP mode.pvp.description = боріться проти інших гравців. mode.attack.name = Атака mode.attack.description = Немає хвиль, мета - знищити базу противника. +mode.custom = Користувальницькі правила +rules.infiniteresources = Нескінченні ресурси +rules.wavetimer = Таймер Хвиль +rules.waves = Хвилі +rules.enemyCheat = Нескінченні ресурси для ШІ +rules.pvp = PvP +rules.unitdrops = Ресурс бойових одиниць +rules.unitbuildspeedmultiplier = Множник Швидкості Створювання Бойов. Од. +rules.unithealthmultiplier = Множник Здоров'я Створювання Бойов. Од. +rules.playerdamagemultiplier = Множник Шкоди Гравця +rules.enemycorebuildradius = Радіус заборони будування для Ворожого Ядра:[LIGHT_GRAY] (плитки) +rules.respawntime = Час відродження:[LIGHT_GRAY] (sec) +rules.wavespacing = Інтервал хвиль:[LIGHT_GRAY] (sec) +rules.buildcostmultiplier = Множник затрат на будівництво +rules.buildspeedmultiplier = Множник швидкості будування content.item.name = Предмети content.liquid.name = Рідини content.unit.name = Бойові одиниці @@ -503,11 +530,11 @@ item.phase-fabric.name = Фазова тканина item.phase-fabric.description = Невагоме речовина, що використовується в сучасній електроніці і технології самовідновлення. Не для вишивання. item.surge-alloy.name = Кінетичний сплав item.surge-alloy.description = Передовий сплав з унікальними електричними властивостями. -item.spore-pod.name = Spore Pod -item.spore-pod.description = Used for conversion into oil, explosives and fuel. +item.spore-pod.name = Споровий стручок +item.spore-pod.description = Використовується для перетворення на нафту, вибухові речовини та паливо. item.sand.name = Пісок item.sand.description = Загальний матеріал, який широко використовується при плавленні, як у процесі плавки, так і у вигляді шлака. -item.blast-compound.name = Вибухонебезпечне з'єднання +item.blast-compound.name = Вибухова суміш item.blast-compound.description = Нестійке з'єднання, що використовується в бомбах та вибухових речовинах. Хоча воно може спалюватися як паливо, та це не рекомендується. item.pyratite.name = Піротит item.pyratite.description = Вкрай легкозаймиста речовина, що використовується у запальній зброї. @@ -521,8 +548,8 @@ liquid.oil.name = Нафта liquid.cryofluid.name = Кріогенна рідина mech.alpha-mech.name = Альфа mech.alpha-mech.weapon = Тяжкий кулемет -mech.alpha-mech.ability = Виклик дронів -mech.alpha-mech.description = Стандартний мех для настільних пристроїв. Має пристойну швидкість і урон; може створити до 3-х дронів для збільшення можливості перемоги. +mech.alpha-mech.ability = Регенерація +mech.alpha-mech.description = Стандартний мех для настільних пристроїв. Має пристойну швидкість і урон. mech.delta-mech.name = Дельта mech.delta-mech.weapon = Генератор дуг mech.delta-mech.ability = Розряд @@ -554,26 +581,27 @@ item.radioactivity = [LIGHT_GRAY]Радіоактивність: {0} unit.health = [LIGHT_GRAY]Здоров'я: {0} unit.speed = [LIGHT_GRAY]Швидкість: {0} mech.weapon = [LIGHT_GRAY]Зброя: {0} -mech.health = [LIGHT_GRAY]Health: {0} +mech.health = [LIGHT_GRAY]Здоров'я: {0} mech.itemcapacity = [LIGHT_GRAY] Ємність елементів: {0} -mech.minespeed = [LIGHT_GRAY]Швидкість видобутку: {0} +mech.minespeed = [LIGHT_GRAY]Швидкість видобутку: {0}% mech.minepower = [LIGHT_GRAY]Потужність видобутку: {0} mech.ability = [LIGHT_GRAY]Здібність: {0} +mech.buildspeed = [LIGHT_GRAY]Швидкість будування: {0}% liquid.heatcapacity = [LIGHT_GRAY]Теплоємність: {0} liquid.viscosity = [LIGHT_GRAY]В'язкість: {0} liquid.temperature = [LIGHT_GRAY]Температура: {0} -block.grass.name = Grass -block.salt.name = Salt -block.sandrocks.name = Sand Rocks -block.spore-pine.name = Spore Pine -block.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.spore-moss.name = Spore Moss -block.shalerocks.name = Shale Rocks +block.grass.name = Трава +block.salt.name = Сіль +block.sandrocks.name = Піщані Скелі +block.spore-pine.name = Спорова сосна +block.sporerocks.name = Спорові камні +block.rock.name = Камінь +block.snowrock.name = Сніжний Камінь +block.shale.name = Сланець +block.shale-boulder.name = Сланцевий валун +block.moss.name = Мох +block.spore-moss.name = Споровий Мох +block.shalerocks.name = Сланцеві Породи block.scrap-wall.name = Стіна з металобрухту block.scrap-wall-large.name = Велика стіна з металобрухту block.scrap-wall-huge.name = Величезна стіна з металобрухту @@ -590,13 +618,17 @@ block.core-foundation.name = Ядро: Штаб block.core-nucleus.name = Ядро: Атом block.deepwater.name = Глибоководдя block.water.name = Вода +block.tainted-water.name = Забруднена вода +block.darksand-tainted-water.name = Темний пісок з забрудненою водою block.tar.name = Tar block.stone.name = Камінь -block.sand.name = Темний пісок +block.sand.name = Пісок +block.darksand.name = Темний пісок block.ice.name = Лід block.snow.name = Сніг block.craters.name = Кратери block.sand-water.name = Пісок з водою +block.darksand-water.name = Темний пісок з водою block.char.name = Випалена Земля block.holostone.name = Голографічний камінь block.ice-snow.name = Крижаний Сніг @@ -608,10 +640,10 @@ block.pine.name = Сосна block.white-tree-dead.name = Мертве Біле Дерево block.white-tree.name = Біле Дерево block.spore-cluster.name = Скупчення спор -block.metal-floor.name = Металевий Пол +block.metal-floor.name = Металевий Пол 1 block.metal-floor-2.name = Металевий Пол 2 block.metal-floor-3.name = Металевий Пол 3 -block.metal-floor-5.name = Металевий Пол 5 +block.metal-floor-5.name = Металевий Пол 4 block.metal-floor-damaged.name = Пошкоджений Металевий Пол block.ignarock.name = Магматичні Гірські Породи block.hotrock.name = Гарячий Камінь @@ -628,7 +660,8 @@ block.thorium-wall-large.name = Велика торієва стіна block.door.name = Двері block.door-large.name = Великі двері block.duo.name = Подвійна -block.scatter.name = Scatter +block.scorch.name = Випалювач +block.scatter.name = Розсіювач block.hail.name = Град block.lancer.name = Списоносець block.conveyor.name = Конвеєр @@ -646,7 +679,7 @@ block.pulverizer.name = Розпилювач block.cryofluidmixer.name = Змішувач кріогненної рідини block.melter.name = Плавильня block.incinerator.name = Сміттєспалювальний завод -block.spore-press.name = Spore Press +block.spore-press.name = Споровий Прес block.separator.name = Сепаратор block.power-node.name = Енергійний вузол block.power-node-large.name = Великий енергетичний вузол @@ -660,10 +693,10 @@ block.impact-reactor.name = Імпульсний реактор block.mechanical-drill.name = Механічний дриль block.pneumatic-drill.name = Пневматичний дриль block.laser-drill.name = Лазерний дриль -block.water-extractor.name = Екстрактор води +block.water-extractor.name = Гідроконденсатор block.cultivator.name = Культиватор block.alpha-dart-mech-pad.name = Реконструктор "Альфа-Дротик" -block.delta-mech-pad.name = Delta Mech Pad +block.delta-mech-pad.name = Реконструктор "Дельта" block.javelin-ship-pad.name = Реконструктор "Джавелін" block.trident-ship-pad.name = Реконструктор "Тризуб" block.glaive-ship-pad.name = Реконструктор "Спис" @@ -689,13 +722,13 @@ block.pyratite-mixer.name = Змішувач піротиту block.blast-mixer.name = Доменний змішувач block.solar-panel.name = Сонячна панель block.solar-panel-large.name = Велика сонячна панель -block.oil-extractor.name = Екстрактор нафти +block.oil-extractor.name = Нафтова вежа block.spirit-factory.name = Завод дронов "Призрак" block.phantom-factory.name = Завод дронов "Фантом" block.wraith-factory.name = Завод винищувачів "Примара" block.ghoul-factory.name = Завод бомбардувальників-винищувачів "Ґуль" block.dagger-factory.name = Завод мехів "Кинджал" -block.crawler-factory.name = Crawler Mech Factory +block.crawler-factory.name = Завод мехів "Камікадзе" block.titan-factory.name = Завод мехів "Титан" block.fortress-factory.name = Завод мехів "Крепость" block.revenant-factory.name = Завод бомбардировщиков "Потусторонний убийца" @@ -713,6 +746,7 @@ block.blast-drill.name = Бурова установка block.thermal-pump.name = Тепловий насос block.thermal-generator.name = Тепловий генератор block.alloy-smelter.name = Сплавовий завод +block.mender.name = Mender block.mend-projector.name = Ремонту гранатомет block.surge-wall.name = Хвиляста стіна block.surge-wall-large.name = Велика хвиляста стіна @@ -727,7 +761,8 @@ block.spectre.name = Мара block.meltdown.name = Розтоплення block.container.name = Склад block.launch-pad.name = Стартовий майданчик -block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. +block.launch-pad.description = Запускає партії елементів без необхідності запуску ядра. Незакінчено. +block.launch-pad-large.name = Великий Стартовий майданчик team.blue.name = Синя team.red.name = Червона team.orange.name = Помаренчева @@ -740,9 +775,9 @@ unit.phantom.name = Фантом unit.phantom.description = Покращений дрон. Автоматично добуває руди та ремонтує блоки. unit.dagger.name = Кинджал unit.dagger.description = Базова наземна бойова одиниця. Корисен у купі. -unit.crawler.name = Crawler +unit.crawler.name = Камікадзе unit.titan.name = Титан -unit.titan.description = Улучшенная бронированная наземная боевая единица. Атакует наземные и воздушные цели. +unit.titan.description = Покращена броньована наземна бойова одиниця. Атакує наземні та повітряні цілі. unit.ghoul.name = Бомбардувальний "Ґуль" unit.ghoul.description = Тяжкий ковровий бомбардувальник. unit.wraith.name = Примарний винищувач @@ -763,7 +798,7 @@ tutorial.turret = Захистні споруди повинні бути поб tutorial.drillturret = Подвійні турелі потребують[accent] мідні патрони []для стрільби.\nПоставте бури поруч з турелею, щоб знаюдити її видобутою міддю. tutorial.waves = [LIGHT_GRAY] Супротивник[] прижується.\n\nЗахистіть своє ядро від двух хвиль противника. Побудуйте більше турелей. tutorial.lead = Стало доступно більше руд. Знайдіть і добудьте[accent] свинець[].\n\nПеретягніть з вашого меху в ядро для передачі ресурсів. -tutorial.smelter = Свинець і мідь тяжкі метали.\nНайліпший[accent] щільний сплав[] може бути створеним у плавильному заводі.\n\nПобудуйте один завод. +tutorial.smelter = Свинець і мідь тяжкі метали.\nНайліпший[accent] графіт[] може бути створеним у плавильному заводі.\n\nПобудуйте один завод. tutorial.densealloy = Плавильний завод тепер буде створювати сплав. tutorial.siliconsmelter = Ядро зараз створить[accent] дрона привида[] для добування і ремонтування блоків.\n\nЗаводи для других одиниць(юнітов) може бути створено за допомогою [accent] кремнія.\nЗробіть кремнієвий завод. tutorial.silicondrill = Кремній потребує[accent] вугілляl[] та[accent] пісок[].\nПочніть зі створення бурів. @@ -790,9 +825,9 @@ block.mend-projector.description = Ремонтує будівлі в невел block.overdrive-projector.description = Прискорює в невеликому радіусі роботу механізмів. block.force-projector.description = Створює в невеликому радіусі силове поле, яке захищає від атак супротивника. block.shock-mine.description = Поставте її на землю. Вона б'ється ЕЛЕКТРИКОЮ О_О -block.duo.description = Маленька і дешева турель.\nДля прискорення стрільби можна підвести воду або кріогенну рідина. -block.scatter.description = A medium-sized anti-air turret. Sprays clumps of lead or scrap flak at enemy units. -block.arc.description = Турель с малым радиусом атаки.\nДля прискорення стрільби можна підвести воду або кріогенну рідину. +block.duo.description = Маленька і дешева турель.Корисно від наземних одиниць.\nДля прискорення стрільби можна підвести воду або кріогенну рідину. +block.scatter.description = Протиповітряна турель середнього розміру. Розпорошує грудки свинцю або металобрухту на ворожих бойових одиниць. +block.arc.description = Невелика турелька з близьким радіусом дії, яка стріляє електрикою у випадковій дузі до ворога.\nДля прискорення стрільби можна підвести воду або кріогенну рідину. block.hail.description = Далекобійна початкова турель.\nДля прискорення стрільби можна підвести воду або кріогенну рідину. block.lancer.description = Турель, яка стріляє лазером на середню відстань.\nДля прискорення стрільби можна підвести воду або кріогенну рідину. block.wave.description = Турель з середнім радіусом атаки, яка відштовхує супротивників в сторони. @@ -812,13 +847,13 @@ block.silicon-smelter.description = За допомогою піску, вугі block.plastanium-compressor.description = Створює пластинійи з титану і нафти. Вимагає енергії. Для прискорення виробництва можна додати в компресор пісок. block.phase-weaver.description = Виробляє фазову тканину торію і піску. Вимагає багато енергії. block.alloy-smelter.description = Створює кінетичний сплав з титану, кременя, міді і свинця. Вимагає енергію. -block.pulverizer.description = Подрібнює камінь в пісок. Вимагає енергії. +block.pulverizer.description = Подрібнює металобрухт в пісок. Вимагає енергії. block.pyratite-mixer.description = Створює піротит з вугілля, свинцю і піску. Вимагає енергії. block.blast-mixer.description = Створює вибухонебезпечне з'єднання з нафти і піротіта. Для прискорення виробництва можна додати в мішалку пісок. block.cryofluidmixer.description = Виробляє криогенну рідину з води і титану. Вимагає енергії. block.melter.description = Розплавляє металобрухт у шлаки для подальшої переробки або використання у турелях. block.incinerator.description = Якщо є непотрібні ресурси, можна просто їх спалити.\nВимагає енергії. -block.spore-press.description = Compresses spore pods into oil. +block.spore-press.description = Стискає спорові стручки в нафту. block.separator.description = Витягує корисні мінерали з шлаку. block.power-node.description = Максимум допустимо 4 підключення.\nЩоб з'єднати з якимось блоком потрібно наступне:\n1. Щоб він знаходився в радіусі дії \n2. Натиснити на потрібний силовий вузол, а потім на інший силовий вузол або блок. block.power-node-large.description = Силовий вузол другого покоління. Збільшено радіус дії і кількість максимально допустимих підключень. @@ -829,7 +864,7 @@ block.turbine-generator.description = Більш ефективний, ніж г block.thermal-generator.description = Генерує енергію при розміщенні в гарячих місцях. block.solar-panel.description = Забезпечує невелику кількість енергії від сонця. block.solar-panel-large.description = Забезпечує набагато краще джерело живлення, ніж стандартна панель, але в той же час набагато дорожче її побудувати. -block.thorium-reactor.description = Генерує величезну кількість енергії з високоактивного торію. Потребує постійного охолодження. Вибухне сильно, якщо постачається недостатня кількість рідини. +block.thorium-reactor.description = Генерує величезну кількість енергії з високорадіоактивного торію. Потрібно постійне охолодження. Буде сильно вибухнути, якщо буде поставлено недостатню кількість охолоджуючої рідини. Вихідна потужність залежить від повноти, з базовою потужністю, що генерується на повну потужність. block.rtg-generator.description = Радіоізотопний термоелектричний генератор, який не потребує охолодження, але забезпечує меншу потужність, ніж торієвий реактор. block.unloader.description = Вивантажує предмети з контейнера, сховища або ядра на конвеєр або безпосередньо в сусідній блок. Тип вивантажуваного елемента можна змінити, торкнувшись розвантажувача. block.container.description = Зберігає невелику кількість предметів кожного типу. Сусідні контейнери, склепіння та ядра будуть розглядатися як одиничне сховище. [LIGHT_GRAY]Розвантажувач [] можна використовувати для вилучення елементів з контейнера. @@ -839,7 +874,7 @@ block.pneumatic-drill.description = Покращена версія механі block.laser-drill.description = Покращена версія пневматичного бура.\nДобивает теж саме, що і пневматичний бур. Також може добувати торій.\nМожно підвести до нього[BLUE] воду []для збільшення швидкості свердління. block.blast-drill.description = Найпотужніший бур.\n\nВидобуває теж саме, що і лазерний бур. Свердлить швидше всіх бурів, але вимагає ще більше енергії.\nМожно підвести до нього[BLUE] воду [] для збільшення швидкості свердління. block.water-extractor.description = Витягує воду з землі. Використовуйте його, коли поблизу немає озера. -block.cultivator.description = Культивує спори водою для отримання біоматеріі. +block.cultivator.description = Культивує крихітні концентрації спор в готових до промисловості стручки. block.oil-extractor.description = Використовує велику кількість енергії для видобутку нафти з піску, динозаврів (закреслено). Використовуйте його, коли поблизу немає прямого джерела нафти. block.trident-ship-pad.description = Залиште свій поточний корабель і перейдіть в досить добре броньований важкий бомбардувальник.\nВикористовуйте подвійне натискання, стоячи на реконструкторів, щоб перетворитися в цей мех. block.javelin-ship-pad.description = Залиште свій поточний корабель і перейдіть в сильний і швидкий перехоплювач з блискавичним зброєю.\nВикористовуйте подвійне натискання, стоячи на реконструкторів, щоб перетворитися в цей мех. @@ -865,7 +900,7 @@ block.liquid-junction.description = Діє як міст для двох пер block.bridge-conduit.description = Покращений блок перевезення рідин. Дозволяє транспортувати рідини понад 3 блоки будь-якої місцевості або будівлі. block.mechanical-pump.description = Дешевий насос з повільною швидкістю, але без споживання енергії. block.rotary-pump.description = Розширений насос, який подвоює швидкість, використовуючи енергію. -block.thermal-pump.description = Остаточний насос. Тричі швидше, ніж механічний насос і єдиний насос, який здатний отримати лаву. +block.thermal-pump.description = Останній насос. block.router.description = Приймає елементи з одного напрямку і рівномірно виводить їх до 3 інших напрямків. Корисно для розділення матеріалів від одного джерела на кілька. block.distributor.description = Розширений маршрутизатор, який рівномірно розбиває елементи на 7 різних напрямків. block.bridge-conveyor.description = Покращений блок транспортування предметів. Дозволяє транспортувати предмети понад 3 блоки над будь-якої місцевостю або будівлеє. diff --git a/core/assets/bundles/bundle_zh_CN.properties b/core/assets/bundles/bundle_zh_CN.properties index 9f61049e3c..7c19291265 100644 --- a/core/assets/bundles/bundle_zh_CN.properties +++ b/core/assets/bundles/bundle_zh_CN.properties @@ -1,4 +1,4 @@ -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 = 由[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 = 致谢 contributors = 译者和贡献者 discord = 加入 Mindustry 的 Discord! @@ -12,64 +12,66 @@ link.wiki.description = 官方 Mindustry 维基 linkfail = 打开链接失败!\nURL 已经复制到剪贴板。 screenshot = 荧幕截图已放在 {0} gameover = 你的核心被摧毁了! -gameover.pvp = accent] {0}[] 队获胜! +gameover.pvp = [accent] {0}[] 队获胜! highscore = [accent]新纪录! -stat.wave = 战胜的波数:[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. +stat.wave = 战胜的波数:[accent]{0} +stat.enemiesDestroyed = 消灭的敌人:[accent]{0} +stat.built = 建造的建筑:[accent]{0} +stat.destroyed = 摧毁的建筑:[accent]{0} +stat.deconstructed = 拆除的建筑:[accent]{0} +stat.delivered = 发射的资源: +stat.rank = 最终排名:[accent]{0} +placeline = 你选择了一个方块。\n你能通过[accent]长按几秒钟[]并向一个方向拖动来[accent]直线放置方块[]。\n试试看吧。 +removearea = 你选择了拆除模式。\n你能通过[accent]长按几秒钟[]并拖动来[accent]删除矩形内的方块[]。\n试试看吧。 +launcheditems = [accent]发射的资源 map.delete = 确定要删除 "[accent]{0}[]" 地图吗? -level.highscore = 最高分: [accent]{0} -level.select = 选择关卡 +level.highscore = 最高分:[accent]{0} +level.select = 选择关卡(?Level Select) level.mode = 游戏模式: -showagain = 不再显示 +showagain = 下次不再显示 coreattack = < 核心正在受到攻击! > -nearpoint = [[ [scarlet]LEAVE DROP POINT IMMEDIATELY[] ]\nannihilation imminent -outofbounds = [[ OUT OF BOUNDS ]\n[]self-destruct in {0} -database = Core Database +nearpoint = [[ [scarlet]立即离开敌人出生点[] ]\n将被清理 +outofbounds = [[ 超出边界 ]\n[]{0}秒后自毁 +database = 核心数据库 savegame = 保存游戏 loadgame = 载入游戏 joingame = 加入游戏 -addplayers = 增加/删除玩家 +addplayers = 添加/删除玩家 customgame = 自定义游戏 newgame = 新游戏 none = <无> +minimap = Minimap close = 关闭 quit = 退出 maps = 地图 continue = 继续 -maps.none = [LIGHT_GRAY]未发现地图! +maps.none = [LIGHT_GRAY]没有找到地图! about.button = 关于 name = 名字: -noname = Pick a[accent] player name[] first. +noname = 先取一个[accent] 玩家名[]。 filename = 文件名: unlocked = 新方块已解锁! -completed = [accent]Completed -techtree = Tech Tree -research.list = [LIGHT_GRAY]Research: -research = Research -researched = [LIGHT_GRAY]{0} researched. +completed = [accent]完成的 +techtree = 科技树 +research.list = [LIGHT_GRAY]研究: +research = 研究 +researched = [LIGHT_GRAY]{0} 己研究。 players = {0} 玩家在线 players.single = {0} 玩家在线 server.closing = [accent]正在关闭服务器…… server.kicked.kick = 你被踢出服务器了! server.kicked.serverClose = 服务器已关闭。 -server.kicked.clientOutdated = 客户端版本过旧!请升级! -server.kicked.serverOutdated = 服务器版本过旧!请联系房主升级! -server.kicked.banned = 你被这个服务器拉黑了。 +server.kicked.clientOutdated = 过旧的客户端!更新你的游戏! +server.kicked.serverOutdated = 过旧的服务器!联系房主升级! +server.kicked.banned = 你在这个服务器上被禁了。 server.kicked.recentKick = 你刚刚被踢出服务器。\n请稍后重新连接! server.kicked.nameInUse = 服务器中已经\n有人有相同的名字了。 -server.kicked.nameEmpty = 你的名字必须至少包含一个字母或数字。 -server.kicked.idInUse = 你已经在服务器中!不允许用两个账号。 -server.kicked.customClient = 这个服务器不支持修改版客户端,请下载官方版本。 -server.kicked.gameover = ! -host.info = [accent]创建局域网游戏[]按钮会在[scarlet]6567[]端口运行一个服务器。[]\n任何在同一个[LIGHT_GRAY]网络或本地网络[]下的人都将在服务器列表中看到你的服务器。\n\n如果你想让别人在任何地方都能通过IP地址连接,你需要设定[accent]端口转发[]。\n\n[LIGHT_GRAY]请注意:如果某人无法连接到你的局域网游戏,请确保你在防火墙设置里允许了Mindustry连接本地网络。 -join.info = 你可以在这里输入[accent]服务器的IP地址[]以连接,或寻找[accent]本地网络[]中的服务器以连接。\n目前支持局域网或广域网多人游戏。\n\n[LIGHT_GRAY]请注意:没有全球服务器列表;如果你想通过IP地址连接某个服务器,你需要向房主询问IP地址。 +server.kicked.nameEmpty = 你选择的名字是无效的。 +server.kicked.idInUse = 你已在这个服务器上!不允许用两个账号连接。 +server.kicked.customClient = 这个服务器不支持定制版本。下载官方版本。 +server.kicked.gameover = 游戏结束! +host.info = [accent]创建局域网游戏[]按钮会在[scarlet]6567[]端口运行一个服务器。[]\n任何在同一个[LIGHT_GRAY]wifi或本地网络[]下的人都应该可以在服务器列表中看到你的服务器。\n\n如果你想让别人在任何地方都能通过IP地址连接,你需要设定[accent]端口转发[]。\n\n[LIGHT_GRAY]注意:如果某人无法连接到你的局域网游戏,请确保你在防火墙设置里允许了Mindustry访问本地网络。 +join.info = 此时,可以输入[accent]服务器的IP地址[]来连接,或寻找[accent]本地网络[]中的服务器来连接。\n局域网或广域网多人游戏都被支持。\n\n[LIGHT_GRAY]注意:没有全球服务器列表;如果你想通过IP地址连接某个服务器,你需要向房主询问IP地址。 hostserver = 创建服务器 hostserver.mobile = 创建\n服务器 host = 创建 @@ -80,189 +82,190 @@ server.refreshing = 正在刷新服务器 hosts.none = [lightgray]未发现局域网游戏! host.invalid = [scarlet]无法连接服务器。 trace = 跟踪玩家 -trace.playername = 玩家名字: [accent]{0} -trace.ip = IP地址: [accent]{0} -trace.id = ID︰[accent]{0} -trace.android = 安卓客户端: [accent]{0} -trace.modclient = 修改版客户端: [accent]{0} +trace.playername = 玩家名称:[accent]{0} +trace.ip = IP地址:[accent]{0} +trace.id = 唯一的ID:[accent]{0} +trace.android = 安卓客户端:[accent]{0} +trace.modclient = 定制版客户端:[accent]{0} trace.totalblocksbroken = 总共破坏了 [accent]{0} 个方块。 -trace.structureblocksbroken = 总共破坏了[accent]{0}个方块。 -trace.lastblockbroken = 最后破坏的方块: [accent]{0} +trace.structureblocksbroken = 总共破坏了 [accent]{0} 个建筑物方块。 +trace.lastblockbroken = 最后破坏的方块:[accent]{0} trace.totalblocksplaced = 总共放置了 [accent]{0} 个方块。 -trace.lastblockplaced = 最后放置的方块: [accent]{0} -invalidid = 无效的客户端ID!请提交错误报告。 +trace.lastblockplaced = 最后放置的方块:[accent]{0} +invalidid = 无效的客户端ID!提交一个错误报告。 server.bans = 黑名单 -server.bans.none = 没有被拉黑的玩家! +server.bans.none = 没有找到被拉黑的玩家! server.admins = 管理员 -server.admins.none = 没有管理员! +server.admins.none = 没有找到管理员! server.add = 添加服务器 -server.delete = 确定要删除这个服务器吗? -server.hostname = 主机︰{0} +server.delete = 你确定要删除这个服务器吗? +server.hostname = 主机:{0} server.edit = 编辑服务器 -server.outdated = [crimson]服务器过旧![] -server.outdated.client = [crimson]客户端过旧![] -server.version = [lightgray]版本: {0} -server.custombuild = [yellow]修改版 -confirmban = 确认拉黑这个玩家吗? -confirmkick = 您确定要踢出这个玩家吗? -confirmunban = 确认要取消拉黑这个玩家吗? -confirmadmin = 确认要添加这个玩家为管理员吗? -confirmunadmin = 确认要取消这个玩家的管理员身份吗? +server.outdated = [crimson]过旧的服务器![] +server.outdated.client = [crimson]过旧的客户端![] +server.version = [lightgray]版本:{0} {1} +server.custombuild = [yellow]定制版 +confirmban = 你确认你想拉黑这名玩家吗? +confirmkick = 你确定你想要踢走这名玩家吗? +confirmunban = 你确定你想要取消拉黑这名玩家吗? +confirmadmin = 你确定你想要使这名玩家成为一个管理员吗? +confirmunadmin = 你确定你想要删除这名玩家的管理员地位吗? joingame.title = 加入游戏 -joingame.ip = IP: +joingame.ip = 地址: disconnect = 已断开 -disconnect.data = 载入世界失败! -connecting = [accent]连接中…… -connecting.data = [accent]加载世界中…… -server.port = 端口︰ -server.addressinuse = 地址已经使用! -server.invalidport = 无效的端口! +disconnect.data = 读取世界数据失败! +connecting = [accent]正在连接... +connecting.data = [accent]正在加载世界数据... +server.port = 端口: +server.addressinuse = 地址已经在使用中! +server.invalidport = 无效的端口号! server.error = [crimson]创建服务器错误:[accent]{0} -save.old = 这个存档属于旧版本游戏,无法继续使用了。\n\n[LIGHT_GRAY]存档向下兼容将在 4.0 版本中实现。 +save.old = 这个存档属于旧版本游戏,不再被使用。\n\n[LIGHT_GRAY]存档向下兼容将在完整的 4.0 版本中被实现。 save.new = 新存档 -save.overwrite = 确认要覆盖这个存档吗? +save.overwrite = 你确定你要覆盖这个存档位吗? overwrite = 覆盖 -save.none = 没有存档! -saveload = [accent]保存中…… +save.none = 没有存档被找到! +saveload = [accent]正在保存... savefail = 保存失败! -save.delete.confirm = 确认要删除这个存档吗? +save.delete.confirm = 你确定你要删除这个存档吗? save.delete = 删除 save.export = 导出存档 -save.import.invalid = [accent]存档无效! +save.import.invalid = [accent]这个存档是无效的! save.import.fail = [crimson]导入存档失败:[accent]{0} save.export.fail = [crimson]导出存档失败:[accent]{0} save.import = 导入存档 -save.newslot = 保存游戏: +save.newslot = 保存的名称: save.rename = 重命名 -save.rename.text = 新名字: +save.rename.text = 新名称: selectslot = 选择一个存档。 -slot = [accent]存档 {0} -save.corrupted = [accent]存档损坏或无效!\n如果你刚刚升级了游戏,那么这可能是因为存档格式改变了,而[scarlet]不是[] bug 。 +slot = [accent]存档位 {0} +save.corrupted = [accent]存档损坏或无效!\n如果你刚刚升级了游戏,那么这可能是因为存档格式改变了,而[scarlet]不是[]bug 。 empty = <空> on = 开 off = 关 save.autosave = 自动保存:{0} save.map = 地图:{0} -save.wave = 第 {0} 波 -save.difficulty = 难度: {0} -save.date = 最后保存日期:{0} +save.wave = 波次 {0} +save.difficulty = 难度:{0} +save.date = 最后保存过:{0} save.playtime = 游戏时间:{0} -warning = Warning. +warning = 警告。 confirm = 确认 delete = 删除 ok = 好的 open = 打开 cancel = 取消 openlink = 打开链接 -copylink = 删除链接 +copylink = 复制链接 back = 返回 -quit.confirm = 确认要退出? +quit.confirm = 你确定你想要退出? changelog.title = 更新日志 changelog.loading = 正在获取更新日志... -changelog.error.android = [accent]请注意更新日志有时在安卓 4.4 以下不工作。\n这是因为安卓系统的一个 bug 。 -changelog.error.ios = [accent]iOS还不支持更新日志。 +changelog.error.android = [accent]注意更新日志有时在安卓 4.4 以下不工作。\n这是安卓系统内部的一个bug。 +changelog.error.ios = [accent]更新日志当前在iOS中不被支持。 changelog.error = [scarlet]获取更新日志失败!\n请检查你的网络。 -changelog.current = [yellow][[Current version] -changelog.latest = [accent][[Latest version] -loading = [accent]加载中…… -saving = [accent]保存中…… -wave = [accent]第 {0} 波 -wave.waiting = 下一波将在 {0} 秒后到来 -waiting = 等待中…… +changelog.current = [yellow][[当前版本] +changelog.latest = [accent][[最新版本] +loading = [accent]正在加载... +saving = [accent]正在保存... +wave = [accent]波次 {0} +wave.waiting = [LIGHT_GRAY]下一波将在{0}秒后到来 waiting.players = 等待玩家中…… -wave.enemies = 剩下 [LIGHT_GRAY]{0} 敌人 -wave.enemy = 剩下 [LIGHT_GRAY]{0} 敌人 +waiting = [LIGHT_GRAY]正在等待... +wave.enemies = [LIGHT_GRAY]剩余 {0} 个敌人 +wave.enemy = [LIGHT_GRAY]剩余 {0} 个敌人 loadimage = 加载图片 saveimage = 保存图片 unknown = 未知 custom = 自定义 builtin = 内建的 -map.delete.confirm = 确认要删除地图吗?这个操作无法撤销! +map.delete.confirm = 你确定你想要删除这张地图吗?这个操作无法取消! map.random = [accent]随机地图 map.nospawn = 这个地图没有核心!请在编辑器中添加一个[ROYAL]蓝色[]的核心。 map.nospawn.pvp = 这个地图没有敌人的核心!请在编辑器中添加一个[ROYAL]红色[]的核心。 +map.nospawn.attack = 这个地图没有敌人的核心!请在编辑中向地图添加一个[SCARLET]红色[]的核心。 map.invalid = 地图载入错误:地图文件可能已经损坏。 editor.brush = 笔刷 editor.openin = 在编辑器中打开 -editor.oregen = 生成矿石 -editor.oregen.info = 生成矿石: -editor.mapinfo = 地图详情 +editor.oregen = 矿石的生成 +editor.oregen.info = 矿石的生成: +editor.mapinfo = 地图信息 editor.author = 作者: editor.description = 描述: -editor.waves = Waves: -waves.title = Waves -waves.remove = Remove +editor.waves = 波数: +waves.title = 波数 +waves.remove = 去除 waves.never = -waves.every = every -waves.waves = wave(s) -waves.perspawn = per spawn -waves.to = to -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 = 名字: -editor.teams = 团队 +waves.every = 每 +waves.waves = 波 +waves.perspawn = 每次生成 +waves.to = 至 +waves.boss = 首领(Boos) +waves.preview = 预览 +waves.edit = 编辑... +waves.copy = 复制到剪贴板 +waves.load = 从剪贴板读取 +waves.invalid = 剪贴板中无效的波次信息。 +waves.copied = 波次信息已复制。 +editor.default = [LIGHT_GRAY]<默认> +edit = 编辑... +editor.name = 名称: +editor.teams = 队伍 editor.elevation = 高度 -editor.errorload = Error loading file:\n[accent]{0} -editor.errorsave = Error saving file:\n[accent]{0} -editor.errorname = Map has no name defined. -editor.update = Update -editor.randomize = Randomize -editor.apply = Apply +editor.errorload = 读取文件时出现错误:\n[accent]{0} +editor.errorsave = 保存文件时出现错误:\n[accent]{0} +editor.errorname = 地图没有被定义的名称。 +editor.update = 更新(Update) +editor.randomize = 随机化 +editor.apply = 应用 editor.generate = 生成 -editor.resize = 调整 +editor.resize = 调整大小 editor.loadmap = 载入地图 editor.savemap = 保存地图 editor.saved = 已保存! -editor.save.noname = 你的地图还没有名字!在“地图信息”菜单里设置一个名字。 -editor.save.overwrite = 你的地图覆盖了一个内建的地图!在“地图信息”菜单里重新设置一个新的名字。 -editor.import.exists = [scarlet]无法导入:[] 已经有一个叫 '{0}' 的内建地图存在。 -editor.import = 导入…… +editor.save.noname = 你的地图没有名字!在“地图信息”菜单里设置一个。 +editor.save.overwrite = 你的地图覆盖了一个内建的地图!在“地图信息”菜单里重新设置一个不同的名称。 +editor.import.exists = [scarlet]无法导入:[]名为‘{0}’的内建地图已存在! +editor.import = 导入... editor.importmap = 导入地图 editor.importmap.description = 导入一个已经存在的地图 editor.importfile = 导入文件 editor.importfile.description = 导入一个外置的地图文件 editor.importimage = 导入地形图像 -editor.importimage.description = 导入外置地图图像文件 -editor.export = 导出…… +editor.importimage.description = 导入一个外置的地图图像文件 +editor.export = 导出... editor.exportfile = 导出文件 editor.exportfile.description = 导出一个地图文件 editor.exportimage = 导出一个地形文件 editor.exportimage.description = 导出一个地图图像文件 editor.loadimage = 导入地形 editor.saveimage = 导出地形 -editor.unsaved = [scarlet]你有未保存的更改![]\n确定要退出? -editor.resizemap = 调整地图 -editor.mapname = 地图名字: +editor.unsaved = [scarlet]你有未保存的更改![]\n你确定你想要要退出? +editor.resizemap = 调整地图大小 +editor.mapname = 地图名称: editor.overwrite = [accent]警告!\n这将会覆盖一个已经存在的地图。 -editor.overwrite.confirm = [scarlet]警告![] 存在同名地图,确定要覆盖? +editor.overwrite.confirm = [scarlet]警告![]存在同名地图。你确定你想要覆盖? editor.selectmap = 选择一个地图加载: -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 +filters.empty = [LIGHT_GRAY]没有过滤器(filters)!用下方的按钮添加一个。 +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 = 方块 +filter.option.floor = 地面 +filter.option.wall = 墙 +filter.option.ore = 矿石 +filter.option.floor2 = 第二地面?(Secondary Floor) +filter.option.threshold2 = 第二门槛?(Secondary Threshold) width = 宽度: height = 高度: menu = 菜单 @@ -278,10 +281,11 @@ tutorial = 教程 editor = 编辑器 mapeditor = 地图编辑器 donate = 捐赠 -abandon = Abandon +abandon = 放弃 abandon.text = 这个区域和它的所有资源会被敌人没收. locked = 已被锁定 complete = [LIGHT_GRAY]完成: +zone.requirement = Wave {0} in zone {1} resume = Resume Zone:\n[LIGHT_GRAY]{0} bestwave = [LIGHT_GRAY]最好: {0} launch = < 发射 > @@ -293,11 +297,11 @@ uncover = Uncover configure = 设定 Loadout configure.locked = [LIGHT_GRAY]到达第 {0} 波\n才设定 loadout. zone.unlocked = [LIGHT_GRAY]{0} 已解锁。 -zone.complete = 区域条件达成。 +zone.requirement.complete = Wave {0} reached:\n{1} zone requirements met. zone.config.complete = Wave {0} reached:\nLoadout config unlocked. zone.resources = 已被发现的资源: add = Add... -boss.health = Boss Health +boss.health = Boss 生命值 connectfail = [crimson]服务器连接失败: [accent]{0} error.unreachable = 服务器无法访问。 error.invalidaddress = 地址无效。 @@ -307,13 +311,13 @@ error.alreadyconnected = 已连接。 error.mapnotfound = 找不到地图文件! error.io = 网络 I/O 错误。 error.any = 未知网络错误。 -zone.groundZero.name = Ground Zero -zone.craters.name = The Craters -zone.frozenForest.name = Frozen Forest -zone.ruinousShores.name = Ruinous Shores -zone.stainedMountains.name = Stained Mountains -zone.desolateRift.name = Desolate Rift -zone.nuclearComplex.name = Nuclear Production Complex +zone.groundZero.name = 零号地区 +zone.craters.name = 陨石地带 +zone.frozenForest.name = 冰冻森林 +zone.ruinousShores.name = 毁灭海岸 +zone.stainedMountains.name = 绵延群山 +zone.desolateRift.name = 荒芜裂谷 +zone.nuclearComplex.name = 核能生产 settings.language = 语言 settings.reset = 恢复默认 settings.rebind = 重新绑定 @@ -332,31 +336,30 @@ no = 不 info.title = [accent]详情 error.title = [crimson]发生了一个错误 error.crashtitle = 发生了一个错误 -blocks.outputspeed = Drill Speed: {0}/s -blocks.efficiency = Efficiency: {0}% -blocks.unknown = [LIGHT_GRAY]??? -blocks.blockinfo = 方块详情 -blocks.powerbalance = Power: {0} -blocks.poweroutput = Power Output: {0} +blocks.input = Input +blocks.output = Output +blocks.booster = Booster +block.unknown = [LIGHT_GRAY]??? blocks.powercapacity = 能量容量 blocks.powershot = 能量/发射 blocks.targetsair = 攻击空中单位 -blocks.targetsground = Targets Ground -blocks.items = Items: {0} +blocks.targetsground = 攻击地面单位 blocks.itemsmoved = 移动速度 +blocks.launchtime = 发射间隔时间 blocks.shootrange = 范围 blocks.size = 尺寸 blocks.liquidcapacity = 液体容量 -blocks.maxitemssecond = 最大物品数量 blocks.powerrange = 能量范围 blocks.poweruse = 能量使用 blocks.powerdamage = 功率/损伤 -blocks.inputitemcapacity = 最大输入 -blocks.outputitemcapacity = 最大输出 blocks.itemcapacity = 物品容量 blocks.basepowergeneration = 基础能源输出 blocks.powertransferspeed = 能量传输 blocks.craftspeed = 生产速度 +blocks.productiontime = 生产时间 +blocks.repairtime = 方块完全修复时间 +blocks.speedincrease = 提速 +blocks.range = 范围 blocks.inputliquid = 液体输入 blocks.inputliquidaux = 辅助液体 blocks.inputitem = 物品输入 @@ -364,31 +367,40 @@ blocks.inputitems = 物品输入 blocks.outputitem = 物品输出 blocks.drilltier = 可钻探矿物 blocks.drillspeed = 基础钻探速度 -blocks.maxunits = Max Active Units -blocks.liquidoutput = 液体输出 -blocks.liquidoutputspeed = 液体输出速度 -blocks.liquiduse = 液体使用速度 -blocks.coolant = 冷却剂 -blocks.liquid = Liquid -blocks.coolantuse = 冷却剂使用速度 -blocks.inputliquidfuel = 液体燃料输入 -blocks.liquidfueluse = 液体燃料使用速度 -blocks.boostitem = 强化物件 -blocks.boostliquid = 强化液体 +blocks.boosteffect = 加成影响 +blocks.maxunits = 最大单位数量 blocks.health = 生命值 -blocks.heat = Heat +blocks.heat = 热量 blocks.power = 电力 -blocks.progress = Build Progress -blocks.spawned = Units: {0}/{1} -blocks.power.satisfaction = 电力见面 +blocks.progress = 制造进度 +blocks.spawned = 单位数量: {0}/{1} +blocks.power.satisfaction = 电力输入 blocks.inaccuracy = 误差 blocks.shots = 发射数 blocks.reload = 重新装弹 -blocks.inputfuel = 燃料 -blocks.fuelburntime = 燃料燃烧时间 -blocks.inputcapacity = 输入容量 -blocks.outputcapacity = 输出容量 blocks.ammo = 子弹 +bar.drillspeed = 挖掘速度: {0}/s +bar.efficiency = 效率: {0}% +bar.powerbalance = 能量: {0} +bar.poweramount = Power: {0} +bar.poweroutput = 能量输出: {0} +bar.items = 物体: {0} +bar.liquid = 液体 +bar.heat = Heat +bar.power = 电力 +bar.progress = 制造进度 +bar.spawned = 单位数量: {0}/{1} +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]x 子弹数量 +bullet.reload = [stat]{0}[lightgray]x 装弹 unit.blocks = 方块 unit.powersecond = 能量单位/秒 unit.liquidsecond = 液体单位/秒 @@ -397,6 +409,9 @@ unit.liquidunits = 液体单位 unit.powerunits = 能量单位 unit.degrees = 度 unit.seconds = 秒 +unit.persecond = /sec +unit.timesspeed = x speed +unit.percent = % unit.items = 物品 category.general = 普通 category.power = 能量 @@ -405,13 +420,16 @@ category.items = 物品 category.crafting = 制造 category.shooting = 发射 category.optional = 可选的增强物品 -setting.animatedwater.name = Animated Water +setting.landscape.name = 锁定横屏 +setting.shadows.name = 影子 +setting.animatedwater.name = 流动的水 +setting.antialias.name = 抗锯齿[LIGHT_GRAY] (需要重新启动)[] setting.indicators.name = 队友指示器 setting.autotarget.name = 自动发射 setting.fpscap.name = 最高 FPS setting.fpscap.none = 无 setting.fpscap.text = {0} FPS -setting.swapdiagonal.name = Always Diagonal Placement +setting.swapdiagonal.name = 总是自动铺设 setting.difficulty.training = 训练 setting.difficulty.easy = 简单 setting.difficulty.normal = 普通 @@ -424,9 +442,11 @@ setting.sensitivity.name = 控制器灵敏度 setting.saveinterval.name = 自动保存间隔 setting.seconds = {0} 秒 setting.fullscreen.name = 全屏 +setting.borderless.name = 无边界 setting.fps.name = 显示 FPS setting.vsync.name = 帧同步 setting.lasers.name = 显示能量射线 +setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance) setting.minimap.name = 显示小地图 setting.musicvol.name = 音乐音量 setting.mutemusic.name = 静音 @@ -448,7 +468,7 @@ keybind.screenshot.name = 地图截图 keybind.move_x.name = 水平移动 keybind.move_y.name = 垂直移动 keybind.select.name = 选择 -keybind.diagonal_placement.name = Diagonal Placement +keybind.diagonal_placement.name = 自动铺设 keybind.pick.name = 选择方块 keybind.break_block.name = 破坏方块 keybind.deselect.name = 取消 @@ -470,7 +490,7 @@ keybind.drop_unit.name = 掉落单位 keybind.zoom_minimap.name = 小地图缩放 mode.help.title = 模式说明 mode.survival.name = 生存 -mode.survival.description = 正常的游戏模式,有限的资源和自动入射波。 +mode.survival.description = 正常的游戏模式,有限的资源和自动波次。 mode.sandbox.name = 沙盒 mode.sandbox.description = 无限的资源,不会自动生成敌人。 mode.freebuild.name = 自由建造 @@ -478,7 +498,19 @@ mode.freebuild.description = 有限的资源,不会自动生成敌人。 mode.pvp.name = PvP mode.pvp.description = 和本地玩家对战. mode.attack.name = 攻击 -mode.attack.description = 没有波数,但是有吹毁敌人基地的任务. +mode.attack.description = 没有波数,但是有摧毁敌人基地的任务. +mode.custom = 自定义模式 +rules.infiniteresources = 无限资源 +rules.wavetimer = 波次计时器 +rules.waves = 波次 +rules.enemyCheat = AI无限资源 +rules.pvp = PvP +rules.unitdrops = 敌人出生点 +rules.enemycorebuildradius = 敌对核心非建设区半径:[LIGHT_GRAY](格) +rules.respawntime = 重生时间:[LIGHT_GRAY](秒) +rules.wavespacing = 波次间隔时间:[LIGHT_GRAY](秒) +rules.buildcostmultiplier = 建设花费倍数 +rules.buildspeedmultiplier = 建设时间倍数 content.item.name = 物品 content.liquid.name = 液体 content.unit.name = 部队 @@ -490,7 +522,7 @@ item.lead.name = 铅 item.lead.description = 一种基本的起始材料。被广泛用于电子设备和液体运输方块。 item.coal.name = 煤 item.coal.description = 一种常见并容易获得的燃料。 -item.graphite.name = Graphite +item.graphite.name = 石墨 item.titanium.name = 钛 item.titanium.description = 一种罕见的超轻金属,被广泛运用于液体运输、钻头和飞机。 item.thorium.name = 钍 @@ -503,39 +535,39 @@ item.phase-fabric.name = 相织物 item.phase-fabric.description = 一种接近0重量的物质,用于先进的电子技术和自我修复技术。 item.surge-alloy.name = 巨浪合金 item.surge-alloy.description = 一种具有独特电气性能的高级合金。 -item.spore-pod.name = Spore Pod -item.spore-pod.description = Used for conversion into oil, explosives and fuel. +item.spore-pod.name = 孢子荚 +item.spore-pod.description = 一种用于制造石油,炸药及燃料的生物质。 item.sand.name = 沙 item.sand.description = 一种常见的材料,广泛用于冶炼,包括制作合金和助熔剂。 item.blast-compound.name = 爆炸混合物 item.blast-compound.description = 一种用于炸弹和炸药的挥发性混合物。虽然它可以作为燃料燃烧,但不建议这样做。 item.pyratite.name = 硫 item.pyratite.description = 一种燃烧武器中使用的极易燃物质。 -item.metaglass.name = Metaglass +item.metaglass.name = 钢化玻璃 item.metaglass.description = 一种超级强硬的复合玻璃。通常用来传送和收藏液体 -item.scrap.name = Scrap -item.scrap.description = Leftover remnants of old structures and units. Contains trace amounts of many different metals. +item.scrap.name = 废料 +item.scrap.description = 一种废弃的建筑物及废弃单位的残骸,富含多种金属元素。 liquid.water.name = 水 -liquid.slag.name = Slag +liquid.slag.name = 岩浆 liquid.oil.name = 石油 liquid.cryofluid.name = 冷冻液 -mech.alpha-mech.name = Alpha +mech.alpha-mech.name = 阿尔法 mech.alpha-mech.weapon = 重型机枪 mech.alpha-mech.ability = 无人机群 mech.alpha-mech.description = 标准的机甲。具有不错的速度和伤害输出;,可以制造多达 3 架无人机以提高进攻能力。 -mech.delta-mech.name = Delta +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 = 后勤机甲。治疗友军。可以熄灭火焰并治疗一定范围内的友军。 -mech.omega-mech.name = Omega +mech.omega-mech.name = 欧米茄 mech.omega-mech.weapon = 导弹群 mech.omega-mech.ability = 配置装甲 mech.omega-mech.description = 一种装甲厚重的机甲,用于在前线攻击。它的护甲可以阻挡高达 90% 的伤害。 -mech.dart-ship.name = Dart +mech.dart-ship.name = 飞镖 mech.dart-ship.weapon = 机枪 mech.dart-ship.description = 标准飞船。快速轻便,但攻击能力低,采矿速度快。 mech.javelin-ship.name = 标枪 @@ -545,7 +577,7 @@ mech.javelin-ship.ability = 放电助推器 mech.trident-ship.name = 三叉戟 mech.trident-ship.description = 一种重型轰炸机。有厚装甲。 mech.trident-ship.weapon = 炸弹 -mech.glaive-ship.name = Glaive +mech.glaive-ship.name = 阔剑 mech.glaive-ship.description = 一种大型,装甲厚重的武装直升机。配备燃烧机枪。有优秀的加速能力和最快的速度。 mech.glaive-ship.weapon = 火焰机枪 item.explosiveness = [LIGHT_GRAY]爆炸性:{0} @@ -554,11 +586,12 @@ item.radioactivity = [LIGHT_GRAY]放射性:{0} unit.health = [LIGHT_GRAY]生命值:{0} unit.speed = [LIGHT_GRAY]速度:{0} mech.weapon = [LIGHT_GRAY]武器:{0} -mech.health = [LIGHT_GRAY]Health: {0} +mech.health = [LIGHT_GRAY]生命值: {0} mech.itemcapacity = [LIGHT_GRAY]物品容量:{0} mech.minespeed = [LIGHT_GRAY]采矿速度:{0} mech.minepower = [LIGHT_GRAY]采矿力量:{0} mech.ability = [LIGHT_GRAY]能力:{0} +mech.buildspeed = [LIGHT_GRAY]建造速度:{0}% liquid.heatcapacity = [LIGHT_GRAY]热容量:{0} liquid.viscosity = [LIGHT_GRAY]粘度:{0} liquid.temperature = [LIGHT_GRAY]温度:{0} @@ -579,24 +612,28 @@ block.scrap-wall-large.name = Large Scrap Wall block.scrap-wall-huge.name = Huge Scrap Wall block.scrap-wall-gigantic.name = Gigantic Scrap Wall block.thruster.name = Thruster -block.kiln.name = Kiln -block.kiln.description = Smelts sand and lead into metaglass. Requires small amounts of power. -block.graphite-press.name = Graphite Press -block.multi-press.name = Multi-Press -block.constructing = {0}\n[LIGHT_GRAY](Constructing) +block.kiln.name = 熔炉 +block.kiln.description = 将铅和沙子熔炼成钢化玻璃,需要少量电力。 +block.graphite-press.name = 石墨压缩机 +block.multi-press.name = 大型石墨压缩机 +block.constructing = {0}\n[LIGHT_GRAY](建造中) block.spawn.name = 敌人出生点 -block.core-shard.name = Core: Shard -block.core-foundation.name = Core: Foundation -block.core-nucleus.name = Core: Nucleus +block.core-shard.name = 小型核心 +block.core-foundation.name = 中型核心 +block.core-nucleus.name = 大型核心 block.deepwater.name = 深水 block.water.name = 水 +block.tainted-water.name = Tainted Water +block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Tar block.stone.name = 石头 block.sand.name = 沙子 +block.darksand.name = Dark Sand block.ice.name = 冰 block.snow.name = 雪 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 @@ -619,8 +656,8 @@ block.magmarock.name = Magma Rock block.cliffs.name = Cliffs block.copper-wall.name = 铜墙 block.copper-wall-large.name = 大型铜墙 -block.titanium-wall.name = Titanium Wall -block.titanium-wall-large.name = Large Titanium Wall +block.titanium-wall.name = 钛墙 +block.titanium-wall-large.name = 大型钛墙 block.phase-wall.name = 相织布墙 block.phase-wall-large.name = 大型相织布墙 block.thorium-wall.name = 钍墙 @@ -628,7 +665,8 @@ block.thorium-wall-large.name = 大型钍墙 block.door.name = 门 block.door-large.name = 大门 block.duo.name = 双管炮 -block.scatter.name = Scatter +block.scorch.name = 火焰炮 +block.scatter.name = 分裂炮 block.hail.name = 冰雹炮 block.lancer.name = 蓝瑟炮 block.conveyor.name = 传送带 @@ -646,29 +684,29 @@ block.pulverizer.name = 粉碎机 block.cryofluidmixer.name = 冷冻液混合器 block.melter.name = 熔炉 block.incinerator.name = 焚化炉 -block.spore-press.name = Spore Press +block.spore-press.name = 孢子压缩机 block.separator.name = 分离机 block.power-node.name = 能量节点 block.power-node-large.name = 大型能量节点 -block.surge-tower.name = Surge Tower +block.surge-tower.name = 远程输电塔 block.battery.name = 电池 block.battery-large.name = 大型电池 block.combustion-generator.name = 燃烧发电机 block.turbine-generator.name = 涡轮发电机 -block.differential-generator.name = Differential Generator -block.impact-reactor.name = Impact Reactor +block.differential-generator.name = 差动发电机 +block.impact-reactor.name = 冲击反应堆 block.mechanical-drill.name = 机械钻头 block.pneumatic-drill.name = 气动钻头 block.laser-drill.name = 激光钻头 block.water-extractor.name = 抽水机 block.cultivator.name = 耕种机 -block.alpha-dart-mech-pad.name = Alpha-Dart Mech Pad -block.delta-mech-pad.name = Delta 机甲平台 +block.alpha-dart-mech-pad.name = 阿尔法-飞镖 机甲平台 +block.delta-mech-pad.name = 德尔塔 机甲平台 block.javelin-ship-pad.name = 标枪 机甲平台 block.trident-ship-pad.name = 三叉戟 机甲平台 -block.glaive-ship-pad.name = Glaive 机甲平台 -block.omega-mech-pad.name = Omega 机甲平台 -block.tau-mech-pad.name = Tau 机甲平台 +block.glaive-ship-pad.name = 阔剑 机甲平台 +block.omega-mech-pad.name = 欧米茄 机甲平台 +block.tau-mech-pad.name = 医疗机 机甲平台 block.conduit.name = 导管 block.mechanical-pump.name = 机械泵 block.item-source.name = 物品源 @@ -695,7 +733,7 @@ block.phantom-factory.name = 鬼怪无人机工厂 block.wraith-factory.name = 幻影战机工厂 block.ghoul-factory.name = 食尸鬼轰炸机工厂 block.dagger-factory.name = 尖刀机甲工厂 -block.crawler-factory.name = Crawler Mech Factory +block.crawler-factory.name = 爬行者机甲工厂 block.titan-factory.name = 泰坦机甲工厂 block.fortress-factory.name = 堡垒机甲工厂 block.revenant-factory.name = 亡魂战机工厂 @@ -713,6 +751,7 @@ block.blast-drill.name = 爆破钻头 block.thermal-pump.name = 热能泵 block.thermal-generator.name = 热能发电机 block.alloy-smelter.name = 合金冶炼厂 +block.mender.name = Mender block.mend-projector.name = 修理投影器 block.surge-wall.name = 波动墙 block.surge-wall-large.name = 大型波动墙 @@ -726,8 +765,9 @@ block.rtg-generator.name = RTG 发电机 block.spectre.name = 幽灵 block.meltdown.name = 熔毁 block.container.name = 容器 -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.name = 发射台 +block.launch-pad.description = 不通过核心发射物体。尚未完成。 +block.launch-pad-large.name = 大型发射台 team.blue.name = 蓝 team.red.name = 红 team.orange.name = 橙 @@ -740,7 +780,7 @@ unit.phantom.name = 鬼怪无人机 unit.phantom.description = 一种先进的无人机单位。自动开采矿石,收集物品和修理块。比初始无人机有效得多。 unit.dagger.name = 尖刀 unit.dagger.description = 基础的地面单位,在蜂群中很有用。 -unit.crawler.name = Crawler +unit.crawler.name = 爬行者 unit.titan.name = 泰坦 unit.titan.description = 高级的有武装地面单位,使用电石作为弹药.攻击地面单位和空中单位. unit.ghoul.name = 食尸鬼轰炸机 @@ -750,11 +790,11 @@ unit.wraith.description = 一种快速,打了就跑的截击机。 unit.fortress.name = 堡垒 unit.fortress.description = 一种重炮地面部队。 unit.revenant.name = 亡魂 -unit.eruptor.name = Eruptor -unit.chaos-array.name = Chaos Array -unit.eradicator.name = Eradicator -unit.lich.name = Lich -unit.reaper.name = Reaper +unit.eruptor.name = 暴君 +unit.chaos-array.name = 混沌者 +unit.eradicator.name = 根除者 +unit.lich.name = 尸鬼 +unit.reaper.name = 死神 tutorial.begin = 你的任务是消灭[LIGHT_GRAY] 敌人 [].\n\n首先开始[accent] 采集铜矿 []。点击核心附近的铜矿开始。 tutorial.drill = 手动采矿效率低.\n[accent] 钻头 []可以自动采矿.\n放一个在铜矿上吧. tutorial.conveyor = [accent]传送带[] 可以把物资传送到核心.\n请造一个传送线,从钻头到核心. @@ -791,7 +831,7 @@ block.overdrive-projector.description = 提高附近建筑物的速度,如钻 block.force-projector.description = 自身周围创建一个六边形力场,保护建筑物和内部单位免受子弹的伤害。 block.shock-mine.description = 伤害踩到它的敌人。敌人几乎看不到它。 block.duo.description = 小而便宜的炮塔。 -block.scatter.description = A medium-sized anti-air turret. Sprays clumps of lead or scrap flak at enemy units. +block.scatter.description = 中型防空炮塔,向空中单位发射铅或废料。 block.arc.description = 小型炮塔,发射电弧。 block.hail.description = 小型炮兵炮台。 block.lancer.description = 中型炮塔,发射带电的电子束。 @@ -818,7 +858,7 @@ block.blast-mixer.description = 用油将硫转化为不易燃但更具爆炸性 block.cryofluidmixer.description = 水和钛结合到低温流体中,冷却效率更高。 block.melter.description = 石头加热到很高的温度以获得熔岩。 block.incinerator.description = 用于除掉任何多余的物品或液体。 -block.spore-press.description = Compresses spore pods into oil. +block.spore-press.description = 压缩孢子荚得到石油。 block.separator.description = 将石头暴露在水压下,以获得石头中含有的各种矿物质。 block.power-node.description = 连接节点传输电源。最多可连接四个电源,接收器或节点。节点将从任何相邻块接收电力或向其供电。 block.power-node-large.description = 传输径大于电源节点,最多可连接六个电源,接收器或节点。 diff --git a/core/assets/bundles/bundle_zh_TW.properties b/core/assets/bundles/bundle_zh_TW.properties index 5c44cbd9dd..d8fec14e43 100644 --- a/core/assets/bundles/bundle_zh_TW.properties +++ b/core/assets/bundles/bundle_zh_TW.properties @@ -20,25 +20,27 @@ stat.built = 建設的建築:[accent]{0} stat.destroyed = 摧毀的建築:[accent]{0} stat.deconstructed = 移除的建築:[accent]{0} stat.delivered = 發射的資源: -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. +stat.rank = 最終排名:[accent]{0} +placeline = 你選擇了一個方塊。\n[accent]按住你的手指幾秒鐘[]並拖動以[accent]直線放置方塊[]。\n試試吧。 +removearea = 你選擇了移除模式。\n[accent]按住你的手指幾秒鐘[]並拖動以[accent]移除矩形中的方塊[]。\n試試吧。 +launcheditems = [accent]發射了的物品 map.delete = 確認要刪除「[accent]{0}[]」地圖嗎? level.highscore = 最高分:[accent]{0} level.select = 選擇關卡 level.mode = 遊戲模式: showagain = 下次不再顯示 coreattack = 〈核心正在受到攻擊!〉 -nearpoint = [[ [scarlet]LEAVE DROP POINT IMMEDIATELY[] ]\nannihilation imminent -outofbounds = [[ OUT OF BOUNDS ]\n[]self-destruct in {0} -database = Core Database +nearpoint = 【[scarlet]立即離開下降點[]】\n湮滅即將來臨 +outofbounds = 【超出界限】\n[]於{0}秒後自我毀滅 +database = 核心數據庫 savegame = 儲存遊戲 loadgame = 載入遊戲 joingame = 多人連線 addplayers = 增加/移除玩家 customgame = 自訂遊戲 -newgame = New Game -none = <沒有> +newgame = 新遊戲 +none = 〈沒有〉 +minimap = Minimap close = 關閉 quit = 退出 maps = 地圖 @@ -49,7 +51,7 @@ name = 名稱: noname = 先選擇一個[accent]玩家名稱[]。 filename = 檔案名稱︰ unlocked = 新方塊已解鎖! -completed = [accent]Completed +completed = [accent]完成 techtree = 科技樹 research.list = [LIGHT_GRAY]研究︰ research = 研究 @@ -138,7 +140,7 @@ save.rename.text = 新名稱: selectslot = 選取一個存檔。 slot = [accent]存檔{0} save.corrupted = [accent]此存檔無效或已損毀!\n如果你剛剛升級了遊戲,那麼這可能是因為存檔格式改變了而[scarlet]不是[]錯誤。 -empty = <空白> +empty = 〈空白〉 on = 開啟 off = 關閉 save.autosave = 自動存檔:{0} @@ -146,8 +148,8 @@ save.map = 地圖:{0} save.wave = 波次:{0} save.difficulty = 難度:{0} save.date = 最後存檔時間:{0} -save.playtime = 遊玩時間: {0} -warning = Warning. +save.playtime = 遊玩時間:{0} +warning = 警告。 confirm = 確認 delete = 刪除 ok = 確定 @@ -181,6 +183,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.invalid = 地圖載入錯誤:地圖可能已經損壞。 editor.brush = 粉刷 editor.openin = 在編輯器中開啟 @@ -189,32 +192,32 @@ editor.oregen.info = 礦石產生: editor.mapinfo = 地圖資訊 editor.author = 作者: editor.description = 描述: -editor.waves = Waves: -waves.title = Waves -waves.remove = Remove -waves.never = -waves.every = every -waves.waves = wave(s) -waves.perspawn = per spawn -waves.to = to -waves.boss = Boss -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.waves = 波次: +waves.title = 波次 +waves.remove = 移除 +waves.never = 〈從來沒有〉 +waves.every = 一切 +waves.waves = 波次 +waves.perspawn = 每個重生 +waves.to = 至 +waves.boss = 頭目 +waves.preview = 預覽 +waves.edit = 編輯…… +waves.copy = 複製到剪貼板 +waves.load = 從剪貼板加載 +waves.invalid = 剪貼板中的波次無效。 +waves.copied = 波浪已被複製。 +editor.default = [LIGHT_GRAY]〈默認〉 +edit = 編輯…… editor.name = 名稱: editor.teams = 隊伍 editor.elevation = 高度 -editor.errorload = Error loading file:\n[accent]{0} -editor.errorsave = Error saving file:\n[accent]{0} -editor.errorname = Map has no name defined. -editor.update = Update -editor.randomize = Randomize -editor.apply = Apply +editor.errorload = 加載文件時出錯:\n[accent]{0} +editor.errorsave = 保存文件時出錯:\n[accent]{0} +editor.errorname = 地圖沒有定義名稱。 +editor.update = 更新 +editor.randomize = 隨機化 +editor.apply = 使用 editor.generate = 產生 editor.resize = 調整大小 editor.loadmap = 載入地圖 @@ -243,26 +246,26 @@ editor.mapname = 地圖名稱: editor.overwrite = [accent]警告!這將會覆蓋現有的地圖。 editor.overwrite.confirm = [scarlet]警告![]同名地圖存在,確定要覆蓋現有地圖? editor.selectmap = 選取要載入的地圖: -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 +filters.empty = [LIGHT_GRAY]沒有過濾器!使用下面的按鈕添加一個。 +filter.distort = 歪曲 +filter.noise = 噪聲 +filter.ore = 礦石 +filter.rivernoise = 河流噪聲 +filter.scatter = 分散 +filter.terrain = 地形 +filter.option.scale = 比例 +filter.option.chance = 機會 +filter.option.mag = 大小 +filter.option.threshold = 閾 +filter.option.circle-scale = 圓形比例 +filter.option.octaves = 倍頻 +filter.option.falloff = 衰減 +filter.option.block = 方塊 +filter.option.floor = 地板 +filter.option.wall = 牆 +filter.option.ore = 礦石 +filter.option.floor2 = 次要地板 +filter.option.threshold2 = 次要閾 width = 寬度: height = 長度: menu = 主選單 @@ -282,22 +285,23 @@ abandon = 放棄 abandon.text = 此區域及其所有資源將會丟失給敵人。 locked = 鎖定 complete = [LIGHT_GRAY]完成: +zone.requirement = Wave {0} in zone {1} resume = 繼續區域:\n[LIGHT_GRAY]{0} bestwave = [LIGHT_GRAY]高分:{0} launch = 發射 launch.title = 發射成功 -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. +launch.next = [LIGHT_GRAY]下次的機會於波次{0} +launch.unable = [scarlet]無法發射。[]有敵人。 +launch.confirm = 這將發射核心中的所有資源。\n你將無法返回這個基地。 +uncover = 揭露 +configure = 配置裝載 +configure.locked = [LIGHT_GRAY]到達波次{0}\n以配置裝載。 zone.unlocked = [LIGHT_GRAY]{0}已解鎖。 -zone.complete = Zone conditions met. -zone.config.complete = Wave {0} reached:\nLoadout config unlocked. -zone.resources = Resources Detected: -add = Add... -boss.health = Boss Health +zone.requirement.complete = Wave {0} reached:\n{1} zone requirements met. +zone.config.complete = 到達波次{0}:\n裝載配置已解鎖。 +zone.resources = 檢測到的資源: +add = 新增…… +boss.health = 頭目血量 connectfail = [crimson]無法連線到伺服器:[accent]{0} error.unreachable = 無法到達伺服器。 error.invalidaddress = 無效地址。 @@ -307,13 +311,13 @@ error.alreadyconnected = 已連接。 error.mapnotfound = 找不到地圖! error.io = 網絡輸入輸出錯誤。 error.any = 未知網絡錯誤。 -zone.groundZero.name = Ground Zero -zone.craters.name = The Craters -zone.frozenForest.name = Frozen Forest -zone.ruinousShores.name = Ruinous Shores -zone.stainedMountains.name = Stained Mountains -zone.desolateRift.name = Desolate Rift -zone.nuclearComplex.name = Nuclear Production Complex +zone.groundZero.name = 歸零地 +zone.craters.name = 隕石坑 +zone.frozenForest.name = 冰凍森林 +zone.ruinousShores.name = 毀滅性的海岸 +zone.stainedMountains.name = 染山 +zone.desolateRift.name = 荒涼的裂痕 +zone.nuclearComplex.name = 核生產綜合體 settings.language = 語言 settings.reset = 重設為預設設定 settings.rebind = 重新綁定 @@ -332,63 +336,59 @@ no = 否 info.title = [accent]資訊 error.title = [crimson]發生錯誤 error.crashtitle = 發生錯誤 -blocks.outputspeed = Drill Speed: {0}/s -blocks.efficiency = Efficiency: {0}% -blocks.unknown = [LIGHT_GRAY]??? -blocks.blockinfo = 方塊資訊 -blocks.powerbalance = Power: {0} -blocks.poweroutput = Power Output: {0} +blocks.input = Input +blocks.output = Output +blocks.booster = Booster +block.unknown = [LIGHT_GRAY]??? blocks.powercapacity = 蓄電量 blocks.powershot = 能量/射擊 blocks.targetsair = 攻擊空中目標 -blocks.targetsground = Targets Ground -blocks.items = Items: {0} -blocks.itemsmoved = Move Speed +blocks.targetsground = 攻擊地面 +blocks.itemsmoved = 移動速度 +blocks.launchtime = Time Between Launches blocks.shootrange = 範圍 blocks.size = 尺寸 blocks.liquidcapacity = 液體容量 -blocks.maxitemssecond = 最高產量 blocks.powerrange = 輸出範圍 blocks.poweruse = 能量使用 blocks.powerdamage = 能量/傷害 -blocks.inputitemcapacity = 最大輸入 -blocks.outputitemcapacity = 最大輸出 blocks.itemcapacity = 物品容量 blocks.basepowergeneration = 基本能量生产 -blocks.powertransferspeed = 能量傳輸 -blocks.craftspeed = 產生速度 -blocks.inputliquid = 輸入液體 -blocks.inputliquidaux = 輔助液體 -blocks.inputitem = 輸入物品 -blocks.inputitems = 輸入物品 -blocks.outputitem = 輸出物品 +blocks.productiontime = Production Time +blocks.repairtime = Block Full Repair Time +blocks.speedincrease = Speed Increase +blocks.range = Range blocks.drilltier = 可鑽取礦物 blocks.drillspeed = 基本鑽取速度 -blocks.maxunits = Max Active Units -blocks.liquidoutput = 輸出液體 -blocks.liquidoutputspeed = 輸出液體速度 -blocks.liquiduse = 使用液體速度 -blocks.coolant = 冷卻劑 -blocks.liquid = Liquid -blocks.coolantuse = 使用冷卻劑 -blocks.inputliquidfuel = 輸入液體燃料 -blocks.liquidfueluse = 使用液體燃料速度 -blocks.boostitem = 強化物品 -blocks.boostliquid = 強化液體 +blocks.boosteffect = Boost Effect +blocks.maxunits = 最大活躍單位 blocks.health = 耐久度 -blocks.heat = Heat -blocks.power = Power -blocks.progress = Build Progress -blocks.spawned = Units: {0}/{1} -blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = 誤差 blocks.shots = 射擊數 blocks.reload = 重裝彈藥 -blocks.inputfuel = 燃料 -blocks.fuelburntime = 燃燒燃料時間 -blocks.inputcapacity = 輸入容量 -blocks.outputcapacity = 輸出容量 -blocks.ammo = Ammo +blocks.ammo = 彈藥 +bar.drillspeed = 鑽頭速度:{0}/秒 +bar.efficiency = 效率:{0}% +bar.powerbalance = 能量變化:{0} +bar.poweramount = Power: {0} +bar.poweroutput = 能量輸出:{0} +bar.items = 物品:{0} +bar.liquid = 液體 +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 unit.blocks = 方塊 unit.powersecond = 能量單位/秒 unit.liquidsecond = 液體單位/秒 @@ -397,6 +397,9 @@ unit.liquidunits = 液體單位 unit.powerunits = 能量單位 unit.degrees = 度 unit.seconds = 秒 +unit.persecond = /sec +unit.timesspeed = x speed +unit.percent = % unit.items = 物品 category.general = 一般 category.power = 能量 @@ -405,13 +408,17 @@ category.items = 物品 category.crafting = 合成 category.shooting = 射擊 category.optional = 可選的強化 -setting.animatedwater.name = Animated Water +setting.landscape.name = Lock Landscape +setting.shadows.name = Shadows +setting.animatedwater.name = 動畫水 +setting.animatedshields.name = Animated Shields +setting.antialias.name = 消除鋸齒[LIGHT_GRAY](需要重啟)[] setting.indicators.name = 盟友指標 setting.autotarget.name = 自動射擊 setting.fpscap.name = 最大FPS setting.fpscap.none = 没有 setting.fpscap.text = {0}FPS -setting.swapdiagonal.name = Always Diagonal Placement +setting.swapdiagonal.name = 始終對角線放置 setting.difficulty.training = 訓練 setting.difficulty.easy = 簡單 setting.difficulty.normal = 普通 @@ -424,9 +431,11 @@ setting.sensitivity.name = 控制器靈敏度 setting.saveinterval.name = 自動存檔間隔 setting.seconds = {0}秒 setting.fullscreen.name = 全螢幕 +setting.borderless.name = 無邊框窗口 setting.fps.name = 顯示FPS setting.vsync.name = 垂直同步 setting.lasers.name = 顯示雷射光束 +setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance) setting.minimap.name = 顯示小地圖 setting.musicvol.name = 音樂音量 setting.mutemusic.name = 靜音 @@ -448,9 +457,9 @@ keybind.screenshot.name = 地圖截圖 keybind.move_x.name = 水平移動 keybind.move_y.name = 垂直移動 keybind.select.name = 選取 -keybind.diagonal_placement.name = Diagonal Placement -keybind.pick.name = Pick Block -keybind.break_block.name = Break Block +keybind.diagonal_placement.name = 對角線放置 +keybind.pick.name = 選擇方塊 +keybind.break_block.name = 移除方塊 keybind.deselect.name = 取消選取 keybind.shoot.name = 射擊 keybind.zoom_hold.name = 按住縮放 @@ -469,8 +478,8 @@ keybind.chat_scroll.name = 聊天記錄滾動 keybind.drop_unit.name = 放下單位 keybind.zoom_minimap.name = 縮放小地圖 mode.help.title = 模式說明 -mode.survival.name = Survival -mode.survival.description = The normal mode. Limited resources and automatic incoming waves. +mode.survival.name = 生存 +mode.survival.description = 一般模式。有限的資源與自動來襲的波次。 mode.sandbox.name = 沙盒 mode.sandbox.description = 無限的資源,與不倒數計時的波次。 mode.freebuild.name = 自由建造 @@ -478,7 +487,22 @@ mode.freebuild.description = 有限的資源,與不倒數計時的波次。 mode.pvp.name = 對戰 mode.pvp.description = 和其他玩家鬥爭。 mode.attack.name = 攻擊 -mode.attack.description = No waves, with the goal to destroy the enemy base. +mode.attack.description = 沒有波次,目標是摧毀敵人的基地。 +mode.custom = Custom Rules +rules.infiniteresources = Infinite Resources +rules.wavetimer = Wave Timer +rules.waves = Waves +rules.enemyCheat = Infinite AI Resources +rules.pvp = PvP +rules.unitdrops = Unit Drops +rules.unitbuildspeedmultiplier = Unit Creation Speed Multiplier +rules.unithealthmultiplier = Unit Health Multiplier +rules.playerdamagemultiplier = Player 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 content.item.name = 物品 content.liquid.name = 液體 content.unit.name = 機組 @@ -503,8 +527,8 @@ item.phase-fabric.name = 相織布 item.phase-fabric.description = 一種近乎無重量的物質,用於先進的電子設備和自修復技術。 item.surge-alloy.name = 波動合金 item.surge-alloy.description = 一種具有獨特電子特性的高級合金。 -item.spore-pod.name = Spore Pod -item.spore-pod.description = Used for conversion into oil, explosives and fuel. +item.spore-pod.name = 孢子莢 +item.spore-pod.description = 用於轉化為石油、爆炸物和燃料。 item.sand.name = 沙 item.sand.description = 一種常見的材料,廣泛用於冶煉,包括製作合金和助熔劑。 item.blast-compound.name = 爆炸混合物 @@ -516,7 +540,7 @@ item.metaglass.description = 一種超級強硬玻璃混合物。廣泛用於液 item.scrap.name = 廢料 item.scrap.description = 舊結構和單位的遺留剩餘物。含有痕量的許多不同的金屬。 liquid.water.name = 水 -liquid.slag.name = Slag +liquid.slag.name = 礦渣 liquid.oil.name = 原油 liquid.cryofluid.name = 冷凍液 mech.alpha-mech.name = 阿爾法 @@ -527,7 +551,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 = Tau機甲 mech.tau-mech.weapon = 重構激光 mech.tau-mech.ability = 修复陣 mech.tau-mech.description = 支援機甲。射擊友好方塊以治療它們。可以使用它的修復能力熄滅火焰並治療一定範圍內的友軍。 @@ -554,73 +578,78 @@ item.radioactivity = [LIGHT_GRAY]放射性:{0} unit.health = [LIGHT_GRAY]耐久度:{0} unit.speed = [LIGHT_GRAY]速度:{0} mech.weapon = [LIGHT_GRAY]武器:{0} -mech.health = [LIGHT_GRAY]Health: {0} +mech.health = [LIGHT_GRAY]血量:{0} mech.itemcapacity = [LIGHT_GRAY]物品容量:{0} mech.minespeed = [LIGHT_GRAY]採礦速度:{0} mech.minepower = [LIGHT_GRAY]採礦力度:{0} mech.ability = [LIGHT_GRAY]能力:{0} +mech.buildspeed = [LIGHT_GRAY]Building Speed: {0}% liquid.heatcapacity = [LIGHT_GRAY]熱容量:{0} liquid.viscosity = [LIGHT_GRAY]粘性:{0} liquid.temperature = [LIGHT_GRAY]温度:{0} -block.grass.name = Grass -block.salt.name = Salt -block.sandrocks.name = Sand Rocks -block.spore-pine.name = Spore Pine -block.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.spore-moss.name = Spore Moss -block.shalerocks.name = Shale Rocks -block.scrap-wall.name = Scrap Wall -block.scrap-wall-large.name = Large Scrap Wall -block.scrap-wall-huge.name = Huge Scrap Wall -block.scrap-wall-gigantic.name = Gigantic Scrap Wall -block.thruster.name = Thruster -block.kiln.name = Kiln -block.kiln.description = Smelts sand and lead into metaglass. Requires small amounts of power. -block.graphite-press.name = Graphite Press -block.multi-press.name = Multi-Press -block.constructing = {0}\n[LIGHT_GRAY](Constructing) +block.grass.name = 草 +block.salt.name = 鹽 +block.sandrocks.name = 沙岩 +block.spore-pine.name = 孢子鬆 +block.sporerocks.name = 孢子岩 +block.rock.name = 岩石 +block.snowrock.name = 雪巖 +block.shale.name = 頁岩 +block.shale-boulder.name = 頁岩巨石 +block.moss.name = 苔蘚 +block.spore-moss.name = 孢子苔蘚 +block.shalerocks.name = 頁岩岩石 +block.scrap-wall.name = 廢牆 +block.scrap-wall-large.name = 大型廢牆 +block.scrap-wall-huge.name = 巨型廢牆 +block.scrap-wall-gigantic.name = 超巨型廢牆 +block.thruster.name = 推進器 +block.kiln.name = 窯 +block.kiln.description = 將沙子和鉛熔煉成金屬玻璃。需要少量能量。 +block.graphite-press.name = 石墨壓縮機 +block.multi-press.name = 多用途壓縮機 +block.constructing = {0}\n[LIGHT_GRAY](建設中) block.spawn.name = 敵人生成 -block.core-shard.name = Core: Shard -block.core-foundation.name = Core: Foundation -block.core-nucleus.name = Core: Nucleus +block.core-shard.name = 核心:碎片 +block.core-foundation.name = 核心:基礎 +block.core-nucleus.name = 核心:核子 block.deepwater.name = 深水 block.water.name = 水 +block.tainted-water.name = 污水 +block.darksand-tainted-water.name = 黑沙污水 block.tar.name = 焦油 block.stone.name = 石頭 block.sand.name = 沙 +block.darksand.name = 黑沙 block.ice.name = 冰 block.snow.name = 雪 -block.craters.name = Craters -block.sand-water.name = 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.ignarock.name = Igna Rock -block.hotrock.name = Hot Rock -block.magmarock.name = Magma Rock -block.cliffs.name = Cliffs +block.craters.name = 隕石坑 +block.sand-water.name = 沙水 +block.darksand-water.name = 黑沙水 +block.char.name = 燒焦 +block.holostone.name = 霍洛石頭 +block.ice-snow.name = 冰雪 +block.rocks.name = 岩石 +block.icerocks.name = 冰岩 +block.snowrocks.name = 雪巖 +block.dunerocks.name = 沙丘岩 +block.pine.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.ignarock.name = 火成岩 +block.hotrock.name = 熱岩 +block.magmarock.name = 岩漿岩 +block.cliffs.name = 懸崖 block.copper-wall.name = 銅牆 block.copper-wall-large.name = 大型銅牆 -block.titanium-wall.name = Titanium Wall -block.titanium-wall-large.name = Large Titanium Wall +block.titanium-wall.name = 鈦牆 +block.titanium-wall-large.name = 大型鈦牆 block.phase-wall.name = 相織布牆 block.phase-wall-large.name = 大型相織布牆 block.thorium-wall.name = 釷牆 @@ -628,7 +657,8 @@ block.thorium-wall-large.name = 大型釷牆 block.door.name = 門 block.door-large.name = 大門 block.duo.name = 雙炮 -block.scatter.name = Scatter +block.scorch.name = 燒焦炮 +block.scatter.name = 分散炮 block.hail.name = 冰雹炮 block.lancer.name = 藍瑟炮 block.conveyor.name = 輸送帶 @@ -646,23 +676,23 @@ block.pulverizer.name = 粉碎機 block.cryofluidmixer.name = 冷凍液混合器 block.melter.name = 熔爐 block.incinerator.name = 焚化爐 -block.spore-press.name = Spore Press +block.spore-press.name = 孢子壓縮機 block.separator.name = 分離機 block.power-node.name = 能量節點 block.power-node-large.name = 大型能量節點 -block.surge-tower.name = Surge Tower +block.surge-tower.name = 波動塔 block.battery.name = 電池 block.battery-large.name = 大型電池 block.combustion-generator.name = 燃燒發電機 block.turbine-generator.name = 渦輪發電機 -block.differential-generator.name = Differential Generator -block.impact-reactor.name = Impact Reactor +block.differential-generator.name = 差動發電機 +block.impact-reactor.name = 衝擊反應堆 block.mechanical-drill.name = 機械鑽頭 block.pneumatic-drill.name = 氣動鑽頭 block.laser-drill.name = 激光鑽頭 block.water-extractor.name = 水提取器 block.cultivator.name = 耕種機 -block.alpha-dart-mech-pad.name = Alpha-Dart Mech Pad +block.alpha-dart-mech-pad.name = 阿爾法鏢船機甲墊 block.delta-mech-pad.name = 德爾塔機甲墊 block.javelin-ship-pad.name = 標槍機甲墊 block.trident-ship-pad.name = 三叉船墊 @@ -695,7 +725,7 @@ block.phantom-factory.name = 幻影無人機工廠 block.wraith-factory.name = 怨靈戰鬥機工廠 block.ghoul-factory.name = 食屍鬼轟炸機工廠 block.dagger-factory.name = 匕首機甲工廠 -block.crawler-factory.name = Crawler Mech Factory +block.crawler-factory.name = 爬行機甲工廠 block.titan-factory.name = 泰坦機甲工廠 block.fortress-factory.name = 堡壘機甲工廠 block.revenant-factory.name = 亡魂戰鬥機工廠 @@ -713,6 +743,7 @@ block.blast-drill.name = 爆破鑽頭 block.thermal-pump.name = 熱能泵 block.thermal-generator.name = 熱能發電機 block.alloy-smelter.name = 合金冶煉廠 +block.mender.name = Mender block.mend-projector.name = 修理投影器 block.surge-wall.name = 波動牆 block.surge-wall-large.name = 大型波動牆 @@ -727,7 +758,8 @@ block.spectre.name = 幽靈炮 block.meltdown.name = 熔毀炮 block.container.name = 容器 block.launch-pad.name = 發射台 -block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. +block.launch-pad.description = 無需從核心發射即可發射物品。未完成。 +block.launch-pad-large.name = Large Launch Pad team.blue.name = 藍 team.red.name = 紅 team.orange.name = 橙 @@ -740,7 +772,7 @@ unit.phantom.name = 幻影無人機 unit.phantom.description = 一種高級的無人機。自動挖掘礦石、收集物品和修理方塊。比輕型無人機明顯更有效。 unit.dagger.name = 匕首 unit.dagger.description = 一種基本的地面單位。最好一群地使用。 -unit.crawler.name = Crawler +unit.crawler.name = 爬行 unit.titan.name = 泰坦 unit.titan.description = 一種高級的具有裝甲的地面單位。使用碳化物作為彈藥。攻擊地面單位和空中單位。 unit.ghoul.name = 食屍鬼轟炸機 @@ -750,11 +782,11 @@ unit.wraith.description = 一種快速、打了就跑的攔截機。 unit.fortress.name = 堡壘 unit.fortress.description = 一種具有重型大砲的地面單位。 unit.revenant.name = 亡魂 -unit.eruptor.name = Eruptor -unit.chaos-array.name = Chaos Array -unit.eradicator.name = Eradicator -unit.lich.name = Lich -unit.reaper.name = Reaper +unit.eruptor.name = 爆發者 +unit.chaos-array.name = 混沌陣 +unit.eradicator.name = 消除者 +unit.lich.name = 巫妖 +unit.reaper.name = 收割者 tutorial.begin = 你的任務是毀滅[LIGHT_GRAY]敵人[]。\n\n首先[accent]挖掘銅礦[]。點擊核心附近的銅脈以開始。 tutorial.drill = 手動挖掘礦石是低效率的。\n[accent]鑽頭[]能夠自動挖掘礦石。\n在銅脈上放置一個鑽頭。 tutorial.conveyor = [accent]輸送帶[]能夠將物品運輸到核心。\n製作一條從鑽頭開始到核心的輸送帶。 @@ -791,7 +823,7 @@ block.overdrive-projector.description = 提高附近建築物的速度,如鑽 block.force-projector.description = 在自身周圍形成一個六角形力場,保護內部的建築物和單位免受子彈的傷害。 block.shock-mine.description = 傷害踩到地雷的敵人。敵人幾乎看不見。 block.duo.description = 一種小而便宜的砲塔。 -block.scatter.description = A medium-sized anti-air turret. Sprays clumps of lead or scrap flak at enemy units. +block.scatter.description = 一種中型防空砲塔。向敵方單位噴射鉛塊或碎片。 block.arc.description = 一種向敵人射出隨機電弧的小砲塔。 block.hail.description = 一種小型火砲。 block.lancer.description = 一種射出電子束的中型砲塔。 @@ -818,7 +850,7 @@ block.blast-mixer.description = 使用油將硫變成比較不易燃但更具爆 block.cryofluidmixer.description = 合水和鈦成冷卻效率更高的冷凍液。 block.melter.description = 將石頭加熱到很高的溫度以獲得熔岩。 block.incinerator.description = 清除任何多餘的物品或液體。 -block.spore-press.description = Compresses spore pods into oil. +block.spore-press.description = 將孢子莢壓縮成油。 block.separator.description = 將石頭暴露在水壓下以獲得石頭中的各種礦物質。 block.power-node.description = 將能量傳輸到連接的節點。最多可連接四個能量來源、接收或節點。節點將從任何相鄰方塊接收能量或向其供能量。 block.power-node-large.description = 範圍大於能量節點,最多可連接六個能量來源、接收或節點。 diff --git a/core/assets/maps/craters.mmap b/core/assets/maps/craters.mmap index 92baaff531..6134ce272a 100644 Binary files a/core/assets/maps/craters.mmap and b/core/assets/maps/craters.mmap differ diff --git a/core/assets/maps/desolateRift.mmap b/core/assets/maps/desolateRift.mmap index 694353537d..0e4f0474e5 100644 Binary files a/core/assets/maps/desolateRift.mmap and b/core/assets/maps/desolateRift.mmap differ diff --git a/core/assets/maps/fortress.mmap b/core/assets/maps/fortress.mmap index 88fa55e854..2b395107e5 100644 Binary files a/core/assets/maps/fortress.mmap and b/core/assets/maps/fortress.mmap differ diff --git a/core/assets/maps/frozenForest.mmap b/core/assets/maps/frozenForest.mmap index 39ec3bb9ee..06354bf306 100644 Binary files a/core/assets/maps/frozenForest.mmap and b/core/assets/maps/frozenForest.mmap differ diff --git a/core/assets/maps/groundZero.mmap b/core/assets/maps/groundZero.mmap index 201b03352c..e4044fd6e4 100644 Binary files a/core/assets/maps/groundZero.mmap and b/core/assets/maps/groundZero.mmap differ diff --git a/core/assets/maps/map_9.mmap b/core/assets/maps/map_9.mmap new file mode 100644 index 0000000000..93d78bbb15 Binary files /dev/null and b/core/assets/maps/map_9.mmap differ diff --git a/core/assets/maps/nuclearProductionComplex.mmap b/core/assets/maps/nuclearProductionComplex.mmap index 0fe2013949..9ed6f320e3 100644 Binary files a/core/assets/maps/nuclearProductionComplex.mmap and b/core/assets/maps/nuclearProductionComplex.mmap differ diff --git a/core/assets/maps/ruinousShores.mmap b/core/assets/maps/ruinousShores.mmap index 861c13a1f6..8723b5daad 100644 Binary files a/core/assets/maps/ruinousShores.mmap and b/core/assets/maps/ruinousShores.mmap differ diff --git a/core/assets/maps/stainedMountains.mmap b/core/assets/maps/stainedMountains.mmap index cbf23b9239..f1119c0e80 100644 Binary files a/core/assets/maps/stainedMountains.mmap and b/core/assets/maps/stainedMountains.mmap differ diff --git a/core/assets/shaders/blockbuild.fragment b/core/assets/shaders/blockbuild.fragment.glsl similarity index 100% rename from core/assets/shaders/blockbuild.fragment rename to core/assets/shaders/blockbuild.fragment.glsl diff --git a/core/assets/shaders/default.vertex b/core/assets/shaders/default.vertex.glsl similarity index 100% rename from core/assets/shaders/default.vertex rename to core/assets/shaders/default.vertex.glsl diff --git a/core/assets/shaders/fog.fragment b/core/assets/shaders/fog.fragment.glsl similarity index 70% rename from core/assets/shaders/fog.fragment rename to core/assets/shaders/fog.fragment.glsl index 7ac266711a..5c07ae1e02 100644 --- a/core/assets/shaders/fog.fragment +++ b/core/assets/shaders/fog.fragment.glsl @@ -8,8 +8,7 @@ uniform sampler2D u_texture; varying vec4 v_color; varying vec2 v_texCoord; -void main() { +void main(){ vec4 color = texture2D(u_texture, v_texCoord.xy); - color = vec4(0.0, 0.0, 0.0, 1.0 - color.r); - gl_FragColor = color; + gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0 - color.r); } diff --git a/core/assets/shaders/menu.fragment b/core/assets/shaders/menu.fragment.glsl similarity index 100% rename from core/assets/shaders/menu.fragment rename to core/assets/shaders/menu.fragment.glsl diff --git a/core/assets/shaders/shadow.fragment b/core/assets/shaders/shadow.fragment.glsl similarity index 100% rename from core/assets/shaders/shadow.fragment rename to core/assets/shaders/shadow.fragment.glsl diff --git a/core/assets/shaders/shield.fragment b/core/assets/shaders/shield.fragment.glsl similarity index 100% rename from core/assets/shaders/shield.fragment rename to core/assets/shaders/shield.fragment.glsl diff --git a/core/assets/shaders/tar.fragment b/core/assets/shaders/tar.fragment.glsl similarity index 97% rename from core/assets/shaders/tar.fragment rename to core/assets/shaders/tar.fragment.glsl index 98aeeeb9f6..bdbd49c4b3 100644 --- a/core/assets/shaders/tar.fragment +++ b/core/assets/shaders/tar.fragment.glsl @@ -56,7 +56,6 @@ void main() { if(color.r > 0.01){ color = texture2D(u_texture, c + vec2(sin(stime/3.0 + coords.y/0.75) * v.x, 0.0)) * vec4(0.9, 0.9, 1, 1.0); - color.a = 1.0; float n1 = snoise(coords / 22.0 + vec2(-time) / 540.0); float n2 = snoise((coords + vec2(632.0)) / 8.0 + vec2(0.0, time) / 510.0); @@ -65,7 +64,6 @@ void main() { if(r < -0.3 && r > -0.6){ color *= 1.4; - color.a = 1.0; } } diff --git a/core/assets/shaders/unitbuild.fragment b/core/assets/shaders/unitbuild.fragment.glsl similarity index 100% rename from core/assets/shaders/unitbuild.fragment rename to core/assets/shaders/unitbuild.fragment.glsl diff --git a/core/assets/shaders/water.fragment b/core/assets/shaders/water.fragment.glsl similarity index 79% rename from core/assets/shaders/water.fragment rename to core/assets/shaders/water.fragment.glsl index 83910bbe5f..bd3e2103e6 100644 --- a/core/assets/shaders/water.fragment +++ b/core/assets/shaders/water.fragment.glsl @@ -61,14 +61,14 @@ void main() { float n2 = snoise((coords + vec2(632.0)) / 25.0 + vec2(0.0, -time) / 190.0); float r = (n1 + n2) * 3.0; + float tester = mod(float(int(coords.x + coords.y*1.1 + sin(stime / 8.0 + coords.x/5.0 - coords.y/100.0)*2.0)) + + sin(stime / 20.0 + coords.y/3.0) * 1.0 + + sin(stime / 10.0 + coords.y/2.0) * 2.0 + + sin(stime / 7.0 + coords.y/1.0) * 0.5 + + sin(coords.x + coords.y) + + sin(stime / 20.0 + coords.x/4.0) * 1.0, mscl) + r; - if(mod(float(int(coords.x + coords.y*1.1 + sin(stime / 8.0 + coords.x/5.0 - coords.y/100.0)*2.0)) + - sin(stime / 20.0 + coords.y/3.0) * 1.0 + - sin(stime / 10.0 + coords.y/2.0) * 2.0 + - sin(stime / 7.0 + coords.y/1.0) * 0.5 + - sin(coords.x + coords.y) + - sin(stime / 20.0 + coords.x/4.0) * 1.0, mscl) + r < mth){ - + if(tester < mth){ color *= 1.2; color.a = 1.0; } diff --git a/core/assets/sprites/block_colors.png b/core/assets/sprites/block_colors.png index dba87393f8..e3f1f7f657 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/icon.icns b/core/assets/sprites/icon.icns index a71732bda5..45b4c89b83 100644 Binary files a/core/assets/sprites/icon.icns and b/core/assets/sprites/icon.icns differ diff --git a/core/assets/sprites/icon.png b/core/assets/sprites/icon.png index c2fa937fb5..737f1c4bf7 100644 Binary files a/core/assets/sprites/icon.png and b/core/assets/sprites/icon.png differ diff --git a/core/assets/sprites/icon_64.png b/core/assets/sprites/icon_64.png new file mode 100644 index 0000000000..8e9259dc88 Binary files /dev/null and b/core/assets/sprites/icon_64.png differ diff --git a/core/assets/sprites/sprites.atlas b/core/assets/sprites/sprites.atlas index 23e75fd37a..96771206c2 100644 --- a/core/assets/sprites/sprites.atlas +++ b/core/assets/sprites/sprites.atlas @@ -6,6328 +6,6671 @@ filter: Nearest,Nearest repeat: none force-projector rotate: false - xy: 415, 1530 + xy: 131, 235 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 force-projector-top rotate: false - xy: 415, 1432 + xy: 131, 137 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mend-projector rotate: false - xy: 1645, 1363 + xy: 992, 1232 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mend-projector-top rotate: false - xy: 1711, 1363 + xy: 926, 1166 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 +mender + rotate: false + xy: 1922, 1204 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +mender-top + rotate: false + xy: 1956, 1204 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 overdrive-projector rotate: false - xy: 1843, 1363 + xy: 992, 1166 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 overdrive-projector-top rotate: false - xy: 1909, 1363 + xy: 1124, 1232 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 shock-mine rotate: false - xy: 563, 152 + xy: 1271, 636 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor rotate: false - xy: 1117, 847 + xy: 1506, 1169 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-bridge rotate: false - xy: 1117, 813 + xy: 1540, 1169 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-end rotate: false - xy: 1117, 779 + xy: 1616, 1211 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-0 rotate: false - xy: 1451, 1121 + xy: 1421, 1006 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-1 rotate: false - xy: 1485, 1121 + xy: 1455, 1006 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-2 rotate: false - xy: 1519, 1121 + xy: 1582, 1182 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-3 rotate: false - xy: 1553, 1121 + xy: 1616, 1177 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-0 rotate: false - xy: 1587, 1121 + xy: 1650, 1172 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-1 rotate: false - xy: 1621, 1105 + xy: 1684, 1172 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-2 rotate: false - xy: 1655, 1105 + xy: 1718, 1172 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-3 rotate: false - xy: 1689, 1096 + xy: 1752, 1172 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-0 rotate: false - xy: 1723, 1096 + xy: 1786, 1172 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-1 rotate: false - xy: 1185, 863 + xy: 1820, 1172 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-2 rotate: false - xy: 1185, 829 + xy: 1854, 1172 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-3 rotate: false - xy: 1185, 795 + xy: 1489, 1135 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-0 rotate: false - xy: 1151, 753 + xy: 1489, 1101 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-1 rotate: false - xy: 1185, 761 + xy: 1523, 1135 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-2 rotate: false - xy: 1235, 913 + xy: 1489, 1067 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-3 rotate: false - xy: 1285, 963 + xy: 1523, 1101 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-0 rotate: false - xy: 1335, 1013 + xy: 1489, 1033 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-1 rotate: false - xy: 1375, 1105 + xy: 1523, 1067 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-2 rotate: false - xy: 1385, 1071 + xy: 1523, 1033 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-3 rotate: false - xy: 1419, 1087 + xy: 1489, 999 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-0 rotate: false - xy: 1693, 960 + xy: 1577, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-1 rotate: false - xy: 1693, 926 + xy: 1611, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-2 rotate: false - xy: 1727, 1028 + xy: 1611, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-3 rotate: false - xy: 1727, 994 + xy: 1611, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-0 rotate: false - xy: 1727, 960 + xy: 919, 616 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-1 rotate: false - xy: 1727, 926 + xy: 953, 616 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-2 rotate: false - xy: 1659, 892 + xy: 987, 616 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-3 rotate: false - xy: 1693, 892 + xy: 1021, 616 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-0 rotate: false - xy: 1727, 892 + xy: 1055, 624 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-1 rotate: false - xy: 1350, 581 + xy: 1089, 612 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-2 rotate: false - xy: 567, 687 + xy: 1123, 612 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-3 rotate: false - xy: 567, 653 + xy: 1157, 612 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-0 rotate: false - xy: 567, 619 + xy: 1191, 612 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-1 rotate: false - xy: 567, 585 + xy: 1055, 590 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-2 rotate: false - xy: 567, 551 + xy: 1089, 578 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-3 rotate: false - xy: 1321, 883 + xy: 1123, 578 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-0 rotate: false - xy: 1321, 849 + xy: 1157, 578 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-1 rotate: false - xy: 1321, 815 + xy: 1191, 578 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-2 rotate: false - xy: 1321, 781 + xy: 1225, 602 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-3 rotate: false - xy: 1321, 747 + xy: 1259, 602 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 distributor rotate: false - xy: 1249, 1429 + xy: 677, 1298 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 junction rotate: false - xy: 1253, 743 + xy: 1515, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mass-driver-base rotate: false - xy: 1395, 1495 + xy: 513, 1333 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 overflow-gate rotate: false - xy: 1181, 693 + xy: 1151, 714 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor rotate: false - xy: 1961, 1049 + xy: 1583, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-arrow rotate: false - xy: 1995, 1049 + xy: 1583, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-bridge rotate: false - xy: 1215, 667 + xy: 1583, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-end rotate: false - xy: 1214, 633 + xy: 1067, 658 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 router rotate: false - xy: 529, 118 + xy: 1569, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sorter rotate: false - xy: 1623, 1071 + xy: 1373, 632 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 blast-drill rotate: false - xy: 1, 601 + xy: 1, 397 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 blast-drill-rim rotate: false - xy: 1, 341 + xy: 1, 137 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 blast-drill-rotator rotate: false - xy: 1, 211 + xy: 1, 7 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 blast-drill-top rotate: false - xy: 1, 81 + xy: 323, 1627 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 laser-drill rotate: false - xy: 905, 1561 + xy: 807, 1560 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 laser-drill-rim rotate: false - xy: 1003, 1577 + xy: 905, 1560 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 laser-drill-rotator rotate: false - xy: 1003, 1479 + xy: 905, 1462 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 laser-drill-top rotate: false - xy: 1101, 1593 + xy: 1003, 1560 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mechanical-drill rotate: false - xy: 1381, 1363 + xy: 860, 1232 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mechanical-drill-rotator rotate: false - xy: 1513, 1363 + xy: 926, 1232 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mechanical-drill-top rotate: false - xy: 1579, 1363 + xy: 860, 1166 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 oil-extractor rotate: false - xy: 1591, 1593 + xy: 807, 1364 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-liquid rotate: false - xy: 1689, 1593 + xy: 1003, 1364 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-rotator rotate: false - xy: 1689, 1495 + xy: 1101, 1364 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-top rotate: false - xy: 1787, 1593 + xy: 204, 1246 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 pneumatic-drill rotate: false - xy: 1645, 1297 + xy: 1049, 1100 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pneumatic-drill-rotator rotate: false - xy: 1777, 1297 + xy: 1181, 1100 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pneumatic-drill-top rotate: false - xy: 1843, 1297 + xy: 653, 1034 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor rotate: false - xy: 319, 904 + xy: 287, 643 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor-liquid rotate: false - xy: 451, 1036 + xy: 485, 775 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor-rotator rotate: false - xy: 319, 838 + xy: 419, 709 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor-top rotate: false - xy: 385, 904 + xy: 353, 643 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-border rotate: false - xy: 1787, 1139 + xy: 1658, 1274 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-middle rotate: false - xy: 1821, 1139 + xy: 1692, 1274 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pump-liquid rotate: false - xy: 1821, 1139 + xy: 1692, 1274 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-select rotate: false - xy: 1855, 1134 + xy: 1726, 1274 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-liquid rotate: false - xy: 1731, 1130 + xy: 634, 610 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 place-arrow rotate: false - xy: 1885, 1593 + xy: 400, 1235 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 rubble-1-0 rotate: false - xy: 253, 1003 + xy: 983, 1034 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rubble-1-1 rotate: false - xy: 253, 937 + xy: 1049, 1034 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rubble-2-0 rotate: false - xy: 253, 871 + xy: 1115, 1034 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rubble-2-1 rotate: false - xy: 253, 805 + xy: 1181, 1034 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rubble-3-0 rotate: false - xy: 155, 1103 + xy: 400, 1137 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 rubble-3-1 rotate: false - xy: 155, 1103 + xy: 400, 1137 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 rubble-4-0 rotate: false - xy: 1696, 1789 + xy: 453, 1627 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 rubble-4-1 rotate: false - xy: 1696, 1789 + xy: 453, 1627 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 spawn rotate: false - xy: 1623, 1037 + xy: 1407, 666 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit rotate: false - xy: 1889, 1134 + xy: 1760, 1274 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit-arrow rotate: false - xy: 1923, 1129 + xy: 1794, 1274 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-arrow rotate: false - xy: 1923, 1129 + xy: 1794, 1274 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit-bridge rotate: false - xy: 1957, 1117 + xy: 1828, 1274 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit-end rotate: false - xy: 1991, 1117 + xy: 1862, 1274 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom rotate: false - xy: 1425, 1155 + xy: 1650, 1206 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-0 rotate: false - xy: 1459, 1155 + xy: 1684, 1206 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-1 rotate: false - xy: 1493, 1155 + xy: 1718, 1206 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-2 rotate: false - xy: 1527, 1155 + xy: 1752, 1206 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-3 rotate: false - xy: 1561, 1155 + xy: 1786, 1206 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-4 rotate: false - xy: 1595, 1155 + xy: 1820, 1206 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-5 rotate: false - xy: 1629, 1139 + xy: 1854, 1206 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-6 rotate: false - xy: 1663, 1139 + xy: 2001, 1752 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-0 rotate: false - xy: 1151, 855 + xy: 1421, 1142 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-1 rotate: false - xy: 1151, 821 + xy: 1421, 1108 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-2 rotate: false - xy: 1151, 787 + xy: 1455, 1142 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-3 rotate: false - xy: 1201, 905 + xy: 1421, 1074 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-4 rotate: false - xy: 1251, 955 + xy: 1455, 1108 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-5 rotate: false - xy: 1301, 1005 + xy: 1421, 1040 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-6 rotate: false - xy: 1351, 1055 + xy: 1455, 1074 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-junction rotate: false - xy: 1287, 751 + xy: 1481, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-router-bottom rotate: false - xy: 1253, 675 + xy: 1549, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-router-liquid rotate: false - xy: 1287, 649 + xy: 1311, 790 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-router-top rotate: false - xy: 495, 488 + xy: 1345, 790 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-tank-bottom rotate: false - xy: 1199, 1593 + xy: 1101, 1560 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 liquid-tank-liquid rotate: false - xy: 1297, 1593 + xy: 219, 1344 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 liquid-tank-top rotate: false - xy: 1297, 1495 + xy: 317, 1333 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mechanical-pump rotate: false - xy: 495, 250 + xy: 1892, 1238 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conduit rotate: false - xy: 1927, 1083 + xy: 1583, 965 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conduit-arrow rotate: false - xy: 1961, 1083 + xy: 1583, 931 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conduit-bridge rotate: false - xy: 1995, 1083 + xy: 1583, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conduit-end rotate: false - xy: 1927, 1049 + xy: 1583, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-0 rotate: false - xy: 499, 526 + xy: 1263, 738 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-1 rotate: false - xy: 533, 696 + xy: 1297, 756 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-2 rotate: false - xy: 533, 662 + xy: 1331, 756 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-3 rotate: false - xy: 533, 628 + xy: 1297, 722 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-4 rotate: false - xy: 533, 594 + xy: 1331, 722 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-5 rotate: false - xy: 533, 560 + xy: 1365, 738 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-6 rotate: false - xy: 533, 526 + xy: 1365, 704 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rotary-pump rotate: false - xy: 253, 1135 + xy: 851, 1034 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thermal-pump rotate: false - xy: 131, 613 + xy: 457, 1039 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 alpha-dart-mech-pad rotate: false - xy: 919, 1397 + xy: 1543, 1624 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 delta-mech-pad rotate: false - xy: 1183, 1429 + xy: 611, 1298 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 glaive-ship-pad rotate: false - xy: 807, 1463 + xy: 709, 1462 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 javelin-ship-pad rotate: false - xy: 1909, 1429 + xy: 662, 1232 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 omega-mech-pad rotate: false - xy: 1787, 1495 + xy: 302, 1235 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 tau-mech-pad rotate: false - xy: 327, 1234 + xy: 353, 841 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 trident-ship-pad rotate: false - xy: 319, 1036 + xy: 287, 709 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 battery rotate: false - xy: 1863, 1168 + xy: 1582, 1216 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 battery-large rotate: false - xy: 219, 1443 + xy: 219, 1442 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 combustion-generator rotate: false - xy: 1267, 997 + xy: 1824, 1240 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 combustion-generator-top rotate: false - xy: 1317, 1047 + xy: 1858, 1240 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 differential-generator rotate: false - xy: 1675, 1691 + xy: 317, 1529 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 differential-generator-top rotate: false - xy: 1773, 1691 + xy: 415, 1529 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 impact-reactor rotate: false - xy: 1102, 1919 + xy: 1232, 1918 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-bottom rotate: false - xy: 1232, 1919 + xy: 1362, 1918 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-light rotate: false - xy: 1492, 1919 + xy: 1622, 1918 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-plasma-0 rotate: false - xy: 1622, 1919 + xy: 1752, 1918 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-plasma-1 rotate: false - xy: 1752, 1919 + xy: 1882, 1918 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-plasma-2 rotate: false - xy: 1882, 1919 + xy: 526, 1788 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-plasma-3 rotate: false - xy: 526, 1789 + xy: 656, 1788 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-top rotate: false - xy: 656, 1789 + xy: 786, 1788 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 power-node rotate: false - xy: 485, 730 + xy: 1195, 792 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 power-node-large rotate: false - xy: 1909, 1297 + xy: 719, 1034 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 power-source rotate: false - xy: 499, 696 + xy: 1195, 758 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 power-void rotate: false - xy: 499, 662 + xy: 1229, 772 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 powerinfinite rotate: false - xy: 499, 628 + xy: 1185, 724 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 powervoid rotate: false - xy: 499, 594 + xy: 1229, 738 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rtg-generator rotate: false - xy: 253, 1069 + xy: 917, 1034 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rtg-generator-top rotate: false - xy: 529, 50 + xy: 1603, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 solar-panel rotate: false - xy: 87, 3 + xy: 1339, 636 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 solar-panel-large rotate: false - xy: 155, 711 + xy: 359, 1039 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 surge-tower rotate: false - xy: 261, 1236 + xy: 353, 907 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thermal-generator rotate: false - xy: 393, 1234 + xy: 287, 775 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thorium-reactor rotate: false - xy: 131, 515 + xy: 555, 1039 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 thorium-reactor-center rotate: false - xy: 131, 417 + xy: 1199, 1560 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 thorium-reactor-lights rotate: false - xy: 131, 319 + xy: 1199, 1462 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 turbine-generator rotate: false - xy: 385, 1102 + xy: 221, 643 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 turbine-generator-top rotate: false - xy: 451, 1168 + xy: 551, 907 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 alloy-smelter rotate: false - xy: 219, 1541 + xy: 219, 1540 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 alloy-smelter-top rotate: false - xy: 1087, 1691 + xy: 1347, 1690 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 blast-mixer rotate: false - xy: 1983, 1779 + xy: 1543, 1558 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +coal-centrifuge + rotate: false + xy: 1609, 1558 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-bottom rotate: false - xy: 229, 513 + xy: 1395, 1476 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-liquid rotate: false - xy: 229, 381 + xy: 1873, 1624 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-top rotate: false - xy: 229, 315 + xy: 1873, 1558 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator rotate: false - xy: 229, 249 + xy: 1956, 1852 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator-middle rotate: false - xy: 229, 117 + xy: 1383, 1410 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator-top rotate: false - xy: 229, 51 + xy: 1449, 1410 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 graphite-press rotate: false - xy: 1843, 1429 + xy: 596, 1232 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 incinerator rotate: false - xy: 1455, 985 + xy: 1515, 931 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-source rotate: false - xy: 1489, 917 + xy: 1277, 848 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-void rotate: false - xy: 1253, 811 + xy: 1447, 836 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 kiln rotate: false - xy: 1051, 1347 + xy: 596, 1166 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 kiln-top rotate: false - xy: 1117, 1363 + xy: 728, 1232 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 silicon-smelter-top rotate: false - xy: 1117, 1363 + xy: 728, 1232 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 lavasmelter rotate: false - xy: 1287, 819 + xy: 1413, 802 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-source rotate: false - xy: 495, 420 + xy: 1413, 768 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 melter rotate: false - xy: 495, 182 + xy: 1960, 1238 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 multi-press rotate: false - xy: 1493, 1495 + xy: 709, 1364 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 phase-weaver rotate: false - xy: 1249, 1297 + xy: 653, 1100 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phase-weaver-bottom rotate: false - xy: 1315, 1297 + xy: 719, 1100 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phase-weaver-weave rotate: false - xy: 1447, 1297 + xy: 851, 1100 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 plastanium-compressor rotate: false - xy: 1513, 1297 + xy: 917, 1100 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 plastanium-compressor-top rotate: false - xy: 1579, 1297 + xy: 983, 1100 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pulverizer rotate: false - xy: 529, 492 + xy: 1399, 734 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulverizer-rotator rotate: false - xy: 529, 424 + xy: 1399, 700 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pyratite-mixer rotate: false - xy: 1975, 1251 + xy: 785, 1034 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 separator rotate: false - xy: 1579, 1231 + xy: 155, 786 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 separator-liquid rotate: false - xy: 1645, 1231 + xy: 155, 720 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 silicon-smelter rotate: false - xy: 1711, 1231 + xy: 155, 654 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 smelter rotate: false - xy: 563, 50 + xy: 1305, 620 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spore-press rotate: false - xy: 1975, 1185 + xy: 361, 973 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-frame0 rotate: false - xy: 319, 1368 + xy: 427, 973 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-frame1 rotate: false - xy: 385, 1366 + xy: 493, 973 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-frame2 rotate: false - xy: 451, 1366 + xy: 559, 973 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-liquid rotate: false - xy: 583, 1350 + xy: 287, 907 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-top rotate: false - xy: 261, 1302 + xy: 221, 841 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 container rotate: false - xy: 1983, 1647 + xy: 1675, 1624 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 core-foundation rotate: false - xy: 972, 1919 + xy: 1102, 1918 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 core-nucleus rotate: false - xy: 1, 1235 + xy: 1, 1031 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 core-shard rotate: false - xy: 1283, 1691 + xy: 1543, 1690 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 core-shard-top rotate: false - xy: 1381, 1691 + xy: 1641, 1690 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 launch-pad rotate: false - xy: 1101, 1495 + xy: 1003, 1462 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 +launch-pad-large + rotate: false + xy: 916, 1788 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 sortedunloader rotate: false - xy: 1589, 1037 + xy: 1373, 666 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 unloader rotate: false - xy: 1355, 799 + xy: 1361, 564 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 vault rotate: false - xy: 131, 25 + xy: 1297, 1478 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 arc-heat rotate: false - xy: 2012, 1921 + xy: 2015, 1286 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-1 rotate: false - xy: 1999, 1151 + xy: 1620, 1245 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-2 rotate: false - xy: 1983, 1713 + xy: 1609, 1624 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-3 rotate: false - xy: 1185, 1691 + xy: 1445, 1690 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-4 rotate: false - xy: 323, 1628 + xy: 582, 1918 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 hail-heat rotate: false - xy: 526, 1919 + xy: 526, 1918 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 lancer-heat rotate: false - xy: 1249, 1363 + xy: 794, 1232 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 meltdown-heat rotate: false - xy: 916, 1789 + xy: 1176, 1788 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 ripple-heat rotate: false - xy: 163, 1299 + xy: 204, 1148 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 salvo-heat rotate: false - xy: 919, 1331 + xy: 1383, 1344 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 salvo-panel-left rotate: false - xy: 1051, 1281 + xy: 1271, 1298 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 salvo-panel-right rotate: false - xy: 1117, 1231 + xy: 1256, 1232 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 +scorch-heat + rotate: false + xy: 851, 646 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 wave-liquid rotate: false - xy: 385, 838 + xy: 419, 643 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 crawler-factory rotate: false - xy: 1983, 1515 + xy: 1741, 1624 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 dagger-factory rotate: false - xy: 1983, 1515 + xy: 1741, 1624 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phantom-factory rotate: false - xy: 1983, 1515 + xy: 1741, 1624 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spirit-factory rotate: false - xy: 1983, 1515 + xy: 1741, 1624 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wraith-factory rotate: false - xy: 1983, 1515 + xy: 1741, 1624 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 crawler-factory-top rotate: false - xy: 229, 645 + xy: 1807, 1624 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 crawler-factory-top-open rotate: false - xy: 229, 579 + xy: 1807, 1558 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 dagger-factory-top rotate: false - xy: 1051, 1413 + xy: 1939, 1654 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 dagger-factory-top-open rotate: false - xy: 1117, 1429 + xy: 1939, 1588 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 fortress-factory rotate: false - xy: 1871, 1691 + xy: 131, 39 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 fortress-factory-top rotate: false - xy: 513, 1432 + xy: 415, 1431 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 ghoul-factory-top rotate: false - xy: 513, 1432 + xy: 415, 1431 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 titan-factory-top rotate: false - xy: 513, 1432 + xy: 415, 1431 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 fortress-factory-top-open rotate: false - xy: 611, 1561 + xy: 513, 1529 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 ghoul-factory-top-open rotate: false - xy: 611, 1561 + xy: 513, 1529 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 titan-factory-top-open rotate: false - xy: 611, 1561 + xy: 513, 1529 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 ghoul-factory rotate: false - xy: 709, 1463 + xy: 611, 1462 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 phantom-factory-top rotate: false - xy: 1975, 1317 + xy: 1190, 1232 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phantom-factory-top-open rotate: false - xy: 1117, 1297 + xy: 1124, 1166 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 repair-point-base rotate: false - xy: 529, 322 + xy: 1501, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 revenant-factory rotate: false - xy: 1176, 1789 + xy: 1436, 1788 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 revenant-factory-top rotate: false - xy: 1436, 1789 + xy: 1696, 1788 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 revenant-factory-top-open rotate: false - xy: 1566, 1789 + xy: 1826, 1788 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 spirit-factory-top rotate: false - xy: 1843, 1231 + xy: 229, 973 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spirit-factory-top-open rotate: false - xy: 1909, 1231 + xy: 295, 973 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 titan-factory rotate: false - xy: 131, 221 + xy: 1199, 1364 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 wraith-factory-top rotate: false - xy: 385, 772 + xy: 485, 643 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wraith-factory-top-open rotate: false - xy: 451, 838 + xy: 551, 643 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 copper-wall rotate: false - xy: 1453, 1087 + xy: 1523, 999 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 copper-wall-large rotate: false - xy: 1983, 1581 + xy: 1675, 1558 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 door rotate: false - xy: 1521, 1019 + xy: 1311, 926 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 door-large rotate: false - xy: 1315, 1429 + xy: 743, 1298 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 door-large-open rotate: false - xy: 1381, 1429 + xy: 809, 1298 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 door-open rotate: false - xy: 1757, 1096 + xy: 1345, 960 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-wall rotate: false - xy: 1249, 641 + xy: 1101, 646 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-wall-large rotate: false - xy: 1183, 1297 + xy: 1190, 1166 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall-gigantic rotate: false - xy: 1826, 1789 + xy: 583, 1658 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 scrap-wall-huge1 rotate: false - xy: 155, 1005 + xy: 498, 1137 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 scrap-wall-huge2 rotate: false - xy: 155, 907 + xy: 163, 1050 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 scrap-wall-huge3 rotate: false - xy: 155, 809 + xy: 261, 1039 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 scrap-wall-large1 rotate: false - xy: 1315, 1231 + xy: 1247, 1034 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall-large2 rotate: false - xy: 1381, 1231 + xy: 163, 984 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall-large3 rotate: false - xy: 1447, 1231 + xy: 155, 918 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall-large4 rotate: false - xy: 1513, 1231 + xy: 155, 852 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall1 rotate: false - xy: 563, 458 + xy: 919, 650 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall2 rotate: false - xy: 563, 424 + xy: 953, 650 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall3 rotate: false - xy: 563, 390 + xy: 987, 650 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall4 rotate: false - xy: 563, 356 + xy: 1021, 650 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall5 rotate: false - xy: 563, 356 + xy: 1021, 650 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 surge-wall rotate: false - xy: 1591, 901 + xy: 1475, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 surge-wall-large rotate: false - xy: 327, 1300 + xy: 287, 841 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thorium-wall rotate: false - xy: 1693, 1028 + xy: 1441, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thorium-wall-large rotate: false - xy: 459, 1234 + xy: 221, 709 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thruster rotate: false - xy: 713, 1659 + xy: 973, 1658 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 titanium-wall rotate: false - xy: 1321, 713 + xy: 1225, 568 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-wall-large rotate: false - xy: 385, 1168 + xy: 353, 775 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 bullet rotate: false - xy: 295, 660 + xy: 799, 980 size: 52, 52 orig: 52, 52 offset: 0, 0 index: -1 bullet-back rotate: false - xy: 295, 606 + xy: 853, 980 size: 52, 52 orig: 52, 52 offset: 0, 0 index: -1 casing rotate: false - xy: 1041, 1313 + xy: 1505, 1326 size: 8, 16 orig: 8, 16 offset: 0, 0 index: -1 +circle-shadow + rotate: false + xy: 1, 1193 + size: 201, 201 + orig: 201, 201 + offset: 0, 0 + index: -1 error rotate: false - xy: 575, 1028 + xy: 429, 235 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 laser rotate: false - xy: 2043, 1103 + xy: 1021, 488 size: 4, 48 orig: 4, 48 offset: 0, 0 index: -1 laser-end rotate: false - xy: 697, 1389 + xy: 1395, 1542 size: 72, 72 orig: 72, 72 offset: 0, 0 index: -1 minelaser rotate: false - xy: 2041, 1399 + xy: 891, 188 size: 4, 48 orig: 4, 48 offset: 0, 0 index: -1 minelaser-end rotate: false - xy: 771, 1389 + xy: 1469, 1616 size: 72, 72 orig: 72, 72 offset: 0, 0 index: -1 missile rotate: false - xy: 1075, 759 + xy: 1506, 1270 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 missile-back rotate: false - xy: 1074, 721 + xy: 1544, 1270 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 scale_marker rotate: false - xy: 517, 1228 + xy: 1313, 1160 size: 4, 4 orig: 4, 4 offset: 0, 0 index: -1 scorch1 rotate: false - xy: 1389, 753 + xy: 679, 428 size: 28, 100 orig: 28, 100 offset: 0, 0 index: -1 scorch2 rotate: false - xy: 1761, 994 + xy: 679, 326 size: 28, 100 orig: 28, 100 offset: 0, 0 index: -1 scorch3 rotate: false - xy: 1761, 892 + xy: 679, 224 size: 28, 100 orig: 28, 100 offset: 0, 0 index: -1 scorch4 rotate: false - xy: 1791, 969 + xy: 679, 122 size: 28, 100 orig: 28, 100 offset: 0, 0 index: -1 scorch5 rotate: false - xy: 1821, 964 + xy: 709, 428 size: 28, 100 orig: 28, 100 offset: 0, 0 index: -1 shell rotate: false - xy: 1711, 1164 + xy: 1506, 1203 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 shell-back rotate: false - xy: 1749, 1164 + xy: 1544, 1232 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 shot rotate: false - xy: 563, 118 + xy: 1305, 688 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 transfer rotate: false - xy: 2041, 1349 + xy: 1021, 438 size: 4, 48 orig: 4, 48 offset: 0, 0 index: -1 transfer-arrow rotate: false - xy: 1355, 901 + xy: 1293, 586 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 transfer-end rotate: false - xy: 845, 1389 + xy: 1469, 1542 size: 72, 72 orig: 72, 72 offset: 0, 0 index: -1 alloy-smelter-icon-large rotate: false - xy: 229, 1 + xy: 907, 984 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 alloy-smelter-icon-medium rotate: false - xy: 691, 1205 + xy: 2015, 1388 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 alloy-smelter-icon-small rotate: false - xy: 1091, 1255 + xy: 583, 1632 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 alpha-dart-mech-pad-icon-large rotate: false - xy: 279, 1 + xy: 957, 984 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 alpha-dart-mech-pad-icon-medium rotate: false - xy: 2012, 1989 + xy: 2015, 1354 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 alpha-dart-mech-pad-icon-small rotate: false - xy: 583, 1633 + xy: 2001, 1726 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 arc rotate: false - xy: 2012, 1955 + xy: 2015, 1320 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 arc-icon-full rotate: false - xy: 1939, 1197 + xy: 2015, 1252 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 arc-icon-large rotate: false - xy: 295, 506 + xy: 1157, 984 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 arc-icon-small rotate: false - xy: 1956, 1819 + xy: 447, 9 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 battery-icon-large rotate: false - xy: 295, 398 + xy: 1257, 984 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 battery-icon-small rotate: false - xy: 891, 1363 + xy: 1429, 531 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 battery-large-icon-large rotate: false - xy: 295, 348 + xy: 213, 528 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 battery-large-icon-medium rotate: false - xy: 1897, 1168 + xy: 2012, 1988 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 battery-large-icon-small rotate: false - xy: 1321, 653 + xy: 1588, 565 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 blast-drill-icon-full rotate: false - xy: 1, 471 + xy: 1, 267 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 blast-drill-icon-large rotate: false - xy: 295, 298 + xy: 229, 478 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 blast-drill-icon-medium rotate: false - xy: 1931, 1163 + xy: 2012, 1954 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 blast-drill-icon-small rotate: false - xy: 1389, 689 + xy: 679, 58 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 blast-mixer-icon-large rotate: false - xy: 295, 248 + xy: 229, 428 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 blast-mixer-icon-medium rotate: false - xy: 1965, 1151 + xy: 2012, 1920 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 blast-mixer-icon-small rotate: false - xy: 1389, 663 + xy: 709, 339 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 bridge-conduit-icon-large rotate: false - xy: 295, 98 + xy: 229, 278 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 bridge-conduit-icon-small rotate: false - xy: 1851, 1002 + xy: 1455, 531 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 bridge-conveyor-icon-large rotate: false - xy: 399, 664 + xy: 229, 228 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 bridge-conveyor-icon-small rotate: false - xy: 1956, 1793 + xy: 1614, 565 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 char-icon-large rotate: false - xy: 435, 722 + xy: 229, 128 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 char-icon-small rotate: false - xy: 1851, 976 + xy: 709, 287 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 cliffs-icon-large rotate: false - xy: 449, 672 + xy: 229, 78 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 cliffs-icon-small rotate: false - xy: 1420, 891 + xy: 709, 261 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +coal-centrifuge-icon-large + rotate: false + xy: 263, 528 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +coal-centrifuge-icon-medium + rotate: false + xy: 1790, 1240 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +coal-centrifuge-icon-small + rotate: false + xy: 709, 235 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 combustion-generator-icon-large rotate: false - xy: 449, 622 + xy: 313, 535 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 combustion-generator-icon-small rotate: false - xy: 1446, 891 + xy: 709, 209 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 conduit-icon-full rotate: false - xy: 1697, 1130 + xy: 1205, 826 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-icon-large rotate: false - xy: 641, 1300 + xy: 363, 535 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 conduit-icon-small rotate: false - xy: 1420, 865 + xy: 709, 183 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 container-icon-large rotate: false - xy: 641, 1250 + xy: 413, 535 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 container-icon-medium rotate: false - xy: 1417, 1121 + xy: 1455, 1040 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 container-icon-small rotate: false - xy: 1472, 891 + xy: 709, 157 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 conveyor-icon-large rotate: false - xy: 641, 1200 + xy: 463, 535 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 conveyor-icon-small rotate: false - xy: 1446, 865 + xy: 709, 131 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 copper-wall-icon-large rotate: false - xy: 349, 564 + xy: 513, 535 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 copper-wall-icon-small rotate: false - xy: 1498, 891 + xy: 2022, 1894 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 copper-wall-large-icon-large rotate: false - xy: 399, 564 + xy: 563, 535 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 copper-wall-large-icon-medium rotate: false - xy: 1487, 1087 + xy: 1557, 1135 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 copper-wall-large-icon-small rotate: false - xy: 1472, 865 + xy: 2022, 1868 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 core-foundation-icon-large rotate: false - xy: 449, 572 + xy: 229, 28 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 core-foundation-icon-medium rotate: false - xy: 1521, 1087 + xy: 1557, 1101 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 core-foundation-icon-small rotate: false - xy: 1524, 891 + xy: 2022, 1842 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 core-nucleus-icon-large rotate: false - xy: 345, 514 + xy: 279, 478 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 core-nucleus-icon-medium rotate: false - xy: 1555, 1087 + xy: 1557, 1067 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 core-nucleus-icon-small rotate: false - xy: 1498, 865 + xy: 2022, 1816 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 core-shard-icon-large rotate: false - xy: 345, 464 + xy: 279, 428 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 core-shard-icon-medium rotate: false - xy: 1385, 1037 + xy: 1557, 1033 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 core-shard-icon-small rotate: false - xy: 1550, 891 + xy: 2022, 1790 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 craters-icon-large rotate: false - xy: 395, 514 + xy: 279, 378 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 craters-icon-small rotate: false - xy: 1524, 865 + xy: 2005, 1700 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 crawler-factory-icon-full rotate: false - xy: 1983, 1449 + xy: 1741, 1558 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 crawler-factory-icon-large rotate: false - xy: 345, 364 + xy: 279, 228 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 crawler-factory-icon-medium rotate: false - xy: 1419, 1053 + xy: 1557, 999 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 crawler-factory-icon-small rotate: false - xy: 1550, 865 + xy: 2005, 1674 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +creeptree-icon-large + rotate: false + xy: 279, 128 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +creeptree-icon-medium + rotate: false + xy: 1117, 714 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +creeptree-icon-small + rotate: false + xy: 2005, 1648 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 cryofluidmixer-icon-full rotate: false - xy: 229, 447 + xy: 1461, 1476 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-icon-large rotate: false - xy: 345, 314 + xy: 279, 78 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 cryofluidmixer-icon-medium rotate: false - xy: 1453, 1053 + xy: 1243, 942 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cryofluidmixer-icon-small rotate: false - xy: 1820, 938 + xy: 2005, 1622 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 cultivator-icon-full rotate: false - xy: 229, 183 + xy: 1956, 1786 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator-icon-large rotate: false - xy: 395, 364 + xy: 279, 28 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 cultivator-icon-medium rotate: false - xy: 1487, 1053 + xy: 1243, 908 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cultivator-icon-small rotate: false - xy: 1820, 912 + xy: 2005, 1596 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 cyclone rotate: false - xy: 1479, 1691 + xy: 1739, 1690 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cyclone-icon-full rotate: false - xy: 1577, 1691 + xy: 1837, 1690 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cyclone-icon-large rotate: false - xy: 345, 264 + xy: 329, 485 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 cyclone-icon-medium rotate: false - xy: 1521, 1053 + xy: 1243, 874 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cyclone-icon-small rotate: false - xy: 1791, 880 + xy: 2005, 1570 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 dagger-factory-icon-full rotate: false - xy: 985, 1397 + xy: 1935, 1720 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 dagger-factory-icon-large rotate: false - xy: 395, 264 + xy: 329, 385 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dagger-factory-icon-medium rotate: false - xy: 1555, 1053 + xy: 1277, 950 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 dagger-factory-icon-small rotate: false - xy: 1880, 1035 + xy: 2005, 1544 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dark-metal-icon-large + rotate: false + xy: 429, 485 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dark-metal-icon-small + rotate: false + xy: 655, 647 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dark-panel-1-icon-large + rotate: false + xy: 329, 335 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dark-panel-1-icon-small + rotate: false + xy: 681, 650 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dark-panel-2-icon-large + rotate: false + xy: 379, 385 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dark-panel-2-icon-small + rotate: false + xy: 707, 650 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dark-panel-3-icon-large + rotate: false + xy: 429, 435 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dark-panel-3-icon-small + rotate: false + xy: 733, 650 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dark-panel-4-icon-large + rotate: false + xy: 479, 485 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dark-panel-4-icon-small + rotate: false + xy: 759, 650 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dark-panel-5-icon-large + rotate: false + xy: 329, 285 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dark-panel-5-icon-small + rotate: false + xy: 785, 650 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dark-panel-6-icon-large + rotate: false + xy: 379, 335 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dark-panel-6-icon-small + rotate: false + xy: 473, 1 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +darksand-icon-large + rotate: false + xy: 429, 385 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +darksand-icon-small + rotate: false + xy: 499, 1 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +darksand-tainted-water-icon-large + rotate: false + xy: 479, 435 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +darksand-tainted-water-icon-small + rotate: false + xy: 1588, 539 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +darksand-water-icon-large + rotate: false + xy: 529, 485 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +darksand-water-icon-small + rotate: false + xy: 1614, 539 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 deepwater-icon-large rotate: false - xy: 345, 114 + xy: 379, 285 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 deepwater-icon-small rotate: false - xy: 1384, 603 + xy: 668, 621 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 delta-mech-pad-icon-large rotate: false - xy: 395, 64 + xy: 329, 185 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 delta-mech-pad-icon-medium rotate: false - xy: 1419, 1019 + xy: 1277, 916 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 delta-mech-pad-icon-small rotate: false - xy: 1384, 577 + xy: 694, 624 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 differential-generator-icon-large rotate: false - xy: 329, 14 + xy: 379, 235 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 differential-generator-icon-medium rotate: false - xy: 1453, 1019 + xy: 1277, 882 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 differential-generator-icon-small rotate: false - xy: 1851, 950 + xy: 720, 624 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 distributor-icon-large rotate: false - xy: 379, 14 + xy: 429, 285 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 distributor-icon-medium rotate: false - xy: 1487, 1019 + xy: 1311, 960 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 distributor-icon-small rotate: false - xy: 1846, 924 + xy: 746, 624 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 door-icon-large rotate: false - xy: 429, 14 + xy: 479, 335 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 door-icon-small rotate: false - xy: 1846, 898 + xy: 772, 624 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 door-large-icon-large rotate: false - xy: 575, 1178 + xy: 529, 385 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 door-large-icon-medium rotate: false - xy: 1555, 1019 + xy: 1311, 892 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 door-large-icon-small rotate: false - xy: 1820, 886 + xy: 668, 595 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 dunerocks-icon-large rotate: false - xy: 575, 1128 + xy: 329, 135 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dunerocks-icon-small rotate: false - xy: 1846, 872 + xy: 694, 598 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 duo rotate: false - xy: 1791, 1105 + xy: 1345, 926 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 duo-icon-full rotate: false - xy: 1791, 1071 + xy: 1345, 892 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 duo-icon-large rotate: false - xy: 575, 1078 + xy: 379, 185 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 duo-icon-small rotate: false - xy: 1576, 875 + xy: 720, 598 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 force-projector-icon-large rotate: false - xy: 575, 812 + xy: 379, 135 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 force-projector-icon-medium rotate: false - xy: 1219, 837 + xy: 1379, 942 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 force-projector-icon-small rotate: false - xy: 1602, 875 + xy: 746, 598 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 fortress-factory-icon-full rotate: false - xy: 513, 1530 + xy: 317, 1431 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 fortress-factory-icon-large rotate: false - xy: 574, 762 + xy: 429, 185 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 fortress-factory-icon-medium rotate: false - xy: 1219, 803 + xy: 1379, 908 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 fortress-factory-icon-small rotate: false - xy: 1628, 875 + xy: 772, 598 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 fuse rotate: false - xy: 611, 1463 + xy: 513, 1431 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 fuse-icon-full rotate: false - xy: 709, 1561 + xy: 611, 1560 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 fuse-icon-large rotate: false - xy: 625, 1150 + xy: 479, 227 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 fuse-icon-medium rotate: false - xy: 1219, 769 + xy: 1413, 972 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 fuse-icon-small rotate: false - xy: 1654, 866 + xy: 663, 569 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 ghoul-factory-icon-full rotate: false - xy: 807, 1561 + xy: 709, 1560 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 ghoul-factory-icon-large rotate: false - xy: 625, 1100 + xy: 529, 285 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ghoul-factory-icon-medium rotate: false - xy: 1185, 727 + xy: 1413, 938 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ghoul-factory-icon-small rotate: false - xy: 1680, 866 + xy: 663, 543 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 glaive-ship-pad-icon-large rotate: false - xy: 625, 1050 + xy: 379, 85 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 glaive-ship-pad-icon-medium rotate: false - xy: 1219, 735 + xy: 1447, 972 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 glaive-ship-pad-icon-small rotate: false - xy: 1706, 866 + xy: 709, 105 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 graphite-press-icon-large rotate: false - xy: 625, 1000 + xy: 429, 135 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 graphite-press-icon-medium rotate: false - xy: 1269, 921 + xy: 1447, 938 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 graphite-press-icon-small rotate: false - xy: 1732, 866 + xy: 708, 79 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 grass-icon-large rotate: false - xy: 625, 950 + xy: 479, 177 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 grass-icon-small rotate: false - xy: 1758, 866 + xy: 705, 53 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 hail rotate: false - xy: 1319, 971 + xy: 1413, 904 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 hail-icon-full rotate: false - xy: 1369, 1003 + xy: 1447, 904 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 hail-icon-large rotate: false - xy: 625, 900 + xy: 529, 235 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 hail-icon-small rotate: false - xy: 1420, 839 + xy: 798, 620 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 holostone-icon-large rotate: false - xy: 625, 800 + xy: 479, 127 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 holostone-icon-small rotate: false - xy: 1446, 839 + xy: 824, 620 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 hotrock-icon-large rotate: false - xy: 624, 750 + xy: 529, 185 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 hotrock-icon-small rotate: false - xy: 1472, 839 + xy: 850, 620 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 ice-icon-large rotate: false - xy: 675, 1150 + xy: 529, 135 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ice-icon-small rotate: false - xy: 1498, 839 + xy: 876, 620 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 ice-snow-icon-large rotate: false - xy: 675, 1100 + xy: 329, 27 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ice-snow-icon-small rotate: false - xy: 1524, 839 + xy: 798, 594 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 icerocks-icon-large rotate: false - xy: 675, 1050 + xy: 379, 35 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 icerocks-icon-small rotate: false - xy: 1550, 839 + xy: 824, 594 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 ignarock-icon-large rotate: false - xy: 675, 950 + xy: 479, 77 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ignarock-icon-small rotate: false - xy: 1419, 813 + xy: 1640, 539 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 impact-reactor-icon-full rotate: false - xy: 1362, 1919 + xy: 1492, 1918 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-icon-large rotate: false - xy: 675, 900 + xy: 529, 85 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 impact-reactor-icon-medium rotate: false - xy: 1421, 985 + xy: 1515, 965 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 impact-reactor-icon-small rotate: false - xy: 1419, 787 + xy: 689, 569 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 incinerator-icon-large rotate: false - xy: 675, 850 + xy: 479, 27 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 incinerator-icon-small rotate: false - xy: 1445, 813 + xy: 689, 543 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-blast-compound-medium rotate: false - xy: 1445, 787 + xy: 715, 530 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-blast-compound-small rotate: false - xy: 1810, 844 + xy: 967, 448 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-blast-compound-xlarge rotate: false - xy: 649, 1374 + xy: 1067, 692 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-coal-medium rotate: false - xy: 1471, 813 + xy: 741, 572 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-coal-small rotate: false - xy: 1828, 850 + xy: 985, 466 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-coal-xlarge rotate: false - xy: 219, 1401 + xy: 1117, 748 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-copper-medium rotate: false - xy: 1445, 761 + xy: 741, 546 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-copper-small rotate: false - xy: 1846, 854 + xy: 1003, 484 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-copper-xlarge rotate: false - xy: 261, 1401 + xy: 1337, 1342 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-graphite-medium rotate: false - xy: 1471, 787 + xy: 767, 572 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-graphite-small rotate: false - xy: 1810, 826 + xy: 967, 430 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-graphite-xlarge rotate: false - xy: 1425, 1189 + xy: 1337, 1300 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-lead-medium rotate: false - xy: 1497, 813 + xy: 767, 546 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-lead-small rotate: false - xy: 1828, 832 + xy: 985, 448 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-lead-xlarge rotate: false - xy: 1075, 839 + xy: 1379, 1302 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-metaglass-medium rotate: false - xy: 1471, 761 + xy: 793, 568 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-metaglass-small rotate: false - xy: 1846, 836 + xy: 1003, 466 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-metaglass-xlarge rotate: false - xy: 1125, 889 + xy: 1421, 1302 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-phase-fabric-medium rotate: false - xy: 1497, 787 + xy: 819, 568 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-phase-fabric-small rotate: false - xy: 1810, 808 + xy: 985, 430 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-phase-fabric-xlarge rotate: false - xy: 1175, 939 + xy: 1463, 1302 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-plastanium-medium rotate: false - xy: 1523, 813 + xy: 845, 568 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-plastanium-small rotate: false - xy: 1828, 814 + xy: 1003, 448 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-plastanium-xlarge rotate: false - xy: 1225, 989 + xy: 1380, 1260 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-pyratite-medium rotate: false - xy: 1497, 761 + xy: 871, 568 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-pyratite-small rotate: false - xy: 1846, 818 + xy: 1003, 430 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-pyratite-xlarge rotate: false - xy: 1275, 1039 + xy: 1380, 1218 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-sand-medium rotate: false - xy: 1523, 787 + xy: 793, 542 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-sand-small rotate: false - xy: 1864, 854 + xy: 207, 3 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-sand-xlarge rotate: false - xy: 1325, 1089 + xy: 1422, 1260 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-scrap-medium rotate: false - xy: 1549, 813 + xy: 819, 542 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-scrap-small rotate: false - xy: 1864, 836 + xy: 225, 10 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-scrap-xlarge rotate: false - xy: 1375, 1139 + xy: 1380, 1176 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-silicon-medium rotate: false - xy: 1523, 761 + xy: 845, 542 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-silicon-small rotate: false - xy: 1864, 818 + xy: 243, 10 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-silicon-xlarge rotate: false - xy: 1467, 1189 + xy: 1422, 1218 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-source-icon-large rotate: false - xy: 675, 800 + xy: 529, 35 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 item-source-icon-small rotate: false - xy: 1549, 787 + xy: 871, 542 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-spore-pod-medium rotate: false - xy: 1549, 761 + xy: 741, 520 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-spore-pod-small rotate: false - xy: 1880, 1017 + xy: 261, 10 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-spore-pod-xlarge rotate: false - xy: 1075, 797 + xy: 1422, 1176 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-surge-alloy-medium rotate: false - xy: 1418, 719 + xy: 767, 520 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-surge-alloy-small rotate: false - xy: 1877, 999 + xy: 279, 10 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-surge-alloy-xlarge rotate: false - xy: 1509, 1189 + xy: 1464, 1260 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-thorium-medium rotate: false - xy: 1654, 840 + xy: 739, 494 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-thorium-small rotate: false - xy: 1877, 981 + xy: 297, 10 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-thorium-xlarge rotate: false - xy: 1551, 1189 + xy: 1464, 1218 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-titanium-medium rotate: false - xy: 1680, 840 + xy: 739, 468 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-titanium-small rotate: false - xy: 1877, 963 + xy: 1211, 686 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-titanium-xlarge rotate: false - xy: 1593, 1189 + xy: 1464, 1176 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-void-icon-large rotate: false - xy: 674, 750 + xy: 579, 485 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 item-void-icon-small rotate: false - xy: 1706, 840 + xy: 765, 494 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 javelin-ship-pad-icon-large rotate: false - xy: 445, 472 + xy: 579, 385 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 javelin-ship-pad-icon-medium rotate: false - xy: 1253, 777 + xy: 1481, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 javelin-ship-pad-icon-small rotate: false - xy: 1732, 840 + xy: 739, 442 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 junction-icon-large rotate: false - xy: 445, 372 + xy: 579, 285 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 junction-icon-small rotate: false - xy: 1758, 840 + xy: 765, 468 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 kiln-icon-large rotate: false - xy: 445, 322 + xy: 579, 235 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 kiln-icon-medium rotate: false - xy: 1219, 701 + xy: 1549, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 kiln-icon-small rotate: false - xy: 1784, 854 + xy: 765, 442 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 lancer rotate: false - xy: 1183, 1363 + xy: 662, 1166 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 lancer-icon-full rotate: false - xy: 1315, 1363 + xy: 728, 1166 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 lancer-icon-large rotate: false - xy: 445, 272 + xy: 579, 185 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 lancer-icon-medium rotate: false - xy: 1253, 709 + xy: 1311, 824 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 lancer-icon-small rotate: false - xy: 1445, 735 + xy: 793, 516 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 laser-drill-icon-full rotate: false - xy: 905, 1463 + xy: 807, 1462 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 laser-drill-icon-large rotate: false - xy: 445, 222 + xy: 579, 135 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 laser-drill-icon-medium rotate: false - xy: 1287, 887 + xy: 1345, 824 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 laser-drill-icon-small rotate: false - xy: 1471, 735 + xy: 819, 516 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 launch-pad-icon-large rotate: false - xy: 445, 172 + xy: 579, 85 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 launch-pad-icon-medium rotate: false - xy: 1287, 853 + xy: 1277, 814 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 launch-pad-icon-small rotate: false - xy: 1497, 735 + xy: 845, 516 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +launch-pad-large-icon-large + rotate: false + xy: 579, 35 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +launch-pad-large-icon-medium + rotate: false + xy: 1379, 806 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +launch-pad-large-icon-small + rotate: false + xy: 871, 516 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 liquid-junction-icon-large rotate: false - xy: 445, 72 + xy: 629, 485 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 liquid-junction-icon-small rotate: false - xy: 1523, 735 + xy: 791, 490 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 liquid-router-icon-full rotate: false - xy: 1287, 683 + xy: 1239, 806 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-router-icon-large rotate: false - xy: 479, 22 + xy: 629, 435 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 liquid-router-icon-small rotate: false - xy: 1549, 735 + xy: 791, 464 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 liquid-source-icon-large rotate: false - xy: 691, 1339 + xy: 629, 385 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 liquid-source-icon-small rotate: false - xy: 1444, 709 + xy: 817, 490 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 liquid-tank-icon-full rotate: false - xy: 1199, 1495 + xy: 1101, 1462 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 liquid-tank-icon-large rotate: false - xy: 691, 1289 + xy: 629, 335 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 liquid-tank-icon-medium rotate: false - xy: 495, 386 + xy: 1447, 768 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-tank-icon-small rotate: false - xy: 1470, 709 + xy: 817, 464 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 magmarock-icon-large rotate: false - xy: 741, 1339 + xy: 629, 285 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 magmarock-icon-small rotate: false - xy: 1496, 709 + xy: 843, 490 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 mass-driver rotate: false - xy: 1395, 1593 + xy: 415, 1333 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mass-driver-icon-full rotate: false - xy: 1493, 1593 + xy: 611, 1364 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mass-driver-icon-large rotate: false - xy: 691, 1239 + xy: 629, 235 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mass-driver-icon-medium rotate: false - xy: 495, 318 + xy: 1515, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mass-driver-icon-small rotate: false - xy: 1522, 709 + xy: 843, 464 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 mech-icon-alpha-mech rotate: false - xy: 741, 1289 + xy: 629, 185 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mech-icon-dart-ship rotate: false - xy: 791, 1339 + xy: 629, 135 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mech-icon-delta-mech rotate: false - xy: 741, 1239 + xy: 629, 85 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mech-icon-glaive-ship rotate: false - xy: 583, 1234 + xy: 286, 585 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 mech-icon-javelin-ship rotate: false - xy: 791, 1289 + xy: 629, 35 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mech-icon-omega-mech rotate: false - xy: 517, 1170 + xy: 344, 585 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 mech-icon-tau-mech rotate: false - xy: 517, 1112 + xy: 402, 585 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 mech-icon-trident-ship rotate: false - xy: 517, 1054 + xy: 460, 585 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 mechanical-drill-icon-full rotate: false - xy: 1447, 1363 + xy: 794, 1166 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mechanical-drill-icon-large rotate: false - xy: 841, 1339 + xy: 1543, 1508 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mechanical-drill-icon-medium rotate: false - xy: 495, 284 + xy: 1549, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mechanical-drill-icon-small rotate: false - xy: 1548, 709 + xy: 869, 490 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 mechanical-pump-icon-large rotate: false - xy: 791, 1239 + xy: 1593, 1508 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mechanical-pump-icon-small rotate: false - xy: 1784, 828 + xy: 869, 464 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 meltdown rotate: false - xy: 786, 1789 + xy: 1046, 1788 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 meltdown-icon-full rotate: false - xy: 1046, 1789 + xy: 1306, 1788 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 meltdown-icon-large rotate: false - xy: 841, 1289 + xy: 1643, 1508 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 meltdown-icon-medium rotate: false - xy: 495, 216 + xy: 1926, 1238 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 meltdown-icon-small rotate: false - xy: 1418, 693 + xy: 791, 438 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 melter-icon-large rotate: false - xy: 841, 1239 + xy: 1693, 1508 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 melter-icon-small rotate: false - xy: 1415, 667 + xy: 817, 438 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 mend-projector-icon-large rotate: false - xy: 891, 1281 + xy: 1743, 1508 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mend-projector-icon-medium rotate: false - xy: 495, 148 + xy: 1888, 1204 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mend-projector-icon-small rotate: false - xy: 1419, 641 + xy: 843, 438 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +mender-icon-large + rotate: false + xy: 1793, 1508 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mender-icon-small + rotate: false + xy: 869, 438 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 metal-floor-2-icon-large rotate: false - xy: 941, 1281 + xy: 1843, 1508 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 metal-floor-2-icon-small rotate: false - xy: 1444, 683 + xy: 739, 416 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 metal-floor-3-icon-large rotate: false - xy: 991, 1281 + xy: 1527, 1458 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 metal-floor-3-icon-small rotate: false - xy: 1470, 683 + xy: 765, 416 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 metal-floor-5-icon-large rotate: false - xy: 891, 1231 + xy: 1577, 1458 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 metal-floor-5-icon-small rotate: false - xy: 1496, 683 + xy: 738, 390 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 metal-floor-damaged-icon-large rotate: false - xy: 941, 1231 + xy: 1627, 1458 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 metal-floor-damaged-icon-small rotate: false - xy: 1522, 683 + xy: 764, 390 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 metal-floor-icon-large rotate: false - xy: 991, 1231 + xy: 1677, 1458 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 metal-floor-icon-small rotate: false - xy: 1548, 683 + xy: 738, 364 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 moss-icon-large rotate: false - xy: 1041, 1231 + xy: 1727, 1458 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 moss-icon-small rotate: false - xy: 1419, 615 + xy: 764, 364 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 multi-press-icon-large rotate: false - xy: 725, 1189 + xy: 1777, 1458 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 multi-press-icon-medium rotate: false - xy: 495, 114 + xy: 1888, 1170 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 multi-press-icon-small rotate: false - xy: 1410, 589 + xy: 735, 338 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 oil-extractor-icon-full rotate: false - xy: 1591, 1495 + xy: 905, 1364 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-icon-large rotate: false - xy: 725, 1139 + xy: 1827, 1458 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 oil-extractor-icon-medium rotate: false - xy: 495, 80 + xy: 1922, 1170 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 oil-extractor-icon-small rotate: false - xy: 1410, 563 + xy: 735, 312 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 omega-mech-pad-icon-large rotate: false - xy: 775, 1189 + xy: 1515, 1408 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 omega-mech-pad-icon-medium rotate: false - xy: 1825, 1100 + xy: 1956, 1170 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 omega-mech-pad-icon-small rotate: false - xy: 1576, 823 + xy: 761, 338 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 ore-coal-icon-full rotate: false - xy: 1859, 1100 + xy: 379, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-coal-icon-medium rotate: false - xy: 1859, 1100 + xy: 379, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-coal-icon-large rotate: false - xy: 725, 1089 + xy: 1515, 1358 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ore-coal-icon-small rotate: false - xy: 1602, 823 + xy: 735, 286 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 ore-copper-icon-full rotate: false - xy: 1825, 1066 + xy: 413, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-copper-icon-medium rotate: false - xy: 1825, 1066 + xy: 413, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-copper-icon-large rotate: false - xy: 775, 1139 + xy: 1565, 1408 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ore-copper-icon-small rotate: false - xy: 1628, 823 + xy: 761, 312 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 ore-lead-icon-full rotate: false - xy: 1859, 1066 + xy: 529, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-lead-icon-medium rotate: false - xy: 1859, 1066 + xy: 529, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-lead-icon-large rotate: false - xy: 825, 1189 + xy: 1565, 1358 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ore-lead-icon-small rotate: false - xy: 1575, 797 + xy: 735, 260 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 ore-scrap-icon-full rotate: false - xy: 1147, 719 + xy: 563, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-scrap-icon-medium rotate: false - xy: 1147, 719 + xy: 563, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-scrap-icon-large rotate: false - xy: 725, 1039 + xy: 1615, 1408 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ore-scrap-icon-small rotate: false - xy: 1575, 771 + xy: 761, 286 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 ore-thorium-icon-full rotate: false - xy: 1146, 685 + xy: 597, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-thorium-icon-medium rotate: false - xy: 1146, 685 + xy: 597, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-thorium-icon-large rotate: false - xy: 775, 1089 + xy: 1615, 1358 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ore-thorium-icon-small rotate: false - xy: 1601, 797 + xy: 735, 234 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 ore-titanium-icon-full rotate: false - xy: 1893, 1095 + xy: 631, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-titanium-icon-medium rotate: false - xy: 1893, 1095 + xy: 631, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-titanium-icon-large rotate: false - xy: 825, 1139 + xy: 1665, 1408 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ore-titanium-icon-small rotate: false - xy: 1575, 745 + xy: 761, 260 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 overdrive-projector-icon-large rotate: false - xy: 725, 989 + xy: 1665, 1358 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 overdrive-projector-icon-medium rotate: false - xy: 1893, 1061 + xy: 665, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 overdrive-projector-icon-small rotate: false - xy: 1601, 771 + xy: 735, 208 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 overflow-gate-icon-large rotate: false - xy: 775, 1039 + xy: 1715, 1408 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 overflow-gate-icon-small rotate: false - xy: 1627, 797 + xy: 761, 234 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +pebbles-icon-large + rotate: false + xy: 1715, 1358 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +pebbles-icon-small + rotate: false + xy: 735, 182 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 phantom-factory-icon-full rotate: false - xy: 1975, 1383 + xy: 1058, 1166 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phantom-factory-icon-large rotate: false - xy: 825, 1089 + xy: 1765, 1408 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 phantom-factory-icon-medium rotate: false - xy: 1180, 659 + xy: 1143, 680 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phantom-factory-icon-small rotate: false - xy: 1601, 745 + xy: 761, 208 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 phase-conduit-icon-large rotate: false - xy: 725, 939 + xy: 1765, 1358 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 phase-conduit-icon-small rotate: false - xy: 1627, 771 + xy: 735, 156 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 phase-conveyor-icon-large rotate: false - xy: 775, 989 + xy: 1815, 1408 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 phase-conveyor-icon-small rotate: false - xy: 1627, 745 + xy: 761, 182 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 phase-wall-icon-large rotate: false - xy: 825, 1039 + xy: 1815, 1358 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 phase-wall-icon-small rotate: false - xy: 1654, 814 + xy: 735, 130 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 phase-wall-large-icon-large rotate: false - xy: 725, 889 + xy: 1877, 1458 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 phase-wall-large-icon-medium rotate: false - xy: 1248, 607 + xy: 1135, 646 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-wall-large-icon-small rotate: false - xy: 1680, 814 + xy: 761, 156 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 phase-weaver-icon-full rotate: false - xy: 1381, 1297 + xy: 785, 1100 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phase-weaver-icon-large rotate: false - xy: 775, 939 + xy: 1865, 1408 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 phase-weaver-icon-medium rotate: false - xy: 1283, 615 + xy: 1177, 680 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-weaver-icon-small rotate: false - xy: 1706, 814 + xy: 761, 130 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 pine-icon-medium rotate: false - xy: 1282, 581 + xy: 1169, 646 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pine-icon-small rotate: false - xy: 1732, 814 + xy: 735, 104 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 plastanium-compressor-icon-large rotate: false - xy: 825, 989 + xy: 1865, 1358 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 plastanium-compressor-icon-medium rotate: false - xy: 1317, 615 + xy: 1203, 646 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plastanium-compressor-icon-small rotate: false - xy: 1758, 814 + xy: 761, 104 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 pneumatic-drill-icon-full rotate: false - xy: 1711, 1297 + xy: 1115, 1100 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pneumatic-drill-icon-large rotate: false - xy: 725, 839 + xy: 1927, 1472 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 pneumatic-drill-icon-medium rotate: false - xy: 1316, 581 + xy: 1161, 800 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pneumatic-drill-icon-small rotate: false - xy: 1653, 788 + xy: 734, 78 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 power-node-icon-large rotate: false - xy: 775, 889 + xy: 1977, 1472 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 power-node-icon-small rotate: false - xy: 1653, 762 + xy: 760, 78 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 power-node-large-icon-large rotate: false - xy: 825, 939 + xy: 1515, 1308 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 power-node-large-icon-medium rotate: false - xy: 519, 730 + xy: 1161, 766 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 power-node-large-icon-small rotate: false - xy: 1679, 788 + xy: 791, 412 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 power-source-icon-large rotate: false - xy: 775, 839 + xy: 1565, 1308 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 power-source-icon-small rotate: false - xy: 1679, 762 + xy: 817, 412 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 power-void-icon-large rotate: false - xy: 825, 889 + xy: 1615, 1308 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 power-void-icon-small rotate: false - xy: 1705, 788 + xy: 843, 412 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 pulse-conduit-icon-full rotate: false - xy: 499, 560 + xy: 1263, 772 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-icon-large rotate: false - xy: 825, 839 + xy: 1665, 1308 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 pulse-conduit-icon-small rotate: false - xy: 1705, 762 + xy: 869, 412 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 pulverizer-icon-full rotate: false - xy: 529, 458 + xy: 1433, 734 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulverizer-icon-large rotate: false - xy: 725, 789 + xy: 1715, 1308 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 pulverizer-icon-small rotate: false - xy: 1731, 788 + xy: 790, 386 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 pyratite-mixer-icon-large rotate: false - xy: 775, 789 + xy: 1765, 1308 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 pyratite-mixer-icon-medium rotate: false - xy: 529, 390 + xy: 1433, 700 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pyratite-mixer-icon-small rotate: false - xy: 1731, 762 + xy: 816, 386 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 repair-point rotate: false - xy: 529, 356 + xy: 1467, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 repair-point-icon-full rotate: false - xy: 529, 288 + xy: 1535, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 repair-point-icon-large rotate: false - xy: 724, 739 + xy: 1865, 1308 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 repair-point-icon-small rotate: false - xy: 1757, 788 + xy: 842, 386 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 revenant-factory-icon-full rotate: false - xy: 1306, 1789 + xy: 1566, 1788 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 revenant-factory-icon-large rotate: false - xy: 774, 739 + xy: 1927, 1422 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 revenant-factory-icon-medium rotate: false - xy: 529, 254 + xy: 1569, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 revenant-factory-icon-small rotate: false - xy: 1757, 762 + xy: 868, 386 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 ripple rotate: false - xy: 1885, 1495 + xy: 498, 1235 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 ripple-icon-full rotate: false - xy: 163, 1201 + xy: 302, 1137 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 ripple-icon-large rotate: false - xy: 875, 1181 + xy: 1915, 1372 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ripple-icon-medium rotate: false - xy: 529, 220 + xy: 1467, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ripple-icon-small rotate: false - xy: 1653, 736 + xy: 731, 52 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 rock-icon-medium rotate: false - xy: 529, 186 + xy: 1501, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rock-icon-small rotate: false - xy: 1679, 736 + xy: 757, 52 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 rocks-icon-large rotate: false - xy: 925, 1181 + xy: 1915, 1322 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 rocks-icon-small rotate: false - xy: 1705, 736 + xy: 790, 360 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 rotary-pump-icon-large rotate: false - xy: 875, 1131 + xy: 1965, 1372 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 rotary-pump-icon-medium rotate: false - xy: 529, 152 + xy: 1535, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rotary-pump-icon-small rotate: false - xy: 1731, 736 + xy: 816, 360 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 router-icon-large rotate: false - xy: 975, 1181 + xy: 1965, 1322 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 router-icon-small rotate: false - xy: 1757, 736 + xy: 842, 360 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 rtg-generator-icon-large rotate: false - xy: 875, 1081 + xy: 1915, 1272 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 rtg-generator-icon-medium rotate: false - xy: 529, 84 + xy: 1603, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rtg-generator-icon-small rotate: false - xy: 1784, 802 + xy: 868, 360 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 salt-icon-large rotate: false - xy: 925, 1131 + xy: 1965, 1272 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 salt-icon-small rotate: false - xy: 1783, 776 + xy: 787, 334 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +saltrocks-icon-large + rotate: false + xy: 1313, 994 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +saltrocks-icon-small + rotate: false + xy: 787, 308 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 salvo rotate: false - xy: 253, 739 + xy: 1939, 1522 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 salvo-icon-full rotate: false - xy: 985, 1331 + xy: 1449, 1344 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 salvo-icon-large rotate: false - xy: 1025, 1181 + xy: 1371, 1110 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 salvo-icon-medium rotate: false - xy: 529, 16 + xy: 1990, 1204 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 salvo-icon-small rotate: false - xy: 1783, 750 + xy: 813, 334 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 sand-icon-large rotate: false - xy: 875, 1031 + xy: 1371, 1060 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 sand-icon-small rotate: false - xy: 1783, 724 + xy: 787, 282 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 sand-water-icon-large rotate: false - xy: 925, 1081 + xy: 1371, 1010 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 sand-water-icon-small rotate: false - xy: 1445, 657 + xy: 813, 308 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 sandrocks-icon-large rotate: false - xy: 975, 1131 + xy: 617, 923 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 sandrocks-icon-small rotate: false - xy: 1445, 631 + xy: 839, 334 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 scatter rotate: false - xy: 1183, 1231 + xy: 1256, 1166 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scatter-icon-full rotate: false - xy: 1249, 1231 + xy: 1247, 1100 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scatter-icon-large rotate: false - xy: 875, 981 + xy: 617, 873 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 scatter-icon-medium rotate: false - xy: 563, 492 + xy: 1990, 1170 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scatter-icon-small rotate: false - xy: 1471, 657 + xy: 787, 256 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +scorch + rotate: false + xy: 817, 646 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scorch-icon-full + rotate: false + xy: 885, 646 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scorch-icon-large + rotate: false + xy: 617, 823 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +scorch-icon-small + rotate: false + xy: 813, 282 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 scrap-wall-gigantic-icon-large rotate: false - xy: 925, 1031 + xy: 617, 773 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 scrap-wall-gigantic-icon-medium rotate: false - xy: 563, 322 + xy: 1219, 704 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall-gigantic-icon-small rotate: false - xy: 1471, 631 + xy: 839, 308 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 scrap-wall-huge-icon-large rotate: false - xy: 975, 1081 + xy: 617, 723 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 scrap-wall-huge-icon-medium rotate: false - xy: 563, 288 + xy: 1253, 704 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall-huge-icon-small rotate: false - xy: 1497, 657 + xy: 865, 334 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 scrap-wall-icon-large rotate: false - xy: 1025, 1131 + xy: 617, 673 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 scrap-wall-icon-small rotate: false - xy: 1497, 631 + xy: 787, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 scrap-wall-large-icon-large rotate: false - xy: 875, 931 + xy: 667, 926 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 scrap-wall-large-icon-medium rotate: false - xy: 563, 254 + xy: 1237, 670 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall-large-icon-small rotate: false - xy: 1523, 657 + xy: 813, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 separator-icon-large rotate: false - xy: 925, 981 + xy: 717, 926 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 separator-icon-medium rotate: false - xy: 563, 186 + xy: 1271, 670 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 separator-icon-small rotate: false - xy: 1549, 620 + xy: 787, 204 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 shale-boulder-icon-large rotate: false - xy: 975, 1031 + xy: 667, 876 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 shale-boulder-icon-small rotate: false - xy: 1445, 605 + xy: 813, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 shale-icon-large rotate: false - xy: 1025, 1081 + xy: 717, 876 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 shale-icon-small rotate: false - xy: 1471, 605 + xy: 839, 240 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 shalerocks-icon-large rotate: false - xy: 875, 881 + xy: 667, 826 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 shalerocks-icon-small rotate: false - xy: 1497, 605 + xy: 865, 271 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 shock-mine-icon-large rotate: false - xy: 925, 931 + xy: 717, 826 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 shock-mine-icon-small rotate: false - xy: 1436, 579 + xy: 787, 178 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +shrubs-icon-large + rotate: false + xy: 717, 776 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +shrubs-icon-small + rotate: false + xy: 813, 204 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 silicon-smelter-icon-large rotate: false - xy: 1025, 1031 + xy: 667, 726 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 silicon-smelter-icon-medium rotate: false - xy: 563, 84 + xy: 1305, 654 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 silicon-smelter-icon-small rotate: false - xy: 1462, 579 + xy: 839, 214 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 snow-icon-large rotate: false - xy: 875, 831 + xy: 717, 726 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 snow-icon-small rotate: false - xy: 1488, 579 + xy: 865, 245 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 snowrock-icon-medium rotate: false - xy: 563, 16 + xy: 1339, 670 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 snowrock-icon-small rotate: false - xy: 1436, 553 + xy: 787, 152 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 snowrocks-icon-large rotate: false - xy: 925, 881 + xy: 667, 676 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 snowrocks-icon-small rotate: false - xy: 1462, 553 + xy: 813, 178 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 solar-panel-icon-large rotate: false - xy: 975, 931 + xy: 717, 676 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 solar-panel-icon-small rotate: false - xy: 1488, 553 + xy: 839, 188 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 solar-panel-large-icon-large rotate: false - xy: 1025, 981 + xy: 767, 926 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 solar-panel-large-icon-medium rotate: false - xy: 1589, 1071 + xy: 1339, 602 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 solar-panel-large-icon-small rotate: false - xy: 1575, 719 + xy: 865, 219 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 sorter-icon-large rotate: false - xy: 925, 831 + xy: 767, 876 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 sorter-icon-small rotate: false - xy: 1601, 719 + xy: 787, 126 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 spawn-icon-large rotate: false - xy: 975, 881 + xy: 767, 826 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 spawn-icon-small rotate: false - xy: 1627, 719 + xy: 813, 152 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 spectre rotate: false - xy: 453, 1628 + xy: 713, 1658 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 spectre-icon-full rotate: false - xy: 583, 1659 + xy: 843, 1658 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 spectre-icon-large rotate: false - xy: 1025, 931 + xy: 767, 776 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 spectre-icon-medium rotate: false - xy: 1591, 1003 + xy: 1407, 632 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spectre-icon-small rotate: false - xy: 1574, 693 + xy: 839, 162 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 spirit-factory-icon-full rotate: false - xy: 1777, 1231 + xy: 155, 588 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spirit-factory-icon-large rotate: false - xy: 1025, 881 + xy: 767, 676 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 spirit-factory-icon-medium rotate: false - xy: 1591, 969 + xy: 1373, 598 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spirit-factory-icon-small rotate: false - xy: 1600, 693 + xy: 865, 193 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 spore-cluster-icon-large rotate: false - xy: 1025, 831 + xy: 817, 930 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 spore-cluster-icon-medium rotate: false - xy: 1591, 935 + xy: 1407, 598 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spore-cluster-icon-small rotate: false - xy: 1626, 693 + xy: 813, 126 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 spore-moss-icon-large rotate: false - xy: 875, 781 + xy: 817, 880 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 spore-moss-icon-small rotate: false - xy: 1653, 710 + xy: 839, 136 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 spore-pine-icon-medium rotate: false - xy: 1625, 1003 + xy: 1441, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spore-pine-icon-small rotate: false - xy: 1679, 710 + xy: 865, 167 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 spore-press-icon-full rotate: false - xy: 517, 1366 + xy: 221, 907 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-icon-large rotate: false - xy: 925, 781 + xy: 817, 830 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 spore-press-icon-medium rotate: false - xy: 1625, 969 + xy: 1441, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spore-press-icon-small rotate: false - xy: 1705, 710 + xy: 865, 141 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 sporerocks-icon-large rotate: false - xy: 975, 781 + xy: 817, 780 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 sporerocks-icon-small rotate: false - xy: 1731, 710 + xy: 787, 100 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 stone-icon-large rotate: false - xy: 1025, 781 + xy: 817, 730 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 stone-icon-small rotate: false - xy: 1757, 710 + xy: 813, 100 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 surge-tower-icon-large rotate: false - xy: 874, 731 + xy: 817, 680 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 surge-tower-icon-medium rotate: false - xy: 1625, 935 + xy: 1475, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 surge-tower-icon-small rotate: false - xy: 1575, 667 + xy: 839, 110 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 surge-wall-icon-large rotate: false - xy: 924, 731 + xy: 867, 930 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 surge-wall-icon-small rotate: false - xy: 1575, 641 + xy: 865, 115 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 surge-wall-large-icon-large rotate: false - xy: 974, 731 + xy: 867, 880 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 surge-wall-large-icon-medium rotate: false - xy: 1625, 901 + xy: 1509, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 surge-wall-large-icon-small rotate: false - xy: 1601, 667 + xy: 786, 74 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 swarmer rotate: false - xy: 393, 1300 + xy: 221, 775 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 swarmer-icon-full rotate: false - xy: 459, 1300 + xy: 419, 907 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 swarmer-icon-large rotate: false - xy: 1075, 1181 + xy: 867, 780 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 swarmer-icon-medium rotate: false - xy: 1657, 1062 + xy: 1509, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 swarmer-icon-small rotate: false - xy: 1601, 641 + xy: 812, 74 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +tainted-water-icon-large + rotate: false + xy: 867, 730 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +tainted-water-icon-small + rotate: false + xy: 783, 48 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 tar-icon-large rotate: false - xy: 1125, 1181 + xy: 867, 680 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 tar-icon-small rotate: false - xy: 1627, 667 + xy: 809, 48 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 tau-mech-pad-icon-large rotate: false - xy: 1075, 1081 + xy: 917, 884 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 tau-mech-pad-icon-medium rotate: false - xy: 1691, 1062 + xy: 1543, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 tau-mech-pad-icon-small rotate: false - xy: 1627, 641 + xy: 839, 84 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 thermal-generator-icon-large rotate: false - xy: 1125, 1131 + xy: 1017, 934 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 thermal-generator-icon-medium rotate: false - xy: 1725, 1062 + xy: 1543, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thermal-generator-icon-small rotate: false - xy: 1575, 615 + xy: 865, 89 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 thermal-pump-icon-large rotate: false - xy: 1225, 1181 + xy: 917, 834 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 thermal-pump-icon-medium rotate: false - xy: 1659, 1028 + xy: 1577, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thermal-pump-icon-small rotate: false - xy: 1601, 615 + xy: 838, 58 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 thorium-reactor-icon-large rotate: false - xy: 1075, 1031 + xy: 967, 884 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 thorium-reactor-icon-medium rotate: false - xy: 1659, 994 + xy: 1577, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thorium-reactor-icon-small rotate: false - xy: 1627, 615 + xy: 835, 32 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 thorium-wall-icon-large rotate: false - xy: 1125, 1081 + xy: 1067, 934 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 thorium-wall-icon-small rotate: false - xy: 1783, 698 + xy: 902, 590 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 thorium-wall-large-icon-large rotate: false - xy: 1175, 1131 + xy: 917, 784 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 thorium-wall-large-icon-medium rotate: false - xy: 1659, 960 + xy: 1475, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thorium-wall-large-icon-small rotate: false - xy: 1523, 589 + xy: 928, 590 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 thruster-icon-large rotate: false - xy: 1275, 1181 + xy: 967, 834 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 thruster-icon-medium rotate: false - xy: 1693, 994 + xy: 1509, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thruster-icon-small rotate: false - xy: 1549, 594 + xy: 954, 590 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 titan-factory-icon-full rotate: false - xy: 131, 123 + xy: 1297, 1576 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 titan-factory-icon-large rotate: false - xy: 1075, 981 + xy: 1017, 884 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 titan-factory-icon-medium rotate: false - xy: 1659, 926 + xy: 1543, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titan-factory-icon-small rotate: false - xy: 1575, 589 + xy: 980, 590 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 titanium-conveyor-icon-large rotate: false - xy: 1125, 1031 + xy: 1117, 934 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 titanium-conveyor-icon-small rotate: false - xy: 1601, 589 + xy: 1006, 590 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 titanium-wall-icon-large rotate: false - xy: 1175, 1081 + xy: 917, 734 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 titanium-wall-icon-small rotate: false - xy: 1627, 589 + xy: 897, 564 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 titanium-wall-large-icon-large rotate: false - xy: 1225, 1131 + xy: 967, 784 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 titanium-wall-large-icon-medium rotate: false - xy: 1321, 679 + xy: 1259, 568 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-wall-large-icon-small rotate: false - xy: 1514, 563 + xy: 923, 564 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 trident-ship-pad-icon-large rotate: false - xy: 1325, 1181 + xy: 1017, 834 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 trident-ship-pad-icon-medium rotate: false - xy: 1355, 867 + xy: 1293, 552 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 trident-ship-pad-icon-small rotate: false - xy: 1549, 568 + xy: 897, 538 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 turbine-generator-icon-large rotate: false - xy: 1075, 931 + xy: 1067, 884 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 turbine-generator-icon-medium rotate: false - xy: 1355, 833 + xy: 1327, 568 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 turbine-generator-icon-small rotate: false - xy: 1575, 563 + xy: 949, 564 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 unit-icon-chaos-array rotate: false - xy: 843, 1659 + xy: 1103, 1658 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 unit-icon-crawler rotate: false - xy: 1125, 981 + xy: 917, 684 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 unit-icon-dagger rotate: false - xy: 1175, 1031 + xy: 967, 734 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 unit-icon-eradicator rotate: false - xy: 1, 731 + xy: 1, 527 size: 152, 124 orig: 152, 124 offset: 0, 0 index: -1 unit-icon-eruptor rotate: false - xy: 319, 970 + xy: 485, 841 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 unit-icon-fortress rotate: false - xy: 385, 1036 + xy: 419, 775 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 unit-icon-titan rotate: false - xy: 451, 1102 + xy: 353, 709 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 unloader-icon-large rotate: false - xy: 1225, 1081 + xy: 1017, 784 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 unloader-icon-small rotate: false - xy: 1601, 563 + xy: 923, 538 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 vault-icon-large rotate: false - xy: 1275, 1131 + xy: 1067, 834 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 vault-icon-medium rotate: false - xy: 1355, 765 + xy: 1395, 564 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 vault-icon-small rotate: false - xy: 1627, 563 + xy: 975, 564 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 water-extractor-icon-full rotate: false - xy: 385, 970 + xy: 551, 841 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor-icon-large rotate: false - xy: 1375, 1181 + xy: 1117, 884 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 water-extractor-icon-medium rotate: false - xy: 1355, 731 + xy: 1327, 534 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 water-extractor-icon-small rotate: false - xy: 1514, 537 + xy: 949, 538 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 water-icon-large rotate: false - xy: 1075, 881 + xy: 967, 684 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 water-icon-small rotate: false - xy: 1540, 542 + xy: 1001, 564 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 wave rotate: false - xy: 451, 970 + xy: 551, 775 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wave-icon-full rotate: false - xy: 319, 772 + xy: 485, 709 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wave-icon-large rotate: false - xy: 1125, 931 + xy: 1017, 734 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 wave-icon-medium rotate: false - xy: 1355, 697 + xy: 1361, 530 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 wave-icon-small rotate: false - xy: 1566, 537 + xy: 975, 538 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 white-tree-dead-icon-large rotate: false - xy: 1175, 981 + xy: 1067, 784 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 white-tree-dead-icon-medium rotate: false - xy: 1355, 663 + xy: 1395, 530 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 white-tree-dead-icon-small rotate: false - xy: 1592, 537 + xy: 1001, 538 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 white-tree-icon-large rotate: false - xy: 1225, 1031 + xy: 1117, 834 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 white-tree-icon-medium rotate: false - xy: 1351, 629 + xy: 1429, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 white-tree-icon-small rotate: false - xy: 1618, 537 + xy: 897, 512 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 wraith-factory-icon-full rotate: false - xy: 451, 904 + xy: 551, 709 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wraith-factory-icon-large rotate: false - xy: 1325, 1131 + xy: 1067, 734 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 wraith-factory-icon-medium rotate: false - xy: 1385, 629 + xy: 1463, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 wraith-factory-icon-small rotate: false - xy: 1540, 516 + xy: 923, 512 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-biomatter rotate: false - xy: 1489, 985 + xy: 1549, 965 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-blast-compound rotate: false - xy: 1523, 985 + xy: 1549, 931 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-coal rotate: false - xy: 1557, 985 + xy: 1481, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-copper rotate: false - xy: 1421, 951 + xy: 1515, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-graphite rotate: false - xy: 1455, 951 + xy: 1549, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-lead rotate: false - xy: 1489, 951 + xy: 1379, 874 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-metaglass rotate: false - xy: 1523, 951 + xy: 1413, 870 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-phase-fabric rotate: false - xy: 1557, 951 + xy: 1447, 870 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-plastanium rotate: false - xy: 1319, 937 + xy: 1481, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-pyratite rotate: false - xy: 1353, 935 + xy: 1515, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-sand rotate: false - xy: 1387, 935 + xy: 1549, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-scrap rotate: false - xy: 1421, 917 + xy: 1109, 680 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-silicon rotate: false - xy: 1455, 917 + xy: 1243, 840 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-spore-pod rotate: false - xy: 1523, 917 + xy: 1311, 858 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-surge-alloy rotate: false - xy: 1557, 917 + xy: 1345, 858 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-thorium rotate: false - xy: 1253, 879 + xy: 1379, 840 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-titanium rotate: false - xy: 1253, 845 + xy: 1413, 836 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-cryofluid rotate: false - xy: 1287, 785 + xy: 1447, 802 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-oil rotate: false - xy: 1287, 717 + xy: 1515, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-slag rotate: false - xy: 495, 454 + xy: 1379, 772 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-water rotate: false - xy: 495, 352 + xy: 1481, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 alpha-mech rotate: false - xy: 349, 664 + xy: 1007, 984 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 alpha-mech-base rotate: false - xy: 295, 556 + xy: 1057, 984 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 alpha-mech-leg rotate: false - xy: 349, 614 + xy: 1107, 984 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 delta-mech rotate: false - xy: 395, 164 + xy: 429, 335 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 delta-mech-base rotate: false - xy: 395, 114 + xy: 479, 385 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 delta-mech-leg rotate: false - xy: 345, 64 + xy: 529, 435 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 omega-mech rotate: false - xy: 517, 996 + xy: 518, 585 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 omega-mech-armor rotate: false - xy: 1777, 1363 + xy: 1058, 1232 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 omega-mech-base rotate: false - xy: 517, 938 + xy: 1313, 1102 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 omega-mech-leg rotate: false - xy: 517, 880 + xy: 1313, 1044 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 tau-mech rotate: false - xy: 319, 714 + xy: 683, 976 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 tau-mech-base rotate: false - xy: 1075, 1131 + xy: 917, 934 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 tau-mech-leg rotate: false - xy: 1175, 1181 + xy: 967, 934 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dart-ship rotate: false - xy: 395, 214 + xy: 329, 235 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 glaive-ship rotate: false - xy: 583, 1292 + xy: 155, 530 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 javelin-ship rotate: false - xy: 449, 522 + xy: 579, 435 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 javelin-ship-shield rotate: false - xy: 445, 422 + xy: 579, 335 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 trident-ship rotate: false - xy: 377, 714 + xy: 741, 976 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 blank rotate: false - xy: 1415, 712 + xy: 625, 973 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 circle rotate: false - xy: 323, 1758 + xy: 323, 1757 size: 201, 201 orig: 201, 201 offset: 0, 0 index: -1 clear rotate: false - xy: 1441, 690 + xy: 201, 1190 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 shape-3 rotate: false - xy: 451, 773 + xy: 221, 578 size: 63, 63 orig: 63, 63 offset: 0, 0 index: -1 bar rotate: false - xy: 1851, 1028 + xy: 679, 84 size: 27, 36 split: 9, 9, 9, 9 orig: 27, 36 @@ -6335,7 +6678,7 @@ bar index: -1 bar-top rotate: false - xy: 1389, 715 + xy: 1559, 553 size: 27, 36 split: 9, 10, 9, 10 orig: 27, 36 @@ -6343,7 +6686,7 @@ bar-top index: -1 button rotate: false - xy: 1825, 1202 + xy: 1167, 839 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -6351,7 +6694,7 @@ button index: -1 button-disabled rotate: false - xy: 526, 1760 + xy: 596, 1137 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -6359,7 +6702,7 @@ button-disabled index: -1 button-down rotate: false - xy: 1, 5 + xy: 163, 1164 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -6367,7 +6710,7 @@ button-down index: -1 button-edge-1 rotate: false - xy: 261, 1207 + xy: 131, 10 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -6375,7 +6718,7 @@ button-edge-1 index: -1 button-edge-2 rotate: false - xy: 295, 69 + xy: 1893, 1529 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -6383,7 +6726,7 @@ button-edge-2 index: -1 button-edge-3 rotate: false - xy: 1635, 1202 + xy: 617, 644 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -6391,7 +6734,7 @@ button-edge-3 index: -1 button-edge-4 rotate: false - xy: 39, 5 + xy: 1167, 955 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -6399,7 +6742,7 @@ button-edge-4 index: -1 button-over rotate: false - xy: 1673, 1202 + xy: 169, 10 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -6407,7 +6750,7 @@ button-over index: -1 button-right rotate: false - xy: 1787, 1202 + xy: 1167, 868 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -6415,7 +6758,7 @@ button-right index: -1 button-right-down rotate: false - xy: 1711, 1202 + xy: 1167, 926 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -6423,7 +6766,7 @@ button-right-down index: -1 button-right-over rotate: false - xy: 1749, 1202 + xy: 1167, 897 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -6431,7 +6774,7 @@ button-right-over index: -1 button-select rotate: false - xy: 891, 1337 + xy: 709, 313 size: 24, 24 split: 4, 4, 4, 4 orig: 24, 24 @@ -6439,42 +6782,42 @@ button-select index: -1 check-off rotate: false - xy: 1113, 745 + xy: 1654, 1240 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 check-on rotate: false - xy: 1112, 711 + xy: 1688, 1240 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 check-on-over rotate: false - xy: 1167, 897 + xy: 1722, 1240 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 check-over rotate: false - xy: 1217, 947 + xy: 1756, 1240 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 clear rotate: false - xy: 333, 86 + xy: 1089, 646 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 content-background rotate: false - xy: 261, 1372 + xy: 1205, 860 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -6482,7 +6825,15 @@ content-background index: -1 content-background-locked rotate: false - xy: 1863, 1202 + xy: 1205, 947 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +content-background-noitems + rotate: false + xy: 1205, 918 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -6490,7 +6841,7 @@ content-background-locked index: -1 content-background-over rotate: false - xy: 1901, 1202 + xy: 1205, 889 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -6498,903 +6849,903 @@ content-background-over index: -1 cursor rotate: false - xy: 317, 1633 + xy: 317, 1632 size: 4, 4 orig: 4, 4 offset: 0, 0 index: -1 discord-banner rotate: false - xy: 1, 34 + xy: 1297, 1431 size: 84, 45 orig: 84, 45 offset: 0, 0 index: -1 empty-sector rotate: false - xy: 1219, 871 + xy: 1379, 976 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 icon-crafting rotate: false - xy: 1091, 1237 + xy: 1896, 1272 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-defense rotate: false - xy: 1906, 1043 + xy: 1994, 1254 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-distribution rotate: false - xy: 567, 533 + xy: 2005, 1526 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-effect rotate: false - xy: 1566, 519 + xy: 634, 592 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-liquid rotate: false - xy: 2030, 1849 + xy: 895, 476 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-power rotate: false - xy: 121, 7 + xy: 949, 484 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-production rotate: false - xy: 139, 7 + xy: 967, 502 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-turret rotate: false - xy: 1978, 1031 + xy: 949, 448 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-units rotate: false - xy: 2014, 1031 + xy: 985, 484 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-upgrade rotate: false - xy: 1810, 862 + xy: 931, 422 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 controller-cursor rotate: false - xy: 295, 51 + xy: 1287, 704 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-about rotate: false - xy: 1101, 1479 + xy: 1363, 994 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-add rotate: false - xy: 973, 1659 + xy: 1233, 1658 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-admin rotate: false - xy: 1003, 1463 + xy: 1347, 1674 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-admin-small rotate: false - xy: 155, 1227 + xy: 155, 1023 size: 6, 6 orig: 6, 6 offset: 0, 0 index: -1 icon-areaDelete rotate: false - xy: 1927, 1117 + xy: 1515, 1464 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-arrow rotate: false - xy: 649, 1356 + xy: 1339, 704 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-arrow-16 rotate: false - xy: 649, 1356 + xy: 1339, 704 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-arrow-down rotate: false - xy: 599, 1420 + xy: 1915, 1446 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-arrow-left rotate: false - xy: 333, 74 + xy: 1055, 672 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-arrow-right rotate: false - xy: 1939, 1117 + xy: 1293, 624 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-arrow-up rotate: false - xy: 1087, 1679 + xy: 1327, 608 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-back rotate: false - xy: 295, 721 + xy: 1159, 748 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-ban rotate: false - xy: 583, 1416 + xy: 1527, 1526 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-break rotate: false - xy: 564, 1771 + xy: 634, 1148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-cancel rotate: false - xy: 299, 1218 + xy: 1893, 1511 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-cancel-2 rotate: false - xy: 1576, 849 + xy: 850, 594 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 icon-chat rotate: false - xy: 568, 1949 + xy: 1915, 1434 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-check rotate: false - xy: 1765, 1146 + xy: 207, 21 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-check-2 rotate: false - xy: 1602, 849 + xy: 876, 594 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 icon-copy rotate: false - xy: 553, 746 + xy: 1896, 1290 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-cursor rotate: false - xy: 1351, 617 + xy: 1915, 1422 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-database rotate: false - xy: 1403, 1021 + xy: 163, 1148 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-database-small rotate: false - xy: 1576, 905 + xy: 1055, 660 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-dev-builds rotate: false - xy: 1589, 1105 + xy: 1380, 1160 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-discord rotate: false - xy: 1605, 1105 + xy: 1994, 1238 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-donate rotate: false - xy: 1765, 1130 + xy: 1249, 1658 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-dots rotate: false - xy: 1019, 1463 + xy: 1363, 1674 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-editor rotate: false - xy: 1035, 1463 + xy: 1379, 1674 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-egg rotate: false - xy: 313, 53 + xy: 1527, 1510 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-elevation rotate: false - xy: 667, 1356 + xy: 679, 40 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-eraser rotate: false - xy: 1584, 519 + xy: 1032, 598 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-exit rotate: false - xy: 625, 1218 + xy: 179, 1148 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-file rotate: false - xy: 1602, 519 + xy: 949, 520 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-file-image rotate: false - xy: 1620, 519 + xy: 1317, 1366 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-file-text rotate: false - xy: 625, 1202 + xy: 1396, 1160 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-fill rotate: false - xy: 585, 533 + xy: 967, 520 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-floppy rotate: false - xy: 1367, 1089 + xy: 1265, 1658 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-floppy-16 rotate: false - xy: 2030, 1903 + xy: 985, 520 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-folder rotate: false - xy: 1369, 1039 + xy: 1281, 1658 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-folder-parent rotate: false - xy: 1303, 947 + xy: 1911, 1513 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-generated rotate: false - xy: 675, 1000 + xy: 429, 35 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 icon-github rotate: false - xy: 1303, 931 + xy: 1481, 541 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-google-play rotate: false - xy: 2033, 1169 + xy: 902, 630 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-grid rotate: false - xy: 2030, 1885 + xy: 1003, 520 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-hold rotate: false - xy: 553, 734 + xy: 204, 1384 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-holdDelete rotate: false - xy: 329, 2 + xy: 596, 1321 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-home rotate: false - xy: 2033, 1153 + xy: 895, 406 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-host rotate: false - xy: 2025, 1117 + xy: 911, 406 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-info rotate: false - xy: 303, 1418 + xy: 927, 406 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-itch.io rotate: false - xy: 303, 1402 + xy: 894, 390 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-item rotate: false - xy: 515, 10 + xy: 568, 1948 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-items-none rotate: false - xy: 77, 24 + xy: 1229, 816 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 icon-line rotate: false - xy: 2030, 1867 + xy: 895, 494 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-link rotate: false - xy: 1403, 1005 + xy: 894, 374 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-liquid-small rotate: false - xy: 1877, 951 + xy: 568, 1776 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-load rotate: false - xy: 303, 1386 + xy: 910, 390 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-load-image rotate: false - xy: 571, 744 + xy: 913, 494 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-load-map rotate: false - xy: 589, 744 + xy: 895, 458 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-loading rotate: false - xy: 567, 721 + xy: 913, 476 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-locked rotate: false - xy: 585, 721 + xy: 931, 494 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-logic rotate: false - xy: 989, 1663 + xy: 1365, 778 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-map rotate: false - xy: 607, 746 + xy: 910, 374 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-menu rotate: false - xy: 2029, 1105 + xy: 652, 598 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-menu-large rotate: false - xy: 1644, 545 + xy: 949, 502 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-missing rotate: false - xy: 1653, 618 + xy: 315, 16 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-mission-background rotate: false - xy: 131, 711 + xy: 1297, 1364 size: 18, 18 orig: 18, 18 offset: 0, 0 index: -1 icon-mission-battle rotate: false - xy: 1669, 634 + xy: 902, 618 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-mission-defense rotate: false - xy: 1685, 650 + xy: 907, 282 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-mission-done rotate: false - xy: 1701, 666 + xy: 923, 298 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-none rotate: false - xy: 1717, 682 + xy: 891, 250 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-paste rotate: false - xy: 2025, 1133 + xy: 895, 440 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-pause rotate: false - xy: 568, 1937 + xy: 204, 1372 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-pencil rotate: false - xy: 479, 4 + xy: 913, 458 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-pencil-small rotate: false - xy: 1652, 694 + xy: 926, 390 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-pick rotate: false - xy: 497, 4 + xy: 931, 476 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-play rotate: false - xy: 1363, 617 + xy: 596, 1309 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-play-2 rotate: false - xy: 1668, 694 + xy: 926, 374 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-play-custom rotate: false - xy: 1684, 694 + xy: 894, 358 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-players rotate: false - xy: 341, 2 + xy: 568, 1936 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-power-requirement rotate: false - xy: 1353, 969 + xy: 1481, 965 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 icon-power-small rotate: false - xy: 2029, 1093 + xy: 568, 1764 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-quit rotate: false - xy: 1700, 694 + xy: 910, 358 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-redo rotate: false - xy: 157, 7 + xy: 895, 422 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-refresh rotate: false - xy: 1716, 694 + xy: 926, 358 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-rename rotate: false - xy: 1732, 694 + xy: 891, 342 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-resize rotate: false - xy: 175, 7 + xy: 913, 440 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-rotate rotate: false - xy: 1748, 694 + xy: 891, 326 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-rotate-arrow rotate: false - xy: 1764, 694 + xy: 907, 342 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-rotate-left rotate: false - xy: 1653, 678 + xy: 891, 310 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-rotate-right rotate: false - xy: 1653, 662 + xy: 907, 326 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-save rotate: false - xy: 1669, 678 + xy: 923, 342 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-save-image rotate: false - xy: 193, 7 + xy: 931, 458 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-save-map rotate: false - xy: 211, 7 + xy: 949, 466 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-settings rotate: false - xy: 1653, 606 + xy: 907, 270 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-spray rotate: false - xy: 1906, 1025 + xy: 967, 484 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-terrain rotate: false - xy: 1924, 1031 + xy: 985, 502 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-tools rotate: false - xy: 1653, 646 + xy: 891, 294 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-touch rotate: false - xy: 1729, 682 + xy: 891, 238 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-touchDelete rotate: false - xy: 568, 1925 + xy: 204, 1360 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-trash rotate: false - xy: 1669, 662 + xy: 907, 310 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-trash-16 rotate: false - xy: 1942, 1031 + xy: 913, 422 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-tree rotate: false - xy: 1960, 1031 + xy: 931, 440 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-tree-locked rotate: false - xy: 1387, 969 + xy: 1481, 931 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 icon-trello rotate: false - xy: 1685, 678 + xy: 923, 326 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-tutorial rotate: false - xy: 1653, 630 + xy: 891, 278 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-undo rotate: false - xy: 1996, 1031 + xy: 967, 466 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-unlocked rotate: false - xy: 1644, 527 + xy: 1003, 502 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-unlocks rotate: false - xy: 1669, 646 + xy: 907, 294 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-wiki rotate: false - xy: 1685, 662 + xy: 923, 310 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-zone rotate: false - xy: 1628, 849 + xy: 1640, 565 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 icon-zone-locked rotate: false - xy: 87, 37 + xy: 1117, 790 size: 42, 42 orig: 42, 42 offset: 0, 0 index: -1 icon-zoom rotate: false - xy: 1828, 868 + xy: 949, 430 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-zoom-small rotate: false - xy: 1701, 678 + xy: 891, 262 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 info-banner rotate: false - xy: 611, 1416 + xy: 1297, 1384 size: 84, 45 orig: 84, 45 offset: 0, 0 index: -1 inventory rotate: false - xy: 1419, 745 + xy: 715, 556 size: 24, 40 split: 10, 10, 10, 14 orig: 24, 40 @@ -7402,14 +7753,14 @@ inventory index: -1 logotext rotate: false - xy: 1, 1961 + xy: 1, 1960 size: 579, 86 orig: 579, 86 offset: 0, 0 index: -1 pane rotate: false - xy: 1673, 1173 + xy: 1582, 1279 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -7417,7 +7768,7 @@ pane index: -1 pane-2 rotate: false - xy: 1635, 1173 + xy: 1506, 1241 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -7425,7 +7776,7 @@ pane-2 index: -1 scroll rotate: false - xy: 1549, 646 + xy: 865, 297 size: 24, 35 split: 10, 10, 6, 5 orig: 24, 35 @@ -7433,7 +7784,7 @@ scroll index: -1 scroll-horizontal rotate: false - xy: 2012, 2023 + xy: 2012, 2022 size: 35, 24 split: 6, 5, 10, 10 orig: 35, 24 @@ -7441,7 +7792,7 @@ scroll-horizontal index: -1 scroll-knob-horizontal-black rotate: false - xy: 253, 713 + xy: 526, 1762 size: 40, 24 split: 11, 10, 10, 10 orig: 40, 24 @@ -7449,7 +7800,7 @@ scroll-knob-horizontal-black index: -1 scroll-knob-vertical-black rotate: false - xy: 1523, 615 + xy: 839, 266 size: 24, 40 split: 10, 10, 6, 10 orig: 24, 40 @@ -7457,56 +7808,56 @@ scroll-knob-vertical-black index: -1 sector-select rotate: false - xy: 563, 220 + xy: 1237, 636 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 selection rotate: false - xy: 2046, 2020 + xy: 2046, 2019 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 slider rotate: false - xy: 1924, 1051 + xy: 835, 64 size: 1, 8 orig: 1, 8 offset: 0, 0 index: -1 slider-knob rotate: false - xy: 1389, 895 + xy: 1497, 551 size: 29, 38 orig: 29, 38 offset: 0, 0 index: -1 slider-knob-down rotate: false - xy: 1389, 855 + xy: 1528, 551 size: 29, 38 orig: 29, 38 offset: 0, 0 index: -1 slider-knob-over rotate: false - xy: 1389, 855 + xy: 1528, 551 size: 29, 38 orig: 29, 38 offset: 0, 0 index: -1 slider-vertical rotate: false - xy: 121, 34 + xy: 155, 527 size: 8, 1 orig: 8, 1 offset: 0, 0 index: -1 underline rotate: false - xy: 1825, 1173 + xy: 1544, 1203 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -7514,7 +7865,15 @@ underline index: -1 underline-2 rotate: false - xy: 1787, 1173 + xy: 1582, 1250 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +underline-red + rotate: false + xy: 1620, 1279 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -7522,14 +7881,14 @@ underline-2 index: -1 white rotate: false - xy: 691, 1200 + xy: 625, 1034 size: 3, 3 orig: 3, 3 offset: 0, 0 index: -1 window-empty rotate: false - xy: 1791, 906 + xy: 709, 365 size: 27, 61 split: 8, 8, 44, 11 orig: 27, 61 @@ -7537,2036 +7896,2253 @@ window-empty index: -1 chaos-array rotate: false - xy: 582, 1919 + xy: 712, 1918 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 chaos-array-base rotate: false - xy: 712, 1919 + xy: 842, 1918 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 chaos-array-leg rotate: false - xy: 842, 1919 + xy: 972, 1918 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 crawler rotate: false - xy: 345, 414 + xy: 279, 328 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 crawler-base rotate: false - xy: 395, 464 + xy: 279, 278 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 crawler-leg rotate: false - xy: 395, 414 + xy: 279, 178 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dagger rotate: false - xy: 395, 314 + xy: 329, 435 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dagger-base rotate: false - xy: 345, 214 + xy: 379, 485 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dagger-leg rotate: false - xy: 345, 164 + xy: 379, 435 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 eradicator rotate: false - xy: 1, 1109 + xy: 1, 905 size: 152, 124 orig: 152, 124 offset: 0, 0 index: -1 eradicator-base rotate: false - xy: 1, 983 + xy: 1, 779 size: 152, 124 orig: 152, 124 offset: 0, 0 index: -1 eradicator-leg rotate: false - xy: 1, 857 + xy: 1, 653 size: 152, 124 orig: 152, 124 offset: 0, 0 index: -1 eruptor rotate: false - xy: 1447, 1429 + xy: 875, 1298 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 eruptor-base rotate: false - xy: 1513, 1429 + xy: 941, 1298 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 eruptor-leg rotate: false - xy: 1579, 1429 + xy: 1007, 1298 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 fortress rotate: false - xy: 1645, 1429 + xy: 1073, 1298 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 fortress-base rotate: false - xy: 1711, 1429 + xy: 1139, 1298 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 titan-base rotate: false - xy: 1711, 1429 + xy: 1139, 1298 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 fortress-leg rotate: false - xy: 1777, 1429 + xy: 1205, 1298 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 ghoul rotate: false - xy: 1956, 1845 + xy: 1395, 1616 size: 72, 72 orig: 72, 72 offset: 0, 0 index: -1 lich rotate: false - xy: 1, 1397 + xy: 1, 1396 size: 216, 240 orig: 216, 240 offset: 0, 0 index: -1 phantom rotate: false - xy: 517, 822 + xy: 576, 585 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 power-cell rotate: false - xy: 516, 764 + xy: 625, 976 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 reaper rotate: false - xy: 1, 1639 + xy: 1, 1638 size: 320, 320 orig: 320, 320 offset: 0, 0 index: -1 revenant rotate: false - xy: 973, 1675 + xy: 1233, 1674 size: 112, 112 orig: 112, 112 offset: 0, 0 index: -1 spirit rotate: false - xy: 975, 831 + xy: 767, 726 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 titan rotate: false - xy: 319, 1168 + xy: 485, 907 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 titan-leg rotate: false - xy: 319, 1102 + xy: 419, 841 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wraith rotate: false - xy: 1275, 1081 + xy: 1017, 684 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 artillery-equip rotate: false - xy: 295, 448 + xy: 1207, 976 size: 48, 56 orig: 48, 56 offset: 0, 0 index: -1 blaster-equip rotate: false - xy: 295, 198 + xy: 229, 378 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 bomber-equip rotate: false - xy: 295, 148 + xy: 229, 328 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 missiles-equip rotate: false - xy: 295, 148 + xy: 229, 328 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 chain-blaster-equip rotate: false - xy: 399, 614 + xy: 229, 178 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 chaos-equip rotate: false - xy: 525, 1228 + xy: 1322, 1160 size: 56, 136 orig: 56, 136 offset: 0, 0 index: -1 eradication-equip rotate: false - xy: 317, 1434 + xy: 131, 333 size: 96, 192 orig: 96, 192 offset: 0, 0 index: -1 eruption-equip rotate: false - xy: 575, 970 + xy: 479, 277 size: 48, 56 orig: 48, 56 offset: 0, 0 index: -1 flakgun-equip rotate: false - xy: 575, 920 + xy: 529, 335 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 flamethrower-equip rotate: false - xy: 575, 862 + xy: 329, 77 size: 48, 56 orig: 48, 56 offset: 0, 0 index: -1 heal-blaster-equip rotate: false - xy: 625, 850 + xy: 429, 85 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 lich-missiles-equip rotate: false - xy: 445, 122 + xy: 613, 535 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 reaper-gun-equip rotate: false - xy: 825, 789 + xy: 1815, 1308 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 revenant-missiles-equip rotate: false - xy: 824, 739 + xy: 1977, 1422 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 shockgun-equip rotate: false - xy: 975, 981 + xy: 667, 776 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 swarmer-equip rotate: false - xy: 1024, 731 + xy: 867, 830 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 sprites2.png -size: 2048,512 +size: 2048,1024 format: RGBA8888 filter: Nearest,Nearest repeat: none alloy-smelter-icon-editor rotate: false - xy: 905, 271 + xy: 745, 920 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 alpha-dart-mech-pad-icon-editor rotate: false - xy: 1395, 335 + xy: 405, 106 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 arc-icon-editor rotate: false - xy: 2015, 465 + xy: 651, 590 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 battery-icon-editor rotate: false - xy: 2015, 431 + xy: 569, 392 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 battery-large-icon-editor rotate: false - xy: 1035, 401 + xy: 111, 16 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 blast-drill-icon-editor rotate: false - xy: 645, 369 + xy: 1, 244 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 blast-mixer-icon-editor rotate: false - xy: 1461, 335 + xy: 471, 106 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-border-editor rotate: false - xy: 2015, 397 + xy: 651, 556 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit-icon-editor rotate: false - xy: 1869, 193 + xy: 603, 392 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-icon-editor rotate: false - xy: 1911, 235 + xy: 651, 522 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 char-icon-editor rotate: false - xy: 1945, 235 + xy: 651, 488 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-char1 rotate: false - xy: 1945, 235 + xy: 651, 488 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 clear-editor rotate: false - xy: 645, 236 + xy: 1, 1 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 cliffs-icon-editor rotate: false - xy: 945, 41 + xy: 651, 454 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 +coal-centrifuge-icon-editor + rotate: false + xy: 307, 8 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 combustion-generator-icon-editor rotate: false - xy: 979, 41 + xy: 685, 590 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-icon-editor rotate: false - xy: 1109, 71 + xy: 685, 556 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 container-icon-editor rotate: false - xy: 1527, 335 + xy: 745, 854 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 conveyor-icon-editor rotate: false - xy: 1143, 71 + xy: 685, 522 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 copper-wall-icon-editor rotate: false - xy: 1177, 71 + xy: 685, 488 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 copper-wall-large-icon-editor rotate: false - xy: 1593, 335 + xy: 811, 854 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 core-foundation-icon-editor rotate: false - xy: 163, 47 + xy: 323, 726 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 core-nucleus-icon-editor rotate: false - xy: 1, 15 + xy: 323, 856 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 core-shard-icon-editor rotate: false - xy: 1133, 401 + xy: 843, 920 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 craters-icon-editor rotate: false - xy: 1211, 71 + xy: 685, 454 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-craters1 rotate: false - xy: 1211, 71 + xy: 685, 454 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 crawler-factory-icon-editor rotate: false - xy: 1659, 335 + xy: 877, 854 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 +creeptree-icon-editor + rotate: false + xy: 1, 4 + size: 108, 108 + orig: 108, 108 + offset: 0, 0 + index: -1 cryofluidmixer-icon-editor rotate: false - xy: 1725, 335 + xy: 943, 854 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator-icon-editor rotate: false - xy: 1791, 335 + xy: 1009, 854 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cyclone-icon-editor rotate: false - xy: 1231, 401 + xy: 941, 920 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 dagger-factory-icon-editor rotate: false - xy: 1857, 335 + xy: 1075, 854 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 +dark-metal-icon-editor + rotate: false + xy: 651, 420 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-1-icon-editor + rotate: false + xy: 685, 420 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-dark-panel-1 + rotate: false + xy: 685, 420 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-2-icon-editor + rotate: false + xy: 537, 138 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-dark-panel-2 + rotate: false + xy: 537, 138 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-3-icon-editor + rotate: false + xy: 537, 104 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-dark-panel-3 + rotate: false + xy: 537, 104 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-4-icon-editor + rotate: false + xy: 537, 70 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-dark-panel-4 + rotate: false + xy: 537, 70 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-5-icon-editor + rotate: false + xy: 537, 36 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-dark-panel-5 + rotate: false + xy: 537, 36 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-6-icon-editor + rotate: false + xy: 569, 358 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-dark-panel-6 + rotate: false + xy: 569, 358 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +darksand-icon-editor + rotate: false + xy: 603, 358 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-darksand1 + rotate: false + xy: 603, 358 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +darksand-tainted-water-icon-editor + rotate: false + xy: 637, 386 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-darksand-tainted-water + rotate: false + xy: 637, 386 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +darksand-water-icon-editor + rotate: false + xy: 671, 386 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-darksand-water + rotate: false + xy: 671, 386 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 deepwater-icon-editor rotate: false - xy: 1245, 71 + xy: 637, 352 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-deepwater rotate: false - xy: 1245, 71 + xy: 637, 352 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 delta-mech-pad-icon-editor rotate: false - xy: 1923, 335 + xy: 1141, 854 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 differential-generator-icon-editor rotate: false - xy: 1329, 401 + xy: 1039, 920 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 distributor-icon-editor rotate: false - xy: 1043, 205 + xy: 1207, 854 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 door-icon-editor rotate: false - xy: 1279, 71 + xy: 671, 352 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 door-large-icon-editor rotate: false - xy: 1043, 139 + xy: 1273, 854 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 dunerocks-icon-editor rotate: false - xy: 1313, 71 + xy: 555, 324 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 duo-icon-editor rotate: false - xy: 163, 13 + xy: 555, 290 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-char2 rotate: false - xy: 197, 13 + xy: 589, 324 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-char3 rotate: false - xy: 231, 13 + xy: 555, 256 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-clear rotate: false - xy: 1871, 147 + xy: 733, 876 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 editor-craters2 rotate: false - xy: 265, 13 + xy: 589, 290 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-craters3 rotate: false - xy: 299, 13 + xy: 555, 222 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -editor-craters4 +editor-darksand2 rotate: false - xy: 333, 13 + xy: 589, 256 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -editor-craters5 +editor-darksand3 rotate: false - xy: 367, 13 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-stone1 - rotate: false - xy: 367, 13 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stone-icon-editor - rotate: false - xy: 367, 13 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-craters6 - rotate: false - xy: 401, 13 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-stone2 - rotate: false - xy: 401, 13 + xy: 555, 188 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-grass1 rotate: false - xy: 435, 13 + xy: 589, 222 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 grass-icon-editor rotate: false - xy: 435, 13 + xy: 589, 222 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-grass2 rotate: false - xy: 469, 13 + xy: 589, 188 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-grass3 rotate: false - xy: 503, 13 + xy: 623, 318 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-holostone1 rotate: false - xy: 1373, 103 + xy: 623, 284 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 holostone-icon-editor rotate: false - xy: 1373, 103 + xy: 623, 284 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-holostone2 rotate: false - xy: 1407, 103 + xy: 657, 318 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-holostone3 rotate: false - xy: 1441, 103 + xy: 623, 250 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-hotrock1 rotate: false - xy: 1475, 103 + xy: 657, 284 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 hotrock-icon-editor rotate: false - xy: 1475, 103 + xy: 657, 284 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-hotrock2 rotate: false - xy: 1509, 103 + xy: 623, 216 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-hotrock3 rotate: false - xy: 1543, 103 + xy: 657, 250 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice-snow1 rotate: false - xy: 1679, 103 + xy: 571, 154 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ice-snow-icon-editor rotate: false - xy: 1679, 103 + xy: 571, 154 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice-snow2 rotate: false - xy: 1713, 103 + xy: 571, 120 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice-snow3 rotate: false - xy: 1769, 135 + xy: 571, 86 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice1 rotate: false - xy: 1577, 103 + xy: 657, 216 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ice-icon-editor rotate: false - xy: 1577, 103 + xy: 657, 216 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice2 rotate: false - xy: 1611, 103 + xy: 623, 182 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice3 rotate: false - xy: 1645, 103 + xy: 657, 182 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ignarock1 rotate: false - xy: 1803, 135 + xy: 571, 52 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ignarock-icon-editor rotate: false - xy: 1803, 135 + xy: 571, 52 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ignarock2 rotate: false - xy: 1837, 135 + xy: 605, 148 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ignarock3 rotate: false - xy: 1979, 235 + xy: 605, 114 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-magmarock1 rotate: false - xy: 1747, 101 + xy: 639, 148 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 magmarock-icon-editor rotate: false - xy: 1747, 101 + xy: 639, 148 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-magmarock2 rotate: false - xy: 1781, 101 + xy: 605, 80 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-magmarock3 rotate: false - xy: 1815, 101 + xy: 639, 114 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor rotate: false - xy: 1849, 101 + xy: 639, 80 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-damaged5 rotate: false - xy: 1849, 101 + xy: 639, 80 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-icon-editor rotate: false - xy: 1849, 101 + xy: 639, 80 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-2 rotate: false - xy: 1903, 193 + xy: 605, 46 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-2-icon-editor rotate: false - xy: 1903, 193 + xy: 605, 46 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-3 rotate: false - xy: 1937, 201 + xy: 639, 46 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-3-icon-editor rotate: false - xy: 1937, 201 + xy: 639, 46 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-5 rotate: false - xy: 1971, 201 + xy: 571, 18 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-5-icon-editor rotate: false - xy: 1971, 201 + xy: 571, 18 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-damaged1 rotate: false - xy: 1871, 159 + xy: 605, 12 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-damaged-icon-editor rotate: false - xy: 1871, 159 + xy: 605, 12 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-damaged2 rotate: false - xy: 1905, 159 + xy: 639, 12 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-damaged3 rotate: false - xy: 1939, 167 + xy: 673, 148 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-damaged4 rotate: false - xy: 1973, 167 + xy: 673, 114 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-damaged6 rotate: false - xy: 1883, 125 + xy: 673, 80 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-moss1 rotate: false - xy: 1883, 91 + xy: 673, 46 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 moss-icon-editor rotate: false - xy: 1883, 91 + xy: 673, 46 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-moss2 rotate: false - xy: 1917, 125 + xy: 673, 12 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-moss3 rotate: false - xy: 1917, 91 + xy: 705, 386 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-coal1 rotate: false - xy: 1951, 133 + xy: 705, 352 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-coal2 rotate: false - xy: 1951, 99 + xy: 691, 318 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-coal3 rotate: false - xy: 1985, 133 + xy: 691, 284 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-copper1 rotate: false - xy: 1985, 99 + xy: 691, 250 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-copper2 rotate: false - xy: 2005, 201 + xy: 691, 216 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-copper3 rotate: false - xy: 2007, 167 + xy: 691, 182 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-lead1 rotate: false - xy: 1989, 363 + xy: 707, 148 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-lead2 rotate: false - xy: 1989, 329 + xy: 707, 114 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-lead3 rotate: false - xy: 1989, 295 + xy: 707, 80 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-scrap1 rotate: false - xy: 1951, 65 + xy: 707, 46 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-scrap2 rotate: false - xy: 1985, 65 + xy: 707, 12 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-scrap3 rotate: false - xy: 1347, 69 + xy: 725, 318 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-thorium1 rotate: false - xy: 1381, 69 + xy: 725, 284 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-thorium2 rotate: false - xy: 1415, 69 + xy: 725, 250 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-thorium3 rotate: false - xy: 1449, 69 + xy: 725, 216 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-titanium1 rotate: false - xy: 1483, 69 + xy: 725, 182 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-titanium2 rotate: false - xy: 1517, 69 + xy: 741, 148 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-titanium3 rotate: false - xy: 1551, 69 + xy: 741, 114 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-pebbles1 + rotate: false + xy: 741, 80 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-pebbles2 + rotate: false + xy: 741, 46 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-pebbles3 + rotate: false + xy: 741, 12 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-salt rotate: false - xy: 1585, 69 + xy: 733, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 salt-icon-editor rotate: false - xy: 1585, 69 + xy: 733, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-sand-water rotate: false - xy: 1721, 67 + xy: 869, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sand-water-icon-editor rotate: false - xy: 1721, 67 + xy: 869, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-sand1 rotate: false - xy: 1619, 69 + xy: 767, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sand-icon-editor rotate: false - xy: 1619, 69 + xy: 767, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-sand2 rotate: false - xy: 1653, 69 + xy: 801, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-sand3 rotate: false - xy: 1687, 69 + xy: 835, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-shale1 rotate: false - xy: 1755, 67 + xy: 903, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shale-icon-editor rotate: false - xy: 1755, 67 + xy: 903, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-shale2 rotate: false - xy: 1789, 67 + xy: 937, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-shale3 rotate: false - xy: 1823, 67 + xy: 971, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-snow1 rotate: false - xy: 1013, 39 + xy: 1005, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 snow-icon-editor rotate: false - xy: 1013, 39 + xy: 1005, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-snow2 rotate: false - xy: 1047, 39 + xy: 1039, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-snow3 rotate: false - xy: 1081, 37 + xy: 1073, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-spore-moss1 rotate: false - xy: 1115, 37 + xy: 1107, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spore-moss-icon-editor rotate: false - xy: 1115, 37 + xy: 1107, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-spore-moss2 rotate: false - xy: 1149, 37 + xy: 1141, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-spore-moss3 rotate: false - xy: 1183, 37 + xy: 1175, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-stone1 + rotate: false + xy: 1209, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stone-icon-editor + rotate: false + xy: 1209, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-stone2 + rotate: false + xy: 1243, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-stone3 rotate: false - xy: 1217, 37 + xy: 1277, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-tainted-water + rotate: false + xy: 1311, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +tainted-water-icon-editor + rotate: false + xy: 1311, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-tar rotate: false - xy: 1251, 37 + xy: 1345, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 tar-icon-editor rotate: false - xy: 1251, 37 + xy: 1345, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-water rotate: false - xy: 1285, 37 + xy: 1379, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 water-icon-editor rotate: false - xy: 1285, 37 + xy: 1379, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 force-projector-icon-editor rotate: false - xy: 1427, 401 + xy: 1137, 920 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 fortress-factory-icon-editor rotate: false - xy: 1525, 401 + xy: 1235, 920 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 fuse-icon-editor rotate: false - xy: 1623, 401 + xy: 1333, 920 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 ghoul-factory-icon-editor rotate: false - xy: 1721, 401 + xy: 1431, 920 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 glaive-ship-pad-icon-editor rotate: false - xy: 1819, 401 + xy: 1529, 920 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 graphite-press-icon-editor rotate: false - xy: 1043, 73 + xy: 1339, 854 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 hail-icon-editor rotate: false - xy: 1319, 35 + xy: 1413, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 icerocks-icon-editor rotate: false - xy: 1353, 35 + xy: 1447, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 impact-reactor-icon-editor rotate: false - xy: 645, 239 + xy: 485, 888 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 incinerator-icon-editor rotate: false - xy: 1387, 35 + xy: 1481, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-source-icon-editor rotate: false - xy: 1421, 35 + xy: 1515, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-void-icon-editor rotate: false - xy: 1455, 35 + xy: 1549, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 javelin-ship-pad-icon-editor rotate: false - xy: 1109, 237 + xy: 1405, 854 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 junction-icon-editor rotate: false - xy: 1489, 35 + xy: 1583, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 kiln-icon-editor rotate: false - xy: 1109, 171 + xy: 1471, 854 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 lancer-icon-editor rotate: false - xy: 1175, 237 + xy: 1537, 854 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 laser-drill-icon-editor rotate: false - xy: 1917, 401 + xy: 1627, 920 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 launch-pad-icon-editor rotate: false - xy: 553, 79 + xy: 1725, 920 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 +launch-pad-large-icon-editor + rotate: false + xy: 1, 114 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 liquid-junction-icon-editor rotate: false - xy: 1523, 35 + xy: 1617, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-router-icon-editor rotate: false - xy: 1557, 35 + xy: 1651, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-source-icon-editor rotate: false - xy: 1591, 35 + xy: 1685, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-tank-icon-editor rotate: false - xy: 651, 141 + xy: 1823, 920 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mass-driver-icon-editor rotate: false - xy: 749, 141 + xy: 1921, 920 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mechanical-drill-icon-editor rotate: false - xy: 1109, 105 + xy: 1603, 854 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mechanical-pump-icon-editor rotate: false - xy: 1625, 35 + xy: 1719, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 meltdown-icon-editor rotate: false - xy: 775, 369 + xy: 131, 244 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 melter-icon-editor rotate: false - xy: 1659, 35 + xy: 1753, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mend-projector-icon-editor rotate: false - xy: 1175, 171 + xy: 1669, 854 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 +mender-icon-editor + rotate: false + xy: 1787, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 multi-press-icon-editor rotate: false - xy: 651, 43 + xy: 323, 368 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-icon-editor rotate: false - xy: 749, 43 + xy: 209, 16 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 omega-mech-pad-icon-editor rotate: false - xy: 847, 141 + xy: 261, 270 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 overdrive-projector-icon-editor rotate: false - xy: 1241, 237 + xy: 1735, 854 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 overflow-gate-icon-editor rotate: false - xy: 1693, 33 + xy: 1821, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pebbles-icon-editor + rotate: false + xy: 1855, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phantom-factory-icon-editor rotate: false - xy: 1175, 105 + xy: 1801, 854 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phase-conduit-icon-editor rotate: false - xy: 1727, 33 + xy: 1889, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-icon-editor rotate: false - xy: 1761, 33 + xy: 1923, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-wall-icon-editor rotate: false - xy: 1795, 33 + xy: 1957, 820 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-wall-large-icon-editor rotate: false - xy: 1241, 171 + xy: 1867, 854 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phase-weaver-icon-editor rotate: false - xy: 1307, 237 + xy: 1933, 854 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pine-icon-editor rotate: false - xy: 1769, 219 + xy: 1999, 870 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 plastanium-compressor-icon-editor rotate: false - xy: 1241, 105 + xy: 405, 40 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pneumatic-drill-icon-editor rotate: false - xy: 1307, 171 + xy: 471, 40 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 power-node-icon-editor rotate: false - xy: 1829, 33 + xy: 717, 786 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 power-node-large-icon-editor rotate: false - xy: 1307, 105 + xy: 485, 822 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 power-source-icon-editor rotate: false - xy: 619, 9 + xy: 717, 752 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 power-void-icon-editor rotate: false - xy: 653, 9 + xy: 751, 786 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-icon-editor rotate: false - xy: 687, 9 + xy: 717, 718 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulverizer-icon-editor rotate: false - xy: 721, 9 + xy: 785, 786 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pyratite-mixer-icon-editor rotate: false - xy: 553, 13 + xy: 551, 822 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 repair-point-icon-editor rotate: false - xy: 755, 9 + xy: 751, 752 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 revenant-factory-icon-editor rotate: false - xy: 293, 47 + xy: 323, 596 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 ripple-icon-editor rotate: false - xy: 847, 43 + xy: 261, 172 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 rock-icon-editor rotate: false - xy: 1769, 169 + xy: 1999, 820 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 rocks-icon-editor rotate: false - xy: 789, 9 + xy: 717, 684 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rotary-pump-icon-editor rotate: false - xy: 1395, 269 + xy: 617, 822 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 router-icon-editor rotate: false - xy: 823, 9 + xy: 819, 786 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rtg-generator-icon-editor rotate: false - xy: 1461, 269 + xy: 453, 756 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 +saltrocks-icon-editor + rotate: false + xy: 785, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 salvo-icon-editor rotate: false - xy: 1527, 269 + xy: 519, 756 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 sandrocks-icon-editor rotate: false - xy: 857, 9 + xy: 751, 718 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scatter-icon-editor rotate: false - xy: 1593, 269 + xy: 453, 690 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 +scorch-icon-editor + rotate: false + xy: 717, 650 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 scrap-wall-gigantic-icon-editor rotate: false - xy: 775, 239 + xy: 615, 888 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 scrap-wall-huge-icon-editor rotate: false - xy: 1003, 271 + xy: 359, 270 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 scrap-wall-icon-editor rotate: false - xy: 891, 9 + xy: 853, 786 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall-large-icon-editor rotate: false - xy: 1659, 269 + xy: 519, 690 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 separator-icon-editor rotate: false - xy: 1725, 269 + xy: 585, 756 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 shale-boulder-icon-editor rotate: false - xy: 925, 7 + xy: 819, 752 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shalerocks-icon-editor rotate: false - xy: 959, 7 + xy: 785, 718 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shock-mine-icon-editor rotate: false - xy: 993, 5 + xy: 751, 684 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shrubs-icon-editor + rotate: false + xy: 887, 786 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 silicon-smelter-icon-editor rotate: false - xy: 1791, 269 + xy: 453, 624 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 snowrock-icon-editor rotate: false - xy: 1819, 219 + xy: 519, 376 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 snowrocks-icon-editor rotate: false - xy: 1027, 5 + xy: 853, 752 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 solar-panel-icon-editor rotate: false - xy: 1061, 3 + xy: 819, 718 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 solar-panel-large-icon-editor rotate: false - xy: 945, 173 + xy: 359, 172 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 sorter-icon-editor rotate: false - xy: 1095, 3 + xy: 785, 684 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spawn-icon-editor rotate: false - xy: 1129, 3 + xy: 751, 650 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spectre-icon-editor rotate: false - xy: 905, 369 + xy: 131, 114 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 spirit-factory-icon-editor rotate: false - xy: 1857, 269 + xy: 519, 624 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-cluster-icon-editor rotate: false - xy: 1869, 227 + xy: 261, 130 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 spore-pine-icon-editor rotate: false - xy: 1819, 169 + xy: 683, 838 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 spore-press-icon-editor rotate: false - xy: 1923, 269 + xy: 585, 690 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 sporerocks-icon-editor rotate: false - xy: 1163, 3 + xy: 921, 786 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 surge-tower-icon-editor rotate: false - xy: 1373, 203 + xy: 453, 558 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 surge-wall-icon-editor rotate: false - xy: 1197, 3 + xy: 887, 752 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 surge-wall-large-icon-editor rotate: false - xy: 1373, 137 + xy: 519, 558 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 swarmer-icon-editor rotate: false - xy: 1439, 203 + xy: 585, 624 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 tau-mech-pad-icon-editor rotate: false - xy: 1439, 137 + xy: 453, 492 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thermal-generator-icon-editor rotate: false - xy: 1505, 203 + xy: 519, 492 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thermal-pump-icon-editor rotate: false - xy: 945, 75 + xy: 421, 368 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 thorium-reactor-icon-editor rotate: false - xy: 1101, 303 + xy: 457, 270 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 thorium-wall-icon-editor rotate: false - xy: 1231, 3 + xy: 853, 718 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thorium-wall-large-icon-editor rotate: false - xy: 1505, 137 + xy: 585, 558 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thruster-icon-editor rotate: false - xy: 423, 47 + xy: 323, 466 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 titan-factory-icon-editor rotate: false - xy: 1199, 303 + xy: 457, 172 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 titanium-conveyor-icon-editor rotate: false - xy: 1265, 3 + xy: 819, 684 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-wall-icon-editor rotate: false - xy: 1299, 1 + xy: 785, 650 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-wall-large-icon-editor rotate: false - xy: 1571, 203 + xy: 585, 492 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 trident-ship-pad-icon-editor rotate: false - xy: 1571, 137 + xy: 519, 426 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 turbine-generator-icon-editor rotate: false - xy: 1637, 203 + xy: 585, 426 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 unloader-icon-editor rotate: false - xy: 1333, 1 + xy: 955, 786 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 vault-icon-editor rotate: false - xy: 1297, 303 + xy: 307, 74 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 water-extractor-icon-editor rotate: false - xy: 1637, 137 + xy: 651, 756 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wave-icon-editor rotate: false - xy: 1703, 203 + xy: 651, 690 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 white-tree-dead-icon-editor rotate: false - xy: 1, 177 + xy: 1, 696 size: 320, 320 orig: 320, 320 offset: 0, 0 index: -1 white-tree-icon-editor rotate: false - xy: 323, 177 + xy: 1, 374 size: 320, 320 orig: 320, 320 offset: 0, 0 index: -1 wraith-factory-icon-editor rotate: false - xy: 1703, 137 + xy: 651, 624 size: 64, 64 orig: 64, 64 offset: 0, 0 @@ -9579,1099 +10155,1351 @@ filter: Nearest,Nearest repeat: none char1 rotate: false - xy: 1773, 865 + xy: 2015, 973 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 char2 rotate: false - xy: 1889, 981 + xy: 2015, 939 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 char3 rotate: false - xy: 729, 491 + xy: 1773, 449 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cliffs1 rotate: false - xy: 1019, 589 + xy: 1839, 821 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 coal1 rotate: false - xy: 1309, 687 + xy: 515, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 coal2 rotate: false - xy: 1591, 785 + xy: 1925, 907 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 coal3 rotate: false - xy: 175, 43 + xy: 1839, 787 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 copper1 rotate: false - xy: 415, 393 + xy: 549, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 copper2 rotate: false - xy: 1773, 831 + xy: 1959, 907 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 copper3 rotate: false - xy: 1923, 981 + xy: 1839, 753 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 craters1 rotate: false - xy: 763, 491 + xy: 583, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 craters2 rotate: false - xy: 1053, 589 + xy: 1839, 719 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 craters3 rotate: false - xy: 1343, 687 + xy: 617, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 craters4 rotate: false - xy: 1625, 785 + xy: 1839, 685 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 craters5 rotate: false - xy: 209, 43 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stone1 - rotate: false - xy: 209, 43 + xy: 651, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 craters6 rotate: false - xy: 449, 393 + xy: 1839, 651 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -stone2 +creeptree rotate: false - xy: 449, 393 + xy: 1773, 897 + size: 108, 108 + orig: 108, 108 + offset: 0, 0 + index: -1 +dark-metal-large + rotate: false + xy: 1, 3 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +dark-metal1 + rotate: false + xy: 685, 385 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-metal2 + rotate: false + xy: 719, 385 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-1 + rotate: false + xy: 753, 385 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-1-edge + rotate: false + xy: 323, 909 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +dark-panel-2 + rotate: false + xy: 787, 385 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-2-edge + rotate: false + xy: 1, 265 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +dark-panel-3 + rotate: false + xy: 821, 385 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-3-edge + rotate: false + xy: 323, 811 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +dark-panel-4 + rotate: false + xy: 855, 385 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-4-edge + rotate: false + xy: 613, 909 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +dark-panel-5 + rotate: false + xy: 889, 385 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-5-edge + rotate: false + xy: 1, 167 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +dark-panel-6 + rotate: false + xy: 923, 385 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-6-edge + rotate: false + xy: 323, 713 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +darksand-edge + rotate: false + xy: 613, 811 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +darksand-tainted-water + rotate: false + xy: 1059, 385 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +darksand-tainted-water-edge + rotate: false + xy: 903, 909 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +darksand-water + rotate: false + xy: 1093, 385 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +darksand-water-edge + rotate: false + xy: 1, 69 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +darksand1 + rotate: false + xy: 957, 385 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +darksand2 + rotate: false + xy: 991, 385 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +darksand3 + rotate: false + xy: 1025, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 deepwater rotate: false - xy: 1957, 981 + xy: 1127, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 deepwater-edge rotate: false - xy: 323, 917 + xy: 323, 615 size: 288, 96 orig: 288, 96 offset: 0, 0 index: -1 dunerocks-large rotate: false - xy: 1, 11 + xy: 1773, 831 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 dunerocks1 rotate: false - xy: 797, 491 + xy: 1161, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 dunerocks2 rotate: false - xy: 1087, 589 + xy: 1195, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 edge-stencil-blocky rotate: false - xy: 1, 273 + xy: 613, 713 size: 288, 96 orig: 288, 96 offset: 0, 0 index: -1 edge-stencil-smooth rotate: false - xy: 323, 819 + xy: 613, 713 size: 288, 96 orig: 288, 96 offset: 0, 0 index: -1 grass-edge rotate: false - xy: 613, 917 + xy: 903, 811 size: 288, 96 orig: 288, 96 offset: 0, 0 index: -1 grass1 rotate: false - xy: 1377, 687 + xy: 1229, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 grass2 rotate: false - xy: 1659, 785 + xy: 1263, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 grass3 rotate: false - xy: 243, 43 + xy: 1297, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 holostone-edge rotate: false - xy: 1, 175 + xy: 1193, 909 size: 288, 96 orig: 288, 96 offset: 0, 0 index: -1 holostone1 rotate: false - xy: 483, 393 + xy: 1331, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 holostone2 rotate: false - xy: 1991, 981 + xy: 1365, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 holostone3 rotate: false - xy: 831, 491 + xy: 1399, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 hotrock1 rotate: false - xy: 1121, 589 + xy: 1433, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 hotrock2 rotate: false - xy: 1411, 687 + xy: 1467, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 hotrock3 rotate: false - xy: 1693, 785 + xy: 1501, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ice-edge rotate: false - xy: 323, 721 + xy: 323, 517 size: 288, 96 orig: 288, 96 offset: 0, 0 index: -1 ice-snow-edge rotate: false - xy: 613, 819 + xy: 613, 615 size: 288, 96 orig: 288, 96 offset: 0, 0 index: -1 ice-snow1 rotate: false - xy: 1445, 687 + xy: 1637, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ice-snow2 rotate: false - xy: 1727, 785 + xy: 1671, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ice-snow3 rotate: false - xy: 551, 393 + xy: 1705, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ice1 rotate: false - xy: 517, 393 + xy: 1535, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ice2 rotate: false - xy: 865, 491 + xy: 1569, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ice3 rotate: false - xy: 1155, 589 + xy: 1603, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 icerocks-large rotate: false - xy: 1773, 949 + xy: 1883, 941 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 icerocks1 rotate: false - xy: 291, 337 + xy: 1739, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 icerocks2 rotate: false - xy: 291, 303 + xy: 1773, 415 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ignarock-edge rotate: false - xy: 903, 917 + xy: 903, 713 size: 288, 96 orig: 288, 96 offset: 0, 0 index: -1 ignarock1 rotate: false - xy: 291, 269 + xy: 291, 329 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ignarock2 rotate: false - xy: 291, 235 + xy: 291, 295 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ignarock3 rotate: false - xy: 291, 201 + xy: 291, 261 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 lead1 rotate: false - xy: 291, 167 + xy: 291, 227 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 lead2 rotate: false - xy: 291, 133 + xy: 291, 193 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 lead3 rotate: false - xy: 291, 99 + xy: 291, 159 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 magmarock1 rotate: false - xy: 613, 425 + xy: 291, 125 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 magmarock2 rotate: false - xy: 903, 523 + xy: 291, 91 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 magmarock3 rotate: false - xy: 1193, 621 + xy: 1773, 381 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor rotate: false - xy: 1483, 719 + xy: 325, 335 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-damaged5 rotate: false - xy: 1483, 719 + xy: 325, 335 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-2 rotate: false - xy: 647, 425 + xy: 325, 301 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-2-edge rotate: false - xy: 1, 77 + xy: 1193, 811 size: 288, 96 orig: 288, 96 offset: 0, 0 index: -1 metal-floor-3 rotate: false - xy: 937, 523 + xy: 359, 335 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-3-edge rotate: false - xy: 323, 623 + xy: 1483, 909 size: 288, 96 orig: 288, 96 offset: 0, 0 index: -1 metal-floor-5 rotate: false - xy: 1227, 621 + xy: 325, 267 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-5-edge rotate: false - xy: 613, 721 + xy: 323, 419 size: 288, 96 orig: 288, 96 offset: 0, 0 index: -1 metal-floor-damaged-edge rotate: false - xy: 903, 819 + xy: 613, 517 size: 288, 96 orig: 288, 96 offset: 0, 0 index: -1 metal-floor-damaged1 rotate: false - xy: 1517, 719 + xy: 359, 301 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-damaged2 rotate: false - xy: 325, 343 + xy: 393, 335 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-damaged3 rotate: false - xy: 325, 309 + xy: 325, 233 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-damaged4 rotate: false - xy: 325, 275 + xy: 359, 267 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-damaged6 rotate: false - xy: 325, 241 + xy: 393, 301 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-edge rotate: false - xy: 1193, 917 + xy: 903, 615 size: 288, 96 orig: 288, 96 offset: 0, 0 index: -1 moss-edge rotate: false - xy: 323, 525 + xy: 1193, 713 size: 288, 96 orig: 288, 96 offset: 0, 0 index: -1 moss1 rotate: false - xy: 325, 207 + xy: 427, 335 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 moss2 rotate: false - xy: 325, 173 + xy: 325, 199 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 moss3 rotate: false - xy: 325, 139 + xy: 359, 233 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-coal1 rotate: false - xy: 325, 105 + xy: 393, 267 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-coal2 rotate: false - xy: 899, 489 + xy: 427, 301 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-coal3 rotate: false - xy: 933, 489 + xy: 325, 165 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-copper1 rotate: false - xy: 1189, 587 + xy: 359, 199 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-copper2 rotate: false - xy: 1223, 587 + xy: 393, 233 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-copper3 rotate: false - xy: 1479, 685 + xy: 427, 267 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-lead1 rotate: false - xy: 1513, 685 + xy: 325, 131 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-lead2 rotate: false - xy: 133, 1 + xy: 359, 165 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-lead3 rotate: false - xy: 291, 65 + xy: 393, 199 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-scrap1 rotate: false - xy: 325, 71 + xy: 427, 233 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-scrap2 rotate: false - xy: 681, 441 + xy: 325, 97 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-scrap3 rotate: false - xy: 971, 539 + xy: 359, 131 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-thorium1 rotate: false - xy: 1261, 637 + xy: 393, 165 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-thorium2 rotate: false - xy: 1823, 915 + xy: 427, 199 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-thorium3 rotate: false - xy: 1807, 865 + xy: 359, 97 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-titanium1 rotate: false - xy: 1807, 831 + xy: 393, 131 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-titanium2 rotate: false - xy: 1889, 947 + xy: 427, 165 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-titanium3 rotate: false - xy: 1923, 947 + xy: 393, 97 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pebbles-edge + rotate: false + xy: 1483, 811 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +pebbles1 + rotate: false + xy: 427, 131 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pebbles2 + rotate: false + xy: 427, 97 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pebbles3 + rotate: false + xy: 265, 35 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pine rotate: false - xy: 323, 377 + xy: 323, 369 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 rock1 rotate: false - xy: 1773, 899 + xy: 1773, 583 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 rock2 rotate: false - xy: 1839, 965 + xy: 373, 369 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 rocks-large rotate: false - xy: 613, 459 + xy: 67, 3 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rocks1 rotate: false - xy: 1957, 947 + xy: 265, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rocks2 rotate: false - xy: 1991, 947 + xy: 1839, 617 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 salt rotate: false - xy: 729, 457 + xy: 1823, 583 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 salt-edge rotate: false - xy: 613, 623 + xy: 613, 419 size: 288, 96 orig: 288, 96 offset: 0, 0 index: -1 +saltrocks-large + rotate: false + xy: 1773, 765 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +saltrocks1 + rotate: false + xy: 1823, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +saltrocks2 + rotate: false + xy: 1823, 515 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 sand-edge rotate: false - xy: 903, 721 + xy: 903, 517 size: 288, 96 orig: 288, 96 offset: 0, 0 index: -1 sand-water rotate: false - xy: 865, 457 + xy: 1807, 379 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sand-water-edge rotate: false - xy: 1193, 819 + xy: 1193, 615 size: 288, 96 orig: 288, 96 offset: 0, 0 index: -1 sand1 rotate: false - xy: 763, 457 + xy: 1823, 481 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sand2 rotate: false - xy: 797, 457 + xy: 1807, 447 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sand3 rotate: false - xy: 831, 457 + xy: 1807, 413 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sandrocks-large rotate: false - xy: 903, 557 + xy: 1949, 941 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 sandrocks1 rotate: false - xy: 899, 455 + xy: 1857, 583 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sandrocks2 rotate: false - xy: 933, 455 + xy: 1857, 549 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap1 rotate: false - xy: 1019, 555 + xy: 1857, 515 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap2 rotate: false - xy: 1053, 555 + xy: 1857, 481 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap3 rotate: false - xy: 1087, 555 + xy: 1841, 447 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shale-boulder1 rotate: false - xy: 1223, 553 + xy: 1875, 413 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shale-boulder2 rotate: false - xy: 1309, 653 + xy: 1875, 379 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shale-edge rotate: false - xy: 1483, 917 + xy: 1483, 713 size: 288, 96 orig: 288, 96 offset: 0, 0 index: -1 shale1 rotate: false - xy: 1121, 555 + xy: 1841, 413 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shale2 rotate: false - xy: 1155, 555 + xy: 1841, 379 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shale3 rotate: false - xy: 1189, 553 + xy: 1875, 447 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shalerocks-large rotate: false - xy: 1193, 655 + xy: 133, 3 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 shalerocks1 rotate: false - xy: 1343, 653 + xy: 461, 335 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shalerocks2 rotate: false - xy: 1377, 653 + xy: 461, 301 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shrubs-large + rotate: false + xy: 1773, 699 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +shrubs1 + rotate: false + xy: 461, 267 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shrubs2 + rotate: false + xy: 461, 233 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 snow-edge rotate: false - xy: 323, 427 + xy: 903, 419 size: 288, 96 orig: 288, 96 offset: 0, 0 index: -1 snow1 rotate: false - xy: 1411, 653 + xy: 461, 199 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 snow2 rotate: false - xy: 1445, 653 + xy: 461, 165 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 snow3 rotate: false - xy: 1479, 651 + xy: 461, 131 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 snowrock1 rotate: false - xy: 679, 475 + xy: 1773, 533 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 snowrock2 rotate: false - xy: 969, 573 + xy: 423, 369 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 snowrocks-large rotate: false - xy: 1483, 753 + xy: 199, 3 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 snowrocks1 rotate: false - xy: 1513, 651 + xy: 461, 97 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 snowrocks2 rotate: false - xy: 681, 407 + xy: 495, 343 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spore-cluster1 rotate: false - xy: 1549, 777 + xy: 1839, 855 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 spore-cluster2 rotate: false - xy: 133, 35 + xy: 1883, 899 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 spore-cluster3 rotate: false - xy: 373, 385 + xy: 473, 377 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 spore-moss-edge rotate: false - xy: 613, 525 + xy: 1193, 517 size: 288, 96 orig: 288, 96 offset: 0, 0 index: -1 spore-moss1 rotate: false - xy: 715, 423 + xy: 495, 309 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spore-moss2 rotate: false - xy: 749, 423 + xy: 495, 275 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spore-moss3 rotate: false - xy: 783, 423 + xy: 495, 241 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spore-pine rotate: false - xy: 1259, 671 + xy: 1773, 483 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 sporerocks-large rotate: false - xy: 67, 11 + xy: 1773, 633 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 sporerocks1 rotate: false - xy: 817, 423 + xy: 495, 207 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sporerocks2 rotate: false - xy: 851, 423 + xy: 495, 173 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 stone-edge rotate: false - xy: 903, 623 + xy: 1483, 615 size: 288, 96 orig: 288, 96 offset: 0, 0 index: -1 -stone3 +stone1 rotate: false - xy: 885, 421 + xy: 495, 139 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 +stone2 + rotate: false + xy: 495, 105 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stone3 + rotate: false + xy: 529, 351 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +tainted-water + rotate: false + xy: 563, 351 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +tainted-water-edge + rotate: false + xy: 1193, 419 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 tar rotate: false - xy: 919, 421 + xy: 529, 317 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 tar-edge rotate: false - xy: 1193, 721 + xy: 1483, 517 size: 288, 96 orig: 288, 96 offset: 0, 0 index: -1 thorium1 rotate: false - xy: 971, 505 + xy: 597, 351 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thorium2 rotate: false - xy: 967, 471 + xy: 529, 283 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thorium3 rotate: false - xy: 1005, 521 + xy: 563, 317 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium1 rotate: false - xy: 1039, 521 + xy: 631, 351 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium2 rotate: false - xy: 1073, 521 + xy: 529, 249 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium3 rotate: false - xy: 1107, 521 + xy: 563, 283 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 water rotate: false - xy: 1141, 521 + xy: 597, 317 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 water-edge rotate: false - xy: 1483, 819 + xy: 1483, 419 size: 288, 96 orig: 288, 96 offset: 0, 0 index: -1 white-tree rotate: false - xy: 1, 693 + xy: 1, 685 size: 320, 320 orig: 320, 320 offset: 0, 0 index: -1 white-tree-dead rotate: false - xy: 1, 371 + xy: 1, 363 size: 320, 320 orig: 320, 320 offset: 0, 0 diff --git a/core/assets/sprites/sprites.png b/core/assets/sprites/sprites.png index 8baf88c126..721c3c3bd6 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 9ae2f80be2..fac0c80af8 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 85dcc5d4b7..2ba5820cfe 100644 Binary files a/core/assets/sprites/sprites3.png and b/core/assets/sprites/sprites3.png differ diff --git a/core/assets/sprites/sprites_fallback.atlas b/core/assets/sprites/sprites_fallback.atlas new file mode 100644 index 0000000000..7628664ece --- /dev/null +++ b/core/assets/sprites/sprites_fallback.atlas @@ -0,0 +1,11530 @@ + +sprites_fallback.png +size: 1024,1024 +format: RGBA8888 +filter: Nearest,Nearest +repeat: none +blast-drill + rotate: false + xy: 799, 845 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +blast-drill-rim + rotate: false + xy: 775, 585 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +blast-drill-rotator + rotate: false + xy: 219, 29 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +blast-drill-top + rotate: false + xy: 349, 29 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +impact-reactor + rotate: false + xy: 818, 325 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +impact-reactor-bottom + rotate: false + xy: 680, 195 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +impact-reactor-light + rotate: false + xy: 869, 65 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +core-foundation + rotate: false + xy: 688, 325 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +core-foundation-icon-editor + rotate: false + xy: 688, 325 + 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 +block-4 + rotate: false + xy: 479, 21 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +blast-drill-icon-editor + rotate: false + xy: 645, 593 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +impact-reactor-icon-editor + rotate: false + xy: 810, 195 + 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: 799, 715 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +impact-reactor-icon-full + rotate: false + xy: 739, 65 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +unit-icon-eradicator + rotate: false + xy: 645, 723 + 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 +chaos-array + rotate: false + xy: 609, 21 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +chaos-array-base + rotate: false + xy: 688, 455 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +chaos-array-leg + rotate: false + xy: 818, 455 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +eradicator + rotate: false + xy: 526, 277 + size: 152, 124 + orig: 152, 124 + offset: 0, 0 + index: -1 +eradicator-base + rotate: false + xy: 526, 151 + size: 152, 124 + orig: 152, 124 + offset: 0, 0 + index: -1 +eradicator-leg + rotate: false + xy: 645, 849 + 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: 229, 425 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +force-projector-icon-editor + rotate: false + xy: 229, 425 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +force-projector-top + rotate: false + xy: 327, 425 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +mass-driver-base + rotate: false + xy: 99, 133 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +laser-drill + rotate: false + xy: 817, 297 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +laser-drill-rim + rotate: false + xy: 99, 231 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +laser-drill-rotator + rotate: false + xy: 197, 229 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +laser-drill-top + rotate: false + xy: 295, 229 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +oil-extractor + rotate: false + xy: 491, 131 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +oil-extractor-liquid + rotate: false + xy: 785, 101 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +oil-extractor-rotator + rotate: false + xy: 883, 101 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +oil-extractor-top + rotate: false + xy: 1, 99 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +place-arrow + rotate: false + xy: 197, 33 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +rubble-3-0 + rotate: false + xy: 687, 33 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +rubble-3-1 + rotate: false + xy: 687, 33 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +rubble-4-0 + rotate: false + xy: 131, 621 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +rubble-4-1 + rotate: false + xy: 131, 621 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +liquid-tank-bottom + rotate: false + xy: 491, 229 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +liquid-tank-liquid + rotate: false + xy: 785, 199 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +liquid-tank-top + rotate: false + xy: 883, 199 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +glaive-ship-pad + rotate: false + xy: 621, 327 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +omega-mech-pad + rotate: false + xy: 99, 35 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +omega-mech-pad-icon-editor + rotate: false + xy: 99, 35 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +battery-large + rotate: false + xy: 131, 523 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +battery-large-icon-editor + rotate: false + xy: 131, 523 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +differential-generator + rotate: false + xy: 817, 493 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +differential-generator-icon-editor + rotate: false + xy: 817, 493 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +differential-generator-top + rotate: false + xy: 915, 493 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +impact-reactor-plasma-0 + rotate: false + xy: 1, 881 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +impact-reactor-plasma-1 + rotate: false + xy: 131, 881 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +impact-reactor-plasma-2 + rotate: false + xy: 261, 881 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +impact-reactor-plasma-3 + rotate: false + xy: 391, 881 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +impact-reactor-top + rotate: false + xy: 521, 881 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +alloy-smelter + rotate: false + xy: 911, 689 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +alloy-smelter-icon-editor + rotate: false + xy: 911, 689 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +alloy-smelter-top + rotate: false + xy: 911, 591 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +multi-press + rotate: false + xy: 393, 131 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +multi-press-icon-editor + rotate: false + xy: 393, 131 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +core-shard + rotate: false + xy: 327, 523 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +core-shard-icon-editor + rotate: false + xy: 327, 523 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +core-shard-top + rotate: false + xy: 425, 523 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +launch-pad + rotate: false + xy: 393, 229 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +launch-pad-icon-editor + rotate: false + xy: 393, 229 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +launch-pad-large + rotate: false + xy: 651, 881 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +launch-pad-large-icon-editor + rotate: false + xy: 651, 881 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +block-3 + rotate: false + xy: 229, 523 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +meltdown-heat + rotate: false + xy: 1, 751 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +ripple-heat + rotate: false + xy: 393, 33 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +fortress-factory + rotate: false + xy: 425, 425 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +fortress-factory-top + rotate: false + xy: 719, 425 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +ghoul-factory-top + rotate: false + xy: 719, 425 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +titan-factory-top + rotate: false + xy: 719, 425 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +fortress-factory-top-open + rotate: false + xy: 817, 395 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +ghoul-factory-top-open + rotate: false + xy: 817, 395 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +titan-factory-top-open + rotate: false + xy: 817, 395 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +ghoul-factory + rotate: false + xy: 327, 327 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +revenant-factory + rotate: false + xy: 391, 751 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +revenant-factory-top + rotate: false + xy: 781, 751 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +revenant-factory-top-open + rotate: false + xy: 1, 621 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +scrap-wall-gigantic + rotate: false + xy: 261, 621 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +scrap-wall-gigantic-icon-editor + rotate: false + xy: 261, 621 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +scrap-wall-huge1 + rotate: false + xy: 785, 3 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +scrap-wall-huge-icon-editor + rotate: false + xy: 785, 3 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +scrap-wall-huge2 + rotate: false + xy: 883, 3 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +scrap-wall-huge3 + rotate: false + xy: 1, 1 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +thruster + rotate: false + xy: 781, 621 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +thruster-icon-editor + rotate: false + xy: 781, 621 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +creeptree-icon-editor + rotate: false + xy: 911, 787 + size: 108, 108 + orig: 108, 108 + offset: 0, 0 + index: -1 +cyclone-icon-editor + rotate: false + xy: 621, 523 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +fortress-factory-icon-editor + rotate: false + xy: 523, 425 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +fuse-icon-editor + rotate: false + xy: 1, 393 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +ghoul-factory-icon-editor + rotate: false + xy: 425, 327 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +glaive-ship-pad-icon-editor + rotate: false + xy: 719, 327 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +laser-drill-icon-editor + rotate: false + xy: 915, 297 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +liquid-tank-icon-editor + rotate: false + xy: 589, 229 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +mass-driver-icon-editor + rotate: false + xy: 197, 131 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +meltdown-icon-editor + rotate: false + xy: 131, 751 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +oil-extractor-icon-editor + rotate: false + xy: 589, 131 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +revenant-factory-icon-editor + rotate: false + xy: 521, 751 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +ripple-icon-editor + rotate: false + xy: 491, 33 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +spectre-icon-editor + rotate: false + xy: 521, 621 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +cyclone + rotate: false + xy: 523, 523 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +cyclone-icon-full + rotate: false + xy: 719, 523 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +fortress-factory-icon-full + rotate: false + xy: 621, 425 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +fuse + rotate: false + xy: 915, 395 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +fuse-icon-full + rotate: false + xy: 229, 327 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +ghoul-factory-icon-full + rotate: false + xy: 523, 327 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +laser-drill-icon-full + rotate: false + xy: 1, 295 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +liquid-tank-icon-full + rotate: false + xy: 687, 229 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +mass-driver + rotate: false + xy: 1, 197 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +mass-driver-icon-full + rotate: false + xy: 295, 131 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +meltdown + rotate: false + xy: 781, 881 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +meltdown-icon-full + rotate: false + xy: 261, 751 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +oil-extractor-icon-full + rotate: false + xy: 687, 131 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +revenant-factory-icon-full + rotate: false + xy: 651, 751 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +ripple + rotate: false + xy: 295, 33 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +ripple-icon-full + rotate: false + xy: 589, 33 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +spectre + rotate: false + xy: 391, 621 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +spectre-icon-full + rotate: false + xy: 651, 621 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +unit-icon-chaos-array + rotate: false + xy: 1, 491 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +revenant + rotate: false + xy: 911, 897 + size: 112, 112 + orig: 112, 112 + offset: 0, 0 + index: -1 +eradication-equip + rotate: false + xy: 131, 329 + 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: 199, 655 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +mend-projector-icon-editor + rotate: false + xy: 199, 655 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +mend-projector-top + rotate: false + xy: 265, 655 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +overdrive-projector + rotate: false + xy: 397, 655 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +overdrive-projector-icon-editor + rotate: false + xy: 397, 655 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +overdrive-projector-top + rotate: false + xy: 1, 616 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +distributor + rotate: false + xy: 529, 729 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +distributor-icon-editor + rotate: false + xy: 529, 729 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +mechanical-drill + rotate: false + xy: 727, 663 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +mechanical-drill-rotator + rotate: false + xy: 925, 663 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +mechanical-drill-top + rotate: false + xy: 133, 655 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +pneumatic-drill + rotate: false + xy: 331, 589 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +pneumatic-drill-rotator + rotate: false + xy: 67, 550 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +pneumatic-drill-top + rotate: false + xy: 463, 531 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +water-extractor + rotate: false + xy: 1, 286 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +water-extractor-liquid + rotate: false + xy: 529, 267 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +water-extractor-rotator + rotate: false + xy: 595, 267 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +water-extractor-top + rotate: false + xy: 661, 267 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +rubble-1-0 + rotate: false + xy: 925, 531 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +rubble-1-1 + rotate: false + xy: 133, 523 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +rubble-2-0 + rotate: false + xy: 199, 523 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +rubble-2-1 + rotate: false + xy: 265, 523 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +rotary-pump + rotate: false + xy: 727, 531 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +thermal-pump + rotate: false + xy: 99, 927 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +alpha-dart-mech-pad + rotate: false + xy: 469, 861 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +alpha-dart-mech-pad-icon-editor + rotate: false + xy: 469, 861 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +delta-mech-pad + rotate: false + xy: 463, 729 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +delta-mech-pad-icon-editor + rotate: false + xy: 463, 729 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +javelin-ship-pad + rotate: false + xy: 331, 721 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +tau-mech-pad + rotate: false + xy: 463, 333 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +tau-mech-pad-icon-editor + rotate: false + xy: 463, 333 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +trident-ship-pad + rotate: false + xy: 859, 333 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +power-node-large + rotate: false + xy: 529, 531 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +rtg-generator + rotate: false + xy: 859, 531 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +rtg-generator-icon-editor + rotate: false + xy: 859, 531 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +solar-panel-large + rotate: false + xy: 1, 927 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +solar-panel-large-icon-editor + rotate: false + xy: 1, 927 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +surge-tower + rotate: false + xy: 265, 391 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +surge-tower-icon-editor + rotate: false + xy: 265, 391 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +thermal-generator + rotate: false + xy: 529, 333 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +thermal-generator-icon-editor + rotate: false + xy: 529, 333 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +thorium-reactor + rotate: false + xy: 295, 927 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +thorium-reactor-icon-editor + rotate: false + xy: 295, 927 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +thorium-reactor-center + rotate: false + xy: 393, 927 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +thorium-reactor-lights + rotate: false + xy: 491, 927 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +turbine-generator + rotate: false + xy: 133, 325 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +turbine-generator-icon-editor + rotate: false + xy: 133, 325 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +turbine-generator-top + rotate: false + xy: 199, 325 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +blast-mixer + rotate: false + xy: 535, 861 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +blast-mixer-icon-editor + rotate: false + xy: 535, 861 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +coal-centrifuge + rotate: false + xy: 667, 861 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +coal-centrifuge-icon-editor + rotate: false + xy: 667, 861 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +cryofluidmixer-bottom + rotate: false + xy: 535, 795 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +cryofluidmixer-liquid + rotate: false + xy: 733, 795 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +cryofluidmixer-top + rotate: false + xy: 799, 795 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +cultivator + rotate: false + xy: 865, 795 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +cultivator-middle + rotate: false + xy: 199, 787 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +cultivator-top + rotate: false + xy: 265, 787 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +graphite-press + rotate: false + xy: 265, 721 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +graphite-press-icon-editor + rotate: false + xy: 265, 721 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +kiln + rotate: false + xy: 1, 682 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +kiln-icon-editor + rotate: false + xy: 1, 682 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +kiln-top + rotate: false + xy: 67, 682 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +silicon-smelter-top + rotate: false + xy: 67, 682 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +phase-weaver + rotate: false + xy: 727, 597 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +phase-weaver-bottom + rotate: false + xy: 793, 597 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +phase-weaver-weave + rotate: false + xy: 133, 589 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +plastanium-compressor + rotate: false + xy: 199, 589 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +plastanium-compressor-icon-editor + rotate: false + xy: 199, 589 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +plastanium-compressor-top + rotate: false + xy: 265, 589 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +pyratite-mixer + rotate: false + xy: 661, 531 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +pyratite-mixer-icon-editor + rotate: false + xy: 661, 531 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +separator + rotate: false + xy: 265, 457 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +separator-icon-editor + rotate: false + xy: 265, 457 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +separator-liquid + rotate: false + xy: 331, 457 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +silicon-smelter + rotate: false + xy: 397, 457 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +silicon-smelter-icon-editor + rotate: false + xy: 397, 457 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spore-press + rotate: false + xy: 595, 399 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spore-press-frame0 + rotate: false + xy: 661, 399 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spore-press-frame1 + rotate: false + xy: 727, 399 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spore-press-frame2 + rotate: false + xy: 793, 399 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spore-press-liquid + rotate: false + xy: 133, 391 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spore-press-top + rotate: false + xy: 199, 391 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +container + rotate: false + xy: 733, 861 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +container-icon-editor + rotate: false + xy: 733, 861 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +vault + rotate: false + xy: 883, 927 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +vault-icon-editor + rotate: false + xy: 883, 927 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +block-2 + rotate: false + xy: 601, 861 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +lancer-heat + rotate: false + xy: 529, 663 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +salvo-heat + rotate: false + xy: 397, 523 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +salvo-panel-left + rotate: false + xy: 463, 465 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +salvo-panel-right + rotate: false + xy: 529, 465 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +wave-liquid + rotate: false + xy: 925, 267 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +crawler-factory + rotate: false + xy: 865, 861 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +dagger-factory + rotate: false + xy: 865, 861 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +phantom-factory + rotate: false + xy: 865, 861 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spirit-factory + rotate: false + xy: 865, 861 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +wraith-factory + rotate: false + xy: 865, 861 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +crawler-factory-top + rotate: false + xy: 67, 814 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +crawler-factory-top-open + rotate: false + xy: 469, 795 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +dagger-factory-top + rotate: false + xy: 1, 748 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +dagger-factory-top-open + rotate: false + xy: 67, 748 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +phantom-factory-top + rotate: false + xy: 529, 597 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +phantom-factory-top-open + rotate: false + xy: 595, 597 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spirit-factory-top + rotate: false + xy: 463, 399 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spirit-factory-top-open + rotate: false + xy: 529, 399 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +titan-factory + rotate: false + xy: 589, 927 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +wraith-factory-top + rotate: false + xy: 265, 259 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +wraith-factory-top-open + rotate: false + xy: 331, 259 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +copper-wall-large + rotate: false + xy: 799, 861 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +copper-wall-large-icon-editor + rotate: false + xy: 799, 861 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +door-large + rotate: false + xy: 595, 729 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +door-large-icon-editor + rotate: false + xy: 595, 729 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +door-large-open + rotate: false + xy: 661, 729 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +phase-wall-large + rotate: false + xy: 661, 597 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +phase-wall-large-icon-editor + rotate: false + xy: 661, 597 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +scrap-wall-large1 + rotate: false + xy: 793, 465 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +scrap-wall-large2 + rotate: false + xy: 859, 465 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +scrap-wall-large3 + rotate: false + xy: 925, 465 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +scrap-wall-large4 + rotate: false + xy: 133, 457 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +surge-wall-large + rotate: false + xy: 331, 391 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +surge-wall-large-icon-editor + rotate: false + xy: 331, 391 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +thorium-wall-large + rotate: false + xy: 595, 333 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +thorium-wall-large-icon-editor + rotate: false + xy: 595, 333 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +titanium-wall-large + rotate: false + xy: 793, 333 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +titanium-wall-large-icon-editor + rotate: false + xy: 793, 333 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +crawler-factory-icon-editor + rotate: false + xy: 931, 861 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +cryofluidmixer-icon-editor + rotate: false + xy: 601, 795 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +cultivator-icon-editor + rotate: false + xy: 931, 795 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +dagger-factory-icon-editor + rotate: false + xy: 331, 787 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +javelin-ship-pad-icon-editor + rotate: false + xy: 397, 721 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +lancer-icon-editor + rotate: false + xy: 595, 663 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +mechanical-drill-icon-editor + rotate: false + xy: 793, 663 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +phantom-factory-icon-editor + rotate: false + xy: 67, 616 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +phase-weaver-icon-editor + rotate: false + xy: 859, 597 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +pneumatic-drill-icon-editor + rotate: false + xy: 397, 589 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +power-node-large-icon-editor + rotate: false + xy: 595, 531 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +rotary-pump-icon-editor + rotate: false + xy: 793, 531 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +salvo-icon-editor + rotate: false + xy: 1, 484 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +scatter-icon-editor + rotate: false + xy: 661, 465 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +scrap-wall-large-icon-editor + rotate: false + xy: 199, 457 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spirit-factory-icon-editor + rotate: false + xy: 1, 418 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spore-press-icon-editor + rotate: false + xy: 859, 399 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +swarmer-icon-editor + rotate: false + xy: 1, 352 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +thermal-pump-icon-editor + rotate: false + xy: 197, 927 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +titan-factory-icon-editor + rotate: false + xy: 687, 927 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +trident-ship-pad-icon-editor + rotate: false + xy: 925, 333 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +water-extractor-icon-editor + rotate: false + xy: 67, 286 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +wave-icon-editor + rotate: false + xy: 793, 267 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +wraith-factory-icon-editor + rotate: false + xy: 133, 259 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +bullet + rotate: false + xy: 175, 205 + size: 52, 52 + orig: 52, 52 + offset: 0, 0 + index: -1 +bullet-back + rotate: false + xy: 229, 205 + size: 52, 52 + orig: 52, 52 + offset: 0, 0 + index: -1 +error + rotate: false + xy: 575, 9 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +laser-end + rotate: false + xy: 247, 853 + size: 72, 72 + orig: 72, 72 + offset: 0, 0 + index: -1 +minelaser-end + rotate: false + xy: 321, 853 + size: 72, 72 + orig: 72, 72 + offset: 0, 0 + index: -1 +transfer-end + rotate: false + xy: 395, 853 + size: 72, 72 + orig: 72, 72 + offset: 0, 0 + index: -1 +alloy-smelter-icon-large + rotate: false + xy: 283, 209 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +alpha-dart-mech-pad-icon-large + rotate: false + xy: 333, 209 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +arc-icon-large + rotate: false + xy: 455, 159 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +battery-icon-large + rotate: false + xy: 555, 159 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +battery-large-icon-large + rotate: false + xy: 605, 159 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +blast-drill-icon-large + rotate: false + xy: 655, 159 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +blast-mixer-icon-large + rotate: false + xy: 705, 159 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +bridge-conduit-icon-large + rotate: false + xy: 855, 159 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +bridge-conveyor-icon-large + rotate: false + xy: 905, 159 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +char-icon-large + rotate: false + xy: 175, 155 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +cliffs-icon-large + rotate: false + xy: 225, 155 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +coal-centrifuge-icon-large + rotate: false + xy: 383, 152 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +combustion-generator-icon-large + rotate: false + xy: 109, 151 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +conduit-icon-large + rotate: false + xy: 59, 128 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +container-icon-large + rotate: false + xy: 275, 109 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +conveyor-icon-large + rotate: false + xy: 325, 109 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +copper-wall-icon-large + rotate: false + xy: 433, 109 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +copper-wall-large-icon-large + rotate: false + xy: 555, 109 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +core-foundation-icon-large + rotate: false + xy: 605, 109 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +core-nucleus-icon-large + rotate: false + xy: 655, 109 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +core-shard-icon-large + rotate: false + xy: 705, 109 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +craters-icon-large + rotate: false + xy: 755, 109 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +crawler-factory-icon-full + rotate: false + xy: 1, 814 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +crawler-factory-icon-large + rotate: false + xy: 905, 109 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +creeptree-icon-large + rotate: false + xy: 159, 105 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +cryofluidmixer-icon-full + rotate: false + xy: 667, 795 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +cryofluidmixer-icon-large + rotate: false + xy: 209, 105 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +cultivator-icon-full + rotate: false + xy: 133, 787 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +cultivator-icon-large + rotate: false + xy: 375, 102 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +cyclone-icon-large + rotate: false + xy: 109, 101 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dagger-factory-icon-full + rotate: false + xy: 397, 787 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +dagger-factory-icon-large + rotate: false + xy: 51, 78 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dark-metal-icon-large + rotate: false + xy: 309, 59 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dark-panel-1-icon-large + rotate: false + xy: 425, 59 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dark-panel-2-icon-large + rotate: false + xy: 533, 59 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dark-panel-3-icon-large + rotate: false + xy: 583, 59 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dark-panel-4-icon-large + rotate: false + xy: 633, 59 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dark-panel-5-icon-large + rotate: false + xy: 683, 59 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dark-panel-6-icon-large + rotate: false + xy: 733, 59 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +darksand-icon-large + rotate: false + xy: 783, 59 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +darksand-tainted-water-icon-large + rotate: false + xy: 833, 59 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +darksand-water-icon-large + rotate: false + xy: 883, 59 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +deepwater-icon-large + rotate: false + xy: 159, 55 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +delta-mech-pad-icon-large + rotate: false + xy: 475, 51 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +differential-generator-icon-large + rotate: false + xy: 1, 48 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +distributor-icon-large + rotate: false + xy: 51, 28 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +door-icon-large + rotate: false + xy: 259, 9 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +door-large-icon-large + rotate: false + xy: 309, 9 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dunerocks-icon-large + rotate: false + xy: 409, 9 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +duo-icon-large + rotate: false + xy: 525, 9 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +force-projector-icon-large + rotate: false + xy: 775, 9 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +fortress-factory-icon-large + rotate: false + xy: 825, 9 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +fuse-icon-large + rotate: false + xy: 875, 9 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ghoul-factory-icon-large + rotate: false + xy: 925, 9 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +glaive-ship-pad-icon-large + rotate: false + xy: 975, 9 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +graphite-press-icon-large + rotate: false + xy: 151, 5 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +grass-icon-large + rotate: false + xy: 201, 5 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +hail-icon-large + rotate: false + xy: 359, 2 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +holostone-icon-large + rotate: false + xy: 459, 1 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +lancer + rotate: false + xy: 463, 663 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +lancer-icon-full + rotate: false + xy: 661, 663 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +mech-icon-glaive-ship + rotate: false + xy: 462, 209 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +mech-icon-omega-mech + rotate: false + xy: 520, 209 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +mech-icon-tau-mech + rotate: false + xy: 578, 209 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +mech-icon-trident-ship + rotate: false + xy: 636, 209 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +mechanical-drill-icon-full + rotate: false + xy: 859, 663 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +phantom-factory-icon-full + rotate: false + xy: 463, 597 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +phase-weaver-icon-full + rotate: false + xy: 925, 597 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +pneumatic-drill-icon-full + rotate: false + xy: 1, 550 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +salvo + rotate: false + xy: 331, 523 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +salvo-icon-full + rotate: false + xy: 67, 484 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +scatter + rotate: false + xy: 595, 465 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +scatter-icon-full + rotate: false + xy: 727, 465 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spirit-factory-icon-full + rotate: false + xy: 67, 418 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spore-press-icon-full + rotate: false + xy: 925, 399 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +swarmer + rotate: false + xy: 397, 391 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +swarmer-icon-full + rotate: false + xy: 67, 352 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +titan-factory-icon-full + rotate: false + xy: 785, 927 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +unit-icon-eruptor + rotate: false + xy: 265, 325 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +unit-icon-fortress + rotate: false + xy: 331, 325 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +unit-icon-titan + rotate: false + xy: 397, 325 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +water-extractor-icon-full + rotate: false + xy: 463, 267 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +wave + rotate: false + xy: 727, 267 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +wave-icon-full + rotate: false + xy: 859, 267 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +wraith-factory-icon-full + rotate: false + xy: 199, 259 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +alpha-mech + rotate: false + xy: 59, 178 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +alpha-mech-base + rotate: false + xy: 283, 159 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +alpha-mech-leg + rotate: false + xy: 333, 159 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +delta-mech + rotate: false + xy: 209, 55 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +delta-mech-base + rotate: false + xy: 359, 52 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +delta-mech-leg + rotate: false + xy: 101, 51 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +omega-mech + rotate: false + xy: 694, 209 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +omega-mech-armor + rotate: false + xy: 331, 655 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +omega-mech-base + rotate: false + xy: 752, 209 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +omega-mech-leg + rotate: false + xy: 810, 209 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +tau-mech + rotate: false + xy: 397, 202 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +dart-ship + rotate: false + xy: 933, 59 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +glaive-ship + rotate: false + xy: 59, 228 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +trident-ship + rotate: false + xy: 117, 201 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +shape-3 + rotate: false + xy: 397, 260 + size: 63, 63 + orig: 63, 63 + offset: 0, 0 + index: -1 +discord-banner + rotate: false + xy: 1, 880 + size: 84, 45 + orig: 84, 45 + offset: 0, 0 + index: -1 +info-banner + rotate: false + xy: 87, 880 + size: 84, 45 + orig: 84, 45 + offset: 0, 0 + index: -1 +crawler + rotate: false + xy: 805, 109 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +crawler-base + rotate: false + xy: 855, 109 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +crawler-leg + rotate: false + xy: 955, 109 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dagger + rotate: false + xy: 483, 101 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dagger-base + rotate: false + xy: 1, 98 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dagger-leg + rotate: false + xy: 259, 59 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +eruptor + rotate: false + xy: 727, 729 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +eruptor-base + rotate: false + xy: 793, 729 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +eruptor-leg + rotate: false + xy: 859, 729 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +fortress + rotate: false + xy: 925, 729 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +fortress-base + rotate: false + xy: 133, 721 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +titan-base + rotate: false + xy: 133, 721 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +fortress-leg + rotate: false + xy: 199, 721 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +ghoul + rotate: false + xy: 173, 853 + size: 72, 72 + orig: 72, 72 + offset: 0, 0 + index: -1 +phantom + rotate: false + xy: 868, 209 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +power-cell + rotate: false + xy: 926, 209 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +titan + rotate: false + xy: 661, 333 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +titan-leg + rotate: false + xy: 727, 333 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +artillery-equip + rotate: false + xy: 505, 151 + size: 48, 56 + orig: 48, 56 + offset: 0, 0 + index: -1 +blaster-equip + rotate: false + xy: 755, 159 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +bomber-equip + rotate: false + xy: 805, 159 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +missiles-equip + rotate: false + xy: 805, 159 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +chain-blaster-equip + rotate: false + xy: 955, 159 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +chaos-equip + rotate: false + xy: 1, 148 + size: 56, 136 + orig: 56, 136 + offset: 0, 0 + index: -1 +eruption-equip + rotate: false + xy: 625, 1 + size: 48, 56 + orig: 48, 56 + offset: 0, 0 + index: -1 +flakgun-equip + rotate: false + xy: 675, 9 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +flamethrower-equip + rotate: false + xy: 725, 1 + size: 48, 56 + orig: 48, 56 + offset: 0, 0 + index: -1 +heal-blaster-equip + rotate: false + xy: 101, 1 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 + +sprites_fallback4.png +size: 1024,1024 +format: RGBA8888 +filter: Nearest,Nearest +repeat: none +mender + rotate: false + xy: 965, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +mender-icon-editor + rotate: false + xy: 965, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +mender-top + rotate: false + xy: 965, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shock-mine + rotate: false + xy: 963, 311 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +bridge-conveyor + rotate: false + xy: 557, 991 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +bridge-conveyor-icon-editor + rotate: false + xy: 557, 991 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +bridge-conveyor-bridge + rotate: false + xy: 557, 957 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +bridge-conveyor-end + rotate: false + xy: 557, 923 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-0-0 + rotate: false + xy: 591, 855 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-icon-editor + rotate: false + xy: 591, 855 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-0-1 + rotate: false + xy: 591, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-0-2 + rotate: false + xy: 591, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-0-3 + rotate: false + xy: 591, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-1-0 + rotate: false + xy: 591, 719 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-1-1 + rotate: false + xy: 587, 651 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-1-2 + rotate: false + xy: 587, 617 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-1-3 + rotate: false + xy: 585, 583 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-2-0 + rotate: false + xy: 581, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-2-1 + rotate: false + xy: 577, 515 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-2-2 + rotate: false + xy: 577, 481 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-2-3 + rotate: false + xy: 596, 447 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-3-0 + rotate: false + xy: 621, 685 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-3-1 + rotate: false + xy: 625, 991 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-3-2 + rotate: false + xy: 625, 957 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-3-3 + rotate: false + xy: 625, 923 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-4-0 + rotate: false + xy: 625, 889 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-4-1 + rotate: false + xy: 625, 855 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-4-2 + rotate: false + xy: 625, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-4-3 + rotate: false + xy: 625, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-0-0 + rotate: false + xy: 759, 243 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-icon-editor + rotate: false + xy: 759, 243 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-0-1 + rotate: false + xy: 793, 243 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-0-2 + rotate: false + xy: 827, 243 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-0-3 + rotate: false + xy: 861, 243 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-1-0 + rotate: false + xy: 895, 243 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-1-1 + rotate: false + xy: 929, 243 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-1-2 + rotate: false + xy: 963, 243 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-1-3 + rotate: false + xy: 521, 209 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-2-0 + rotate: false + xy: 419, 190 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-2-1 + rotate: false + xy: 351, 167 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-2-2 + rotate: false + xy: 385, 167 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-2-3 + rotate: false + xy: 453, 190 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-3-0 + rotate: false + xy: 487, 190 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-3-1 + rotate: false + xy: 555, 209 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-3-2 + rotate: false + xy: 589, 209 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-3-3 + rotate: false + xy: 623, 209 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-4-0 + rotate: false + xy: 657, 209 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-4-1 + rotate: false + xy: 691, 209 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-4-2 + rotate: false + xy: 725, 209 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-4-3 + rotate: false + xy: 759, 209 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +junction + rotate: false + xy: 927, 651 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +junction-icon-editor + rotate: false + xy: 927, 651 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +overflow-gate + rotate: false + xy: 453, 394 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +overflow-gate-icon-editor + rotate: false + xy: 453, 394 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-conveyor + rotate: false + xy: 725, 413 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-conveyor-icon-editor + rotate: false + xy: 725, 413 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-conveyor-arrow + rotate: false + xy: 759, 413 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-conveyor-bridge + rotate: false + xy: 793, 413 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-conveyor-end + rotate: false + xy: 827, 413 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +router + rotate: false + xy: 827, 345 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +router-icon-editor + rotate: false + xy: 827, 345 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sorter + rotate: false + xy: 691, 277 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sorter-icon-editor + rotate: false + xy: 691, 277 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +block-border + rotate: false + xy: 519, 685 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +block-border-editor + rotate: false + xy: 519, 685 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +block-middle + rotate: false + xy: 519, 651 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pump-liquid + rotate: false + xy: 519, 651 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +block-select + rotate: false + xy: 519, 617 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-liquid + rotate: false + xy: 385, 405 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spawn + rotate: false + xy: 725, 277 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +bridge-conduit + rotate: false + xy: 517, 583 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +bridge-conduit-icon-editor + rotate: false + xy: 517, 583 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +bridge-conduit-arrow + rotate: false + xy: 513, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +bridge-conveyor-arrow + rotate: false + xy: 513, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +bridge-conduit-bridge + rotate: false + xy: 543, 515 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +bridge-conduit-end + rotate: false + xy: 553, 685 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-bottom + rotate: false + xy: 547, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-bottom-0 + rotate: false + xy: 543, 481 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-bottom-1 + rotate: false + xy: 426, 462 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-bottom-2 + rotate: false + xy: 351, 439 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-bottom-3 + rotate: false + xy: 385, 439 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-bottom-4 + rotate: false + xy: 460, 462 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-bottom-5 + rotate: false + xy: 494, 466 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-bottom-6 + rotate: false + xy: 528, 447 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-top-0 + rotate: false + xy: 453, 428 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-top-1 + rotate: false + xy: 487, 428 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-top-2 + rotate: false + xy: 562, 447 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-top-3 + rotate: false + xy: 587, 685 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-top-4 + rotate: false + xy: 591, 991 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-top-5 + rotate: false + xy: 591, 957 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-top-6 + rotate: false + xy: 591, 923 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-junction + rotate: false + xy: 931, 855 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-junction-icon-editor + rotate: false + xy: 931, 855 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-router-bottom + rotate: false + xy: 931, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-router-liquid + rotate: false + xy: 936, 447 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-router-top + rotate: false + xy: 951, 515 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +mechanical-pump + rotate: false + xy: 965, 991 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-conduit + rotate: false + xy: 589, 413 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-conduit-icon-editor + rotate: false + xy: 589, 413 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-conduit-arrow + rotate: false + xy: 623, 413 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-conduit-bridge + rotate: false + xy: 657, 413 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-conduit-end + rotate: false + xy: 691, 413 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulse-conduit-top-0 + rotate: false + xy: 759, 379 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulse-conduit-top-1 + rotate: false + xy: 793, 379 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulse-conduit-top-2 + rotate: false + xy: 827, 379 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulse-conduit-top-3 + rotate: false + xy: 861, 379 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulse-conduit-top-4 + rotate: false + xy: 895, 379 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulse-conduit-top-5 + rotate: false + xy: 929, 379 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulse-conduit-top-6 + rotate: false + xy: 963, 379 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +battery + rotate: false + xy: 523, 855 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +battery-icon-editor + rotate: false + xy: 523, 855 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +combustion-generator + rotate: false + xy: 553, 617 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +combustion-generator-icon-editor + rotate: false + xy: 553, 617 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +combustion-generator-top + rotate: false + xy: 551, 583 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +power-node + rotate: false + xy: 351, 337 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +power-node-icon-editor + rotate: false + xy: 351, 337 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +power-source + rotate: false + xy: 453, 360 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +power-void + rotate: false + xy: 555, 379 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +powerinfinite + rotate: false + xy: 623, 379 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +powervoid + rotate: false + xy: 657, 379 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +rtg-generator-top + rotate: false + xy: 895, 345 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +solar-panel + rotate: false + xy: 589, 277 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +solar-panel-icon-editor + rotate: false + xy: 589, 277 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +incinerator + rotate: false + xy: 868, 447 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +incinerator-icon-editor + rotate: false + xy: 868, 447 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-source + rotate: false + xy: 897, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-source-icon-editor + rotate: false + xy: 897, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-void + rotate: false + xy: 925, 583 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-void-icon-editor + rotate: false + xy: 925, 583 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +lavasmelter + rotate: false + xy: 931, 923 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-source + rotate: false + xy: 955, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-source-icon-editor + rotate: false + xy: 955, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +melter + rotate: false + xy: 965, 889 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +melter-icon-editor + rotate: false + xy: 965, 889 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulverizer + rotate: false + xy: 521, 345 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulverizer-rotator + rotate: false + xy: 385, 303 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +smelter + rotate: false + xy: 453, 258 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sortedunloader + rotate: false + xy: 657, 277 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +unloader + rotate: false + xy: 963, 209 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +unloader-icon-editor + rotate: false + xy: 963, 209 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +arc-heat + rotate: false + xy: 523, 957 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +block-1 + rotate: false + xy: 523, 719 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +hail-heat + rotate: false + xy: 395, 533 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +scorch-heat + rotate: false + xy: 385, 269 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +repair-point-base + rotate: false + xy: 555, 345 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +copper-wall + rotate: false + xy: 625, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +copper-wall-icon-editor + rotate: false + xy: 625, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +door + rotate: false + xy: 689, 685 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +door-icon-editor + rotate: false + xy: 689, 685 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +door-open + rotate: false + xy: 693, 957 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-wall + rotate: false + xy: 861, 413 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-wall-icon-editor + rotate: false + xy: 861, 413 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall1 + rotate: false + xy: 555, 311 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall2 + rotate: false + xy: 589, 311 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall3 + rotate: false + xy: 623, 311 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall4 + rotate: false + xy: 657, 311 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall5 + rotate: false + xy: 657, 311 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +surge-wall + rotate: false + xy: 419, 224 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +surge-wall-icon-editor + rotate: false + xy: 419, 224 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thorium-wall + rotate: false + xy: 623, 243 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thorium-wall-icon-editor + rotate: false + xy: 623, 243 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-wall + rotate: false + xy: 793, 209 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-wall-icon-editor + rotate: false + xy: 793, 209 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +arc-icon-editor + rotate: false + xy: 523, 923 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +char-icon-editor + rotate: false + xy: 557, 889 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-char1 + rotate: false + xy: 557, 889 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +cliffs-icon-editor + rotate: false + xy: 557, 719 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-icon-editor + rotate: false + xy: 419, 428 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +craters-icon-editor + rotate: false + xy: 615, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-craters1 + rotate: false + xy: 615, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-metal-icon-editor + rotate: false + xy: 659, 923 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-1-icon-editor + rotate: false + xy: 659, 889 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-dark-panel-1 + rotate: false + xy: 659, 889 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-2-icon-editor + rotate: false + xy: 659, 855 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-dark-panel-2 + rotate: false + xy: 659, 855 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-3-icon-editor + rotate: false + xy: 659, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-dark-panel-3 + rotate: false + xy: 659, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-4-icon-editor + rotate: false + xy: 659, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-dark-panel-4 + rotate: false + xy: 659, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-5-icon-editor + rotate: false + xy: 659, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-dark-panel-5 + rotate: false + xy: 659, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-6-icon-editor + rotate: false + xy: 659, 719 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-dark-panel-6 + rotate: false + xy: 659, 719 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +darksand-icon-editor + rotate: false + xy: 655, 651 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-darksand1 + rotate: false + xy: 655, 651 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +darksand-tainted-water-icon-editor + rotate: false + xy: 655, 617 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-darksand-tainted-water + rotate: false + xy: 655, 617 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +darksand-water-icon-editor + rotate: false + xy: 653, 583 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-darksand-water + rotate: false + xy: 653, 583 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +deepwater-icon-editor + rotate: false + xy: 649, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-deepwater + rotate: false + xy: 649, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dunerocks-icon-editor + rotate: false + xy: 693, 923 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +duo-icon-editor + rotate: false + xy: 693, 855 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-char2 + rotate: false + xy: 693, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-char3 + rotate: false + xy: 693, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-craters2 + rotate: false + xy: 693, 719 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-craters3 + rotate: false + xy: 689, 651 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-darksand2 + rotate: false + xy: 689, 617 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-darksand3 + rotate: false + xy: 687, 583 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-grass1 + rotate: false + xy: 683, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +grass-icon-editor + rotate: false + xy: 683, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-grass2 + rotate: false + xy: 679, 515 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-grass3 + rotate: false + xy: 679, 481 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-holostone1 + rotate: false + xy: 698, 447 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +holostone-icon-editor + rotate: false + xy: 698, 447 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-holostone2 + rotate: false + xy: 723, 685 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-holostone3 + rotate: false + xy: 723, 651 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-hotrock1 + rotate: false + xy: 723, 617 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +hotrock-icon-editor + rotate: false + xy: 723, 617 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-hotrock2 + rotate: false + xy: 721, 583 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-hotrock3 + rotate: false + xy: 727, 991 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ice-snow1 + rotate: false + xy: 727, 855 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice-snow-icon-editor + rotate: false + xy: 727, 855 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ice-snow2 + rotate: false + xy: 727, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ice-snow3 + rotate: false + xy: 727, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ice1 + rotate: false + xy: 727, 957 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice-icon-editor + rotate: false + xy: 727, 957 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ice2 + rotate: false + xy: 727, 923 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ice3 + rotate: false + xy: 727, 889 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ignarock1 + rotate: false + xy: 727, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ignarock-icon-editor + rotate: false + xy: 727, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ignarock2 + rotate: false + xy: 727, 719 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ignarock3 + rotate: false + xy: 717, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-magmarock1 + rotate: false + xy: 713, 515 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +magmarock-icon-editor + rotate: false + xy: 713, 515 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-magmarock2 + rotate: false + xy: 713, 481 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-magmarock3 + rotate: false + xy: 732, 447 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor + rotate: false + xy: 757, 685 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-damaged5 + rotate: false + xy: 757, 685 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-icon-editor + rotate: false + xy: 757, 685 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-2 + rotate: false + xy: 757, 651 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-2-icon-editor + rotate: false + xy: 757, 651 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-3 + rotate: false + xy: 757, 617 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-3-icon-editor + rotate: false + xy: 757, 617 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-5 + rotate: false + xy: 755, 583 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-5-icon-editor + rotate: false + xy: 755, 583 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-damaged1 + rotate: false + xy: 751, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged-icon-editor + rotate: false + xy: 751, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-damaged2 + rotate: false + xy: 747, 515 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-damaged3 + rotate: false + xy: 747, 481 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-damaged4 + rotate: false + xy: 761, 991 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-damaged6 + rotate: false + xy: 761, 957 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-moss1 + rotate: false + xy: 761, 923 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +moss-icon-editor + rotate: false + xy: 761, 923 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-moss2 + rotate: false + xy: 761, 889 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-moss3 + rotate: false + xy: 761, 855 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-coal1 + rotate: false + xy: 761, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-coal2 + rotate: false + xy: 761, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-coal3 + rotate: false + xy: 761, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-copper1 + rotate: false + xy: 761, 719 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-copper2 + rotate: false + xy: 766, 447 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-copper3 + rotate: false + xy: 789, 583 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-lead1 + rotate: false + xy: 791, 685 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-lead2 + rotate: false + xy: 791, 651 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-lead3 + rotate: false + xy: 791, 617 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap1 + rotate: false + xy: 785, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap2 + rotate: false + xy: 781, 515 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap3 + rotate: false + xy: 781, 481 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-thorium1 + rotate: false + xy: 795, 991 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-thorium2 + rotate: false + xy: 795, 957 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-thorium3 + rotate: false + xy: 795, 923 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-titanium1 + rotate: false + xy: 795, 889 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-titanium2 + rotate: false + xy: 795, 855 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-titanium3 + rotate: false + xy: 795, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-pebbles1 + rotate: false + xy: 795, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-pebbles2 + rotate: false + xy: 795, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-pebbles3 + rotate: false + xy: 795, 719 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-salt + rotate: false + xy: 800, 447 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +salt-icon-editor + rotate: false + xy: 800, 447 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-sand-water + rotate: false + xy: 825, 617 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand-water-icon-editor + rotate: false + xy: 825, 617 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-sand1 + rotate: false + xy: 823, 583 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand-icon-editor + rotate: false + xy: 823, 583 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-sand2 + rotate: false + xy: 825, 685 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-sand3 + rotate: false + xy: 825, 651 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-shale1 + rotate: false + xy: 819, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shale-icon-editor + rotate: false + xy: 819, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-shale2 + rotate: false + xy: 815, 515 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-shale3 + rotate: false + xy: 815, 481 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-snow1 + rotate: false + xy: 829, 991 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snow-icon-editor + rotate: false + xy: 829, 991 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-snow2 + rotate: false + xy: 829, 957 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-snow3 + rotate: false + xy: 829, 923 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-spore-moss1 + rotate: false + xy: 829, 889 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spore-moss-icon-editor + rotate: false + xy: 829, 889 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-spore-moss2 + rotate: false + xy: 829, 855 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-spore-moss3 + rotate: false + xy: 829, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-stone1 + rotate: false + xy: 829, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stone-icon-editor + rotate: false + xy: 829, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-stone2 + rotate: false + xy: 829, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-stone3 + rotate: false + xy: 829, 719 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-tainted-water + rotate: false + xy: 834, 447 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +tainted-water-icon-editor + rotate: false + xy: 834, 447 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-tar + rotate: false + xy: 857, 583 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +tar-icon-editor + rotate: false + xy: 857, 583 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-water + rotate: false + xy: 859, 685 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +water-icon-editor + rotate: false + xy: 859, 685 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +hail-icon-editor + rotate: false + xy: 863, 889 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icerocks-icon-editor + rotate: false + xy: 863, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-router-icon-editor + rotate: false + xy: 931, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +mechanical-pump-icon-editor + rotate: false + xy: 965, 957 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pebbles-icon-editor + rotate: false + xy: 487, 394 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pine-icon-editor + rotate: false + xy: 151, 975 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +power-source-icon-editor + rotate: false + xy: 487, 360 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +power-void-icon-editor + rotate: false + xy: 589, 379 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulse-conduit-icon-editor + rotate: false + xy: 691, 379 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulverizer-icon-editor + rotate: false + xy: 419, 326 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +repair-point-icon-editor + rotate: false + xy: 589, 345 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +rock-icon-editor + rotate: false + xy: 151, 225 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +rocks-icon-editor + rotate: false + xy: 759, 345 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +saltrocks-icon-editor + rotate: false + xy: 929, 345 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sandrocks-icon-editor + rotate: false + xy: 521, 311 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scorch-icon-editor + rotate: false + xy: 453, 292 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall-icon-editor + rotate: false + xy: 759, 311 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shale-boulder-icon-editor + rotate: false + xy: 895, 311 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shalerocks-icon-editor + rotate: false + xy: 929, 311 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shock-mine-icon-editor + rotate: false + xy: 521, 277 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shrubs-icon-editor + rotate: false + xy: 351, 235 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snowrock-icon-editor + rotate: false + xy: 251, 925 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +snowrocks-icon-editor + rotate: false + xy: 555, 277 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spawn-icon-editor + rotate: false + xy: 759, 277 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spore-cluster-icon-editor + rotate: false + xy: 443, 747 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +spore-pine-icon-editor + rotate: false + xy: 251, 375 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +sporerocks-icon-editor + rotate: false + xy: 963, 277 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +missile + rotate: false + xy: 485, 726 + size: 36, 36 + orig: 36, 36 + offset: 0, 0 + index: -1 +missile-back + rotate: false + xy: 481, 688 + size: 36, 36 + orig: 36, 36 + offset: 0, 0 + index: -1 +scorch1 + rotate: false + xy: 995, 617 + size: 28, 100 + orig: 28, 100 + offset: 0, 0 + index: -1 +scorch2 + rotate: false + xy: 419, 54 + size: 28, 100 + orig: 28, 100 + offset: 0, 0 + index: -1 +scorch3 + rotate: false + xy: 351, 31 + size: 28, 100 + orig: 28, 100 + offset: 0, 0 + index: -1 +scorch4 + rotate: false + xy: 381, 31 + size: 28, 100 + orig: 28, 100 + offset: 0, 0 + index: -1 +scorch5 + rotate: false + xy: 449, 54 + size: 28, 100 + orig: 28, 100 + offset: 0, 0 + index: -1 +shell + rotate: false + xy: 479, 592 + size: 36, 36 + orig: 36, 36 + offset: 0, 0 + index: -1 +shell-back + rotate: false + xy: 437, 496 + size: 36, 36 + orig: 36, 36 + offset: 0, 0 + index: -1 +shot + rotate: false + xy: 419, 258 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +transfer-arrow + rotate: false + xy: 861, 209 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +alloy-smelter-icon-medium + rotate: false + xy: 475, 500 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +alloy-smelter-icon-small + rotate: false + xy: 479, 566 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +alpha-dart-mech-pad-icon-medium + rotate: false + xy: 509, 500 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +alpha-dart-mech-pad-icon-small + rotate: false + xy: 993, 591 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +arc + rotate: false + xy: 523, 991 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +arc-icon-full + rotate: false + xy: 523, 889 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +arc-icon-small + rotate: false + xy: 443, 605 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +battery-icon-small + rotate: false + xy: 401, 579 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +battery-large-icon-medium + rotate: false + xy: 523, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +battery-large-icon-small + rotate: false + xy: 552, 143 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +blast-drill-icon-medium + rotate: false + xy: 523, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +blast-drill-icon-small + rotate: false + xy: 578, 143 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +blast-mixer-icon-medium + rotate: false + xy: 523, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +blast-mixer-icon-small + rotate: false + xy: 999, 999 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +bridge-conduit-icon-small + rotate: false + xy: 999, 973 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +bridge-conveyor-icon-small + rotate: false + xy: 999, 947 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +char-icon-small + rotate: false + xy: 999, 895 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +cliffs-icon-small + rotate: false + xy: 999, 869 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +coal-centrifuge-icon-medium + rotate: false + xy: 553, 651 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +coal-centrifuge-icon-small + rotate: false + xy: 999, 843 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +combustion-generator-icon-small + rotate: false + xy: 999, 817 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +conduit-icon-full + rotate: false + xy: 351, 405 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-icon-small + rotate: false + xy: 999, 791 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +container-icon-medium + rotate: false + xy: 591, 889 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +container-icon-small + rotate: false + xy: 999, 765 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +conveyor-icon-small + rotate: false + xy: 999, 739 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +copper-wall-icon-small + rotate: false + xy: 644, 183 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +copper-wall-large-icon-medium + rotate: false + xy: 625, 719 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +copper-wall-large-icon-small + rotate: false + xy: 670, 183 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +core-foundation-icon-medium + rotate: false + xy: 621, 651 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +core-foundation-icon-small + rotate: false + xy: 696, 183 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +core-nucleus-icon-medium + rotate: false + xy: 621, 617 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +core-nucleus-icon-small + rotate: false + xy: 722, 183 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +core-shard-icon-medium + rotate: false + xy: 619, 583 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +core-shard-icon-small + rotate: false + xy: 748, 183 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +craters-icon-small + rotate: false + xy: 774, 183 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +crawler-factory-icon-medium + rotate: false + xy: 611, 515 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +crawler-factory-icon-small + rotate: false + xy: 800, 183 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +creeptree-icon-medium + rotate: false + xy: 611, 481 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +creeptree-icon-small + rotate: false + xy: 826, 183 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +cryofluidmixer-icon-medium + rotate: false + xy: 630, 447 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +cryofluidmixer-icon-small + rotate: false + xy: 852, 183 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +cultivator-icon-medium + rotate: false + xy: 655, 685 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +cultivator-icon-small + rotate: false + xy: 878, 183 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +cyclone-icon-medium + rotate: false + xy: 659, 991 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +cyclone-icon-small + rotate: false + xy: 904, 183 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dagger-factory-icon-medium + rotate: false + xy: 659, 957 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dagger-factory-icon-small + rotate: false + xy: 930, 183 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dark-metal-icon-small + rotate: false + xy: 956, 183 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dark-panel-1-icon-small + rotate: false + xy: 982, 183 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dark-panel-2-icon-small + rotate: false + xy: 997, 421 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dark-panel-3-icon-small + rotate: false + xy: 997, 395 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dark-panel-4-icon-small + rotate: false + xy: 997, 369 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dark-panel-5-icon-small + rotate: false + xy: 997, 343 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dark-panel-6-icon-small + rotate: false + xy: 997, 317 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +darksand-icon-small + rotate: false + xy: 997, 291 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +darksand-tainted-water-icon-small + rotate: false + xy: 997, 265 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +darksand-water-icon-small + rotate: false + xy: 997, 239 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +deepwater-icon-small + rotate: false + xy: 997, 213 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +delta-mech-pad-icon-medium + rotate: false + xy: 645, 515 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +delta-mech-pad-icon-small + rotate: false + xy: 644, 157 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +differential-generator-icon-medium + rotate: false + xy: 645, 481 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +differential-generator-icon-small + rotate: false + xy: 670, 157 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +distributor-icon-medium + rotate: false + xy: 664, 447 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +distributor-icon-small + rotate: false + xy: 696, 157 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +door-icon-small + rotate: false + xy: 722, 157 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +door-large-icon-medium + rotate: false + xy: 693, 991 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +door-large-icon-small + rotate: false + xy: 748, 157 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dunerocks-icon-small + rotate: false + xy: 774, 157 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +duo + rotate: false + xy: 693, 889 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +duo-icon-full + rotate: false + xy: 693, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +duo-icon-small + rotate: false + xy: 800, 157 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +force-projector-icon-medium + rotate: false + xy: 859, 617 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +force-projector-icon-small + rotate: false + xy: 826, 157 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +fortress-factory-icon-medium + rotate: false + xy: 853, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +fortress-factory-icon-small + rotate: false + xy: 852, 157 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +fuse-icon-medium + rotate: false + xy: 849, 515 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +fuse-icon-small + rotate: false + xy: 878, 157 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ghoul-factory-icon-medium + rotate: false + xy: 849, 481 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ghoul-factory-icon-small + rotate: false + xy: 904, 157 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +glaive-ship-pad-icon-medium + rotate: false + xy: 863, 991 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +glaive-ship-pad-icon-small + rotate: false + xy: 930, 157 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +graphite-press-icon-medium + rotate: false + xy: 863, 957 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +graphite-press-icon-small + rotate: false + xy: 956, 157 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +grass-icon-small + rotate: false + xy: 982, 157 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +hail + rotate: false + xy: 863, 923 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +hail-icon-full + rotate: false + xy: 863, 855 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +hail-icon-small + rotate: false + xy: 644, 131 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +holostone-icon-small + rotate: false + xy: 508, 109 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +hotrock-icon-large + rotate: false + xy: 1, 975 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +hotrock-icon-small + rotate: false + xy: 479, 92 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ice-icon-large + rotate: false + xy: 1, 925 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ice-icon-small + rotate: false + xy: 534, 109 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ice-snow-icon-large + rotate: false + xy: 1, 875 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ice-snow-icon-small + rotate: false + xy: 560, 117 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +icerocks-icon-large + rotate: false + xy: 1, 825 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icerocks-icon-small + rotate: false + xy: 586, 117 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ignarock-icon-large + rotate: false + xy: 1, 725 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ignarock-icon-small + rotate: false + xy: 722, 131 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +impact-reactor-icon-large + rotate: false + xy: 1, 675 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +impact-reactor-icon-medium + rotate: false + xy: 863, 719 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +impact-reactor-icon-small + rotate: false + xy: 748, 131 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +incinerator-icon-large + rotate: false + xy: 1, 625 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +incinerator-icon-small + rotate: false + xy: 774, 131 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-blast-compound-medium + rotate: false + xy: 638, 105 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-blast-compound-xlarge + rotate: false + xy: 401, 983 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-coal-medium + rotate: false + xy: 560, 91 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-coal-xlarge + rotate: false + xy: 401, 941 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-copper-medium + rotate: false + xy: 479, 66 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-copper-xlarge + rotate: false + xy: 401, 899 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-graphite-medium + rotate: false + xy: 505, 83 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-graphite-xlarge + rotate: false + xy: 401, 857 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-lead-medium + rotate: false + xy: 531, 83 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-lead-xlarge + rotate: false + xy: 401, 815 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-metaglass-medium + rotate: false + xy: 586, 91 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-metaglass-xlarge + rotate: false + xy: 401, 773 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-phase-fabric-medium + rotate: false + xy: 612, 94 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-phase-fabric-xlarge + rotate: false + xy: 401, 731 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-plastanium-medium + rotate: false + xy: 664, 105 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-plastanium-xlarge + rotate: false + xy: 401, 689 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-pyratite-medium + rotate: false + xy: 690, 105 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-pyratite-xlarge + rotate: false + xy: 401, 647 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-sand-medium + rotate: false + xy: 716, 105 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-sand-xlarge + rotate: false + xy: 401, 605 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-scrap-medium + rotate: false + xy: 742, 105 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-scrap-xlarge + rotate: false + xy: 437, 563 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-silicon-medium + rotate: false + xy: 768, 105 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-silicon-xlarge + rotate: false + xy: 443, 983 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-source-icon-large + rotate: false + xy: 1, 575 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +item-source-icon-small + rotate: false + xy: 826, 131 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-spore-pod-medium + rotate: false + xy: 852, 131 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-spore-pod-xlarge + rotate: false + xy: 443, 941 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-surge-alloy-medium + rotate: false + xy: 878, 131 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-surge-alloy-xlarge + rotate: false + xy: 443, 899 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-thorium-medium + rotate: false + xy: 904, 131 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-thorium-xlarge + rotate: false + xy: 443, 857 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-titanium-medium + rotate: false + xy: 930, 131 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-titanium-xlarge + rotate: false + xy: 443, 815 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-void-icon-large + rotate: false + xy: 1, 525 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +item-void-icon-small + rotate: false + xy: 956, 131 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +javelin-ship-pad-icon-large + rotate: false + xy: 1, 425 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +javelin-ship-pad-icon-medium + rotate: false + xy: 927, 685 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +javelin-ship-pad-icon-small + rotate: false + xy: 982, 131 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +junction-icon-large + rotate: false + xy: 1, 325 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +junction-icon-small + rotate: false + xy: 826, 105 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +kiln-icon-large + rotate: false + xy: 1, 275 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +kiln-icon-medium + rotate: false + xy: 927, 617 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +kiln-icon-small + rotate: false + xy: 794, 89 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +lancer-icon-large + rotate: false + xy: 1, 225 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +lancer-icon-medium + rotate: false + xy: 917, 515 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +lancer-icon-small + rotate: false + xy: 638, 79 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +laser-drill-icon-large + rotate: false + xy: 1, 175 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +laser-drill-icon-medium + rotate: false + xy: 917, 481 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +laser-drill-icon-small + rotate: false + xy: 557, 65 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +launch-pad-icon-large + rotate: false + xy: 1, 125 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +launch-pad-icon-medium + rotate: false + xy: 931, 991 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +launch-pad-icon-small + rotate: false + xy: 479, 40 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +launch-pad-large-icon-large + rotate: false + xy: 1, 75 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +launch-pad-large-icon-medium + rotate: false + xy: 931, 957 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +launch-pad-large-icon-small + rotate: false + xy: 411, 28 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +liquid-junction-icon-large + rotate: false + xy: 51, 975 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +liquid-junction-icon-small + rotate: false + xy: 437, 28 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +liquid-router-icon-full + rotate: false + xy: 931, 719 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-router-icon-large + rotate: false + xy: 51, 925 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +liquid-router-icon-small + rotate: false + xy: 351, 5 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +liquid-source-icon-large + rotate: false + xy: 51, 875 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +liquid-source-icon-small + rotate: false + xy: 377, 5 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +liquid-tank-icon-large + rotate: false + xy: 51, 825 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +liquid-tank-icon-medium + rotate: false + xy: 951, 481 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-tank-icon-small + rotate: false + xy: 505, 57 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +magmarock-icon-large + rotate: false + xy: 51, 775 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +magmarock-icon-small + rotate: false + xy: 531, 57 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +mass-driver-icon-large + rotate: false + xy: 51, 725 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mass-driver-icon-medium + rotate: false + xy: 961, 651 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +mass-driver-icon-small + rotate: false + xy: 583, 65 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +mech-icon-alpha-mech + rotate: false + xy: 51, 675 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mech-icon-dart-ship + rotate: false + xy: 51, 625 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mech-icon-delta-mech + rotate: false + xy: 51, 575 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mech-icon-javelin-ship + rotate: false + xy: 51, 525 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mechanical-drill-icon-large + rotate: false + xy: 51, 475 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mechanical-drill-icon-medium + rotate: false + xy: 961, 617 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +mechanical-drill-icon-small + rotate: false + xy: 609, 65 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +mechanical-pump-icon-large + rotate: false + xy: 51, 425 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mechanical-pump-icon-small + rotate: false + xy: 664, 79 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +meltdown-icon-large + rotate: false + xy: 51, 375 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +meltdown-icon-medium + rotate: false + xy: 965, 923 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +meltdown-icon-small + rotate: false + xy: 690, 79 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +melter-icon-large + rotate: false + xy: 51, 325 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +melter-icon-small + rotate: false + xy: 716, 79 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +mend-projector-icon-large + rotate: false + xy: 51, 275 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mend-projector-icon-medium + rotate: false + xy: 965, 855 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +mend-projector-icon-small + rotate: false + xy: 742, 79 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +mender-icon-large + rotate: false + xy: 51, 225 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mender-icon-small + rotate: false + xy: 768, 79 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +metal-floor-2-icon-large + rotate: false + xy: 51, 175 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +metal-floor-2-icon-small + rotate: false + xy: 852, 105 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +metal-floor-3-icon-large + rotate: false + xy: 51, 125 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +metal-floor-3-icon-small + rotate: false + xy: 878, 105 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +metal-floor-5-icon-large + rotate: false + xy: 51, 75 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +metal-floor-5-icon-small + rotate: false + xy: 904, 105 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +metal-floor-damaged-icon-large + rotate: false + xy: 51, 25 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +metal-floor-damaged-icon-small + rotate: false + xy: 930, 105 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +metal-floor-icon-large + rotate: false + xy: 101, 975 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +metal-floor-icon-small + rotate: false + xy: 956, 105 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +moss-icon-large + rotate: false + xy: 101, 925 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +moss-icon-small + rotate: false + xy: 982, 105 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +multi-press-icon-large + rotate: false + xy: 101, 875 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +multi-press-icon-medium + rotate: false + xy: 965, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +multi-press-icon-small + rotate: false + xy: 820, 79 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +oil-extractor-icon-large + rotate: false + xy: 101, 825 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +oil-extractor-icon-medium + rotate: false + xy: 965, 719 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +oil-extractor-icon-small + rotate: false + xy: 794, 63 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +omega-mech-pad-icon-large + rotate: false + xy: 101, 775 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +omega-mech-pad-icon-medium + rotate: false + xy: 970, 447 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +omega-mech-pad-icon-small + rotate: false + xy: 635, 53 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-coal-icon-full + rotate: false + xy: 985, 515 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-icon-medium + rotate: false + xy: 985, 515 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-icon-large + rotate: false + xy: 101, 725 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-coal-icon-small + rotate: false + xy: 557, 39 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-copper-icon-full + rotate: false + xy: 989, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-icon-medium + rotate: false + xy: 989, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-icon-large + rotate: false + xy: 101, 675 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-copper-icon-small + rotate: false + xy: 505, 31 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-lead-icon-full + rotate: false + xy: 985, 481 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-icon-medium + rotate: false + xy: 985, 481 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-icon-large + rotate: false + xy: 101, 625 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-lead-icon-small + rotate: false + xy: 463, 14 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-scrap-icon-full + rotate: false + xy: 521, 413 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-icon-medium + rotate: false + xy: 521, 413 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-icon-large + rotate: false + xy: 101, 575 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-scrap-icon-small + rotate: false + xy: 531, 31 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-thorium-icon-full + rotate: false + xy: 419, 394 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-icon-medium + rotate: false + xy: 419, 394 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-icon-large + rotate: false + xy: 101, 525 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-thorium-icon-small + rotate: false + xy: 403, 2 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-titanium-icon-full + rotate: false + xy: 351, 371 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-icon-medium + rotate: false + xy: 351, 371 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-icon-large + rotate: false + xy: 101, 475 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-titanium-icon-small + rotate: false + xy: 429, 2 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +overdrive-projector-icon-large + rotate: false + xy: 101, 425 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +overdrive-projector-icon-medium + rotate: false + xy: 385, 371 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +overdrive-projector-icon-small + rotate: false + xy: 583, 39 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +overflow-gate-icon-large + rotate: false + xy: 101, 375 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +overflow-gate-icon-small + rotate: false + xy: 609, 39 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +pebbles-icon-large + rotate: false + xy: 101, 325 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +pebbles-icon-small + rotate: false + xy: 661, 53 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +phantom-factory-icon-large + rotate: false + xy: 101, 275 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +phantom-factory-icon-medium + rotate: false + xy: 555, 413 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phantom-factory-icon-small + rotate: false + xy: 687, 53 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +phase-conduit-icon-large + rotate: false + xy: 101, 225 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +phase-conduit-icon-small + rotate: false + xy: 713, 53 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +phase-conveyor-icon-large + rotate: false + xy: 101, 175 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +phase-conveyor-icon-small + rotate: false + xy: 739, 53 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +phase-wall-icon-large + rotate: false + xy: 101, 125 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +phase-wall-icon-small + rotate: false + xy: 765, 53 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +phase-wall-large-icon-large + rotate: false + xy: 101, 75 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +phase-wall-large-icon-medium + rotate: false + xy: 895, 413 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-wall-large-icon-small + rotate: false + xy: 846, 79 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +phase-weaver-icon-large + rotate: false + xy: 101, 25 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +phase-weaver-icon-medium + rotate: false + xy: 929, 413 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-weaver-icon-small + rotate: false + xy: 872, 79 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +pine-icon-medium + rotate: false + xy: 963, 413 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pine-icon-small + rotate: false + xy: 898, 79 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +plastanium-compressor-icon-large + rotate: false + xy: 151, 925 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +plastanium-compressor-icon-medium + rotate: false + xy: 521, 379 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +plastanium-compressor-icon-small + rotate: false + xy: 924, 79 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +pneumatic-drill-icon-large + rotate: false + xy: 151, 875 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +pneumatic-drill-icon-medium + rotate: false + xy: 419, 360 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pneumatic-drill-icon-small + rotate: false + xy: 950, 79 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +power-node-icon-large + rotate: false + xy: 151, 825 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +power-node-icon-small + rotate: false + xy: 976, 79 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +power-node-large-icon-large + rotate: false + xy: 151, 775 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +power-node-large-icon-medium + rotate: false + xy: 385, 337 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +power-node-large-icon-small + rotate: false + xy: 820, 53 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +power-source-icon-large + rotate: false + xy: 151, 725 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +power-source-icon-small + rotate: false + xy: 791, 37 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +power-void-icon-large + rotate: false + xy: 151, 675 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +power-void-icon-small + rotate: false + xy: 635, 27 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +pulse-conduit-icon-full + rotate: false + xy: 725, 379 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulse-conduit-icon-large + rotate: false + xy: 151, 625 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +pulse-conduit-icon-small + rotate: false + xy: 557, 13 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +pulverizer-icon-full + rotate: false + xy: 351, 303 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulverizer-icon-large + rotate: false + xy: 151, 575 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +pulverizer-icon-small + rotate: false + xy: 583, 13 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +pyratite-mixer-icon-large + rotate: false + xy: 151, 525 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +pyratite-mixer-icon-medium + rotate: false + xy: 453, 326 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pyratite-mixer-icon-small + rotate: false + xy: 609, 13 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +repair-point + rotate: false + xy: 487, 326 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +repair-point-icon-full + rotate: false + xy: 623, 345 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +repair-point-icon-large + rotate: false + xy: 151, 425 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +repair-point-icon-small + rotate: false + xy: 489, 5 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +revenant-factory-icon-large + rotate: false + xy: 151, 375 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +revenant-factory-icon-medium + rotate: false + xy: 657, 345 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +revenant-factory-icon-small + rotate: false + xy: 515, 5 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ripple-icon-large + rotate: false + xy: 151, 275 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ripple-icon-medium + rotate: false + xy: 691, 345 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ripple-icon-small + rotate: false + xy: 661, 27 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +rock-icon-medium + rotate: false + xy: 725, 345 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +rock-icon-small + rotate: false + xy: 687, 27 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +rocks-icon-large + rotate: false + xy: 151, 175 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +rocks-icon-small + rotate: false + xy: 713, 27 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +rotary-pump-icon-large + rotate: false + xy: 151, 125 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +rotary-pump-icon-medium + rotate: false + xy: 793, 345 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +rotary-pump-icon-small + rotate: false + xy: 739, 27 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +router-icon-large + rotate: false + xy: 151, 75 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +router-icon-small + rotate: false + xy: 765, 27 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +rtg-generator-icon-large + rotate: false + xy: 151, 25 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +rtg-generator-icon-medium + rotate: false + xy: 861, 345 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +rtg-generator-icon-small + rotate: false + xy: 846, 53 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +salt-icon-large + rotate: false + xy: 201, 975 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +salt-icon-small + rotate: false + xy: 872, 53 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +saltrocks-icon-large + rotate: false + xy: 201, 925 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +saltrocks-icon-small + rotate: false + xy: 898, 53 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +salvo-icon-large + rotate: false + xy: 201, 875 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +salvo-icon-medium + rotate: false + xy: 963, 345 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +salvo-icon-small + rotate: false + xy: 924, 53 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +sand-icon-large + rotate: false + xy: 201, 825 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +sand-icon-small + rotate: false + xy: 950, 53 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +sand-water-icon-large + rotate: false + xy: 201, 775 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +sand-water-icon-small + rotate: false + xy: 976, 53 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +sandrocks-icon-large + rotate: false + xy: 201, 725 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +sandrocks-icon-small + rotate: false + xy: 817, 27 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +scatter-icon-large + rotate: false + xy: 201, 675 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +scatter-icon-medium + rotate: false + xy: 419, 292 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scatter-icon-small + rotate: false + xy: 791, 11 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +scorch + rotate: false + xy: 351, 269 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scorch-icon-full + rotate: false + xy: 487, 292 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scorch-icon-large + rotate: false + xy: 201, 625 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +scorch-icon-small + rotate: false + xy: 635, 1 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +scrap-wall-gigantic-icon-large + rotate: false + xy: 201, 575 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +scrap-wall-gigantic-icon-medium + rotate: false + xy: 691, 311 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall-gigantic-icon-small + rotate: false + xy: 661, 1 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +scrap-wall-huge-icon-large + rotate: false + xy: 201, 525 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +scrap-wall-huge-icon-medium + rotate: false + xy: 725, 311 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall-huge-icon-small + rotate: false + xy: 687, 1 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +scrap-wall-icon-large + rotate: false + xy: 201, 475 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +scrap-wall-icon-small + rotate: false + xy: 713, 1 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +scrap-wall-large-icon-large + rotate: false + xy: 201, 425 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +scrap-wall-large-icon-medium + rotate: false + xy: 793, 311 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall-large-icon-small + rotate: false + xy: 739, 1 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +separator-icon-large + rotate: false + xy: 201, 375 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +separator-icon-medium + rotate: false + xy: 861, 311 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +separator-icon-small + rotate: false + xy: 765, 1 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +shale-boulder-icon-large + rotate: false + xy: 201, 325 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +shale-boulder-icon-small + rotate: false + xy: 817, 1 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +shale-icon-large + rotate: false + xy: 201, 275 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +shale-icon-small + rotate: false + xy: 895, 27 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +shalerocks-icon-large + rotate: false + xy: 201, 225 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +shalerocks-icon-small + rotate: false + xy: 921, 27 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +shock-mine-icon-large + rotate: false + xy: 201, 175 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +shock-mine-icon-small + rotate: false + xy: 947, 27 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +shrubs-icon-large + rotate: false + xy: 201, 75 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +shrubs-icon-small + rotate: false + xy: 973, 27 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +silicon-smelter-icon-large + rotate: false + xy: 201, 25 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +silicon-smelter-icon-medium + rotate: false + xy: 385, 235 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +silicon-smelter-icon-small + rotate: false + xy: 999, 27 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +snow-icon-large + rotate: false + xy: 251, 975 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +snow-icon-small + rotate: false + xy: 895, 1 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +snowrock-icon-medium + rotate: false + xy: 487, 258 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snowrock-icon-small + rotate: false + xy: 921, 1 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +snowrocks-icon-large + rotate: false + xy: 251, 875 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +snowrocks-icon-small + rotate: false + xy: 947, 1 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +solar-panel-icon-large + rotate: false + xy: 251, 825 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +solar-panel-icon-small + rotate: false + xy: 973, 1 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +solar-panel-large-icon-large + rotate: false + xy: 251, 775 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +solar-panel-large-icon-medium + rotate: false + xy: 623, 277 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +solar-panel-large-icon-small + rotate: false + xy: 999, 1 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +sorter-icon-large + rotate: false + xy: 251, 725 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +spawn-icon-large + rotate: false + xy: 251, 675 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +spectre-icon-large + rotate: false + xy: 251, 625 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +spectre-icon-medium + rotate: false + xy: 793, 277 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spirit-factory-icon-large + rotate: false + xy: 251, 525 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +spirit-factory-icon-medium + rotate: false + xy: 827, 277 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spore-cluster-icon-large + rotate: false + xy: 251, 475 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +spore-cluster-icon-medium + rotate: false + xy: 861, 277 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spore-moss-icon-large + rotate: false + xy: 251, 425 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +spore-pine-icon-medium + rotate: false + xy: 895, 277 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spore-press-icon-large + rotate: false + xy: 251, 325 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +spore-press-icon-medium + rotate: false + xy: 929, 277 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sporerocks-icon-large + rotate: false + xy: 251, 275 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +stone-icon-large + rotate: false + xy: 251, 225 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +surge-tower-icon-large + rotate: false + xy: 251, 175 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +surge-tower-icon-medium + rotate: false + xy: 521, 243 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +surge-wall-icon-large + rotate: false + xy: 251, 125 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +surge-wall-large-icon-large + rotate: false + xy: 251, 75 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +surge-wall-large-icon-medium + rotate: false + xy: 351, 201 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +swarmer-icon-large + rotate: false + xy: 301, 975 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +swarmer-icon-medium + rotate: false + xy: 385, 201 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +tainted-water-icon-large + rotate: false + xy: 301, 925 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +tar-icon-large + rotate: false + xy: 301, 875 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +tau-mech-pad-icon-large + rotate: false + xy: 301, 725 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +tau-mech-pad-icon-medium + rotate: false + xy: 453, 224 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thermal-generator-icon-large + rotate: false + xy: 301, 675 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +thermal-generator-icon-medium + rotate: false + xy: 487, 224 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thermal-pump-icon-large + rotate: false + xy: 301, 625 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +thermal-pump-icon-medium + rotate: false + xy: 555, 243 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thorium-reactor-icon-large + rotate: false + xy: 301, 575 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +thorium-reactor-icon-medium + rotate: false + xy: 589, 243 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thorium-wall-icon-large + rotate: false + xy: 301, 525 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +thorium-wall-large-icon-large + rotate: false + xy: 301, 475 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +thorium-wall-large-icon-medium + rotate: false + xy: 657, 243 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thruster-icon-large + rotate: false + xy: 301, 425 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +thruster-icon-medium + rotate: false + xy: 691, 243 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titan-factory-icon-large + rotate: false + xy: 301, 375 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +titan-factory-icon-medium + rotate: false + xy: 725, 243 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-icon-large + rotate: false + xy: 301, 325 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +titanium-wall-icon-large + rotate: false + xy: 301, 275 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +titanium-wall-large-icon-large + rotate: false + xy: 301, 225 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +titanium-wall-large-icon-medium + rotate: false + xy: 827, 209 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +trident-ship-pad-icon-large + rotate: false + xy: 301, 175 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +trident-ship-pad-icon-medium + rotate: false + xy: 895, 209 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +turbine-generator-icon-large + rotate: false + xy: 301, 125 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +turbine-generator-icon-medium + rotate: false + xy: 929, 209 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +unit-icon-crawler + rotate: false + xy: 301, 75 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +unit-icon-dagger + rotate: false + xy: 301, 25 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +unloader-icon-large + rotate: false + xy: 351, 975 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +vault-icon-large + rotate: false + xy: 351, 925 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +vault-icon-medium + rotate: false + xy: 521, 175 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +water-extractor-icon-large + rotate: false + xy: 351, 875 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +water-extractor-icon-medium + rotate: false + xy: 419, 156 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +water-icon-large + rotate: false + xy: 351, 825 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +wave-icon-large + rotate: false + xy: 351, 775 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +wave-icon-medium + rotate: false + xy: 351, 133 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +white-tree-dead-icon-large + rotate: false + xy: 351, 725 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +white-tree-dead-icon-medium + rotate: false + xy: 385, 133 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +white-tree-icon-large + rotate: false + xy: 351, 675 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +white-tree-icon-medium + rotate: false + xy: 453, 156 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +wraith-factory-icon-large + rotate: false + xy: 351, 575 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +wraith-factory-icon-medium + rotate: false + xy: 487, 156 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-biomatter + rotate: false + xy: 891, 583 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-blast-compound + rotate: false + xy: 893, 685 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-coal + rotate: false + xy: 893, 651 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-copper + rotate: false + xy: 893, 617 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-graphite + rotate: false + xy: 887, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-lead + rotate: false + xy: 883, 515 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-metaglass + rotate: false + xy: 883, 481 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-phase-fabric + rotate: false + xy: 897, 991 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-plastanium + rotate: false + xy: 897, 957 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-pyratite + rotate: false + xy: 897, 923 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-sand + rotate: false + xy: 897, 889 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-scrap + rotate: false + xy: 897, 855 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-silicon + rotate: false + xy: 897, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-spore-pod + rotate: false + xy: 897, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-surge-alloy + rotate: false + xy: 897, 719 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-thorium + rotate: false + xy: 902, 447 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-titanium + rotate: false + xy: 921, 549 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-cryofluid + rotate: false + xy: 931, 889 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-oil + rotate: false + xy: 931, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-slag + rotate: false + xy: 959, 583 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-water + rotate: false + xy: 961, 685 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +tau-mech-base + rotate: false + xy: 301, 825 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +tau-mech-leg + rotate: false + xy: 301, 775 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +javelin-ship + rotate: false + xy: 1, 475 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +javelin-ship-shield + rotate: false + xy: 1, 375 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +bar + rotate: false + xy: 586, 171 + size: 27, 36 + split: 9, 9, 9, 9 + orig: 27, 36 + offset: 0, 0 + index: -1 +bar-top + rotate: false + xy: 479, 118 + size: 27, 36 + split: 9, 10, 9, 10 + orig: 27, 36 + offset: 0, 0 + index: -1 +button + rotate: false + xy: 485, 880 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-disabled + rotate: false + xy: 443, 718 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-down + rotate: false + xy: 443, 689 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-edge-1 + rotate: false + xy: 443, 660 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-edge-2 + rotate: false + xy: 443, 631 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-edge-3 + rotate: false + xy: 437, 534 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-edge-4 + rotate: false + xy: 475, 534 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-over + rotate: false + xy: 485, 996 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-right + rotate: false + xy: 485, 909 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-right-down + rotate: false + xy: 485, 967 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-right-over + rotate: false + xy: 485, 938 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-select + rotate: false + xy: 999, 921 + size: 24, 24 + split: 4, 4, 4, 4 + orig: 24, 24 + offset: 0, 0 + index: -1 +check-off + rotate: false + xy: 557, 855 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +check-on + rotate: false + xy: 557, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +check-on-over + rotate: false + xy: 557, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +check-over + rotate: false + xy: 557, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +content-background + rotate: false + xy: 485, 764 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +content-background-locked + rotate: false + xy: 485, 851 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +content-background-noitems + rotate: false + xy: 485, 822 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +content-background-over + rotate: false + xy: 485, 793 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +empty-sector + rotate: false + xy: 859, 651 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-cancel-2 + rotate: false + xy: 612, 120 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +icon-check-2 + rotate: false + xy: 670, 131 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +icon-generated + rotate: false + xy: 1, 775 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-power-requirement + rotate: false + xy: 863, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-tree-locked + rotate: false + xy: 863, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-zone + rotate: false + xy: 696, 131 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +icon-zone-locked + rotate: false + xy: 351, 531 + size: 42, 42 + orig: 42, 42 + offset: 0, 0 + index: -1 +inventory + rotate: false + xy: 800, 115 + size: 24, 40 + split: 10, 10, 10, 14 + orig: 24, 40 + offset: 0, 0 + index: -1 +pane + rotate: false + xy: 481, 630 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +pane-2 + rotate: false + xy: 481, 659 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +scroll + rotate: false + xy: 869, 16 + size: 24, 35 + split: 10, 10, 6, 5 + orig: 24, 35 + offset: 0, 0 + index: -1 +scroll-horizontal + rotate: false + xy: 389, 476 + size: 35, 24 + split: 6, 5, 10, 10 + orig: 35, 24 + offset: 0, 0 + index: -1 +scroll-knob-horizontal-black + rotate: false + xy: 443, 789 + size: 40, 24 + split: 11, 10, 10, 10 + orig: 40, 24 + offset: 0, 0 + index: -1 +scroll-knob-vertical-black + rotate: false + xy: 843, 11 + size: 24, 40 + split: 10, 10, 6, 10 + orig: 24, 40 + offset: 0, 0 + index: -1 +sector-select + rotate: false + xy: 827, 311 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +slider-knob + rotate: false + xy: 555, 169 + size: 29, 38 + orig: 29, 38 + offset: 0, 0 + index: -1 +slider-knob-down + rotate: false + xy: 521, 135 + size: 29, 38 + orig: 29, 38 + offset: 0, 0 + index: -1 +slider-knob-over + rotate: false + xy: 521, 135 + size: 29, 38 + orig: 29, 38 + offset: 0, 0 + index: -1 +underline + rotate: false + xy: 389, 502 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +underline-2 + rotate: false + xy: 351, 502 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +underline-red + rotate: false + xy: 351, 473 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +window-empty + rotate: false + xy: 615, 146 + size: 27, 61 + split: 8, 8, 44, 11 + orig: 27, 61 + offset: 0, 0 + index: -1 +spirit + rotate: false + xy: 251, 575 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +wraith + rotate: false + xy: 351, 625 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +lich-missiles-equip + rotate: false + xy: 1, 25 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +reaper-gun-equip + rotate: false + xy: 151, 475 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +revenant-missiles-equip + rotate: false + xy: 151, 325 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +shockgun-equip + rotate: false + xy: 201, 125 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +swarmer-equip + rotate: false + xy: 251, 25 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 + +sprites_fallback5.png +size: 512,128 +format: RGBA8888 +filter: Nearest,Nearest +repeat: none +casing + rotate: false + xy: 481, 63 + size: 8, 16 + orig: 8, 16 + offset: 0, 0 + index: -1 +laser + rotate: false + xy: 503, 79 + size: 4, 48 + orig: 4, 48 + offset: 0, 0 + index: -1 +minelaser + rotate: false + xy: 495, 67 + size: 4, 48 + orig: 4, 48 + offset: 0, 0 + index: -1 +scale_marker + rotate: false + xy: 387, 1 + size: 4, 4 + orig: 4, 4 + offset: 0, 0 + index: -1 +transfer + rotate: false + xy: 501, 29 + size: 4, 48 + orig: 4, 48 + offset: 0, 0 + index: -1 +item-blast-compound-small + rotate: false + xy: 325, 93 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-coal-small + rotate: false + xy: 333, 111 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-copper-small + rotate: false + xy: 325, 75 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-graphite-small + rotate: false + xy: 325, 57 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-lead-small + rotate: false + xy: 325, 39 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-metaglass-small + rotate: false + xy: 327, 21 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-phase-fabric-small + rotate: false + xy: 327, 3 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-plastanium-small + rotate: false + xy: 343, 93 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-pyratite-small + rotate: false + xy: 351, 111 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-sand-small + rotate: false + xy: 343, 75 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-scrap-small + rotate: false + xy: 343, 57 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-silicon-small + rotate: false + xy: 343, 39 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-spore-pod-small + rotate: false + xy: 345, 21 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-surge-alloy-small + rotate: false + xy: 345, 3 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-thorium-small + rotate: false + xy: 361, 93 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-titanium-small + rotate: false + xy: 369, 111 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +sorter-icon-small + rotate: false + xy: 1, 103 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +spawn-icon-small + rotate: false + xy: 1, 77 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +spectre-icon-small + rotate: false + xy: 1, 51 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +spirit-factory-icon-small + rotate: false + xy: 1, 25 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +spore-cluster-icon-small + rotate: false + xy: 27, 103 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +spore-moss-icon-small + rotate: false + xy: 27, 77 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +spore-pine-icon-small + rotate: false + xy: 27, 51 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +spore-press-icon-small + rotate: false + xy: 27, 25 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +sporerocks-icon-small + rotate: false + xy: 53, 103 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +stone-icon-small + rotate: false + xy: 53, 77 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +surge-tower-icon-small + rotate: false + xy: 53, 51 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +surge-wall-icon-small + rotate: false + xy: 53, 25 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +surge-wall-large-icon-small + rotate: false + xy: 79, 103 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +swarmer-icon-small + rotate: false + xy: 79, 77 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +tainted-water-icon-small + rotate: false + xy: 79, 51 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +tar-icon-small + rotate: false + xy: 79, 25 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +tau-mech-pad-icon-small + rotate: false + xy: 105, 103 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +thermal-generator-icon-small + rotate: false + xy: 105, 77 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +thermal-pump-icon-small + rotate: false + xy: 105, 51 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +thorium-reactor-icon-small + rotate: false + xy: 105, 25 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +thorium-wall-icon-small + rotate: false + xy: 131, 103 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +thorium-wall-large-icon-small + rotate: false + xy: 131, 77 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +thruster-icon-small + rotate: false + xy: 131, 51 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +titan-factory-icon-small + rotate: false + xy: 131, 25 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +titanium-conveyor-icon-small + rotate: false + xy: 157, 103 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +titanium-wall-icon-small + rotate: false + xy: 157, 77 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +titanium-wall-large-icon-small + rotate: false + xy: 157, 51 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +trident-ship-pad-icon-small + rotate: false + xy: 157, 25 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +turbine-generator-icon-small + rotate: false + xy: 183, 103 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +unloader-icon-small + rotate: false + xy: 183, 77 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +vault-icon-small + rotate: false + xy: 183, 51 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +water-extractor-icon-small + rotate: false + xy: 183, 25 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +water-icon-small + rotate: false + xy: 209, 103 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +wave-icon-small + rotate: false + xy: 209, 77 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +white-tree-dead-icon-small + rotate: false + xy: 209, 51 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +white-tree-icon-small + rotate: false + xy: 209, 25 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +wraith-factory-icon-small + rotate: false + xy: 235, 103 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +blank + rotate: false + xy: 467, 114 + size: 1, 1 + orig: 1, 1 + offset: 0, 0 + index: -1 +clear + rotate: false + xy: 471, 102 + size: 1, 1 + orig: 1, 1 + offset: 0, 0 + index: -1 +clear-editor + rotate: false + xy: 471, 102 + size: 1, 1 + orig: 1, 1 + offset: 0, 0 + index: -1 +clear + rotate: false + xy: 395, 3 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +editor-clear + rotate: false + xy: 395, 3 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +cursor + rotate: false + xy: 387, 7 + size: 4, 4 + orig: 4, 4 + offset: 0, 0 + index: -1 +icon-crafting + rotate: false + xy: 147, 7 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-defense + rotate: false + xy: 165, 7 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-distribution + rotate: false + xy: 183, 7 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-effect + rotate: false + xy: 201, 7 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-liquid + rotate: false + xy: 253, 67 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-power + rotate: false + xy: 273, 21 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-production + rotate: false + xy: 273, 3 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-turret + rotate: false + xy: 315, 111 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-units + rotate: false + xy: 307, 57 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-upgrade + rotate: false + xy: 309, 21 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +controller-cursor + rotate: false + xy: 21, 7 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-about + rotate: false + xy: 361, 77 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-add + rotate: false + xy: 361, 61 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-admin + rotate: false + xy: 361, 45 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-admin-small + rotate: false + xy: 261, 103 + size: 6, 6 + orig: 6, 6 + offset: 0, 0 + index: -1 +icon-areaDelete + rotate: false + xy: 363, 1 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-arrow + rotate: false + xy: 39, 7 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-arrow-16 + rotate: false + xy: 39, 7 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-arrow-down + rotate: false + xy: 375, 1 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-arrow-left + rotate: false + xy: 237, 1 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-arrow-right + rotate: false + xy: 249, 1 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-arrow-up + rotate: false + xy: 261, 1 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-back + rotate: false + xy: 57, 7 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-ban + rotate: false + xy: 363, 29 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-break + rotate: false + xy: 75, 7 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-cancel + rotate: false + xy: 93, 7 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-chat + rotate: false + xy: 457, 85 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-check + rotate: false + xy: 111, 7 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-copy + rotate: false + xy: 129, 7 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-cursor + rotate: false + xy: 459, 101 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-database + rotate: false + xy: 363, 13 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-database-small + rotate: false + xy: 467, 117 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-dev-builds + rotate: false + xy: 377, 77 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-discord + rotate: false + xy: 379, 95 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-donate + rotate: false + xy: 387, 113 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-dots + rotate: false + xy: 377, 61 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-editor + rotate: false + xy: 377, 45 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-egg + rotate: false + xy: 379, 29 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-elevation + rotate: false + xy: 219, 7 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-eraser + rotate: false + xy: 235, 85 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-exit + rotate: false + xy: 379, 13 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-file + rotate: false + xy: 235, 67 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-file-image + rotate: false + xy: 235, 49 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-file-text + rotate: false + xy: 393, 79 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-fill + rotate: false + xy: 235, 31 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-floppy + rotate: false + xy: 395, 97 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-floppy-16 + rotate: false + xy: 237, 13 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-folder + rotate: false + xy: 403, 113 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-folder-parent + rotate: false + xy: 393, 63 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-github + rotate: false + xy: 393, 47 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-google-play + rotate: false + xy: 395, 31 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-grid + rotate: false + xy: 253, 85 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-hold + rotate: false + xy: 457, 73 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-holdDelete + rotate: false + xy: 457, 61 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-home + rotate: false + xy: 395, 15 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-host + rotate: false + xy: 409, 81 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-info + rotate: false + xy: 411, 97 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-itch.io + rotate: false + xy: 419, 113 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-item + rotate: false + xy: 457, 49 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-items-none + rotate: false + xy: 481, 53 + size: 8, 8 + orig: 8, 8 + offset: 0, 0 + index: -1 +icon-line + rotate: false + xy: 261, 111 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-link + rotate: false + xy: 409, 65 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-liquid-small + rotate: false + xy: 459, 37 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-load + rotate: false + xy: 409, 49 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-load-image + rotate: false + xy: 253, 49 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-load-map + rotate: false + xy: 253, 31 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-loading + rotate: false + xy: 255, 13 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-locked + rotate: false + xy: 271, 93 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-logic + rotate: false + xy: 459, 25 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-map + rotate: false + xy: 411, 33 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-menu + rotate: false + xy: 459, 13 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-menu-large + rotate: false + xy: 279, 111 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-missing + rotate: false + xy: 459, 1 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-mission-background + rotate: false + xy: 1, 5 + size: 18, 18 + orig: 18, 18 + offset: 0, 0 + index: -1 +icon-mission-battle + rotate: false + xy: 469, 89 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-mission-defense + rotate: false + xy: 471, 105 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-mission-done + rotate: false + xy: 479, 117 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-none + rotate: false + xy: 469, 77 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-paste + rotate: false + xy: 271, 75 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-pause + rotate: false + xy: 469, 65 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-pencil + rotate: false + xy: 271, 57 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-pencil-small + rotate: false + xy: 411, 17 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-pick + rotate: false + xy: 271, 39 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-play + rotate: false + xy: 469, 53 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-play-2 + rotate: false + xy: 411, 1 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-play-custom + rotate: false + xy: 425, 81 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-players + rotate: false + xy: 471, 41 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-power-small + rotate: false + xy: 481, 93 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-quit + rotate: false + xy: 427, 97 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-redo + rotate: false + xy: 289, 93 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-refresh + rotate: false + xy: 435, 113 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-rename + rotate: false + xy: 425, 65 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-resize + rotate: false + xy: 297, 111 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-rotate + rotate: false + xy: 425, 49 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-rotate-arrow + rotate: false + xy: 427, 33 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-rotate-left + rotate: false + xy: 427, 17 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-rotate-right + rotate: false + xy: 427, 1 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-save + rotate: false + xy: 441, 81 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-save-image + rotate: false + xy: 289, 75 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-save-map + rotate: false + xy: 289, 57 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-settings + rotate: false + xy: 483, 105 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-spray + rotate: false + xy: 289, 39 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-terrain + rotate: false + xy: 291, 21 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-tools + rotate: false + xy: 443, 97 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-touch + rotate: false + xy: 491, 117 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-touchDelete + rotate: false + xy: 481, 81 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-trash + rotate: false + xy: 451, 113 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-trash-16 + rotate: false + xy: 291, 3 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-tree + rotate: false + xy: 307, 93 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-trello + rotate: false + xy: 441, 65 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-tutorial + rotate: false + xy: 441, 49 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-undo + rotate: false + xy: 307, 75 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-unlocked + rotate: false + xy: 307, 39 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-unlocks + rotate: false + xy: 443, 33 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-wiki + rotate: false + xy: 443, 17 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-zoom + rotate: false + xy: 309, 3 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-zoom-small + rotate: false + xy: 443, 1 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +selection + rotate: false + xy: 474, 102 + size: 1, 1 + orig: 1, 1 + offset: 0, 0 + index: -1 +slider + rotate: false + xy: 407, 5 + size: 1, 8 + orig: 1, 8 + offset: 0, 0 + index: -1 +slider-vertical + rotate: false + xy: 459, 98 + size: 8, 1 + orig: 8, 1 + offset: 0, 0 + index: -1 +white + rotate: false + xy: 507, 74 + size: 3, 3 + orig: 3, 3 + offset: 0, 0 + index: -1 + +sprites_fallback6.png +size: 1024,1024 +format: RGBA8888 +filter: Nearest,Nearest +repeat: none +dark-panel-1-edge + rotate: false + xy: 645, 911 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +dark-panel-2-edge + rotate: false + xy: 645, 813 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +dark-panel-3-edge + rotate: false + xy: 645, 715 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +dark-panel-4-edge + rotate: false + xy: 645, 617 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +dark-panel-5-edge + rotate: false + xy: 1, 589 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +dark-panel-6-edge + rotate: false + xy: 291, 589 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +darksand-edge + rotate: false + xy: 581, 519 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +darksand-tainted-water-edge + rotate: false + xy: 1, 491 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +darksand-water-edge + rotate: false + xy: 291, 491 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +deepwater-edge + rotate: false + xy: 581, 421 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +edge-stencil-blocky + rotate: false + xy: 1, 393 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +edge-stencil-smooth + rotate: false + xy: 1, 393 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +grass-edge + rotate: false + xy: 291, 393 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +holostone-edge + rotate: false + xy: 581, 323 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +ice-edge + rotate: false + xy: 1, 295 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +ice-snow-edge + rotate: false + xy: 291, 295 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +ignarock-edge + rotate: false + xy: 581, 225 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +metal-floor-2-edge + rotate: false + xy: 1, 197 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +metal-floor-3-edge + rotate: false + xy: 291, 197 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +metal-floor-5-edge + rotate: false + xy: 581, 127 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +metal-floor-damaged-edge + rotate: false + xy: 1, 99 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +metal-floor-edge + rotate: false + xy: 291, 99 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +moss-edge + rotate: false + xy: 581, 29 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +pebbles-edge + rotate: false + xy: 1, 1 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +salt-edge + rotate: false + xy: 291, 1 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +white-tree + rotate: false + xy: 1, 687 + size: 320, 320 + orig: 320, 320 + offset: 0, 0 + index: -1 +white-tree-dead + rotate: false + xy: 323, 687 + size: 320, 320 + orig: 320, 320 + offset: 0, 0 + index: -1 + +sprites_fallback7.png +size: 1024,512 +format: RGBA8888 +filter: Nearest,Nearest +repeat: none +char1 + rotate: false + xy: 291, 117 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +char2 + rotate: false + xy: 539, 183 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +char3 + rotate: false + xy: 829, 281 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +cliffs1 + rotate: false + xy: 151, 19 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +coal1 + rotate: false + xy: 981, 435 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +coal2 + rotate: false + xy: 291, 83 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +coal3 + rotate: false + xy: 325, 117 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +copper1 + rotate: false + xy: 981, 401 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +copper2 + rotate: false + xy: 979, 367 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +copper3 + rotate: false + xy: 325, 83 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +craters1 + rotate: false + xy: 359, 117 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +craters2 + rotate: false + xy: 359, 83 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +craters3 + rotate: false + xy: 393, 117 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +craters4 + rotate: false + xy: 393, 83 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +craters5 + rotate: false + xy: 427, 117 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +craters6 + rotate: false + xy: 427, 83 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +creeptree + rotate: false + xy: 871, 401 + size: 108, 108 + orig: 108, 108 + offset: 0, 0 + index: -1 +dark-metal-large + rotate: false + xy: 1, 53 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +dark-metal1 + rotate: false + xy: 581, 215 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-metal2 + rotate: false + xy: 615, 215 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-1 + rotate: false + xy: 649, 215 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-2 + rotate: false + xy: 683, 215 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-3 + rotate: false + xy: 717, 215 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-4 + rotate: false + xy: 461, 117 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-5 + rotate: false + xy: 461, 83 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-6 + rotate: false + xy: 751, 215 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +darksand-tainted-water + rotate: false + xy: 641, 181 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +darksand-water + rotate: false + xy: 675, 181 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +darksand1 + rotate: false + xy: 937, 325 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +darksand2 + rotate: false + xy: 573, 181 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +darksand3 + rotate: false + xy: 607, 181 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +deepwater + rotate: false + xy: 709, 181 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dunerocks-large + rotate: false + xy: 291, 151 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +dunerocks1 + rotate: false + xy: 743, 181 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dunerocks2 + rotate: false + xy: 871, 301 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +grass1 + rotate: false + xy: 495, 133 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +grass2 + rotate: false + xy: 495, 99 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +grass3 + rotate: false + xy: 785, 231 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +holostone1 + rotate: false + xy: 539, 149 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +holostone2 + rotate: false + xy: 573, 147 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +holostone3 + rotate: false + xy: 607, 147 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +hotrock1 + rotate: false + xy: 641, 147 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +hotrock2 + rotate: false + xy: 675, 147 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +hotrock3 + rotate: false + xy: 709, 147 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice-snow1 + rotate: false + xy: 597, 113 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice-snow2 + rotate: false + xy: 631, 113 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice-snow3 + rotate: false + xy: 665, 113 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice1 + rotate: false + xy: 743, 147 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice2 + rotate: false + xy: 529, 115 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice3 + rotate: false + xy: 563, 113 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icerocks-large + rotate: false + xy: 581, 249 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +icerocks1 + rotate: false + xy: 699, 113 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icerocks2 + rotate: false + xy: 733, 113 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ignarock1 + rotate: false + xy: 529, 81 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ignarock2 + rotate: false + xy: 495, 65 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ignarock3 + rotate: false + xy: 563, 79 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +lead1 + rotate: false + xy: 597, 79 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +lead2 + rotate: false + xy: 631, 79 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +lead3 + rotate: false + xy: 665, 79 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +magmarock1 + rotate: false + xy: 699, 79 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +magmarock2 + rotate: false + xy: 733, 79 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +magmarock3 + rotate: false + xy: 529, 47 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor + rotate: false + xy: 563, 45 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged5 + rotate: false + xy: 563, 45 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-2 + rotate: false + xy: 597, 45 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-3 + rotate: false + xy: 631, 45 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-5 + rotate: false + xy: 665, 45 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged1 + rotate: false + xy: 699, 45 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged2 + rotate: false + xy: 733, 45 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged3 + rotate: false + xy: 829, 247 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged4 + rotate: false + xy: 863, 267 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged6 + rotate: false + xy: 863, 233 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +moss1 + rotate: false + xy: 785, 197 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +moss2 + rotate: false + xy: 777, 163 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +moss3 + rotate: false + xy: 819, 213 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal1 + rotate: false + xy: 199, 35 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal2 + rotate: false + xy: 777, 129 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal3 + rotate: false + xy: 767, 95 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper1 + rotate: false + xy: 767, 61 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper2 + rotate: false + xy: 819, 179 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper3 + rotate: false + xy: 811, 145 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead1 + rotate: false + xy: 853, 199 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead2 + rotate: false + xy: 853, 165 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead3 + rotate: false + xy: 233, 35 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap1 + rotate: false + xy: 767, 27 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap2 + rotate: false + xy: 811, 111 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap3 + rotate: false + xy: 845, 131 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium1 + rotate: false + xy: 801, 77 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium2 + rotate: false + xy: 801, 43 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium3 + rotate: false + xy: 845, 97 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium1 + rotate: false + xy: 835, 63 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium2 + rotate: false + xy: 835, 29 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium3 + rotate: false + xy: 801, 9 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pebbles1 + rotate: false + xy: 267, 43 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pebbles2 + rotate: false + xy: 301, 49 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pebbles3 + rotate: false + xy: 335, 49 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pine + rotate: false + xy: 1, 3 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +rock1 + rotate: false + xy: 199, 69 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +rock2 + rotate: false + xy: 489, 167 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +rocks-large + rotate: false + xy: 871, 335 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +rocks1 + rotate: false + xy: 369, 49 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +rocks2 + rotate: false + xy: 403, 49 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +salt + rotate: false + xy: 437, 49 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +saltrocks-large + rotate: false + xy: 67, 53 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +saltrocks1 + rotate: false + xy: 887, 199 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +saltrocks2 + rotate: false + xy: 887, 165 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand-edge + rotate: false + xy: 1, 413 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +sand-water + rotate: false + xy: 869, 29 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand-water-edge + rotate: false + xy: 1, 315 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +sand1 + rotate: false + xy: 879, 131 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand2 + rotate: false + xy: 879, 97 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand3 + rotate: false + xy: 869, 63 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sandrocks-large + rotate: false + xy: 357, 151 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +sandrocks1 + rotate: false + xy: 903, 63 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sandrocks2 + rotate: false + xy: 903, 29 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap1 + rotate: false + xy: 979, 333 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap2 + rotate: false + xy: 267, 9 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap3 + rotate: false + xy: 301, 15 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shale-boulder1 + rotate: false + xy: 437, 15 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shale-boulder2 + rotate: false + xy: 471, 31 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shale-edge + rotate: false + xy: 291, 413 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +shale1 + rotate: false + xy: 335, 15 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shale2 + rotate: false + xy: 369, 15 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shale3 + rotate: false + xy: 403, 15 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shalerocks-large + rotate: false + xy: 647, 249 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +shalerocks1 + rotate: false + xy: 897, 267 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shalerocks2 + rotate: false + xy: 897, 233 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shrubs-large + rotate: false + xy: 133, 53 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +shrubs1 + rotate: false + xy: 921, 199 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shrubs2 + rotate: false + xy: 921, 165 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snow-edge + rotate: false + xy: 1, 217 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +snow1 + rotate: false + xy: 913, 131 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snow2 + rotate: false + xy: 913, 97 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snow3 + rotate: false + xy: 937, 63 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snowrock1 + rotate: false + xy: 779, 265 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +snowrock2 + rotate: false + xy: 51, 3 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +snowrocks-large + rotate: false + xy: 423, 151 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +snowrocks1 + rotate: false + xy: 937, 29 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snowrocks2 + rotate: false + xy: 947, 131 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spore-cluster1 + rotate: false + xy: 981, 469 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +spore-cluster2 + rotate: false + xy: 937, 359 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +spore-cluster3 + rotate: false + xy: 249, 77 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +spore-moss-edge + rotate: false + xy: 291, 315 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +spore-moss1 + rotate: false + xy: 947, 97 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spore-moss2 + rotate: false + xy: 971, 63 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spore-moss3 + rotate: false + xy: 971, 29 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spore-pine + rotate: false + xy: 101, 3 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +sporerocks-large + rotate: false + xy: 713, 249 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +sporerocks1 + rotate: false + xy: 931, 291 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sporerocks2 + rotate: false + xy: 931, 257 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stone-edge + rotate: false + xy: 581, 413 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +stone1 + rotate: false + xy: 965, 291 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stone2 + rotate: false + xy: 965, 257 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stone3 + rotate: false + xy: 955, 223 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +tainted-water + rotate: false + xy: 955, 189 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +tainted-water-edge + rotate: false + xy: 1, 119 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +tar + rotate: false + xy: 989, 223 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +tar-edge + rotate: false + xy: 291, 217 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +thorium1 + rotate: false + xy: 989, 189 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thorium2 + rotate: false + xy: 981, 155 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thorium3 + rotate: false + xy: 981, 121 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium1 + rotate: false + xy: 185, 1 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium2 + rotate: false + xy: 219, 1 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium3 + rotate: false + xy: 505, 13 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +water + rotate: false + xy: 539, 11 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +water-edge + rotate: false + xy: 581, 315 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 diff --git a/core/assets/sprites/sprites_fallback.png b/core/assets/sprites/sprites_fallback.png new file mode 100644 index 0000000000..b65d1c8f03 Binary files /dev/null and b/core/assets/sprites/sprites_fallback.png differ diff --git a/core/assets/sprites/sprites_fallback2.png b/core/assets/sprites/sprites_fallback2.png new file mode 100644 index 0000000000..c6d404ee89 Binary files /dev/null and b/core/assets/sprites/sprites_fallback2.png differ diff --git a/core/assets/sprites/sprites_fallback3.png b/core/assets/sprites/sprites_fallback3.png new file mode 100644 index 0000000000..e58c3ca380 Binary files /dev/null and b/core/assets/sprites/sprites_fallback3.png differ diff --git a/core/assets/sprites/sprites_fallback4.png b/core/assets/sprites/sprites_fallback4.png new file mode 100644 index 0000000000..204586e1a7 Binary files /dev/null and b/core/assets/sprites/sprites_fallback4.png differ diff --git a/core/assets/sprites/sprites_fallback5.png b/core/assets/sprites/sprites_fallback5.png new file mode 100644 index 0000000000..7f51c22dba Binary files /dev/null and b/core/assets/sprites/sprites_fallback5.png differ diff --git a/core/assets/sprites/sprites_fallback6.png b/core/assets/sprites/sprites_fallback6.png new file mode 100644 index 0000000000..a4c52c6963 Binary files /dev/null and b/core/assets/sprites/sprites_fallback6.png differ diff --git a/core/assets/sprites/sprites_fallback7.png b/core/assets/sprites/sprites_fallback7.png new file mode 100644 index 0000000000..dbe205fa14 Binary files /dev/null and b/core/assets/sprites/sprites_fallback7.png differ diff --git a/core/assets/sprites/uiskin.json b/core/assets/sprites/uiskin.json index a88dd9e2de..7921494553 100644 --- a/core/assets/sprites/uiskin.json +++ b/core/assets/sprites/uiskin.json @@ -283,6 +283,7 @@ disabledFontColor: gray, selection: selection, background: underline, + invalidBackground: underline-red, cursor: cursor, messageFont: default-font, messageFontColor: gray diff --git a/core/src/io/anuke/mindustry/Mindustry.java b/core/src/io/anuke/mindustry/Mindustry.java index 44840a9aa4..195d2153f7 100644 --- a/core/src/io/anuke/mindustry/Mindustry.java +++ b/core/src/io/anuke/mindustry/Mindustry.java @@ -1,8 +1,6 @@ package io.anuke.mindustry; -import io.anuke.arc.ApplicationCore; -import io.anuke.arc.Core; -import io.anuke.arc.Events; +import io.anuke.arc.*; import io.anuke.arc.util.Log; import io.anuke.arc.util.Time; import io.anuke.mindustry.core.*; @@ -55,7 +53,7 @@ public class Mindustry extends ApplicationCore{ int fpsCap = Core.settings.getInt("fpscap", 125); if(fpsCap <= 120){ - long target = (1000 * 1000000)/fpsCap; //target in nanos + long target = (1000 * 1000000) / fpsCap; //target in nanos long elapsed = Time.timeSinceNanos(lastFrameTime); if(elapsed < target){ try{ diff --git a/core/src/io/anuke/mindustry/Vars.java b/core/src/io/anuke/mindustry/Vars.java index 1685852eb4..8b3a7d2de9 100644 --- a/core/src/io/anuke/mindustry/Vars.java +++ b/core/src/io/anuke/mindustry/Vars.java @@ -14,12 +14,8 @@ import io.anuke.mindustry.entities.effect.Puddle; import io.anuke.mindustry.entities.impl.EffectEntity; import io.anuke.mindustry.entities.traits.DrawTrait; import io.anuke.mindustry.entities.traits.SyncTrait; -import io.anuke.mindustry.entities.type.BaseUnit; -import io.anuke.mindustry.entities.type.Player; -import io.anuke.mindustry.entities.type.TileEntity; -import io.anuke.mindustry.game.GlobalData; -import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.game.Version; +import io.anuke.mindustry.entities.type.*; +import io.anuke.mindustry.game.*; import io.anuke.mindustry.gen.Serialization; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.world.blocks.defense.ForceProjector.ShieldEntity; @@ -30,93 +26,95 @@ import java.util.Locale; @SuppressWarnings("unchecked") public class Vars{ - /**IO buffer size.*/ + /** IO buffer size. */ public static final int bufferSize = 8192; - /**global charset*/ + /** global charset */ public static final Charset charset = Charset.forName("UTF-8"); - /**main application name, capitalized*/ + /** main application name, capitalized */ public static final String appName = "Mindustry"; - /**URL for discord invite.*/ + /** URL for itch.io donations. */ + 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*/ + /** URL for Github API for releases */ public static final String releasesURL = "https://api.github.com/repos/Anuken/Mindustry/releases"; - /**URL for Github API for contributors*/ + /** URL for Github API for contributors */ public static final String contributorsURL = "https://api.github.com/repos/Anuken/Mindustry/contributors"; - /**URL for sending crash reports to*/ + /** URL for sending crash reports to */ public static final String crashReportURL = "http://mindustry.us.to/report"; - /**maximum distance between mine and core that supports automatic transferring*/ + /** maximum distance between mine and core that supports automatic transferring */ public static final float mineTransferRange = 220f; - /**team of the player by default*/ + /** team of the player by default */ public static final Team defaultTeam = Team.blue; - /**team of the enemy in waves/sectors*/ + /** team of the enemy in waves/sectors */ public static final Team waveTeam = Team.red; - /**how many times longer a boss wave takes*/ + /** how many times longer a boss wave takes */ public static final float bossWaveMultiplier = 3f; - /**how many times longer a launch wave takes*/ + /** how many times longer a launch wave takes */ public static final float launchWaveMultiplier = 2f; - /**max chat message length*/ + /** max chat message length */ public static final int maxTextLength = 150; - /**max player name length in bytes*/ + /** max player name length in bytes */ public static final int maxNameLength = 40; - /**displayed item size when ingame, TODO remove.*/ + /** displayed item size when ingame, TODO remove. */ public static final float itemSize = 5f; - /**extra padding around the world; units outside this bound will begin to self-destruct.*/ + /** extra padding around the world; units outside this bound will begin to self-destruct. */ public static final float worldBounds = 100f; - /**units outside of this bound will simply die instantly*/ + /** units outside of this bound will simply die instantly */ public static final float finalWorldBounds = worldBounds + 500; - /**ticks spent out of bound until self destruct.*/ - public static final float boundsCountdown = 60*7; - /**for map generator dialog*/ + /** ticks spent out of bound until self destruct. */ + public static final float boundsCountdown = 60 * 7; + /** for map generator dialog */ public static boolean updateEditorOnChange = false; - /**size of tiles in units*/ + /** size of tiles in units */ public static final int tilesize = 8; - /**all choosable player colors in join/host dialog*/ + /** all choosable player colors in join/host dialog */ public static final Color[] playerColors = { - Color.valueOf("82759a"), - Color.valueOf("c0c1c5"), - Color.valueOf("fff0e7"), - Color.valueOf("7d2953"), - Color.valueOf("ff074e"), - Color.valueOf("ff072a"), - Color.valueOf("ff76a6"), - Color.valueOf("a95238"), - Color.valueOf("ffa108"), - Color.valueOf("feeb2c"), - Color.valueOf("ffcaa8"), - Color.valueOf("008551"), - Color.valueOf("00e339"), - Color.valueOf("423c7b"), - Color.valueOf("4b5ef1"), - Color.valueOf("2cabfe"), + Color.valueOf("82759a"), + Color.valueOf("c0c1c5"), + Color.valueOf("fff0e7"), + Color.valueOf("7d2953"), + Color.valueOf("ff074e"), + Color.valueOf("ff072a"), + Color.valueOf("ff76a6"), + Color.valueOf("a95238"), + Color.valueOf("ffa108"), + Color.valueOf("feeb2c"), + Color.valueOf("ffcaa8"), + Color.valueOf("008551"), + Color.valueOf("00e339"), + Color.valueOf("423c7b"), + Color.valueOf("4b5ef1"), + Color.valueOf("2cabfe"), }; - /**default server port*/ + /** default server port */ public static final int port = 6567; - /**if true, UI is not drawn*/ + /** 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*/ + /** if true, game is set up in mobile mode, even on desktop. used for debugging */ public static boolean testMobile; - /**whether the game is running on a mobile device*/ + /** whether the game is running on a mobile device */ public static boolean mobile; - /**whether the game is running on an iOS device*/ + /** whether the game is running on an iOS device */ public static boolean ios; - /**whether the game is running on an Android device*/ + /** whether the game is running on an Android device */ public static boolean android; - /**whether the game is running on a headless server*/ + /** whether the game is running on a headless server */ public static boolean headless; - /**application data directory, equivalent to {@link io.anuke.arc.Settings#getDataDirectory()}*/ + /** application data directory, equivalent to {@link io.anuke.arc.Settings#getDataDirectory()} */ public static FileHandle dataDirectory; - /**data subdirectory used for screenshots*/ + /** data subdirectory used for screenshots */ public static FileHandle screenshotDirectory; - /**data subdirectory used for custom mmaps*/ + /** data subdirectory used for custom mmaps */ public static FileHandle customMapDirectory; - /**data subdirectory used for saves*/ + /** data subdirectory used for saves */ public static FileHandle saveDirectory; - /**map file extension*/ + /** map file extension */ public static final String mapExtension = "mmap"; - /**save file extension*/ + /** save file extension */ public static final String saveExtension = "msav"; - /**list of all locales that can be switched to*/ + /** list of all locales that can be switched to */ public static Locale[] locales; public static ContentLoader content; @@ -141,8 +139,8 @@ public class Vars{ public static EntityGroup fireGroup; public static EntityGroup[] unitGroups; - /**all local players, currently only has one player. may be used for local co-op in the future*/ - public static Player[] players = {}; + /** all local players, currently only has one player. may be used for local co-op in the future */ + public static Player player; public static void init(){ Serialization.init(); diff --git a/core/src/io/anuke/mindustry/ai/BlockIndexer.java b/core/src/io/anuke/mindustry/ai/BlockIndexer.java index 761140642e..f3cba3a173 100644 --- a/core/src/io/anuke/mindustry/ai/BlockIndexer.java +++ b/core/src/io/anuke/mindustry/ai/BlockIndexer.java @@ -17,31 +17,33 @@ import io.anuke.mindustry.world.meta.BlockFlag; import static io.anuke.mindustry.Vars.*; -/**Class used for indexing special target blocks for AI.*/ +/** Class used for indexing special target blocks for AI. */ @SuppressWarnings("unchecked") public class BlockIndexer{ - /**Size of one ore quadrant.*/ + /** Size of one ore quadrant. */ private final static int oreQuadrantSize = 20; - /**Size of one structure quadrant.*/ + /** Size of one structure quadrant. */ private final static int structQuadrantSize = 12; - /**Set of all ores that are being scanned.*/ + /** Set of all ores that are being scanned. */ private final ObjectSet scanOres = ObjectSet.with(Item.getAllOres().toArray(Item.class)); private final ObjectSet itemSet = new ObjectSet<>(); - /**Stores all ore quadtrants on the map.*/ + /** Stores all ore quadtrants on the map. */ private ObjectMap> ores; - /**Tags all quadrants.*/ + /** Tags all quadrants. */ private Bits[] structQuadrants; - /**Stores all damaged tile entities by team.*/ + /** Stores all damaged tile entities by team. */ private ObjectSet[] damagedTiles = new ObjectSet[Team.all.length]; + /**All ores available on this map.*/ + private ObjectSet allOres = new ObjectSet<>(); - /**Maps teams to a map of flagged tiles by type.*/ + /** Maps teams to a map of flagged tiles by type. */ private ObjectSet[][] flagMap = new ObjectSet[Team.all.length][BlockFlag.all.length]; - /**Maps tile positions to their last known tile index data.*/ + /** Maps tile positions to their last known tile index data. */ private IntMap typeMap = new IntMap<>(); - /**Empty set used for returning.*/ + /** Empty set used for returning. */ private ObjectSet emptySet = new ObjectSet<>(); - /**Array used for returning and reusing.*/ + /** Array used for returning and reusing. */ private Array returnArray = new Array<>(); public BlockIndexer(){ @@ -67,12 +69,13 @@ public class BlockIndexer{ } typeMap.clear(); + allOres.clear(); ores = null; //create bitset for each team type that contains each quadrant structQuadrants = new Bits[Team.all.length]; for(int i = 0; i < Team.all.length; i++){ - structQuadrants[i] = new Bits(Mathf.ceil(world.width() / (float) structQuadrantSize) * Mathf.ceil(world.height() / (float) structQuadrantSize)); + structQuadrants[i] = new Bits(Mathf.ceil(world.width() / (float)structQuadrantSize) * Mathf.ceil(world.height() / (float)structQuadrantSize)); } for(int x = 0; x < world.width(); x++){ @@ -84,6 +87,8 @@ public class BlockIndexer{ if(tile.entity != null && tile.entity.damaged()){ notifyTileDamaged(tile.entity); } + + if(tile.drop() != null) allOres.add(tile.drop()); } } @@ -101,7 +106,12 @@ public class BlockIndexer{ return flagMap[team.ordinal()]; } - /**Returns all damaged tiles by team.*/ + /** @return whether this item is present on this map.*/ + public boolean hasOre(Item item){ + return allOres.contains(item); + } + + /** Returns all damaged tiles by team. */ public ObjectSet getDamaged(Team team){ returnArray.clear(); @@ -123,12 +133,12 @@ public class BlockIndexer{ return set; } - /**Get all allied blocks with a flag.*/ + /** Get all allied blocks with a flag. */ public ObjectSet getAllied(Team team, BlockFlag type){ return flagMap[team.ordinal()][type.ordinal()]; } - /**Get all enemy blocks with a flag.*/ + /** Get all enemy blocks with a flag. */ public Array getEnemy(Team team, BlockFlag type){ returnArray.clear(); for(Team enemy : state.teams.enemiesOf(team)){ @@ -154,8 +164,8 @@ 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 / 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++){ if(!getQuad(team, rx, ry)) continue; @@ -167,7 +177,8 @@ public class BlockIndexer{ other = other.target(); - if(other.entity == null || other.getTeam() != team || !pred.test(other) || !other.block().targetable) continue; + if(other.entity == null || other.getTeam() != team || !pred.test(other) || !other.block().targetable) + continue; TileEntity e = other.entity; @@ -194,7 +205,7 @@ public class BlockIndexer{ return ores.get(item, emptySet); } - /**Find the closest ore block relative to a position.*/ + /** 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)); @@ -214,7 +225,7 @@ public class BlockIndexer{ private void process(Tile tile){ if(tile.block().flags.size() > 0 && - tile.getTeam() != Team.none){ + tile.getTeam() != Team.none){ ObjectSet[] map = getFlagged(tile.getTeam()); for(BlockFlag flag : tile.block().flags){ @@ -235,13 +246,13 @@ public class BlockIndexer{ 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)); + Mathf.clamp(quadrantY * oreQuadrantSize + oreQuadrantSize / 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++){ Tile result = world.tile(x, y); - if( result == null || result.drop() == null || !scanOres.contains(result.drop())) continue; + if(result == null || result.drop() == null || !scanOres.contains(result.drop())) continue; itemSet.add(result.drop()); } @@ -261,6 +272,8 @@ public class BlockIndexer{ } private void updateQuadrant(Tile tile){ + if(structQuadrants == null) return; + //this quadrant is now 'dirty', re-scan the whole thing int quadrantX = tile.x / structQuadrantSize; int quadrantY = tile.y / structQuadrantSize; @@ -292,16 +305,16 @@ public class BlockIndexer{ } private boolean getQuad(Team team, int quadrantX, int quadrantY){ - int index = quadrantX + quadrantY * Mathf.ceil(world.width() / (float) structQuadrantSize); + int index = quadrantX + quadrantY * Mathf.ceil(world.width() / (float)structQuadrantSize); return structQuadrants[team.ordinal()].get(index); } private int quadWidth(){ - return Mathf.ceil(world.width() / (float) structQuadrantSize); + return Mathf.ceil(world.width() / (float)structQuadrantSize); } private int quadHeight(){ - return Mathf.ceil(world.height() / (float) structQuadrantSize); + return Mathf.ceil(world.height() / (float)structQuadrantSize); } private void scanOres(){ @@ -322,9 +335,9 @@ public class BlockIndexer{ //add position of quadrant to list when an ore is found 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))); + //make sure to clamp quadrant middle position, since it might go off bounds + Mathf.clamp(qx * oreQuadrantSize + oreQuadrantSize / 2, 0, world.width() - 1), + Mathf.clamp(qy * oreQuadrantSize + oreQuadrantSize / 2, 0, world.height() - 1))); } } } diff --git a/core/src/io/anuke/mindustry/ai/Pathfinder.java b/core/src/io/anuke/mindustry/ai/Pathfinder.java index bd162140e5..7710c48588 100644 --- a/core/src/io/anuke/mindustry/ai/Pathfinder.java +++ b/core/src/io/anuke/mindustry/ai/Pathfinder.java @@ -66,8 +66,8 @@ public class Pathfinder{ if(other == null) continue; if(values[dx][dy] < value && (target == null || values[dx][dy] < tl) && - !other.solid() && - !(point.x != 0 && point.y != 0 && (world.solid(tile.x + point.x, tile.y) || world.solid(tile.x, tile.y + point.y)))){ //diagonal corner trap + !other.solid() && + !(point.x != 0 && point.y != 0 && (world.solid(tile.x + point.x, tile.y) || world.solid(tile.x, tile.y + point.y)))){ //diagonal corner trap target = other; tl = values[dx][dy]; } @@ -86,11 +86,13 @@ public class Pathfinder{ return (!tile.solid()) || (tile.breakable() && (tile.target().getTeam() != team)); } - /**Clears the frontier, increments the search and sets up all flow sources. - * This only occurs for active teams.*/ + /** + * Clears the frontier, increments the search and sets up all flow sources. + * This only occurs for active teams. + */ private void update(Tile tile, Team team){ //make sure team exists - if(paths[team.ordinal()] != null && paths[team.ordinal()].weights != null){ + if(paths != null && paths[team.ordinal()] != null && paths[team.ordinal()].weights != null){ PathData path = paths[team.ordinal()]; //impassable tiles have a weight of float.max @@ -126,7 +128,7 @@ public class Pathfinder{ Tile tile = world.tile(x, y); if(state.teams.areEnemies(tile.getTeam(), team) - && tile.block().flags.contains(BlockFlag.target)){ + && tile.block().flags.contains(BlockFlag.target)){ path.frontier.addFirst(tile.pos()); path.weights[x][y] = 0; path.searches[x][y] = (short)path.search; @@ -162,7 +164,7 @@ public class Pathfinder{ Tile other = world.tile(dx, dy); if(other != null && (path.weights[dx][dy] > cost + other.cost || path.searches[dx][dy] < path.search) - && passable(other, team)){ + && passable(other, team)){ if(other.cost < 0) throw new IllegalArgumentException("Tile cost cannot be negative! " + other); path.frontier.addFirst(Pos.get(dx, dy)); path.weights[dx][dy] = cost + other.cost; diff --git a/core/src/io/anuke/mindustry/ai/WaveSpawner.java b/core/src/io/anuke/mindustry/ai/WaveSpawner.java index fca6df51a7..e2fce15b7c 100644 --- a/core/src/io/anuke/mindustry/ai/WaveSpawner.java +++ b/core/src/io/anuke/mindustry/ai/WaveSpawner.java @@ -5,8 +5,7 @@ import io.anuke.arc.collection.Array; import io.anuke.arc.collection.IntArray; import io.anuke.arc.math.Angles; 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.Blocks; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.entities.Damage; @@ -14,11 +13,10 @@ import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.type.BaseUnit; import io.anuke.mindustry.game.EventType.WorldLoadEvent; import io.anuke.mindustry.game.SpawnGroup; +import io.anuke.mindustry.net.Net; import io.anuke.mindustry.world.Pos; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.*; @@ -52,9 +50,13 @@ public class WaveSpawner{ } } - /**@return true if the player is near a ground spawn point.*/ + public int countSpawns(){ + return groundSpawns.size; + } + + /** @return true if the player is near a ground spawn point. */ public boolean playerNear(){ - return groundSpawns.count(g -> Mathf.dst(g.x * tilesize, g.y * tilesize, players[0].x, players[0].y) < maxShockwaveDst) > 0; + return groundSpawns.count(g -> Mathf.dst(g.x * tilesize, g.y * tilesize, player.x, player.y) < maxShockwaveDst) > 0; } public void spawnEnemies(){ @@ -84,7 +86,7 @@ public class WaveSpawner{ for(GroundSpawn spawn : groundSpawns){ spawnX = spawn.x * tilesize; spawnY = spawn.y * tilesize; - spread = tilesize*2; + spread = tilesize * 2; for(int i = 0; i < spawned; i++){ Tmp.v1.rnd(spread); @@ -92,11 +94,11 @@ 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), () -> shockwave(unit)); } Time.run(20f, () -> Effects.effect(Fx.spawnShockwave, spawn.x * tilesize, spawn.y * tilesize)); //would be interesting to see player structures survive this without hacks - Time.run(40f, () -> Damage.damage(waveTeam, spawn.x * tilesize, spawn.y * tilesize, shockwaveBase + Mathf.random(shockwaveRand), 99999999f)); + Time.run(40f, () -> Damage.damage(waveTeam, spawn.x * tilesize, spawn.y * tilesize, shockwaveBase + Mathf.random(shockwaveRand), 99999999f, true)); } } } @@ -105,7 +107,7 @@ public class WaveSpawner{ } public boolean isSpawning(){ - return spawning; + return spawning && !Net.client(); } private void reset(){ @@ -115,6 +117,7 @@ public class WaveSpawner{ for(int x = 0; x < world.width(); x++){ for(int y = 0; y < world.height(); y++){ + if(world.tile(x, y).block() == Blocks.spawn){ addSpawns(x, y); @@ -139,7 +142,7 @@ public class WaveSpawner{ groundSpawns.add(spawn); FlyerSpawn fspawn = new FlyerSpawn(); - fspawn.angle = Angles.angle(world.width()/2f, world.height()/2f, x, y); + fspawn.angle = Angles.angle(world.width() / 2f, world.height() / 2f, x, y); flySpawns.add(fspawn); } diff --git a/core/src/io/anuke/mindustry/content/Blocks.java b/core/src/io/anuke/mindustry/content/Blocks.java index 62fee69f2c..708de83446 100644 --- a/core/src/io/anuke/mindustry/content/Blocks.java +++ b/core/src/io/anuke/mindustry/content/Blocks.java @@ -2,12 +2,12 @@ package io.anuke.mindustry.content; 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.mindustry.Vars; import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.graphics.CacheLayer; -import io.anuke.mindustry.type.Category; -import io.anuke.mindustry.type.ItemStack; +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.blocks.*; @@ -17,16 +17,11 @@ import io.anuke.mindustry.world.blocks.distribution.*; import io.anuke.mindustry.world.blocks.power.*; import io.anuke.mindustry.world.blocks.production.*; import io.anuke.mindustry.world.blocks.sandbox.*; -import io.anuke.mindustry.world.blocks.storage.CoreBlock; -import io.anuke.mindustry.world.blocks.storage.LaunchPad; -import io.anuke.mindustry.world.blocks.storage.Unloader; -import io.anuke.mindustry.world.blocks.storage.Vault; -import io.anuke.mindustry.world.blocks.units.MechPad; -import io.anuke.mindustry.world.blocks.units.RepairPoint; -import io.anuke.mindustry.world.blocks.units.UnitFactory; -import io.anuke.mindustry.world.consumers.ConsumeItemFilter; +import io.anuke.mindustry.world.blocks.storage.*; +import io.anuke.mindustry.world.blocks.units.*; import io.anuke.mindustry.world.consumers.ConsumeLiquidFilter; import io.anuke.mindustry.world.meta.Attribute; +import io.anuke.mindustry.world.modules.LiquidModule; import static io.anuke.mindustry.Vars.state; import static io.anuke.mindustry.Vars.world; @@ -35,17 +30,20 @@ public class Blocks implements ContentList{ public static Block //environment - air, part, spawn, deepwater, water, tar, stone, craters, charr, sand, ice, snow, - holostone, rocks, sporerocks, icerocks, cliffs, sporePine, pine, whiteTree, whiteTreeDead, sporeCluster, - iceSnow, sandWater, duneRocks, sandRocks, moss, sporeMoss, shale, shaleRocks, shaleBoulder, grass, salt, - metalFloor, metalFloorDamaged, metalFloor2, metalFloor3, metalFloor5, ignarock, magmarock, hotrock, snowrocks, rock, snowrock, + air, part, 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, + metalFloor, metalFloorDamaged, metalFloor2, metalFloor3, metalFloor5, ignarock, magmarock, hotrock, snowrocks, rock, snowrock, saltRocks, + creeptree, + darkPanel1, darkPanel2, darkPanel3, darkPanel4, darkPanel5, darkPanel6, darkMetal, + pebbles, //ores oreCopper, oreLead, oreScrap, oreCoal, oreTitanium, oreThorium, //crafting siliconSmelter, kiln, graphitePress, plastaniumCompressor, multiPress, phaseWeaver, surgeSmelter, pyratiteMixer, blastMixer, cryofluidMixer, - melter, separator, sporePress, pulverizer, incinerator, + melter, separator, sporePress, pulverizer, incinerator, coalCentrifuge, //sandbox powerVoid, powerSource, itemSource, liquidSource, itemVoid, @@ -53,7 +51,7 @@ public class Blocks implements ContentList{ //defense scrapWall, scrapWallLarge, scrapWallHuge, scrapWallGigantic, thruster, //ok, these names are getting ridiculous, but at least I don't have humongous walls yet copperWall, copperWallLarge, titaniumWall, titaniumWallLarge, thoriumWall, thoriumWallLarge, door, doorLarge, - phaseWall, phaseWallLarge, surgeWall, surgeWallLarge, mendProjector, overdriveProjector, forceProjector, shockMine, + phaseWall, phaseWallLarge, surgeWall, surgeWallLarge, mender, mendProjector, overdriveProjector, forceProjector, shockMine, //transport conveyor, titaniumConveyor, distributor, junction, itemBridge, phaseConveyor, sorter, router, overflowGate, massDriver, @@ -69,10 +67,10 @@ public class Blocks implements ContentList{ mechanicalDrill, pneumaticDrill, laserDrill, blastDrill, waterExtractor, oilExtractor, cultivator, //storage - coreShard, coreFoundation, coreNucleus, vault, container, unloader, launchPad, + coreShard, coreFoundation, coreNucleus, vault, container, unloader, launchPad, launchPadLarge, //turrets - duo, scatter, hail, arc, wave, lancer, swarmer, salvo, fuse, ripple, cyclone, spectre, meltdown, + duo, scatter, scorch, hail, arc, wave, lancer, swarmer, salvo, fuse, ripple, cyclone, spectre, meltdown, //units spiritFactory, phantomFactory, wraithFactory, ghoulFactory, revenantFactory, daggerFactory, crawlerFactory, titanFactory, @@ -85,14 +83,25 @@ public class Blocks implements ContentList{ public void load(){ //region environment - air = new Floor("air"){{ + air = new Floor("air"){ + { alwaysReplace = true; + hasShadow = false; + } + + public void draw(Tile tile){ + } + + public void load(){ + } + + public void init(){ + } + + public boolean isHidden(){ + return true; } - public void draw(Tile tile){} - public void load(){} - public void init(){} - public boolean isHidden(){ return true; } public TextureRegion[] variantRegions(){ if(variantRegions == null){ variantRegions = new TextureRegion[]{Core.atlas.find("clear")}; @@ -104,7 +113,8 @@ public class Blocks implements ContentList{ part = new BlockPart(); spawn = new Block("spawn"){ - public void drawShadow(Tile tile){} + public void drawShadow(Tile tile){ + } }; //Registers build blocks from size 1-6 @@ -114,7 +124,6 @@ public class Blocks implements ContentList{ } deepwater = new Floor("deepwater"){{ - liquidColor = Color.valueOf("4d5ca4"); speedMultiplier = 0.2f; variants = 0; liquidDrop = Liquids.water; @@ -126,7 +135,6 @@ public class Blocks implements ContentList{ }}; water = new Floor("water"){{ - liquidColor = Color.valueOf("596ab8"); speedMultiplier = 0.5f; variants = 0; status = StatusEffects.wet; @@ -136,9 +144,49 @@ public class Blocks implements ContentList{ cacheLayer = CacheLayer.water; }}; + taintedWater = new Floor("tainted-water"){{ + speedMultiplier = 0.17f; + variants = 0; + status = StatusEffects.wet; + statusDuration = 140f; + drownTime = 120f; + liquidDrop = Liquids.water; + isLiquid = true; + cacheLayer = CacheLayer.water; + }}; + + darksandTaintedWater = new Floor("darksand-tainted-water"){{ + speedMultiplier = 0.75f; + variants = 0; + status = StatusEffects.wet; + statusDuration = 60f; + liquidDrop = Liquids.water; + isLiquid = true; + cacheLayer = CacheLayer.water; + }}; + + sandWater = new Floor("sand-water"){{ + speedMultiplier = 0.8f; + variants = 0; + status = StatusEffects.wet; + statusDuration = 50f; + liquidDrop = Liquids.water; + isLiquid = true; + cacheLayer = CacheLayer.water; + }}; + + darksandWater = new Floor("darksand-water"){{ + speedMultiplier = 0.8f; + variants = 0; + status = StatusEffects.wet; + statusDuration = 50f; + liquidDrop = Liquids.water; + isLiquid = true; + cacheLayer = CacheLayer.water; + }}; + tar = new Floor("tar"){{ drownTime = 150f; - liquidColor = Color.valueOf("292929"); status = StatusEffects.tarred; statusDuration = 240f; speedMultiplier = 0.19f; @@ -153,7 +201,7 @@ public class Blocks implements ContentList{ }}; craters = new Floor("craters"){{ - variants = 6; + variants = 3; blendGroup = stone; }}; @@ -161,15 +209,19 @@ public class Blocks implements ContentList{ blendGroup = stone; }}; - sandWater = new Floor("sand-water"){{ - liquidColor = Color.valueOf("596ab8"); - speedMultiplier = 0.8f; - variants = 0; - status = StatusEffects.wet; - statusDuration = 50f; - liquidDrop = Liquids.water; - isLiquid = true; - cacheLayer = CacheLayer.water; + ignarock = new Floor("ignarock"){{ + + }}; + + hotrock = new Floor("hotrock"){{ + attributes.set(Attribute.heat, 0.5f); + blendGroup = ignarock; + }}; + + magmarock = new Floor("magmarock"){{ + attributes.set(Attribute.heat, 0.75f); + updateEffect = Fx.magmasmoke; + blendGroup = ignarock; }}; sand = new Floor("sand"){{ @@ -177,8 +229,13 @@ public class Blocks implements ContentList{ playerUnmineable = true; }}; + darksand = new Floor("darksand"){{ + itemDrop = Items.sand; + playerUnmineable = true; + }}; + holostone = new Floor("holostone"){{ - edgeStyle = "blocky"; + }}; grass = new Floor("grass"){{ @@ -198,6 +255,7 @@ public class Blocks implements ContentList{ dragMultiplier = 1f; speedMultiplier = 1f; attributes.set(Attribute.water, 0.4f); + edgeStyle = "blocky"; }}; iceSnow = new Floor("ice-snow"){{ @@ -243,6 +301,9 @@ public class Blocks implements ContentList{ variants = 2; }}; + saltRocks = new StaticWall("saltrocks"){{ + }}; + sporePine = new StaticWall("spore-pine"){{ variants = 0; }}; @@ -251,12 +312,20 @@ public class Blocks implements ContentList{ variants = 0; }}; + shrubs = new StaticWall("shrubs"){{ + + }}; + whiteTreeDead = new TreeBlock("white-tree-dead"){{ }}; whiteTree = new TreeBlock("white-tree"){{ }}; + creeptree = new TreeBlock("creeptree"){{ + }}; + + sporeCluster = new Rock("spore-cluster"){{ variants = 3; }}; @@ -305,20 +374,17 @@ public class Blocks implements ContentList{ variants = 0; }}; - ignarock = new Floor("ignarock"){{ + darkPanel1 = new Floor("dark-panel-1"){{ variants = 0; }}; + darkPanel2 = new Floor("dark-panel-2"){{ variants = 0; }}; + darkPanel3 = new Floor("dark-panel-3"){{ variants = 0; }}; + darkPanel4 = new Floor("dark-panel-4"){{ variants = 0; }}; + darkPanel5 = new Floor("dark-panel-5"){{ variants = 0; }}; + darkPanel6 = new Floor("dark-panel-6"){{ variants = 0; }}; + darkMetal = new StaticWall("dark-metal"){{ }}; - hotrock = new Floor("hotrock"){{ - attributes.set(Attribute.heat, 0.5f); - blendGroup = ignarock; - }}; - - magmarock = new Floor("magmarock"){{ - attributes.set(Attribute.heat, 0.75f); - updateEffect = Fx.magmasmoke; - blendGroup = ignarock; - }}; + pebbles = new OverlayFloor("pebbles"); //endregion //region ore @@ -337,7 +403,7 @@ public class Blocks implements ContentList{ requirements(Category.crafting, ItemStack.with(Items.copper, 150, Items.lead, 60)); craftEffect = Fx.pulverizeMedium; - output = Items.graphite; + outputItem = new ItemStack(Items.graphite, 1); craftTime = 90f; size = 2; hasItems = true; @@ -349,7 +415,7 @@ public class Blocks implements ContentList{ requirements(Category.crafting, ItemStack.with(Items.titanium, 200, Items.silicon, 50, Items.lead, 200, Items.graphite, 100)); craftEffect = Fx.pulverizeMedium; - output = Items.graphite; + outputItem = new ItemStack(Items.graphite, 2); craftTime = 30f; size = 3; hasItems = true; @@ -357,16 +423,17 @@ public class Blocks implements ContentList{ hasPower = true; consumes.power(2f); - consumes.item(Items.coal, 2); + consumes.item(Items.coal, 4); consumes.liquid(Liquids.water, 0.1f); }}; - siliconSmelter = new PowerSmelter("silicon-smelter"){{ + siliconSmelter = new GenericSmelter("silicon-smelter"){{ requirements(Category.crafting, ItemStack.with(Items.copper, 60, Items.lead, 50)); craftEffect = Fx.smeltsmoke; - output = Items.silicon; + outputItem = new ItemStack(Items.silicon, 1); craftTime = 40f; size = 2; + hasPower = true; hasLiquids = false; flameColor = Color.valueOf("ffef99"); @@ -374,10 +441,10 @@ public class Blocks implements ContentList{ consumes.power(0.50f); }}; - kiln = new PowerSmelter("kiln"){{ + kiln = new GenericSmelter("kiln"){{ requirements(Category.crafting, ItemStack.with(Items.copper, 120, Items.graphite, 60, Items.lead, 60)); craftEffect = Fx.smeltsmoke; - output = Items.metaglass; + outputItem = new ItemStack(Items.metaglass, 1); craftTime = 30f; size = 2; hasPower = hasItems = true; @@ -387,12 +454,12 @@ public class Blocks implements ContentList{ consumes.power(0.60f); }}; - plastaniumCompressor = new PlastaniumCompressor("plastanium-compressor"){{ + plastaniumCompressor = new GenericCrafter("plastanium-compressor"){{ requirements(Category.crafting, ItemStack.with(Items.silicon, 160, Items.lead, 230, Items.graphite, 120, Items.titanium, 160)); hasItems = true; liquidCapacity = 60f; craftTime = 60f; - output = Items.plastanium; + outputItem = new ItemStack(Items.plastanium, 1); size = 2; health = 320; hasPower = hasLiquids = true; @@ -402,59 +469,135 @@ public class Blocks implements ContentList{ consumes.liquid(Liquids.oil, 0.25f); consumes.power(3f); consumes.item(Items.titanium, 2); + + int topRegion = reg("-top"); + + drawer = tile -> { + Draw.rect(region, tile.drawx(), tile.drawy()); + + GenericCrafterEntity entity = tile.entity(); + + Draw.alpha(Mathf.absin(entity.totalProgress, 3f, 0.9f) * entity.warmup); + Draw.rect(reg(topRegion), tile.drawx(), tile.drawy()); + Draw.reset(); + }; }}; - phaseWeaver = new PhaseWeaver("phase-weaver"){{ + phaseWeaver = new GenericCrafter("phase-weaver"){{ requirements(Category.crafting, ItemStack.with(Items.silicon, 260, Items.lead, 240, Items.thorium, 150)); craftEffect = Fx.smeltsmoke; - output = Items.phasefabric; + outputItem = new ItemStack(Items.phasefabric, 1); craftTime = 120f; size = 2; + hasPower = true; consumes.items(new ItemStack(Items.thorium, 4), new ItemStack(Items.sand, 10)); consumes.power(5f); + + int bottomRegion = reg("-bottom"), weaveRegion = reg("-weave"); + + drawIcons = () -> new TextureRegion[]{Core.atlas.find(name + "-bottom"), Core.atlas.find(name)}; + + drawer = tile -> { + GenericCrafterEntity entity = tile.entity(); + + Draw.rect(reg(bottomRegion), tile.drawx(), tile.drawy()); + + float progress = 0.5f; + + Shaders.build.region = reg(weaveRegion); + Shaders.build.progress = progress; + Shaders.build.color.set(Pal.accent); + Shaders.build.color.a = entity.warmup; + Shaders.build.time = -entity.totalProgress / 10f; + + Draw.shader(Shaders.build, false); + Shaders.build.apply(); + Draw.rect(reg(weaveRegion), tile.drawx(), tile.drawy(), entity.totalProgress); + Draw.shader(); + + Draw.color(Pal.accent); + Draw.alpha(entity.warmup); + + Lines.lineAngleCenter( + tile.drawx() + Mathf.sin(entity.totalProgress, 6f, Vars.tilesize / 3f * size), + tile.drawy(), + 90, + size * Vars.tilesize / 2f); + + Draw.reset(); + + Draw.rect(region, tile.drawx(), tile.drawy()); + }; }}; - surgeSmelter = new PowerSmelter("alloy-smelter"){{ + surgeSmelter = new GenericSmelter("alloy-smelter"){{ requirements(Category.crafting, ItemStack.with(Items.silicon, 160, Items.lead, 160, Items.thorium, 140)); craftEffect = Fx.smeltsmoke; - output = Items.surgealloy; + outputItem = new ItemStack(Items.surgealloy, 1); craftTime = 75f; size = 3; + hasPower = true; consumes.power(4f); consumes.items(new ItemStack(Items.titanium, 2), new ItemStack(Items.lead, 4), new ItemStack(Items.silicon, 3), new ItemStack(Items.copper, 3)); }}; - cryofluidMixer = new LiquidMixer("cryofluidmixer"){{ + cryofluidMixer = new LiquidConverter("cryofluidmixer"){{ requirements(Category.crafting, ItemStack.with(Items.lead, 130, Items.silicon, 80, Items.thorium, 90)); - outputLiquid = Liquids.cryofluid; - liquidPerItem = 50f; + outputLiquid = new LiquidStack(Liquids.cryofluid, 0.1f); + craftTime = 60f; size = 2; hasPower = true; + hasItems = true; + hasLiquids = true; + rotate = false; + solid = true; + outputsLiquid = true; consumes.power(1f); consumes.item(Items.titanium); - consumes.liquid(Liquids.water, 0.3f); + consumes.liquid(Liquids.water, 0.1f); + + int liquidRegion = reg("-liquid"), topRegion = reg("-top"), bottomRegion = reg("-bottom"); + + drawIcons = () -> new TextureRegion[]{Core.atlas.find(name + "-bottom"), Core.atlas.find(name + "-top")}; + + drawer = tile -> { + LiquidModule mod = tile.entity.liquids; + + int rotation = rotate ? tile.getRotation() * 90 : 0; + + Draw.rect(reg(bottomRegion), tile.drawx(), tile.drawy(), rotation); + + if(mod.total() > 0.001f){ + Draw.color(outputLiquid.liquid.color); + Draw.alpha(mod.get(outputLiquid.liquid) / liquidCapacity); + Draw.rect(reg(liquidRegion), tile.drawx(), tile.drawy(), rotation); + Draw.color(); + } + + Draw.rect(reg(topRegion), tile.drawx(), tile.drawy(), rotation); + }; }}; blastMixer = new GenericCrafter("blast-mixer"){{ requirements(Category.crafting, ItemStack.with(Items.lead, 60, Items.titanium, 40)); hasItems = true; hasPower = true; - output = Items.blastCompound; + outputItem = new ItemStack(Items.blastCompound, 1); size = 2; consumes.items(new ItemStack(Items.pyratite, 1), new ItemStack(Items.sporePod, 1)); consumes.power(0.40f); }}; - pyratiteMixer = new PowerSmelter("pyratite-mixer"){{ + pyratiteMixer = new GenericSmelter("pyratite-mixer"){{ requirements(Category.crafting, ItemStack.with(Items.copper, 100, Items.lead, 50)); flameColor = Color.CLEAR; hasItems = true; hasPower = true; - output = Items.pyratite; + outputItem = new ItemStack(Items.pyratite, 1); size = 2; @@ -462,11 +605,10 @@ public class Blocks implements ContentList{ consumes.items(new ItemStack(Items.coal, 1), new ItemStack(Items.lead, 2), new ItemStack(Items.sand, 2)); }}; - melter = new PowerCrafter("melter"){{ + melter = new GenericCrafter("melter"){{ requirements(Category.crafting, ItemStack.with(Items.copper, 60, Items.lead, 70, Items.graphite, 90)); health = 200; - outputLiquid = Liquids.slag; - outputLiquidAmount = 2f; + outputLiquid = new LiquidStack(Liquids.slag, 2f); craftTime = 10f; hasLiquids = hasPower = true; @@ -483,7 +625,7 @@ public class Blocks implements ContentList{ Items.titanium, 2 ); hasPower = true; - filterTime = 35f; + craftTime = 35f; spinnerLength = 1.5f; spinnerRadius = 3.5f; spinnerThickness = 1.5f; @@ -494,36 +636,45 @@ public class Blocks implements ContentList{ consumes.liquid(Liquids.slag, 0.07f); }}; - cultivator = new Cultivator("cultivator"){{ - requirements(Category.crafting, ItemStack.with(Items.copper, 20, Items.lead, 50, Items.silicon, 20)); - output = Items.sporePod; - craftTime = 200; - size = 2; - hasLiquids = true; - hasPower = true; - hasItems = true; - - consumes.power(0.80f); - consumes.liquid(Liquids.water, 0.15f); - }}; - - sporePress = new Compressor("spore-press"){{ + sporePress = new GenericCrafter("spore-press"){{ requirements(Category.crafting, ItemStack.with(Items.lead, 70, Items.silicon, 60)); liquidCapacity = 60f; craftTime = 20f; - outputLiquid = Liquids.oil; - outputLiquidAmount = 2.5f; + outputLiquid = new LiquidStack(Liquids.oil, 6f); size = 2; health = 320; hasLiquids = true; + hasPower = true; + craftEffect = Fx.none; consumes.item(Items.sporePod, 1); consumes.power(0.60f); + + int[] frameRegions = new int[3]; + for(int i = 0; i < 3; i++){ + frameRegions[i] = reg("-frame" + i); + } + + int liquidRegion = reg("-liquid"); + int topRegion = reg("-top"); + + drawIcons = () -> new TextureRegion[]{Core.atlas.find(name), Core.atlas.find(name + "-top")}; + + drawer = tile -> { + GenericCrafterEntity entity = tile.entity(); + + Draw.rect(region, tile.drawx(), tile.drawy()); + Draw.rect(reg(frameRegions[(int)Mathf.absin(entity.totalProgress, 5f, 2.999f)]), tile.drawx(), tile.drawy()); + Draw.color(Color.CLEAR, tile.entity.liquids.current().color, tile.entity.liquids.total() / liquidCapacity); + Draw.rect(reg(liquidRegion), tile.drawx(), tile.drawy()); + Draw.color(); + Draw.rect(reg(topRegion), tile.drawx(), tile.drawy()); + }; }}; - pulverizer = new Pulverizer("pulverizer"){{ + pulverizer = new GenericCrafter("pulverizer"){{ requirements(Category.crafting, ItemStack.with(Items.copper, 60, Items.lead, 50)); - output = Items.sand; + outputItem = new ItemStack(Items.sand, 1); craftEffect = Fx.pulverize; craftTime = 40f; updateEffect = Fx.pulverizeSmall; @@ -531,6 +682,29 @@ public class Blocks implements ContentList{ consumes.item(Items.scrap, 1); consumes.power(0.50f); + + int rotatorRegion = reg("-rotator"); + + drawIcons = () -> new TextureRegion[]{Core.atlas.find(name), Core.atlas.find(name + "-rotator")}; + + drawer = tile -> { + GenericCrafterEntity entity = tile.entity(); + + Draw.rect(region, tile.drawx(), tile.drawy()); + Draw.rect(reg(rotatorRegion), tile.drawx(), tile.drawy(), entity.totalProgress * 2f); + }; + }}; + + coalCentrifuge = new GenericCrafter("coal-centrifuge"){{ + requirements(Category.crafting, ItemStack.with(Items.titanium, 40, Items.graphite, 80, Items.lead, 60)); + craftEffect = Fx.smeltsmoke; + outputItem = new ItemStack(Items.coal, 1); + craftTime = 30f; + size = 2; + hasPower = hasItems = hasLiquids = true; + + consumes.liquid(Liquids.oil, 0.09f); + consumes.power(0.5f); }}; incinerator = new Incinerator("incinerator"){{ @@ -566,7 +740,7 @@ public class Blocks implements ContentList{ //endregion //region defense - int wallHealthMultiplier = 3; + int wallHealthMultiplier = 4; scrapWall = new Wall("scrap-wall"){{ health = 60 * wallHealthMultiplier; @@ -663,28 +837,46 @@ public class Blocks implements ContentList{ size = 2; }}; + mender = new MendProjector("mender"){{ + requirements(Category.effect, ItemStack.with(Items.lead, 60, Items.copper, 50)); + consumes.power(0.3f); + size = 1; + reload = 200f; + range = 40f; + healPercent = 4f; + phaseBoost = 4f; + phaseRangeBoost = 20f; + health = 80; + consumes.item(Items.silicon).boost(); + }}; + mendProjector = new MendProjector("mend-projector"){{ - requirements(Category.effect, ItemStack.with(Items.lead, 200, Items.titanium, 50, Items.silicon, 180)); - consumes.power(2f); + requirements(Category.effect, ItemStack.with(Items.lead, 200, Items.titanium, 50, Items.silicon, 80)); + consumes.power(1.5f); size = 2; - consumes.item(Items.phasefabric).optional(true); + reload = 250f; + range = 85f; + healPercent = 14f; + health = 80 * size * size; + consumes.item(Items.phasefabric).boost(); }}; overdriveProjector = new OverdriveProjector("overdrive-projector"){{ requirements(Category.effect, ItemStack.with(Items.lead, 200, Items.titanium, 150, Items.silicon, 150, Items.plastanium, 60)); consumes.power(3.50f); size = 2; - consumes.item(Items.phasefabric).optional(true).boost(true); + consumes.item(Items.phasefabric).boost(); }}; forceProjector = new ForceProjector("force-projector"){{ requirements(Category.effect, ItemStack.with(Items.lead, 200, Items.titanium, 150, Items.silicon, 250)); size = 3; - consumes.item(Items.phasefabric).optional(true).boost(true); + consumes.item(Items.phasefabric).boost(); }}; shockMine = new ShockMine("shock-mine"){{ requirements(Category.effect, ItemStack.with(Items.lead, 50, Items.silicon, 25)); + hasShadow = false; health = 40; damage = 11; tileDamage = 7f; @@ -704,7 +896,7 @@ public class Blocks implements ContentList{ titaniumConveyor = new Conveyor("titanium-conveyor"){{ requirements(Category.distribution, ItemStack.with(Items.copper, 2, Items.lead, 1, Items.titanium, 1)); health = 65; - speed = 0.07f; + speed = 0.08f; }}; junction = new Junction("junction"){{ @@ -846,20 +1038,20 @@ public class Blocks implements ContentList{ }}; battery = new Battery("battery"){{ - requirements(Category.power, ItemStack.with(Items.copper, 8, Items.lead, 30, Items.silicon, 4)); - consumes.powerBuffered(3200f, 1f); + requirements(Category.power, ItemStack.with(Items.copper, 8, Items.lead, 40)); + consumes.powerBuffered(4000f, 1f); }}; batteryLarge = new Battery("battery-large"){{ - requirements(Category.power, ItemStack.with(Items.titanium, 40, Items.lead, 80, Items.silicon, 30)); + requirements(Category.power, ItemStack.with(Items.titanium, 40, Items.lead, 80, Items.silicon, 40)); size = 3; - consumes.powerBuffered(20000f, 1f); + consumes.powerBuffered(50000f, 1f); }}; combustionGenerator = new BurnerGenerator("combustion-generator"){{ requirements(Category.power, ItemStack.with(Items.copper, 50, Items.lead, 30)); powerProduction = 1f; - itemDuration = 40f; + itemDuration = 60f; }}; thermalGenerator = new ThermalGenerator("thermal-generator"){{ @@ -869,24 +1061,24 @@ public class Blocks implements ContentList{ size = 2; }}; - turbineGenerator = new TurbineGenerator("turbine-generator"){{ + turbineGenerator = new BurnerGenerator("turbine-generator"){{ requirements(Category.power, ItemStack.with(Items.copper, 70, Items.graphite, 50, Items.lead, 80, Items.silicon, 60)); powerProduction = 6f; - itemDuration = 30f; + itemDuration = 40f; consumes.liquid(Liquids.water, 0.05f); hasLiquids = true; size = 2; }}; - differentialGenerator = new DifferentialGenerator("differential-generator"){{ + differentialGenerator = new SingleTypeGenerator(true, false, "differential-generator"){{ requirements(Category.power, ItemStack.with(Items.copper, 140, Items.titanium, 100, Items.lead, 200, Items.silicon, 130, Items.metaglass, 100)); - powerProduction = 13f; + powerProduction = 16f; itemDuration = 50f; - consumes.remove(ConsumeItemFilter.class); - consumes.remove(ConsumeLiquidFilter.class); - consumes.item(Items.pyratite); - consumes.liquid(Liquids.cryofluid, 0.2f); + hasLiquids = true; size = 3; + + consumes.item(Items.pyratite).optional(true, false); + consumes.liquid(Liquids.cryofluid, 0.2f); }}; rtgGenerator = new DecayGenerator("rtg-generator"){{ @@ -898,33 +1090,34 @@ public class Blocks implements ContentList{ solarPanel = new SolarGenerator("solar-panel"){{ requirements(Category.power, ItemStack.with(Items.lead, 20, Items.silicon, 30)); - powerProduction = 0.045f; + powerProduction = 0.06f; }}; largeSolarPanel = new SolarGenerator("solar-panel-large"){{ requirements(Category.power, ItemStack.with(Items.lead, 200, Items.silicon, 290, Items.phasefabric, 30)); size = 3; - powerProduction = 0.55f; + powerProduction = 0.9f; }}; thoriumReactor = new NuclearReactor("thorium-reactor"){{ - requirements(Category.power, ItemStack.with(Items.lead, 600, Items.silicon, 400, Items.graphite, 300, Items.thorium, 300)); + requirements(Category.power, ItemStack.with(Items.lead, 600, Items.silicon, 400, Items.graphite, 300, Items.thorium, 300, Items.metaglass, 100)); size = 3; health = 700; powerProduction = 14f; consumes.item(Items.thorium); - consumes.liquid(Liquids.cryofluid, 0.1f); + heating = 0.02f; + consumes.liquid(Liquids.cryofluid, 0.1f).update(false); }}; impactReactor = new ImpactReactor("impact-reactor"){{ requirements(Category.power, ItemStack.with(Items.lead, 1000, Items.silicon, 600, Items.graphite, 800, Items.thorium, 200, Items.surgealloy, 500, Items.metaglass, 500)); size = 4; health = 900; - powerProduction = 80f; - useTime = 40f; - consumes.power(23f); + powerProduction = 110f; + itemDuration = 40f; + consumes.power(25f); consumes.item(Items.blastCompound); - consumes.liquid(Liquids.cryofluid, 0.8f); + consumes.liquid(Liquids.cryofluid, 0.3f); }}; //endregion power @@ -936,6 +1129,7 @@ public class Blocks implements ContentList{ drillTime = 600; size = 2; drawMineItem = true; + consumes.liquid(Liquids.water, 0.05f).boost(); }}; pneumaticDrill = new Drill("pneumatic-drill"){{ @@ -944,7 +1138,7 @@ public class Blocks implements ContentList{ drillTime = 480; size = 2; drawMineItem = true; - consumes.liquid(Liquids.water, 0.06f).optional(true); + consumes.liquid(Liquids.water, 0.06f).boost(); }}; laserDrill = new Drill("laser-drill"){{ @@ -957,7 +1151,7 @@ public class Blocks implements ContentList{ drillEffect = Fx.mineBig; consumes.power(1.10f); - consumes.liquid(Liquids.water, 0.08f).optional(true); + consumes.liquid(Liquids.water, 0.08f).boost(); }}; blastDrill = new Drill("blast-drill"){{ @@ -974,7 +1168,7 @@ public class Blocks implements ContentList{ warmupSpeed = 0.01f; consumes.power(3f); - consumes.liquid(Liquids.water, 0.1f).optional(true); + consumes.liquid(Liquids.water, 0.1f).boost(); }}; waterExtractor = new SolidPump("water-extractor"){{ @@ -989,6 +1183,19 @@ public class Blocks implements ContentList{ consumes.power(0.90f); }}; + 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; + size = 2; + hasLiquids = true; + hasPower = true; + hasItems = true; + + consumes.power(0.80f); + consumes.liquid(Liquids.water, 0.15f); + }}; + oilExtractor = new Fracker("oil-extractor"){{ requirements(Category.production, ItemStack.with(Items.copper, 300, Items.graphite, 350, Items.lead, 230, Items.thorium, 230, Items.silicon, 150)); result = Liquids.oil; @@ -1046,12 +1253,12 @@ public class Blocks implements ContentList{ }}; unloader = new Unloader("unloader"){{ - requirements(Category.distribution, ItemStack.with(Items.titanium, 50, Items.silicon, 60)); + requirements(Category.effect, ItemStack.with(Items.titanium, 50, Items.silicon, 60)); speed = 7f; }}; launchPad = new LaunchPad("launch-pad"){{ - requirements(Category.effect, () -> world.isZone(), ItemStack.with(Items.copper, 500, Items.titanium, 200, Items.silicon, 200, Items.lead, 200)); + requirements(Category.effect, () -> world.isZone(), ItemStack.with(Items.copper, 500, Items.silicon, 150, Items.lead, 200)); size = 3; itemCapacity = 100; launchTime = 60f * 8; @@ -1059,6 +1266,16 @@ public class Blocks implements ContentList{ consumes.power(1f); }}; + launchPadLarge = new LaunchPad("launch-pad-large"){{ + 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; + hasPower = true; + consumes.power(2f); + }}; + + //endregion //region turrets @@ -1086,23 +1303,38 @@ public class Blocks implements ContentList{ Items.scrap, Bullets.flakScrap, Items.lead, Bullets.flakLead ); - reload = 43f; - range = 160f; + reload = 15f; + range = 180f; size = 2; burstSpacing = 5f; shots = 2; targetGround = false; recoil = 2f; - rotatespeed = 10f; + rotatespeed = 15f; inaccuracy = 17f; shootCone = 35f; - health = 260*size*size; + health = 260 * size * size; + }}; + + scorch = new ItemTurret("scorch"){{ + requirements(Category.turret, ItemStack.with(Items.copper, 50, Items.graphite, 45)); + ammo( + Items.coal, Bullets.basicFlame, + Items.pyratite, Bullets.pyraFlame + ); + recoil = 0f; + reload = 4f; + range = 60f; + shootCone = 50f; + targetAir = false; + ammoUseEffect = Fx.none; + health = 400; }}; hail = new ArtilleryTurret("hail"){{ - requirements(Category.turret, ItemStack.with(Items.copper, 60, Items.graphite, 35)); + requirements(Category.turret, ItemStack.with(Items.copper, 80, Items.graphite, 35)); ammo( Items.graphite, Bullets.artilleryDense, Items.silicon, Bullets.artilleryHoming, @@ -1126,12 +1358,12 @@ public class Blocks implements ContentList{ ); size = 2; recoil = 0f; - reload = 3f; + reload = 2f; inaccuracy = 5f; shootCone = 50f; shootEffect = Fx.shootLiquid; - range = 100f; - health = 250*size*size; + range = 110f; + health = 250 * size * size; drawer = (tile, entity) -> { Draw.rect(region, tile.drawx() + tr2.x, tile.drawy() + tr2.y, entity.rotation - 90); @@ -1162,20 +1394,20 @@ public class Blocks implements ContentList{ chargeBeginEffect = Fx.lancerLaserChargeBegin; heatColor = Color.RED; size = 2; - health = 280*size*size; + health = 280 * size * size; targetAir = false; }}; arc = new PowerTurret("arc"){{ requirements(Category.turret, ItemStack.with(Items.copper, 70, Items.lead, 70)); shootType = Bullets.arc; - reload = 20f; + reload = 24f; shootCone = 40f; rotatespeed = 8f; powerUsed = 1f / 2f; targetAir = false; - consumes.powerBuffered(80f); - range = 80f; + consumes.powerBuffered(60f, 60f); + range = 95f; shootEffect = Fx.lightningShoot; heatColor = Color.RED; recoil = 1f; @@ -1197,7 +1429,7 @@ public class Blocks implements ContentList{ range = 140f; xRand = 6f; size = 2; - health = 300*size*size; + health = 300 * size * size; }}; salvo = new BurstTurret("salvo"){{ @@ -1257,12 +1489,12 @@ public class Blocks implements ContentList{ Items.surgealloy, Bullets.flakSurge ); xRand = 4f; - reload = 8f; - range = 160f; + reload = 6f; + range = 200f; size = 3; recoil = 3f; rotatespeed = 10f; - inaccuracy = 13f; + inaccuracy = 10f; shootCone = 30f; health = 145 * size * size; @@ -1290,7 +1522,6 @@ public class Blocks implements ContentList{ ); reload = 6f; coolantMultiplier = 0.5f; - maxCoolantUsed = 1.5f; restitution = 0.1f; ammoUseEffect = Fx.shellEjectBig; range = 200f; @@ -1304,6 +1535,7 @@ public class Blocks implements ContentList{ shootCone = 24f; health = 155 * size * size; + consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, 2f)).update(false).optional(true, false); }}; meltdown = new LaserTurret("meltdown"){{ @@ -1314,24 +1546,26 @@ public class Blocks implements ContentList{ recoil = 4f; size = 4; shootShake = 2f; - powerUsed = 0.5f; - consumes.powerBuffered(1200f); - range = 160f; - reload = 170f; - firingMoveFract = 0.1f; + range = 190f; + reload = 50f; + firingMoveFract = 0.5f; shootDuration = 220f; + powerUsed = 1f / 2f; - health = 165 * size * size; + health = 200 * size * size; + consumes.powerBuffered(1200f); + consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, 0.5f)).update(false); }}; //endregion //region units spiritFactory = new UnitFactory("spirit-factory"){{ - requirements(Category.units, ItemStack.with(Items.copper, 70, Items.lead, 110, Items.silicon, 130)); + requirements(Category.units, ItemStack.with(Items.copper, 70, Items.lead, 110, Items.silicon, 80)); type = UnitTypes.spirit; produceTime = 5700; size = 2; + maxSpawn = 2; consumes.power(0.80f); consumes.items(new ItemStack(Items.silicon, 30), new ItemStack(Items.lead, 30)); }}; @@ -1341,6 +1575,7 @@ public class Blocks implements ContentList{ type = UnitTypes.phantom; produceTime = 7300; size = 2; + maxSpawn = 2; consumes.power(2f); consumes.items(new ItemStack(Items.silicon, 70), new ItemStack(Items.lead, 80), new ItemStack(Items.titanium, 80)); }}; @@ -1404,6 +1639,7 @@ public class Blocks implements ContentList{ type = UnitTypes.fortress; produceTime = 5000; size = 3; + maxSpawn = 3; consumes.power(2f); consumes.items(new ItemStack(Items.silicon, 40), new ItemStack(Items.thorium, 50)); }}; diff --git a/core/src/io/anuke/mindustry/content/Bullets.java b/core/src/io/anuke/mindustry/content/Bullets.java index 1dec6813d2..ae356cb001 100644 --- a/core/src/io/anuke/mindustry/content/Bullets.java +++ b/core/src/io/anuke/mindustry/content/Bullets.java @@ -1,20 +1,15 @@ package io.anuke.mindustry.content; -import io.anuke.mindustry.entities.Effects; import io.anuke.arc.graphics.Color; -import io.anuke.arc.graphics.g2d.CapStyle; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Fill; -import io.anuke.arc.graphics.g2d.Lines; +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.mindustry.entities.Damage; -import io.anuke.mindustry.entities.type.Unit; +import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.bullet.*; -import io.anuke.mindustry.entities.effect.Fire; -import io.anuke.mindustry.entities.effect.Lightning; -import io.anuke.mindustry.entities.effect.Puddle; +import io.anuke.mindustry.entities.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; @@ -37,7 +32,7 @@ public class Bullets implements ContentList{ //standard standardCopper, standardDense, standardThorium, standardHoming, standardIncendiary, standardMechSmall, - standardGlaive, standardDenseBig, standardThoriumBig, standardIncendiaryBig, + standardGlaive, standardDenseBig, standardThoriumBig, standardIncendiaryBig, //electric lancerLaser, meltdownLaser, lightning, arc, damageLightning, @@ -46,7 +41,7 @@ public class Bullets implements ContentList{ waterShot, cryoShot, slagShot, oilShot, //environment, misc. - fireball, basicFlame, fuseShot, driverBolt, healBullet, frag, eruptorShot, + fireball, basicFlame, pyraFlame, fuseShot, driverBolt, healBullet, frag, eruptorShot, //bombs bombExplosive, bombIncendiary, bombOil, explode; @@ -134,28 +129,32 @@ public class Bullets implements ContentList{ bulletWidth = bulletHeight = 14f; collides = true; collidesTiles = true; - splashDamageRadius = 45f; - splashDamage = 50f; + splashDamageRadius = 20f; + splashDamage = 38f; backColor = Pal.bulletYellowBack; frontColor = Pal.bulletYellow; }}; - flakLead = new FlakBulletType(3.9f, 3){{ + flakLead = new FlakBulletType(4.2f, 3){{ + lifetime = 60f; + ammoMultiplier = 3f; shootEffect = Fx.shootSmall; bulletWidth = 6f; bulletHeight = 8f; hitEffect = Fx.flakExplosion; - splashDamage = 25f; + splashDamage = 35f; splashDamageRadius = 15f; }}; - flakScrap = new FlakBulletType(3.5f, 3){{ + flakScrap = new FlakBulletType(4f, 3){{ + lifetime = 60f; + ammoMultiplier = 3f; shootEffect = Fx.shootSmall; reloadMultiplier = 0.5f; bulletWidth = 6f; bulletHeight = 8f; hitEffect = Fx.flakExplosion; - splashDamage = 16f; + splashDamage = 26f; splashDamageRadius = 24f; }}; @@ -269,7 +268,7 @@ public class Bullets implements ContentList{ keepVelocity = false; splashDamageRadius = 25f; splashDamage = 10f; - lifetime = 80f; + lifetime = 50f; trailColor = Pal.unitBack; backColor = Pal.unitBack; frontColor = Pal.unitFront; @@ -290,7 +289,6 @@ public class Bullets implements ContentList{ standardDense = new BasicBulletType(3.5f, 18, "bullet"){{ bulletWidth = 9f; bulletHeight = 12f; - armorPierce = 0.2f; reloadMultiplier = 0.6f; ammoMultiplier = 2; }}; @@ -298,7 +296,6 @@ public class Bullets implements ContentList{ standardThorium = new BasicBulletType(4f, 29, "bullet"){{ bulletWidth = 10f; bulletHeight = 13f; - armorPierce = 0.5f; shootEffect = Fx.shootBig; smokeEffect = Fx.shootBigSmoke; ammoMultiplier = 2; @@ -344,14 +341,12 @@ public class Bullets implements ContentList{ standardDenseBig = new BasicBulletType(7f, 42, "bullet"){{ bulletWidth = 15f; bulletHeight = 21f; - armorPierce = 0.2f; shootEffect = Fx.shootBig; }}; standardThoriumBig = new BasicBulletType(8f, 65, "bullet"){{ bulletWidth = 16f; bulletHeight = 23f; - armorPierce = 0.5f; shootEffect = Fx.shootBig; }}; @@ -454,10 +449,11 @@ public class Bullets implements ContentList{ } }; - basicFlame = new BulletType(2.3f, 5){ + basicFlame = new BulletType(3f, 6f){ { + ammoMultiplier = 3f; hitSize = 7f; - lifetime = 35f; + lifetime = 42f; pierce = true; drag = 0.05f; statusDuration = 60f * 4; @@ -472,6 +468,25 @@ public class Bullets implements ContentList{ } }; + pyraFlame = new BulletType(3.3f, 9f){ + { + ammoMultiplier = 4f; + hitSize = 7f; + lifetime = 42f; + pierce = true; + drag = 0.05f; + statusDuration = 60f * 6; + shootEffect = Fx.shootPyraFlame; + hitEffect = Fx.hitFlameSmall; + despawnEffect = Fx.none; + status = StatusEffects.burning; + } + + @Override + public void draw(Bullet b){ + } + }; + lancerLaser = new BulletType(0.001f, 140){ Color[] colors = {Pal.lancerLaser.cpy().mul(1f, 1f, 1f, 0.4f), Pal.lancerLaser, Color.WHITE}; float[] tscales = {1f, 0.7f, 0.5f, 0.2f}; @@ -513,13 +528,13 @@ public class Bullets implements ContentList{ } }; - meltdownLaser = new BulletType(0.001f, 35){ + meltdownLaser = new BulletType(0.001f, 70){ Color tmpColor = new Color(); Color[] colors = {Color.valueOf("ec745855"), Color.valueOf("ec7458aa"), Color.valueOf("ff9c5a"), Color.WHITE}; float[] tscales = {1f, 0.7f, 0.5f, 0.2f}; float[] strokes = {2f, 1.5f, 1f, 0.3f}; float[] lenscales = {1f, 1.12f, 1.15f, 1.17f}; - float length = 200f; + float length = 220f; { hitEffect = Fx.hitMeltdown; @@ -542,7 +557,7 @@ public class Bullets implements ContentList{ public void hit(Bullet b, float hitx, float hity){ Effects.effect(hitEffect, colors[2], hitx, hity); if(Mathf.chance(0.4)){ - Fire.create(world.tileWorld(hitx+Mathf.range(5f), hity+Mathf.range(5f))); + Fire.create(world.tileWorld(hitx + Mathf.range(5f), hity + Mathf.range(5f))); } } @@ -566,6 +581,7 @@ public class Bullets implements ContentList{ fuseShot = new BulletType(0.01f, 70){ int rays = 3; float rayLength = 80f; + { hitEffect = Fx.hitFuse; lifetime = 13f; @@ -574,23 +590,23 @@ public class Bullets implements ContentList{ } @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); + 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) { + public void draw(Bullet b){ super.draw(b); Draw.color(Color.WHITE, Pal.surge, b.fin()); 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); + 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, 13f, (rayLength+50) * b.fout(), b.rot()); + Shapes.tri(b.x, b.y, 13f, (rayLength + 50) * b.fout(), b.rot()); Shapes.tri(b.x, b.y, 13f, 10f * b.fout(), b.rot() + 180f); Draw.reset(); } @@ -606,7 +622,6 @@ public class Bullets implements ContentList{ slagShot = new LiquidBulletType(Liquids.slag){{ damage = 4; - speed = 1.9f; drag = 0.03f; }}; @@ -624,6 +639,8 @@ public class Bullets implements ContentList{ lightning = new BulletType(0.001f, 12f){ { lifetime = 1f; + shootEffect = Fx.hitLancer; + smokeEffect = Fx.none; despawnEffect = Fx.none; hitEffect = Fx.hitLancer; keepVelocity = false; @@ -644,18 +661,20 @@ public class Bullets implements ContentList{ } }; - arc = new BulletType(0.001f, 20){{ + arc = new BulletType(0.001f, 25){ + { lifetime = 1; despawnEffect = Fx.none; hitEffect = Fx.hitLancer; } @Override - public void draw(Bullet b){} + public void draw(Bullet b){ + } @Override public void init(Bullet b){ - Lightning.create(b.getTeam(), Pal.lancerLaser, damage, b.x, b.y, b.rot(), 14); + Lightning.create(b.getTeam(), Pal.lancerLaser, damage, b.x, b.y, b.rot(), 25); } }; @@ -673,6 +692,8 @@ public class Bullets implements ContentList{ bulletWidth = 9f; bulletHeight = 13f; hitEffect = Fx.flakExplosion; + shootEffect = Fx.none; + smokeEffect = Fx.none; }}; bombIncendiary = new BombBulletType(7f, 10f, "shell"){{ @@ -686,7 +707,8 @@ public class Bullets implements ContentList{ incendSpread = 10f; }}; - bombOil = new BombBulletType(2f, 3f, "shell"){{ + bombOil = new BombBulletType(2f, 3f, "shell"){ + { bulletWidth = 8f; bulletHeight = 12f; hitEffect = Fx.pulverize; @@ -705,12 +727,13 @@ public class Bullets implements ContentList{ } }; - explode = new BombBulletType(2f, 3f, "clear"){{ + explode = new BombBulletType(2f, 3f, "clear"){ + { hitEffect = Fx.pulverize; lifetime = 23f; speed = 1f; splashDamageRadius = 50f; - splashDamage = 20f; + splashDamage = 28f; } @Override diff --git a/core/src/io/anuke/mindustry/content/Fx.java b/core/src/io/anuke/mindustry/content/Fx.java index d99024d745..8cd9ad826c 100644 --- a/core/src/io/anuke/mindustry/content/Fx.java +++ b/core/src/io/anuke/mindustry/content/Fx.java @@ -2,9 +2,7 @@ package io.anuke.mindustry.content; import io.anuke.arc.Core; import io.anuke.arc.graphics.Color; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Fill; -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.util.Tmp; @@ -32,25 +30,26 @@ public class Fx implements ContentList{ plasticExplosion, artilleryTrail, incendTrail, missileTrail, absorb, flakExplosionBig, plasticExplosionFlak, burning, fire, fireSmoke, steam, fireballsmoke, ballfire, freezing, melting, wet, oily, overdriven, dropItem, shockwave, bigShockwave, nuclearShockwave, explosion, blockExplosion, blockExplosionSmoke, shootSmall, shootHeal, shootSmallSmoke, shootBig, shootBig2, shootBigSmoke, - shootBigSmoke2, shootSmallFlame, shootLiquid, shellEjectSmall, shellEjectMedium, + shootBigSmoke2, shootSmallFlame, shootPyraFlame, shootLiquid, shellEjectSmall, shellEjectMedium, shellEjectBig, lancerLaserShoot, lancerLaserShootSmoke, lancerLaserCharge, lancerLaserChargeBegin, lightningCharge, lightningShoot, - unitSpawn, spawnShockwave, magmasmoke, impactShockwave, impactcloud, impactsmoke, dynamicExplosion; + unitSpawn, spawnShockwave, magmasmoke, impactShockwave, impactcloud, impactsmoke, dynamicExplosion, padlaunch; @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; Draw.alpha(e.fin()); - float scl = 1f + e.fout()*2f; + float scl = 1f + e.fout() * 2f; BaseUnit unit = (BaseUnit)e.data; Draw.rect(unit.getIconRegion(), e.x, e.y, - unit.getIconRegion().getWidth() * Draw.scl * scl, unit.getIconRegion().getWidth() * Draw.scl * scl, 180f); + unit.getIconRegion().getWidth() * Draw.scl * scl, unit.getIconRegion().getWidth() * Draw.scl * scl, 180f); Draw.reset(); }); @@ -74,7 +73,7 @@ public class Fx implements ContentList{ Lines.stroke(3f - e.fin() * 2f); Lines.square(e.x, e.y, tilesize / 2f * e.rotation + e.fin() * 3f); - Angles.randLenVectors(e.id, 3 + (int) (e.rotation * 3), e.rotation * 2f + (tilesize * e.rotation) * e.finpow(), (x, y) -> { + Angles.randLenVectors(e.id, 3 + (int)(e.rotation * 3), e.rotation * 2f + (tilesize * e.rotation) * e.finpow(), (x, y) -> { Fill.square(e.x + x, e.y + y, 1f + e.fout() * (3f + e.rotation)); }); Draw.reset(); @@ -106,7 +105,14 @@ public class Fx implements ContentList{ Lines.poly(e.x, e.y, 4, 5f + e.fin() * 12f); Draw.reset(); }); - + + padlaunch = new Effect(10, e -> { + Lines.stroke(4f * e.fout()); + Draw.color(Pal.accent); + Lines.poly(e.x, e.y, 4, 5f + e.fin() * 60f); + Draw.reset(); + }); + vtolHover = new Effect(40f, e -> { float len = e.finpow() * 10f; float ang = e.rotation + Mathf.randomSeedRange(e.id, 30f); @@ -172,7 +178,7 @@ public class Fx implements ContentList{ e.scaled(7f, s -> { Lines.stroke(0.5f + s.fout()); - Lines.circle(e.x, e.y, s.fin()*5f); + Lines.circle(e.x, e.y, s.fin() * 5f); }); @@ -191,7 +197,7 @@ public class Fx implements ContentList{ e.scaled(7f, s -> { Lines.stroke(0.5f + s.fout()); - Lines.circle(e.x, e.y, s.fin()*7f); + Lines.circle(e.x, e.y, s.fin() * 7f); }); @@ -221,7 +227,7 @@ public class Fx implements ContentList{ Draw.color(Pal.lightFlame, Pal.darkFlame, e.fin()); Lines.stroke(0.5f + e.fout()); - Angles.randLenVectors(e.id, 5, e.fin() * 15f, e.rotation, 50f, (x, y) -> { + Angles.randLenVectors(e.id, 2, e.fin() * 15f, e.rotation, 50f, (x, y) -> { float ang = Mathf.angle(x, y); Lines.lineAngle(e.x + x, e.y + y, ang, e.fout() * 3 + 1f); }); @@ -266,7 +272,7 @@ public class Fx implements ContentList{ hitLaser = new Effect(8, e -> { Draw.color(Color.WHITE, Pal.heal, e.fin()); Lines.stroke(0.5f + e.fout()); - Lines.circle(e.x, e.y, e.fin()*5f); + Lines.circle(e.x, e.y, e.fin() * 5f); Draw.reset(); }); @@ -532,7 +538,7 @@ public class Fx implements ContentList{ Draw.color(Pal.accent); Angles.randLenVectors(e.id, 2, 1f + e.fin() * 2f, (x, y) -> { - Fill.square(e.x + x, e.y + y, e.fout() * 2.3f+0.5f); + Fill.square(e.x + x, e.y + y, e.fout() * 2.3f + 0.5f); }); Draw.color(); @@ -542,7 +548,7 @@ public class Fx implements ContentList{ float length = 20f * e.finpow(); float size = 7f * e.fout(); - Draw.rect(((Item) e.data).icon(Icon.large), e.x + Angles.trnsx(e.rotation, length), e.y + Angles.trnsy(e.rotation, length), size, size); + Draw.rect(((Item)e.data).icon(Icon.large), e.x + Angles.trnsx(e.rotation, length), e.y + Angles.trnsy(e.rotation, length), size, size); }); @@ -607,23 +613,23 @@ public class Fx implements ContentList{ dynamicExplosion = new Effect(30, e -> { float intensity = e.rotation; - e.scaled(5 + intensity*2, i -> { + e.scaled(5 + intensity * 2, i -> { Lines.stroke(3.1f * i.fout()); Lines.poly(e.x, e.y, (int)(20 * intensity), (3f + i.fin() * 14f) * intensity); }); Draw.color(Color.GRAY); - Angles.randLenVectors(e.id, e.finpow(), (int)(6 * intensity), 21f*intensity, (x, y, in, out) -> { - Fill.circle(e.x + x, e.y + y, out * (2f+intensity) * 3 + 0.5f); + Angles.randLenVectors(e.id, e.finpow(), (int)(6 * intensity), 21f * intensity, (x, y, in, out) -> { + Fill.circle(e.x + x, e.y + y, out * (2f + intensity) * 3 + 0.5f); Fill.circle(e.x + x / 2f, e.y + y / 2f, out * (intensity) * 3); }); Draw.color(Pal.lighterOrange, Pal.lightOrange, Color.GRAY, e.fin()); Lines.stroke((1.7f * e.fout()) * (1f + (intensity - 1f) / 2f)); - Angles.randLenVectors(e.id + 1, e.finpow(), (int)(9*intensity), 40f*intensity, (x, y, in, out) -> { - Lines.lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), 1f + out * 4 * (3f+intensity)); + Angles.randLenVectors(e.id + 1, e.finpow(), (int)(9 * intensity), 40f * intensity, (x, y, in, out) -> { + Lines.lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), 1f + out * 4 * (3f + intensity)); }); Draw.reset(); @@ -736,6 +742,16 @@ public class Fx implements ContentList{ Draw.reset(); }); + shootPyraFlame = new Effect(33f, e -> { + Draw.color(Pal.lightPyraFlame, Pal.darkPyraFlame, Color.GRAY, e.fin()); + + Angles.randLenVectors(e.id, 10, e.finpow() * 50f, e.rotation, 10f, (x, y) -> { + Fill.circle(e.x + x, e.y + y, 0.65f + e.fout() * 1.6f); + }); + + Draw.reset(); + }); + shootLiquid = new Effect(40f, e -> { Draw.color(e.color, Color.WHITE, e.fout() / 6f + Mathf.randomSeedRange(e.id, 0.1f)); @@ -755,8 +771,8 @@ public class Fx implements ContentList{ float len = (2f + e.finpow() * 6f) * i; float lr = rot + e.fin() * 30f * i; Fill.rect(e.x + Angles.trnsx(lr, len) + Mathf.randomSeedRange(e.id + i + 7, 3f * e.fin()), - e.y + Angles.trnsy(lr, len) + Mathf.randomSeedRange(e.id + i + 8, 3f * e.fin()), - 1f, 2f, rot + e.fin() * 50f * i); + e.y + Angles.trnsy(lr, len) + Mathf.randomSeedRange(e.id + i + 8, 3f * e.fin()), + 1f, 2f, rot + e.fin() * 50f * i); Draw.color(); }); @@ -768,9 +784,9 @@ public class Fx implements ContentList{ float len = (2f + e.finpow() * 10f) * i; float lr = rot + e.fin() * 20f * i; Draw.rect(Core.atlas.find("casing"), - e.x + Angles.trnsx(lr, len) + Mathf.randomSeedRange(e.id + i + 7, 3f * e.fin()), - e.y + Angles.trnsy(lr, len) + Mathf.randomSeedRange(e.id + i + 8, 3f * e.fin()), - 2f, 3f, rot); + e.x + Angles.trnsx(lr, len) + Mathf.randomSeedRange(e.id + i + 7, 3f * e.fin()), + e.y + Angles.trnsy(lr, len) + Mathf.randomSeedRange(e.id + i + 8, 3f * e.fin()), + 2f, 3f, rot); } Draw.color(Color.LIGHT_GRAY, Color.GRAY, e.fin()); @@ -791,10 +807,10 @@ public class Fx implements ContentList{ float len = (4f + e.finpow() * 8f) * i; float lr = rot + Mathf.randomSeedRange(e.id + i + 6, 20f * e.fin()) * i; Draw.rect(Core.atlas.find("casing"), - e.x + Angles.trnsx(lr, len) + Mathf.randomSeedRange(e.id + i + 7, 3f * e.fin()), - e.y + Angles.trnsy(lr, len) + Mathf.randomSeedRange(e.id + i + 8, 3f * e.fin()), - 2.5f, 4f, - rot + e.fin() * 30f * i + Mathf.randomSeedRange(e.id + i + 9, 40f * e.fin())); + e.x + Angles.trnsx(lr, len) + Mathf.randomSeedRange(e.id + i + 7, 3f * e.fin()), + e.y + Angles.trnsy(lr, len) + Mathf.randomSeedRange(e.id + i + 8, 3f * e.fin()), + 2.5f, 4f, + rot + e.fin() * 30f * i + Mathf.randomSeedRange(e.id + i + 9, 40f * e.fin())); } Draw.color(Color.LIGHT_GRAY); @@ -1161,7 +1177,7 @@ public class Fx implements ContentList{ healBlock = new Effect(20, e -> { Draw.color(Pal.heal); Lines.stroke(2f * e.fout() + 0.5f); - Lines.square(e.x, e.y, 1f + (e.fin() * e.rotation * tilesize/2f-1f)); + Lines.square(e.x, e.y, 1f + (e.fin() * e.rotation * tilesize / 2f - 1f)); Draw.color(); }); diff --git a/core/src/io/anuke/mindustry/content/Items.java b/core/src/io/anuke/mindustry/content/Items.java index ad5f0ba779..6ee41034c2 100644 --- a/core/src/io/anuke/mindustry/content/Items.java +++ b/core/src/io/anuke/mindustry/content/Items.java @@ -14,24 +14,28 @@ public class Items implements ContentList{ copper = new Item("copper", Color.valueOf("d99d73")){{ type = ItemType.material; hardness = 1; - cost = 0.6f; + cost = 0.5f; alwaysUnlocked = true; }}; lead = new Item("lead", Color.valueOf("8c7fa9")){{ type = ItemType.material; hardness = 1; - cost = 0.9f; + cost = 0.7f; }}; metaglass = new Item("metaglass", Color.valueOf("ebeef5")){{ type = ItemType.material; - cost = 2f; + cost = 1.5f; }}; graphite = new Item("graphite", Color.valueOf("b2c6d2")){{ type = ItemType.material; - cost = 1.3f; + cost = 1f; + }}; + + sand = new Item("sand", Color.valueOf("f7cba4")){{ + }}; coal = new Item("coal", Color.valueOf("272727")){{ @@ -43,7 +47,7 @@ public class Items implements ContentList{ titanium = new Item("titanium", Color.valueOf("8da1e3")){{ type = ItemType.material; hardness = 3; - cost = 1.1f; + cost = 1f; }}; thorium = new Item("thorium", Color.valueOf("f9a3c7")){{ @@ -51,7 +55,7 @@ public class Items implements ContentList{ explosiveness = 0.2f; hardness = 4; radioactivity = 1f; - cost = 1.4f; + cost = 1.1f; }}; scrap = new Item("scrap", Color.valueOf("777777")){{ @@ -60,19 +64,19 @@ public class Items implements ContentList{ silicon = new Item("silicon", Color.valueOf("53565c")){{ type = ItemType.material; - cost = 0.9f; + cost = 0.8f; }}; plastanium = new Item("plastanium", Color.valueOf("cbd97f")){{ type = ItemType.material; - flammability = 0.2f; + flammability = 0.1f; explosiveness = 0.2f; - cost = 1.6f; + cost = 1.3f; }}; phasefabric = new Item("phase-fabric", Color.valueOf("f4ba6e")){{ type = ItemType.material; - cost = 1.5f; + cost = 1.3f; radioactivity = 0.6f; }}; @@ -84,10 +88,6 @@ public class Items implements ContentList{ flammability = 1.05f; }}; - sand = new Item("sand", Color.valueOf("f7cba4")){{ - - }}; - blastCompound = new Item("blast-compound", Color.valueOf("ff795e")){{ flammability = 0.4f; explosiveness = 1.2f; diff --git a/core/src/io/anuke/mindustry/content/Mechs.java b/core/src/io/anuke/mindustry/content/Mechs.java index cc96e1ece2..51daec4090 100644 --- a/core/src/io/anuke/mindustry/content/Mechs.java +++ b/core/src/io/anuke/mindustry/content/Mechs.java @@ -21,7 +21,7 @@ import io.anuke.mindustry.type.Weapon; public class Mechs implements ContentList{ public static Mech alpha, delta, tau, omega, dart, javelin, trident, glaive; - /**These are not new mechs, just re-assignments for convenience.*/ + /** These are not new mechs, just re-assignments for convenience. */ public static Mech starterDesktop, starterMobile; @Override @@ -35,6 +35,7 @@ public class Mechs implements ContentList{ mass = 1.2f; speed = 0.5f; boostSpeed = 0.85f; + buildPower = 1.2f; engineColor = Color.valueOf("ffd37f"); health = 300f; @@ -47,6 +48,11 @@ public class Mechs implements ContentList{ }}; } + @Override + public void updateAlt(Player player){ + player.healBy(Time.delta() * 0.09f); + } + @Override public boolean alwaysUnlocked(){ return true; @@ -63,17 +69,19 @@ public class Mechs implements ContentList{ itemCapacity = 15; mass = 0.9f; health = 250f; + buildPower = 0.9f; weaponOffsetX = -1; weaponOffsetY = -1; engineColor = Color.valueOf("d3ddff"); weapon = new Weapon("shockgun"){{ + shake = 2f; length = 1f; reload = 40f; + shotDelay = 3f; roundrobin = true; - shots = 1; + shots = 2; inaccuracy = 0f; - velocityRnd = 0.2f; ejectEffect = Fx.none; bullet = Bullets.lightning; }}; @@ -110,6 +118,7 @@ public class Mechs implements ContentList{ boostSpeed = 0.8f; canHeal = true; health = 200f; + buildPower = 1.6f; engineColor = Pal.heal; weapon = new Weapon("heal-blaster"){{ @@ -128,7 +137,7 @@ public class Mechs implements ContentList{ if(player.timer.get(Player.timerAbility, healReload)){ wasHealed = false; - rect.setSize(healRange*2f).setCenter(player.x, player.y); + rect.setSize(healRange * 2f).setCenter(player.x, player.y); Units.getNearby(player.getTeam(), rect, unit -> { if(unit.dst(player) <= healRange){ if(unit.health < unit.maxHealth()){ @@ -161,6 +170,7 @@ public class Mechs implements ContentList{ weaponOffsetY = 0; engineColor = Color.valueOf("feb380"); health = 300f; + buildPower = 1.5f; weapon = new Weapon("swarmer"){{ length = 1.5f; recoil = 4f; @@ -182,7 +192,7 @@ public class Mechs implements ContentList{ @Override public float spreadX(Player player){ - return player.shootHeat*2f; + return player.shootHeat * 2f; } @Override @@ -193,7 +203,7 @@ public class Mechs implements ContentList{ @Override public void updateAlt(Player player){ - float scl = 1f - player.shootHeat/2f; + float scl = 1f - player.shootHeat / 2f; player.velocity().scl(scl); } @@ -227,6 +237,7 @@ public class Mechs implements ContentList{ weaponOffsetY = -1; engineColor = Pal.lightTrail; cellTrnsY = 1f; + buildPower = 1.1f; weapon = new Weapon("blaster"){{ length = 1.5f; reload = 20f; @@ -246,6 +257,7 @@ public class Mechs implements ContentList{ float minV = 3.6f; float maxV = 6f; TextureRegion shield; + { drillPower = -1; speed = 0.11f; @@ -281,7 +293,7 @@ public class Mechs implements ContentList{ @Override public void updateAlt(Player player){ float scl = scld(player); - if(Mathf.chance(Time.delta() * (0.15*scl))){ + if(Mathf.chance(Time.delta() * (0.15 * scl))){ Effects.effect(Fx.hitLancer, Pal.lancerLaser, player.x, player.y); Lightning.create(player.getTeam(), Pal.lancerLaser, 10f, player.x + player.velocity().x, player.y + player.velocity().y, player.rotation, 14); @@ -293,9 +305,9 @@ public class Mechs implements ContentList{ float scl = scld(player); if(scl < 0.01f) return; Draw.color(Pal.lancerLaser); - Draw.alpha(scl/2f); + Draw.alpha(scl / 2f); Draw.blend(Blending.additive); - Draw.rect(shield, player.x + Mathf.range(scl/2f), player.y + Mathf.range(scl/2f), player.rotation - 90); + Draw.rect(shield, player.x + Mathf.range(scl / 2f), player.y + Mathf.range(scl / 2f), player.rotation - 90); Draw.blend(); } @@ -315,6 +327,7 @@ public class Mechs implements ContentList{ itemCapacity = 30; engineColor = Color.valueOf("84f491"); cellTrnsY = 1f; + buildPower = 2f; weapon = new Weapon("bomber"){{ length = 0f; width = 2f; @@ -346,6 +359,7 @@ public class Mechs implements ContentList{ itemCapacity = 60; engineColor = Color.valueOf("feb380"); cellTrnsY = 1f; + buildPower = 1.2f; weapon = new Weapon("bomber"){{ length = 1.5f; diff --git a/core/src/io/anuke/mindustry/content/StatusEffects.java b/core/src/io/anuke/mindustry/content/StatusEffects.java index e9c87b39b6..f10340df75 100644 --- a/core/src/io/anuke/mindustry/content/StatusEffects.java +++ b/core/src/io/anuke/mindustry/content/StatusEffects.java @@ -1,7 +1,7 @@ package io.anuke.mindustry.content; -import io.anuke.mindustry.entities.Effects; import io.anuke.arc.math.Mathf; +import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.game.ContentList; import io.anuke.mindustry.type.StatusEffect; diff --git a/core/src/io/anuke/mindustry/content/TechTree.java b/core/src/io/anuke/mindustry/content/TechTree.java index 330cdc8114..db98cb4877 100644 --- a/core/src/io/anuke/mindustry/content/TechTree.java +++ b/core/src/io/anuke/mindustry/content/TechTree.java @@ -19,15 +19,20 @@ public class TechTree implements ContentList{ node(junction, () -> { node(itemBridge); node(router, () -> { + node(launchPad, () -> { + node(launchPadLarge, () -> { + + }); + }); + node(distributor); - node(overflowGate); - node(sorter); + node(sorter, () -> { + node(overflowGate); + }); node(container, () -> { node(unloader); node(vault, () -> { - node(launchPad, () -> { - }); }); }); @@ -64,22 +69,25 @@ public class TechTree implements ContentList{ }); }); - node(arc, () -> { - node(wave, () -> { - - }); - - node(lancer, () -> { - node(meltdown, () -> { + node(scorch, () -> { + node(arc, () -> { + node(wave, () -> { }); - node(shockMine, () -> { + node(lancer, () -> { + node(meltdown, () -> { + }); + + node(shockMine, () -> { + + }); }); }); }); + node(copperWall, () -> { node(copperWallLarge); node(titaniumWall, () -> { @@ -129,6 +137,9 @@ public class TechTree implements ContentList{ node(siliconSmelter, () -> { node(sporePress, () -> { + node(coalCentrifuge, () -> { + + }); node(multiPress, () -> { }); @@ -163,7 +174,6 @@ public class TechTree implements ContentList{ }); - node(mechanicalPump, () -> { node(conduit, () -> { node(liquidJunction, () -> { @@ -190,14 +200,18 @@ public class TechTree implements ContentList{ node(combustionGenerator, () -> { node(powerNode, () -> { node(powerNodeLarge, () -> { - node(battery, () -> { - node(batteryLarge, () -> { - node(surgeTower, () -> { + node(surgeTower, () -> { - }); - }); }); + }); + node(battery, () -> { + node(batteryLarge, () -> { + + }); + }); + + node(mender, () -> { node(mendProjector, () -> { node(forceProjector, () -> { node(overdriveProjector, () -> { @@ -232,11 +246,12 @@ public class TechTree implements ContentList{ }); }); + node(spiritFactory, () -> { + node(phantomFactory); + }); + node(alphaDartPad, () -> { node(deltaPad, () -> { - node(spiritFactory, () -> { - node(phantomFactory); - }); node(javelinPad, () -> { node(tridentPad, () -> { @@ -259,14 +274,15 @@ public class TechTree implements ContentList{ private TechNode node(Block block, Runnable children){ ItemStack[] requirements = new ItemStack[block.buildRequirements.length]; for(int i = 0; i < requirements.length; i++){ - requirements[i] = new ItemStack(block.buildRequirements[i].item, block.buildRequirements[i].amount * 8); + requirements[i] = new ItemStack(block.buildRequirements[i].item, block.buildRequirements[i].amount * 5); } - + return new TechNode(block, requirements, children); } private TechNode node(Block block){ - return node(block, () -> {}); + return node(block, () -> { + }); } public static class TechNode{ diff --git a/core/src/io/anuke/mindustry/content/UnitTypes.java b/core/src/io/anuke/mindustry/content/UnitTypes.java index 01410348cc..217e8227ee 100644 --- a/core/src/io/anuke/mindustry/content/UnitTypes.java +++ b/core/src/io/anuke/mindustry/content/UnitTypes.java @@ -8,9 +8,9 @@ import io.anuke.mindustry.type.Weapon; public class UnitTypes implements ContentList{ public static UnitType - spirit, phantom, - wraith, ghoul, revenant, lich, reaper, - dagger, crawler, titan, fortress, eruptor, chaosArray, eradicator; + spirit, phantom, + wraith, ghoul, revenant, lich, reaper, + dagger, crawler, titan, fortress, eruptor, chaosArray, eradicator; @Override public void load(){ @@ -91,7 +91,7 @@ public class UnitTypes implements ContentList{ hitsize = 10f; rotatespeed = 0.06f; targetAir = false; - health = 800; + health = 750; weapon = new Weapon("artillery"){{ length = 1f; reload = 60f; @@ -178,8 +178,9 @@ public class UnitTypes implements ContentList{ drag = 0.01f; mass = 1.5f; isFlying = true; - health = 70; + health = 75; engineOffset = 5.5f; + range = 140f; weapon = new Weapon("chain-blaster"){{ length = 1.5f; reload = 28f; @@ -190,7 +191,7 @@ public class UnitTypes implements ContentList{ }}; ghoul = new UnitType("ghoul", Ghoul.class, Ghoul::new){{ - health = 250; + health = 220; speed = 0.2f; maxVelocity = 1.4f; mass = 3f; @@ -198,6 +199,7 @@ public class UnitTypes implements ContentList{ isFlying = true; targetAir = false; engineOffset = 7.8f; + range = 140f; weapon = new Weapon("bomber"){{ length = 0f; width = 2f; diff --git a/core/src/io/anuke/mindustry/content/Zones.java b/core/src/io/anuke/mindustry/content/Zones.java index 1c12202b73..7b7ee1e8e7 100644 --- a/core/src/io/anuke/mindustry/content/Zones.java +++ b/core/src/io/anuke/mindustry/content/Zones.java @@ -2,15 +2,18 @@ package io.anuke.mindustry.content; import io.anuke.mindustry.game.ContentList; import io.anuke.mindustry.game.Rules; +import io.anuke.mindustry.maps.zonegen.DesertWastesGenerator; import io.anuke.mindustry.maps.generators.MapGenerator; import io.anuke.mindustry.maps.generators.MapGenerator.Decoration; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.type.Zone; +import io.anuke.mindustry.maps.zonegen.OvergrowthGenerator; +import io.anuke.mindustry.type.*; import io.anuke.mindustry.world.Block; public class Zones implements ContentList{ - public static Zone groundZero, craters, frozenForest, ruinousShores, stainedMountains, + public static Zone + groundZero, desertWastes, + craters, frozenForest, ruinousShores, stainedMountains, + saltFlats, overgrowth, infestedIslands, desolateRift, nuclearComplex; @Override @@ -30,28 +33,65 @@ public class Zones implements ContentList{ }}; }}; - craters = new Zone("craters", new MapGenerator("craters", 1).dist(0).decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.01))){{ + desertWastes = new Zone("desertWastes", new DesertWastesGenerator(260, 260)){{ startingItems = ItemStack.list(Items.copper, 200); conditionWave = 10; - itemRequirements = ItemStack.with(Items.copper, 2000); - zoneRequirements = new Zone[]{groundZero}; + zoneRequirements = ZoneRequirement.with(groundZero, 10); blockRequirements = new Block[]{Blocks.router}; - resources = new Item[]{Items.copper, Items.lead}; + resources = new Item[]{Items.copper, Items.lead, Items.coal, Items.sand}; rules = () -> new Rules(){{ waves = true; waveTimer = true; - waveSpacing = 60 * 60 * 1f; + waveSpacing = 60 * 60 * 1.5f; + }}; + }}; + + saltFlats = new Zone("saltFlats", new DesertWastesGenerator(260, 260)){{ + 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, Items.sand}; + rules = () -> new Rules(){{ + waves = true; + waveTimer = true; + waveSpacing = 60 * 60 * 1.5f; + }}; + }}; + + overgrowth = new Zone("overgrowth", new OvergrowthGenerator(320, 320)){{ + 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; + }}; + }}; + + 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; }}; }}; frozenForest = new Zone("frozenForest", new MapGenerator("frozenForest", 1) - .decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.02))){{ + .decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.02))){{ loadout = Loadouts.basicFoundation; baseLaunchCost = ItemStack.with(); startingItems = ItemStack.list(Items.copper, 400); conditionWave = 10; - zoneRequirements = new Zone[]{craters}; - itemRequirements = ItemStack.with(Items.copper, 4000, Items.lead, 2000); + zoneRequirements = ZoneRequirement.with(craters, 10); resources = new Item[]{Items.copper, Items.lead, Items.coal}; rules = () -> new Rules(){{ waves = true; @@ -66,8 +106,7 @@ public class Zones implements ContentList{ startingItems = ItemStack.list(Items.copper, 400); conditionWave = 20; launchPeriod = 20; - zoneRequirements = new Zone[]{frozenForest}; - itemRequirements = ItemStack.with(Items.lead, 6000, Items.graphite, 2000); + zoneRequirements = ZoneRequirement.with(frozenForest, 10, craters, 15); blockRequirements = new Block[]{Blocks.graphitePress, Blocks.combustionGenerator}; resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.sand}; rules = () -> new Rules(){{ @@ -92,17 +131,16 @@ public class Zones implements ContentList{ }};*/ stainedMountains = new Zone("stainedMountains", new MapGenerator("stainedMountains", 2) - .dist(2.5f, true) - .decor(new Decoration(Blocks.moss, Blocks.shaleBoulder, 0.02))){{ + .dist(0f, false) + .decor(new Decoration(Blocks.moss, Blocks.shaleBoulder, 0.02))){{ loadout = Loadouts.basicFoundation; baseLaunchCost = ItemStack.with(); startingItems = ItemStack.list(Items.copper, 400, Items.lead, 100); conditionWave = 10; launchPeriod = 10; - zoneRequirements = new Zone[]{frozenForest}; + zoneRequirements = ZoneRequirement.with(frozenForest, 15); blockRequirements = new Block[]{Blocks.pneumaticDrill}; - itemRequirements = ItemStack.with(Items.copper, 8000, Items.silicon, 2000); - resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.titanium}; + resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.titanium, Items.sand}; rules = () -> new Rules(){{ waves = true; waveTimer = true; @@ -114,16 +152,15 @@ public class Zones implements ContentList{ loadout = Loadouts.basicNucleus; baseLaunchCost = ItemStack.with(); startingItems = ItemStack.list(Items.copper, 1500); - itemRequirements = ItemStack.with(Items.copper, 8000, Items.metaglass, 2000, Items.graphite, 3000); conditionWave = 10; launchPeriod = 20; - zoneRequirements = new Zone[]{ruinousShores}; + zoneRequirements = ZoneRequirement.with(stainedMountains, 20); blockRequirements = new Block[]{Blocks.thermalGenerator}; 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 * 1.5f; + waveSpacing = 60 * 60 * 1.3f; }}; }}; @@ -133,11 +170,10 @@ public class Zones implements ContentList{ loadout = Loadouts.basicNucleus; baseLaunchCost = ItemStack.with(); startingItems = ItemStack.list(Items.copper, 2500, Items.lead, 3000, Items.silicon, 800, Items.metaglass, 400); - itemRequirements = ItemStack.with(Items.copper, 10000, Items.titanium, 8000, Items.metaglass, 6000, Items.plastanium, 2000); conditionWave = 30; launchPeriod = 15; - zoneRequirements = new Zone[]{desolateRift}; - blockRequirements = new Block[]{Blocks.blastDrill, Blocks.thermalGenerator}; + zoneRequirements = ZoneRequirement.with(desolateRift, 20); + blockRequirements = new Block[]{Blocks.thermalGenerator}; resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.titanium, Items.thorium, Items.sand}; rules = () -> new Rules(){{ waves = true; diff --git a/core/src/io/anuke/mindustry/core/ContentLoader.java b/core/src/io/anuke/mindustry/core/ContentLoader.java index 67bbf503ab..72df701ddc 100644 --- a/core/src/io/anuke/mindustry/core/ContentLoader.java +++ b/core/src/io/anuke/mindustry/core/ContentLoader.java @@ -1,8 +1,6 @@ package io.anuke.mindustry.core; -import io.anuke.arc.collection.Array; -import io.anuke.arc.collection.ObjectMap; -import io.anuke.arc.collection.ObjectSet; +import io.anuke.arc.collection.*; import io.anuke.arc.function.Consumer; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.Pixmap; @@ -10,14 +8,10 @@ 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.Fire; -import io.anuke.mindustry.entities.effect.Lightning; -import io.anuke.mindustry.entities.effect.Puddle; +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.Content; -import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.game.MappableContent; +import io.anuke.mindustry.game.*; import io.anuke.mindustry.type.*; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.LegacyColorMapper; @@ -58,7 +52,7 @@ public class ContentLoader{ verbose = true; } - /**Creates all content types.*/ + /** Creates all content types. */ public void load(){ if(loaded){ Log.info("Content already loaded, skipping."); @@ -69,7 +63,7 @@ public class ContentLoader{ for(ContentType type : ContentType.values()){ contentMap[type.ordinal()] = new Array<>(); - contentNameMap[type.ordinal()] = new ObjectMap<>(); + contentNameMap[type.ordinal()] = new ObjectMap<>(); } for(ContentList list : content){ @@ -82,13 +76,13 @@ public class ContentLoader{ for(Content c : contentMap[type.ordinal()]){ if(c instanceof MappableContent){ - String name = ((MappableContent) c).name; + String name = ((MappableContent)c).name; if(contentNameMap[type.ordinal()].containsKey(name)){ throw new IllegalArgumentException("Two content objects cannot have the same name! (issue: '" + name + "')"); } - contentNameMap[type.ordinal()].put(name, (MappableContent) c); + contentNameMap[type.ordinal()].put(name, (MappableContent)c); } - total ++; + total++; } } @@ -119,7 +113,7 @@ public class ContentLoader{ loaded = true; } - /**Initializes all content with the specified function.*/ + /** Initializes all content with the specified function. */ public void initialize(Consumer callable){ if(initialization.contains(callable)) return; @@ -132,7 +126,7 @@ public class ContentLoader{ initialization.add(callable); } - /**Loads block colors.*/ + /** Loads block colors. */ public void loadColors(){ Pixmap pixmap = new Pixmap(files.internal("sprites/block_colors.png")); for(int i = 0; i < 256; i++){ @@ -193,7 +187,7 @@ public class ContentLoader{ } public Array getBy(ContentType type){ - return (Array) contentMap[type.ordinal()]; + return (Array)contentMap[type.ordinal()]; } //utility methods, just makes things a bit shorter @@ -203,7 +197,7 @@ public class ContentLoader{ } public Block block(int id){ - return (Block) getByID(ContentType.block, id); + return (Block)getByID(ContentType.block, id); } public Array items(){ @@ -211,7 +205,7 @@ public class ContentLoader{ } public Item item(int id){ - return (Item) getByID(ContentType.item, id); + return (Item)getByID(ContentType.item, id); } public Array liquids(){ @@ -219,7 +213,7 @@ public class ContentLoader{ } public Liquid liquid(int id){ - return (Liquid) getByID(ContentType.liquid, id); + return (Liquid)getByID(ContentType.liquid, id); } public Array bullets(){ @@ -227,7 +221,7 @@ public class ContentLoader{ } public BulletType bullet(int id){ - return (BulletType) getByID(ContentType.bullet, id); + return (BulletType)getByID(ContentType.bullet, id); } public Array zones(){ @@ -250,5 +244,9 @@ public class ContentLoader{ TypeTrait.registerType(Lightning.class, Lightning::new); } - private class ImpendingDoomException extends RuntimeException{ ImpendingDoomException(String s){ super(s); }} + private class ImpendingDoomException extends RuntimeException{ + ImpendingDoomException(String s){ + super(s); + } + } } diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index 5a3f7d47f7..1de9fc48d4 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -1,30 +1,23 @@ package io.anuke.mindustry.core; -import io.anuke.arc.ApplicationListener; -import io.anuke.arc.Core; -import io.anuke.arc.Events; +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.util.Interval; -import io.anuke.arc.util.Strings; -import io.anuke.arc.util.Time; +import io.anuke.arc.scene.ui.Dialog; +import io.anuke.arc.scene.ui.TextField; +import io.anuke.arc.util.*; import io.anuke.mindustry.content.Mechs; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.EntityQuery; import io.anuke.mindustry.entities.type.Player; -import io.anuke.mindustry.game.Content; +import io.anuke.mindustry.game.*; import io.anuke.mindustry.game.EventType.*; -import io.anuke.mindustry.game.GlobalData; -import io.anuke.mindustry.game.Rules; -import io.anuke.mindustry.game.Saves; import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.input.Binding; -import io.anuke.mindustry.input.DesktopInput; -import io.anuke.mindustry.input.InputHandler; -import io.anuke.mindustry.input.MobileInput; +import io.anuke.mindustry.input.*; import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.type.Item; @@ -32,6 +25,7 @@ import io.anuke.mindustry.ui.dialogs.FloatingDialog; import io.anuke.mindustry.world.Tile; import java.io.IOException; +import java.nio.IntBuffer; import static io.anuke.arc.Core.scene; import static io.anuke.mindustry.Vars.*; @@ -48,9 +42,13 @@ public class Control implements ApplicationListener{ private Interval timer = new Interval(2); private boolean hiscore = false; private boolean wasPaused = false; - private InputHandler[] inputs = {}; + private InputHandler input; public Control(){ + IntBuffer buf = BufferUtils.newIntBuffer(1); + Core.gl.glGetIntegerv(GL20.GL_MAX_TEXTURE_SIZE, buf); + int maxSize = buf.get(0); + saves = new Saves(); data = new GlobalData(); @@ -59,7 +57,7 @@ public class Control implements ApplicationListener{ Effects.setShakeFalloff(10000f); content.initialize(Content::init); - Core.atlas = new TextureAtlas("sprites/sprites.atlas"); + Core.atlas = new TextureAtlas(maxSize < 2048 ? "sprites/sprites_fallback.atlas" : "sprites/sprites.atlas"); Draw.scl = 1f / Core.atlas.find("scale_marker").getWidth(); content.initialize(Content::load); @@ -76,7 +74,7 @@ public class Control implements ApplicationListener{ "lastBuild", 0 ); - addPlayer(0); + createPlayer(); saves.load(); @@ -87,21 +85,17 @@ public class Control implements ApplicationListener{ }); Events.on(PlayEvent.class, event -> { - for(Player player : players){ - player.add(); - } + player.add(); state.set(State.playing); }); Events.on(WorldLoadEvent.class, event -> { - Core.app.post(() -> Core.camera.position.set(players[0])); + Core.app.post(() -> Core.app.post(() -> Core.camera.position.set(player))); }); Events.on(ResetEvent.class, event -> { - for(Player player : players){ - player.reset(); - } + player.reset(); hiscore = false; @@ -135,7 +129,7 @@ public class Control implements ApplicationListener{ if(state.rules.pvp && !Net.active()){ try{ Net.host(port); - players[0].isAdmin = true; + player.isAdmin = true; }catch(IOException e){ ui.showError(Core.bundle.format("server.error", Strings.parseException(e, false))); Core.app.post(() -> state.set(State.menu)); @@ -146,29 +140,29 @@ public class Control implements ApplicationListener{ Events.on(UnlockEvent.class, e -> ui.hudfrag.showUnlock(e.content)); Events.on(BlockBuildEndEvent.class, e -> { - if(e.team == players[0].getTeam()){ + if(e.team == player.getTeam()){ if(e.breaking){ state.stats.buildingsDeconstructed++; }else{ - state.stats.buildingsBuilt ++; + state.stats.buildingsBuilt++; } } }); Events.on(BlockDestroyEvent.class, e -> { - if(e.tile.getTeam() == players[0].getTeam()){ - state.stats.buildingsDestroyed ++; + if(e.tile.getTeam() == player.getTeam()){ + state.stats.buildingsDestroyed++; } }); Events.on(UnitDestroyEvent.class, e -> { - if(e.unit.getTeam() != players[0].getTeam()){ - state.stats.enemyUnitsDestroyed ++; + if(e.unit.getTeam() != player.getTeam()){ + state.stats.enemyUnitsDestroyed++; } }); - Events.on(ZoneCompleteEvent.class, e -> { - ui.hudfrag.showToast(Core.bundle.format("zone.complete", e.zone.conditionWave)); + Events.on(ZoneRequireCompleteEvent.class, e -> { + ui.hudfrag.showToast(Core.bundle.format("zone.requirement.complete", state.wave, e.zone.localizedName)); }); Events.on(ZoneConfigureCompleteEvent.class, e -> { @@ -176,65 +170,29 @@ public class Control implements ApplicationListener{ }); } - public void addPlayer(int index){ - if(players.length != index + 1){ - Player[] old = players; - players = new Player[index + 1]; - System.arraycopy(old, 0, players, 0, old.length); - } - - if(inputs.length != index + 1){ - InputHandler[] oldi = inputs; - inputs = new InputHandler[index + 1]; - System.arraycopy(oldi, 0, inputs, 0, oldi.length); - } - - Player setTo = (index == 0 ? null : players[0]); - - Player player = new Player(); + void createPlayer(){ + player = new Player(); player.name = Core.settings.getString("name"); player.mech = mobile ? Mechs.starterMobile : Mechs.starterDesktop; - player.color.set(Core.settings.getInt("color-" + index)); + player.color.set(Core.settings.getInt("color-0")); player.isLocal = true; - player.playerIndex = index; player.isMobile = mobile; - players[index] = player; - if(setTo != null){ - player.set(setTo.x, setTo.y); + if(mobile){ + input = new MobileInput(); + }else{ + input = new DesktopInput(); } if(!state.is(State.menu)){ player.add(); } - InputHandler input; - - if(mobile){ - input = new MobileInput(player); - }else{ - input = new DesktopInput(player); - } - - inputs[index] = input; Core.input.addProcessor(input); } - public void removePlayer(){ - players[players.length - 1].remove(); - inputs[inputs.length - 1].remove(); - - Player[] old = players; - players = new Player[players.length - 1]; - System.arraycopy(old, 0, players, 0, players.length); - - InputHandler[] oldi = inputs; - inputs = new InputHandler[inputs.length - 1]; - System.arraycopy(oldi, 0, inputs, 0, inputs.length); - } - - public InputHandler input(int index){ - return inputs[index]; + public InputHandler input(){ + return input; } public void playMap(Map map, Rules rules){ @@ -255,8 +213,6 @@ public class Control implements ApplicationListener{ content.dispose(); Net.dispose(); ui.editor.dispose(); - inputs = new InputHandler[]{}; - players = new Player[]{}; } @Override @@ -288,9 +244,9 @@ public class Control implements ApplicationListener{ Core.settings.save(); }).size(100f, 60f); dialog.cont.add("Reminder: The alpha version you are about to play is very unstable, and is [accent]not representative of the final v4 release.[]\n\n " + - "\nThere is currently[scarlet] no sound implemented[]; this is intentional.\n" + - "All current art and UI is unfinished, and will be changed before release. " + - "\n\n[accent]Saves may be corrupted without warning between updates.").wrap().width(400f); + "\nThere is currently[scarlet] no sound implemented[]; this is intentional.\n" + + "All current art and UI is unfinished, and will be changed before release. " + + "\n\n[accent]Saves may be corrupted without warning between updates.").wrap().width(400f); dialog.show(); }); } @@ -300,20 +256,16 @@ public class Control implements ApplicationListener{ public void update(){ saves.update(); - for(InputHandler inputHandler : inputs){ - inputHandler.updateController(); - } + input.updateController(); //autosave global data if it's modified data.checkSave(); if(!state.is(State.menu)){ - for(InputHandler input : inputs){ - input.update(); - } + input.update(); if(world.isZone()){ - for(Tile tile : state.teams.get(players[0].getTeam()).cores){ + for(Tile tile : state.teams.get(player.getTeam()).cores){ for(Item item : content.items()){ if(tile.entity.items.has(item)){ data.unlockContent(item); @@ -340,10 +292,18 @@ public class Control implements ApplicationListener{ } } + if(!mobile && Core.input.keyTap(Binding.screenshot) && !(scene.getKeyboardFocus() instanceof TextField) && !ui.chatfrag.chatOpen()){ + renderer.takeMapScreenshot(); + } + }else{ if(!state.isPaused()){ Time.update(); } + + if(!scene.hasDialog() && !(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 9765ae1786..2cedcda4bc 100644 --- a/core/src/io/anuke/mindustry/core/GameState.java +++ b/core/src/io/anuke/mindustry/core/GameState.java @@ -3,30 +3,28 @@ package io.anuke.mindustry.core; import io.anuke.arc.Events; import io.anuke.mindustry.entities.type.BaseUnit; import io.anuke.mindustry.game.EventType.StateChangeEvent; -import io.anuke.mindustry.game.Rules; -import io.anuke.mindustry.game.Stats; -import io.anuke.mindustry.game.Teams; +import io.anuke.mindustry.game.*; import io.anuke.mindustry.net.Net; import static io.anuke.mindustry.Vars.unitGroups; import static io.anuke.mindustry.Vars.waveTeam; public class GameState{ - /**Current wave number, can be anything in non-wave modes.*/ + /** Current wave number, can be anything in non-wave modes. */ public int wave = 1; - /**Wave countdown in ticks.*/ + /** Wave countdown in ticks. */ public float wavetime; - /**Whether the game is in game over state.*/ + /** Whether the game is in game over state. */ public boolean gameOver = false, launched = false; - /**The current game rules.*/ + /** The current game rules. */ public Rules rules = new Rules(); - /**Statistics for this save/game. Displayed after game over.*/ + /** Statistics for this save/game. Displayed after game over. */ public Stats stats = new Stats(); - /**Team data. Gets reset every new game.*/ + /** Team data. Gets reset every new game. */ public Teams teams = new Teams(); - /**Number of enemies in the game; only used clientside in servers.*/ + /** Number of enemies in the game; only used clientside in servers. */ public int enemies; - /**Current game state.*/ + /** Current game state. */ private State state = State.menu; public int enemies(){ diff --git a/core/src/io/anuke/mindustry/core/Logic.java b/core/src/io/anuke/mindustry/core/Logic.java index 565685ad57..a450acf61c 100644 --- a/core/src/io/anuke/mindustry/core/Logic.java +++ b/core/src/io/anuke/mindustry/core/Logic.java @@ -8,15 +8,9 @@ import io.anuke.arc.collection.ObjectSet.ObjectSetIterator; import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.Entities; -import io.anuke.mindustry.entities.EntityGroup; -import io.anuke.mindustry.entities.EntityQuery; +import io.anuke.mindustry.entities.*; import io.anuke.mindustry.entities.type.TileEntity; -import io.anuke.mindustry.game.EventType.GameOverEvent; -import io.anuke.mindustry.game.EventType.PlayEvent; -import io.anuke.mindustry.game.EventType.ResetEvent; -import io.anuke.mindustry.game.EventType.WaveEvent; +import io.anuke.mindustry.game.EventType.*; import io.anuke.mindustry.game.*; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.type.Item; @@ -51,7 +45,7 @@ public class Logic implements ApplicationListener{ }); } - /**Handles the event of content being used by either the player or some block.*/ + /** Handles the event of content being used by either the player or some block. */ public void handleContent(UnlockableContent content){ if(!headless){ data.unlockContent(content); @@ -85,7 +79,7 @@ public class Logic implements ApplicationListener{ world.spawner.spawnEnemies(); state.wave++; state.wavetime = world.isZone() && world.getZone().isBossWave(state.wave) ? state.rules.waveSpacing * bossWaveMultiplier : - world.isZone() && world.getZone().isLaunchWave(state.wave) ? state.rules.waveSpacing * launchWaveMultiplier : state.rules.waveSpacing; + world.isZone() && world.getZone().isLaunchWave(state.wave) ? state.rules.waveSpacing * launchWaveMultiplier : state.rules.waveSpacing; Events.fire(new WaveEvent()); } diff --git a/core/src/io/anuke/mindustry/core/NetClient.java b/core/src/io/anuke/mindustry/core/NetClient.java index 6d2b6d8632..534d98093c 100644 --- a/core/src/io/anuke/mindustry/core/NetClient.java +++ b/core/src/io/anuke/mindustry/core/NetClient.java @@ -1,17 +1,12 @@ package io.anuke.mindustry.core; -import io.anuke.annotations.Annotations.Loc; -import io.anuke.annotations.Annotations.PacketPriority; -import io.anuke.annotations.Annotations.Remote; -import io.anuke.annotations.Annotations.Variant; +import io.anuke.annotations.Annotations.*; import io.anuke.arc.ApplicationListener; import io.anuke.arc.Core; import io.anuke.arc.collection.IntSet; import io.anuke.arc.graphics.Color; import io.anuke.arc.math.RandomXS128; -import io.anuke.arc.util.Interval; -import io.anuke.arc.util.Log; -import io.anuke.arc.util.Time; +import io.anuke.arc.util.*; import io.anuke.arc.util.io.ReusableByteArrayInputStream; import io.anuke.arc.util.serialization.Base64Coder; import io.anuke.mindustry.Vars; @@ -25,11 +20,9 @@ import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.game.Version; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.gen.RemoteReadClient; -import io.anuke.mindustry.net.Net; +import io.anuke.mindustry.net.*; import io.anuke.mindustry.net.Net.SendMode; -import io.anuke.mindustry.net.NetworkIO; import io.anuke.mindustry.net.Packets.*; -import io.anuke.mindustry.net.ValidateException; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.modules.ItemModule; @@ -45,25 +38,25 @@ public class NetClient implements ApplicationListener{ public final static float viewScale = 2f; private Interval timer = new Interval(5); - /**Whether the client is currently connecting.*/ + /** Whether the client is currently connecting. */ private boolean connecting = false; - /**If true, no message will be shown on disconnect.*/ + /** If true, no message will be shown on disconnect. */ private boolean quiet = false; - /**Counter for data timeout.*/ + /** Counter for data timeout. */ private float timeoutTime = 0f; - /**Last sent client snapshot ID.*/ + /** Last sent client snapshot ID. */ private int lastSent; - /**List of entities that were removed, and need not be added while syncing.*/ + /** List of entities that were removed, and need not be added while syncing. */ private IntSet removed = new IntSet(); - /**Byte stream for reading in snapshots.*/ + /** Byte stream for reading in snapshots. */ private ReusableByteArrayInputStream byteStream = new ReusableByteArrayInputStream(); private DataInputStream dataStream = new DataInputStream(byteStream); public NetClient(){ Net.handleClient(Connect.class, packet -> { - Player player = players[0]; + Log.info("Connecting to server: {0}", packet.addressTCP); player.isAdmin = false; @@ -100,6 +93,7 @@ public class NetClient implements ApplicationListener{ Net.handleClient(Disconnect.class, packet -> { state.set(State.menu); connecting = false; + logic.reset(); Platform.instance.updateRPC(); if(quiet) return; @@ -122,26 +116,42 @@ public class NetClient implements ApplicationListener{ }); } - @Remote(called = Loc.server, targets = Loc.both, forward = true) - public static void sendMessage(Player player, String message){ - if(message.length() > maxTextLength){ - throw new ValidateException(player, "Player has sent a message above the text limit."); + //called on all clients + @Remote(called = Loc.server, targets = Loc.server) + public static void sendMessage(String message, String sender, Player playersender){ + if(Vars.ui != null){ + Vars.ui.chatfrag.addMessage(message, sender); } - Log.info("&y{0}: &lb{1}", (player == null || player.name == null ? "" : player.name), message); - - if(Vars.ui != null){ - Vars.ui.chatfrag.addMessage(message, player == null ? null : colorizeName(player.id, player.name)); + if(playersender != null){ + playersender.lastText = message; + playersender.textFadeTime = 1f; } } - @Remote(called = Loc.server, variants = Variant.both, forward = true) + //equivalent to above method but there's no sender and no console log + @Remote(called = Loc.server, targets = Loc.server) public static void sendMessage(String message){ if(Vars.ui != null){ Vars.ui.chatfrag.addMessage(message, null); } } + //called when a server recieves a chat message from a player + @Remote(called = Loc.server, targets = Loc.client) + public static void sendChatMessage(Player player, String message){ + if(message.length() > maxTextLength){ + throw new ValidateException(player, "Player has sent a message above the text limit."); + } + + //server console logging + Log.info("&y{0}: &lb{1}", player.name, message); + + //invoke event for all clients but also locally + //this is required so other clients get the correct name even if they don't know who's sending it yet + Call.sendMessage(message, colorizeName(player.id, player.name), player); + } + private static String colorizeName(int id, String name){ Player player = playerGroup.getByID(id); if(name == null || player == null) return null; @@ -188,8 +198,8 @@ public class NetClient implements ApplicationListener{ @Remote(variants = Variant.one) public static void onPositionSet(float x, float y){ - players[0].x = x; - players[0].y = y; + player.x = x; + player.y = y; } @Remote @@ -210,12 +220,17 @@ public class NetClient implements ApplicationListener{ int id = input.readInt(); byte typeID = input.readByte(); - SyncTrait entity = (SyncTrait) group.getByID(id); + SyncTrait entity = (SyncTrait)group.getByID(id); boolean add = false; + if(entity == null && id == player.id){ + entity = player; + add = true; + } + //entity must not be added yet, so create it if(entity == null){ - entity = (SyncTrait) TypeTrait.getTypeByID(typeID).get(); //create entity from supplier + entity = (SyncTrait)TypeTrait.getTypeByID(typeID).get(); //create entity from supplier entity.resetID(id); if(!netClient.isEntityUsed(entity.getID())){ add = true; @@ -249,6 +264,7 @@ public class NetClient implements ApplicationListener{ for(int i = 0; i < cores; i++){ int pos = input.readInt(); Tile tile = world.tile(pos); + if(tile != null && tile.entity != null){ tile.entity.items.read(input); }else{ @@ -317,7 +333,7 @@ public class NetClient implements ApplicationListener{ Net.disconnect(); } - /**When set, any disconnects will be ignored and no dialogs will be shown.*/ + /** When set, any disconnects will be ignored and no dialogs will be shown. */ public void setQuiet(){ quiet = true; } @@ -333,8 +349,6 @@ public class NetClient implements ApplicationListener{ void sync(){ if(timer.get(0, playerSyncTime)){ - Player player = players[0]; - BuildRequest[] requests; //limit to 10 to prevent buffer overflows int usedRequests = Math.min(player.getPlaceQueue().size, 10); @@ -345,12 +359,13 @@ public class NetClient implements ApplicationListener{ } Call.onClientShapshot(lastSent++, player.x, player.y, - player.pointerX, player.pointerY, player.rotation, player.baseRotation, - player.velocity().x, player.velocity().y, - player.getMineTile(), - player.isBoosting, player.isShooting, requests, - Core.camera.position.x, Core.camera.position.y, - Core.camera.width * viewScale, Core.camera.height * viewScale); + player.pointerX, player.pointerY, player.rotation, player.baseRotation, + player.velocity().x, player.velocity().y, + player.getMineTile(), + player.isBoosting, player.isShooting, ui.chatfrag.chatOpen(), + requests, + Core.camera.position.x, Core.camera.position.y, + Core.camera.width * viewScale, Core.camera.height * viewScale); } if(timer.get(1, 60)){ diff --git a/core/src/io/anuke/mindustry/core/NetServer.java b/core/src/io/anuke/mindustry/core/NetServer.java index 8c70a164ae..9a812ef964 100644 --- a/core/src/io/anuke/mindustry/core/NetServer.java +++ b/core/src/io/anuke/mindustry/core/NetServer.java @@ -4,18 +4,13 @@ import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.ApplicationListener; import io.anuke.arc.Events; -import io.anuke.arc.collection.Array; -import io.anuke.arc.collection.IntMap; -import io.anuke.arc.collection.ObjectSet; +import io.anuke.arc.collection.*; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.Colors; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.math.geom.Vector2; -import io.anuke.arc.util.Log; -import io.anuke.arc.util.Structs; -import io.anuke.arc.util.Time; -import io.anuke.arc.util.Tmp; +import io.anuke.arc.util.*; import io.anuke.arc.util.io.ByteBufferOutput; import io.anuke.arc.util.io.CountableByteArrayOutputStream; import io.anuke.mindustry.content.Blocks; @@ -23,7 +18,6 @@ import io.anuke.mindustry.content.Mechs; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.Entities; import io.anuke.mindustry.entities.EntityGroup; -import io.anuke.mindustry.entities.EntityQuery; import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest; import io.anuke.mindustry.entities.traits.Entity; import io.anuke.mindustry.entities.traits.SyncTrait; @@ -33,18 +27,13 @@ import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Version; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.gen.RemoteReadServer; -import io.anuke.mindustry.net.Administration; +import io.anuke.mindustry.net.*; import io.anuke.mindustry.net.Administration.PlayerInfo; -import io.anuke.mindustry.net.Net; -import io.anuke.mindustry.net.NetConnection; -import io.anuke.mindustry.net.NetworkIO; import io.anuke.mindustry.net.Packets.*; import io.anuke.mindustry.world.Tile; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.IOException; +import java.io.*; +import java.lang.StringBuilder; import java.nio.ByteBuffer; import java.util.zip.DeflaterOutputStream; @@ -52,25 +41,24 @@ import static io.anuke.mindustry.Vars.*; public class NetServer implements ApplicationListener{ public final static int maxSnapshotSize = 430; - private final static float serverSyncTime = 4, kickDuration = 30 * 1000; + private final static float serverSyncTime = 20, kickDuration = 30 * 1000; private final static Vector2 vector = new Vector2(); private final static Rectangle viewport = new Rectangle(); - private final static Array returnArray = new Array<>(); - /**If a player goes away of their server-side coordinates by this distance, they get teleported back.*/ + /** If a player goes away of their server-side coordinates by this distance, they get teleported back. */ private final static float correctDist = 16f; public final Administration admins = new Administration(); - /**Maps connection IDs to players.*/ + /** Maps connection IDs to players. */ private IntMap connections = new IntMap<>(); private boolean closing = false; private ByteBuffer writeBuffer = ByteBuffer.allocate(127); private ByteBufferOutput outputBuffer = new ByteBufferOutput(writeBuffer); - /**Stream for writing player sync data to.*/ + /** Stream for writing player sync data to. */ private CountableByteArrayOutputStream syncStream = new CountableByteArrayOutputStream(); - /**Data stream for writing player sync data to.*/ + /** Data stream for writing player sync data to. */ private DataOutputStream dataStream = new DataOutputStream(syncStream); public NetServer(){ @@ -100,7 +88,7 @@ public class NetServer implements ApplicationListener{ NetConnection connection = Net.getConnection(id); if(connection == null || - admins.isIPBanned(connection.address)) return; + admins.isIPBanned(connection.address)) return; if(connection.hasBegunConnecting){ kick(id, KickReason.idInUse); @@ -190,20 +178,7 @@ public class NetServer implements ApplicationListener{ //playing in pvp mode automatically assigns players to teams if(state.rules.pvp){ - //find team with minimum amount of players and auto-assign player to that. - Team min = Structs.findMin(Team.all, team -> { - if(state.teams.isActive(team)){ - int count = 0; - for(Player other : playerGroup.all()){ - if(other.getTeam() == team){ - count ++; - } - } - return count; - } - return Integer.MAX_VALUE; - }); - player.setTeam(min); + player.setTeam(assignTeam(playerGroup.all())); Log.info("Auto-assigned player {0} to team {1}.", player.name, player.getTeam()); } @@ -221,6 +196,22 @@ public class NetServer implements ApplicationListener{ }); } + public Team assignTeam(Iterable players){ + //find team with minimum amount of players and auto-assign player to that. + return Structs.findMin(Team.all, team -> { + if(state.teams.isActive(team)){ + int count = 0; + for(Player other : players){ + if(other.getTeam() == team){ + count++; + } + } + return count; + } + return Integer.MAX_VALUE; + }); + } + public void sendWorldData(Player player, int clientID){ ByteArrayOutputStream stream = new ByteArrayOutputStream(); DeflaterOutputStream def = new DeflaterOutputStream(stream); @@ -259,16 +250,16 @@ public class NetServer implements ApplicationListener{ @Remote(targets = Loc.client, unreliable = true) public static void onClientShapshot( - Player player, - int snapshotID, - float x, float y, - float pointerX, float pointerY, - float rotation, float baseRotation, - float xVelocity, float yVelocity, - Tile mining, - boolean boosting, boolean shooting, - BuildRequest[] requests, - float viewX, float viewY, float viewWidth, float viewHeight + Player player, + int snapshotID, + float x, float y, + float pointerX, float pointerY, + float rotation, float baseRotation, + float xVelocity, float yVelocity, + Tile mining, + boolean boosting, boolean shooting, boolean chatting, + BuildRequest[] requests, + float viewX, float viewY, float viewWidth, float viewHeight ){ NetConnection connection = player.con; if(connection == null || snapshotID < connection.lastRecievedClientSnapshot) return; @@ -290,14 +281,17 @@ public class NetServer implements ApplicationListener{ player.pointerX = pointerX; player.pointerY = pointerY; player.setMineTile(mining); + player.isTyping = chatting; player.isBoosting = boosting; player.isShooting = shooting; player.getPlaceQueue().clear(); for(BuildRequest req : requests){ + Tile tile = world.tile(req.x, req.y); + if(tile == null) continue; //auto-skip done requests - if(req.breaking && world.tile(req.x, req.y).block() == Blocks.air){ + if(req.breaking && tile.block() == Blocks.air){ continue; - }else if(!req.breaking && world.tile(req.x, req.y).block() == req.block && (!req.block.rotate || world.tile(req.x, req.y).getRotation() == req.rotation)){ + }else if(!req.breaking && tile.block() == req.block && (!req.block.rotate || tile.getRotation() == req.rotation)){ continue; } player.getPlaceQueue().addLast(req); @@ -342,7 +336,7 @@ public class NetServer implements ApplicationListener{ if(!player.isAdmin){ Log.warn("ACCESS DENIED: Player {0} / {1} attempted to perform admin action without proper security access.", - player.name, player.con.address); + player.name, player.con.address); return; } @@ -388,7 +382,7 @@ public class NetServer implements ApplicationListener{ int used = 0; for(Team t : Team.all){ if(playerGroup.count(p -> p.getTeam() == t) > 0){ - used ++; + used++; } } return used < 2; @@ -425,7 +419,7 @@ public class NetServer implements ApplicationListener{ Log.err("Cannot kick unknown player!"); return; }else{ - Log.info("Kicking connection #{0} / IP: {1}. Reason: {2}", connection, con.address, reason); + Log.info("Kicking connection #{0} / IP: {1}. Reason: {2}", connection, con.address, reason.name()); } Player player = connections.get(con.id); @@ -458,47 +452,33 @@ public class NetServer implements ApplicationListener{ byte[] stateBytes = syncStream.toByteArray(); //write basic state data. - Call.onStateSnapshot(player.con.id, state.wavetime, state.wave, state.enemies, (short)stateBytes.length, Net.compressSnapshot(stateBytes)); + Call.onStateSnapshot(player.con.id, state.wavetime, state.wave, state.enemies(), (short)stateBytes.length, Net.compressSnapshot(stateBytes)); viewport.setSize(player.con.viewWidth, player.con.viewHeight).setCenter(player.con.viewX, player.con.viewY); //check for syncable groups for(EntityGroup group : Entities.getAllGroups()){ if(group.isEmpty() || !(group.all().get(0) instanceof SyncTrait)) continue; - //clipping is done by representatives - SyncTrait represent = (SyncTrait) group.all().get(0); //make sure mapping is enabled for this group if(!group.mappingEnabled()){ throw new RuntimeException("Entity group '" + group.getType() + "' contains SyncTrait entities, yet mapping is not enabled. In order for syncing to work, you must enable mapping for this group."); } - returnArray.clear(); - if(represent.isClipped()){ - EntityQuery.getNearby(group, viewport, entity -> { - if(((SyncTrait) entity).isSyncing() && viewport.overlaps(Tmp.r3.setSize(((SyncTrait)entity).clipSize(), ((SyncTrait)entity).clipSize()).setCenter(entity.getX(), entity.getY()))){ - returnArray.add(entity); - } - }); - }else{ - for(Entity entity : group.all()){ - if(((SyncTrait) entity).isSyncing()){ - returnArray.add(entity); - } - } - } - syncStream.reset(); int sent = 0; - for(Entity entity : returnArray){ + for(Entity entity : group.all()){ + SyncTrait sync = (SyncTrait)entity; + if(!sync.isSyncing()) continue; + //write all entities now dataStream.writeInt(entity.getID()); //write id - dataStream.writeByte(((SyncTrait) entity).getTypeID()); //write type ID - ((SyncTrait) entity).write(dataStream); //write entity + dataStream.writeByte(sync.getTypeID()); //write type ID + sync.write(dataStream); //write entity - sent ++; + sent++; if(syncStream.position() > maxSnapshotSize){ dataStream.close(); @@ -573,7 +553,7 @@ public class NetServer implements ApplicationListener{ try{ //iterate through each player - for(int i = 0; i < playerGroup.size(); i ++){ + for(int i = 0; i < playerGroup.size(); i++){ Player player = playerGroup.all().get(i); if(player.isLocal) continue; diff --git a/core/src/io/anuke/mindustry/core/Platform.java b/core/src/io/anuke/mindustry/core/Platform.java index 4e7591f323..381865907b 100644 --- a/core/src/io/anuke/mindustry/core/Platform.java +++ b/core/src/io/anuke/mindustry/core/Platform.java @@ -10,15 +10,17 @@ import io.anuke.arc.util.serialization.Base64Coder; import static io.anuke.mindustry.Vars.mobile; -public abstract class Platform { - /**Each separate game platform should set this instance to their own implementation.*/ - public static Platform instance = new Platform() {}; +public abstract class Platform{ + /** Each separate game platform should set this instance to their own implementation. */ + public static Platform instance = new Platform(){ + }; - /**Add a text input dialog that should show up after the field is tapped.*/ + /** Add a text input dialog that should show up after the field is tapped. */ public void addDialog(TextField field){ addDialog(field, 16); } - /**See addDialog().*/ + + /** See addDialog(). */ public void addDialog(TextField field, int maxLength){ if(!mobile) return; //this is mobile only, desktop doesn't need dialogs @@ -35,15 +37,17 @@ public abstract class Platform { Core.input.getTextInput(input); }); } - /**Update discord RPC.*/ - public void updateRPC(){} - /**Open donation dialog. Currently android only.*/ - public void openDonations(){} - /**Whether donating is supported.*/ + + /** Update discord RPC. */ + public void updateRPC(){ + } + + /** Whether donating is supported. */ public boolean canDonate(){ return false; } - /**Must be a base64 string 8 bytes in length.*/ + + /** Must be a base64 string 8 bytes in length. */ public String getUUID(){ String uuid = Core.settings.getString("uuid", ""); if(uuid.isEmpty()){ @@ -56,22 +60,31 @@ public abstract class Platform { } return uuid; } - /**Only used for iOS or android: open the share menu for a map or save.*/ - public void shareFile(FileHandle file){} - /**Show a file chooser. Desktop only. - * + /** Only used for iOS or android: open the share menu for a map or save. */ + public void shareFile(FileHandle file){ + } + + /** + * Show a file chooser. Desktop only. * @param text File chooser title text * @param content Description of the type of files to be loaded * @param cons Selection listener * @param open Whether to open or save files * @param filetype File extension to filter */ - public void showFileChooser(String text, String content, Consumer cons, boolean open, String filetype){} + public void showFileChooser(String text, String content, Consumer cons, boolean open, String filetype){ + } - /**Forces the app into landscape mode. Currently Android only.*/ - public void beginForceLandscape(){} + /** Hide the app. Android only. */ + public void hide(){ + } - /**Stops forcing the app into landscape orientation. Currently Android only.*/ - public void endForceLandscape(){} + /** Forces the app into landscape mode. Currently Android only. */ + public void beginForceLandscape(){ + } + + /** Stops forcing the app into landscape orientation. Currently Android only. */ + public void endForceLandscape(){ + } } \ No newline at end of file diff --git a/core/src/io/anuke/mindustry/core/Renderer.java b/core/src/io/anuke/mindustry/core/Renderer.java index c6518854a9..9e4c6bfb2d 100644 --- a/core/src/io/anuke/mindustry/core/Renderer.java +++ b/core/src/io/anuke/mindustry/core/Renderer.java @@ -2,35 +2,25 @@ package io.anuke.mindustry.core; import io.anuke.arc.ApplicationListener; import io.anuke.arc.Core; +import io.anuke.arc.files.FileHandle; import io.anuke.arc.function.Consumer; import io.anuke.arc.function.Predicate; -import io.anuke.arc.graphics.Camera; -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.SpriteBatch; +import io.anuke.arc.graphics.*; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.graphics.glutils.FrameBuffer; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.math.geom.Vector2; -import io.anuke.arc.util.Time; -import io.anuke.arc.util.Tmp; +import io.anuke.arc.util.*; import io.anuke.arc.util.pooling.Pools; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.EntityDraw; -import io.anuke.mindustry.entities.EntityGroup; +import io.anuke.mindustry.entities.*; import io.anuke.mindustry.entities.effect.GroundEffectEntity; import io.anuke.mindustry.entities.effect.GroundEffectEntity.GroundEffect; import io.anuke.mindustry.entities.impl.EffectEntity; -import io.anuke.mindustry.entities.traits.BelowLiquidTrait; -import io.anuke.mindustry.entities.traits.DrawTrait; -import io.anuke.mindustry.entities.traits.Entity; -import io.anuke.mindustry.entities.type.BaseUnit; -import io.anuke.mindustry.entities.type.Player; -import io.anuke.mindustry.entities.type.TileEntity; -import io.anuke.mindustry.entities.type.Unit; +import io.anuke.mindustry.entities.traits.*; +import io.anuke.mindustry.entities.type.*; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.graphics.*; import io.anuke.mindustry.world.blocks.defense.ForceProjector.ShieldEntity; @@ -42,6 +32,7 @@ public class Renderer implements ApplicationListener{ public final BlockRenderer blocks = new BlockRenderer(); public final MinimapRenderer minimap = new MinimapRenderer(); public final OverlayRenderer overlays = new OverlayRenderer(); + public final Pixelator pixelator = new Pixelator(); public FrameBuffer shieldBuffer = new FrameBuffer(2, 2); private Color clearColor; @@ -53,7 +44,7 @@ public class Renderer implements ApplicationListener{ public Renderer(){ batch = new SpriteBatch(4096); camera = new Camera(); - Lines.setCircleVertices(14); + Lines.setCircleVertices(20); Shaders.init(); Effects.setScreenShakeProvider((intensity, duration) -> { @@ -78,7 +69,7 @@ public class Renderer implements ApplicationListener{ entity.id++; entity.set(x, y); if(data instanceof Entity){ - entity.setParent((Entity) data); + entity.setParent((Entity)data); } effectGroup.add(entity); }else{ @@ -90,7 +81,7 @@ public class Renderer implements ApplicationListener{ entity.data = data; entity.set(x, y); if(data instanceof Entity){ - entity.setParent((Entity) data); + entity.setParent((Entity)data); } groundEffectGroup.add(entity); } @@ -113,11 +104,11 @@ public class Renderer implements ApplicationListener{ if(state.is(State.menu)){ graphics.clear(Color.BLACK); }else{ - Vector2 position = Tmp.v3.set(players[0]); + Vector2 position = Tmp.v3.set(player); - if(players[0].isDead()){ - TileEntity core = players[0].getClosestCore(); - if(core != null && players[0].spawner == null){ + if(player.isDead()){ + TileEntity core = player.getClosestCore(); + if(core != null && player.spawner == null){ camera.position.lerpDelta(core.x, core.y, 0.08f); }else{ camera.position.lerpDelta(position, 0.08f); @@ -127,8 +118,11 @@ public class Renderer implements ApplicationListener{ } updateShake(0.75f); - - draw(); + if(pixelator.enabled()){ + pixelator.drawPixelate(); + }else{ + draw(); + } } } @@ -148,13 +142,13 @@ public class Renderer implements ApplicationListener{ camera.update(); if(Float.isNaN(camera.position.x) || Float.isNaN(camera.position.y)){ - camera.position.x = players[0].x; - camera.position.y = players[0].y; + camera.position.x = player.x; + camera.position.y = player.y; } graphics.clear(clearColor); - if(graphics.getWidth() >= 2 && graphics.getHeight() >= 2 && (shieldBuffer.getWidth() != graphics.getWidth() || shieldBuffer.getHeight() != graphics.getHeight())){ + if(!graphics.isHidden() && (Core.settings.getBool("animatedwater") || Core.settings.getBool("animatedshields")) && (shieldBuffer.getWidth() != graphics.getWidth() || shieldBuffer.getHeight() != graphics.getHeight())){ shieldBuffer.resize(graphics.getWidth(), graphics.getHeight()); } @@ -169,6 +163,7 @@ public class Renderer implements ApplicationListener{ blocks.processBlocks(); blocks.drawShadows(); + Draw.color(); blocks.floor.beginDraw(); blocks.floor.drawLayer(CacheLayer.walls); @@ -183,6 +178,8 @@ public class Renderer implements ApplicationListener{ blocks.drawBlocks(Layer.overlay); + drawGroundShadows(); + drawAllTeams(false); blocks.skipLayer(Layer.turret); @@ -199,30 +196,54 @@ public class Renderer implements ApplicationListener{ drawAndInterpolate(playerGroup, p -> true, Player::drawBuildRequests); if(EntityDraw.countInBounds(shieldGroup) > 0){ - Draw.flush(); - shieldBuffer.begin(); - graphics.clear(Color.CLEAR); - EntityDraw.draw(shieldGroup); - EntityDraw.drawWith(shieldGroup, shield -> true, shield -> ((ShieldEntity)shield).drawOver()); - Draw.flush(); - shieldBuffer.end(); - Draw.shader(Shaders.shield); - Draw.color(Pal.accent); - Draw.rect(Draw.wrap(shieldBuffer.getTexture()), camera.position.x, camera.position.y, camera.width, -camera.height); - Draw.color(); - Draw.shader(); + if(settings.getBool("animatedshields")){ + Draw.flush(); + shieldBuffer.begin(); + graphics.clear(Color.CLEAR); + EntityDraw.draw(shieldGroup); + EntityDraw.drawWith(shieldGroup, shield -> true, shield -> ((ShieldEntity)shield).drawOver()); + Draw.flush(); + shieldBuffer.end(); + Draw.shader(Shaders.shield); + Draw.color(Pal.accent); + Draw.rect(Draw.wrap(shieldBuffer.getTexture()), camera.position.x, camera.position.y, camera.width, -camera.height); + Draw.color(); + Draw.shader(); + }else{ + EntityDraw.drawWith(shieldGroup, shield -> true, shield -> ((ShieldEntity)shield).drawSimple()); + } } overlays.drawTop(); - EntityDraw.setClip(false); drawAndInterpolate(playerGroup, p -> !p.isDead() && !p.isLocal, Player::drawName); - EntityDraw.setClip(true); Draw.color(); Draw.flush(); } + private void drawGroundShadows(){ + Draw.color(0, 0, 0, 0.4f); + float rad = 1.6f; + + Consumer draw = u -> { + float size = Math.max(u.getIconRegion().getWidth(), u.getIconRegion().getHeight()) * Draw.scl; + Draw.rect("circle-shadow", u.x, u.y, size * rad, size * rad); + }; + + for(EntityGroup group : unitGroups){ + if(!group.isEmpty()){ + drawAndInterpolate(group, unit -> !unit.isDead(), draw::accept); + } + } + + if(!playerGroup.isEmpty()){ + drawAndInterpolate(playerGroup, unit -> !unit.isDead(), draw::accept); + } + + Draw.color(); + } + private void drawFlyerShadows(){ float trnsX = -12, trnsY = -13; Draw.color(0, 0, 0, 0.22f); @@ -245,7 +266,7 @@ public class Renderer implements ApplicationListener{ EntityGroup group = unitGroups[team.ordinal()]; if(group.count(p -> p.isFlying() == flying) + - playerGroup.count(p -> p.isFlying() == flying && p.getTeam() == team) == 0 && flying) continue; + 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); @@ -271,10 +292,6 @@ public class Renderer implements ApplicationListener{ EntityDraw.drawWith(group, toDraw, drawer); } - public float cameraScale(){ - return camerascale; - } - public void scaleCamera(float amount){ targetscale += amount; clampScale(); @@ -282,7 +299,68 @@ public class Renderer implements ApplicationListener{ public void clampScale(){ float s = io.anuke.arc.scene.ui.layout.Unit.dp.scl(1f); - targetscale = Mathf.clamp(targetscale, s * 1.5f, Math.round(s * 5)); + targetscale = Mathf.clamp(targetscale, s * 1.5f, Math.round(s * 6)); + } + + public float getScale(){ + return targetscale; + } + + public void setScale(float scl){ + targetscale = scl; + clampScale(); + } + + public void takeMapScreenshot(){ + drawGroundShadows(); + + int w = world.width() * tilesize, h = world.height() * tilesize; + int memory = w * h * 4 / 1024 / 1024; + + if(memory >= 65){ + ui.showInfo("$screenshot.invalid"); + return; + } + + boolean hadShields = Core.settings.getBool("animatedshields"); + boolean hadWater = Core.settings.getBool("animatedwater"); + Core.settings.put("animatedwater", false); + Core.settings.put("animatedshields", false); + + FrameBuffer buffer = new FrameBuffer(w, h); + + float vpW = camera.width, vpH = camera.height, px = camera.position.x, py = camera.position.y; + disableUI = true; + camera.width = w; + camera.height = h; + camera.position.x = w / 2f + tilesize / 2f; + camera.position.y = h / 2f + tilesize / 2f; + Draw.flush(); + buffer.begin(); + draw(); + Draw.flush(); + buffer.end(); + disableUI = false; + camera.width = vpW; + camera.height = vpH; + camera.position.set(px, py); + buffer.begin(); + byte[] lines = ScreenUtils.getFrameBufferPixels(0, 0, w, h, true); + for(int i = 0; i < lines.length; i += 4){ + lines[i + 3] = (byte)255; + } + buffer.end(); + Pixmap fullPixmap = new Pixmap(w, h, Pixmap.Format.RGBA8888); + BufferUtils.copy(lines, 0, fullPixmap.getPixels(), lines.length); + FileHandle file = screenshotDirectory.child("screenshot-" + Time.millis() + ".png"); + PixmapIO.writePNG(file, fullPixmap); + fullPixmap.dispose(); + ui.showInfoFade(Core.bundle.format("screenshot", file.toString())); + + buffer.dispose(); + + Core.settings.put("animatedwater", hadWater); + Core.settings.put("animatedshields", hadShields); } } diff --git a/core/src/io/anuke/mindustry/core/UI.java b/core/src/io/anuke/mindustry/core/UI.java index 9965e1a32e..0706a3d371 100644 --- a/core/src/io/anuke/mindustry/core/UI.java +++ b/core/src/io/anuke/mindustry/core/UI.java @@ -1,8 +1,6 @@ package io.anuke.mindustry.core; -import io.anuke.arc.ApplicationListener; -import io.anuke.arc.Core; -import io.anuke.arc.Events; +import io.anuke.arc.*; import io.anuke.arc.Graphics.Cursor; import io.anuke.arc.Graphics.Cursor.SystemCursor; import io.anuke.arc.freetype.FreeTypeFontGenerator; @@ -13,19 +11,13 @@ 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.scene.Group; -import io.anuke.arc.scene.Scene; -import io.anuke.arc.scene.Skin; +import io.anuke.arc.scene.*; import io.anuke.arc.scene.actions.Actions; -import io.anuke.arc.scene.ui.Dialog; -import io.anuke.arc.scene.ui.TextField; +import io.anuke.arc.scene.ui.*; import io.anuke.arc.scene.ui.TextField.TextFieldFilter; -import io.anuke.arc.scene.ui.TooltipManager; 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.Strings; -import io.anuke.arc.util.Time; +import io.anuke.arc.util.*; import io.anuke.mindustry.editor.MapEditorDialog; import io.anuke.mindustry.game.EventType.ResizeEvent; import io.anuke.mindustry.graphics.Pal; @@ -63,11 +55,11 @@ public class UI implements ApplicationListener{ public AdminsDialog admins; public TraceDialog traces; public ChangelogDialog changelog; - public LocalPlayerDialog localplayers; public DatabaseDialog database; public ContentInfoDialog content; public DeployDialog deploy; public TechTreeDialog tech; + public MinimapDialog minimap; public Cursor drillCursor, unloadCursor; @@ -84,21 +76,21 @@ public class UI implements ApplicationListener{ 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) - ) + 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.setHideAction(() -> sequence( - parallel( - scaleTo(0.01f, 0.01f, 0.1f, Interpolation.fade), - fadeOut(0.1f, Interpolation.fade) - ) + parallel( + scaleTo(0.01f, 0.01f, 0.1f, Interpolation.fade), + fadeOut(0.1f, Interpolation.fade) + ) )); TooltipManager.getInstance().animations = false; @@ -109,6 +101,7 @@ public class UI implements ApplicationListener{ }); Colors.put("accent", Pal.accent); + Colors.put("stat", Pal.stat); loadCursors(); } @@ -125,11 +118,11 @@ public class UI implements ApplicationListener{ Core.graphics.restoreCursor(); } - + void generateFonts(Skin skin){ generator = new FreeTypeFontGenerator(Core.files.internal("fonts/font.ttf")); FreeTypeFontParameter param = new FreeTypeFontParameter(); - param.size = (int)(9*2 * Math.max(Unit.dp.scl(1f), 0.5f)); + param.size = (int)(9 * 2 * Math.max(Unit.dp.scl(1f), 0.5f)); param.shadowColor = Color.DARK_GRAY; param.shadowOffsetY = 2; param.incremental = true; @@ -175,15 +168,15 @@ public class UI implements ApplicationListener{ admins = new AdminsDialog(); traces = new TraceDialog(); maps = new MapsDialog(); - localplayers = new LocalPlayerDialog(); content = new ContentInfoDialog(); deploy = new DeployDialog(); tech = new TechTreeDialog(); + minimap = new MinimapDialog(); Group group = Core.scene.root; backfrag.build(group); - control.input(0).getFrag().build(group); + control.input().getFrag().build(group); hudfrag.build(group); menufrag.build(group); chatfrag.container().build(group); @@ -219,7 +212,7 @@ public class UI implements ApplicationListener{ cont.margin(30).add(text).padRight(6f); TextField field = cont.addField(def, t -> { }).size(170f, 50f).get(); - field.setTextFieldFilter((f, c) -> field.getText().length() < 12 && filter.acceptChar(f, c)); + field.setFilter((f, c) -> field.getText().length() < 12 && filter.acceptChar(f, c)); Platform.instance.addDialog(field); buttons.defaults().size(120, 54).pad(4); buttons.addButton("$ok", () -> { @@ -288,11 +281,11 @@ public class UI implements ApplicationListener{ public String formatAmount(int number){ if(number >= 1000000){ - return Strings.toFixed(number / 1000000f, 1) + "[gray]mil[]"; + return Strings.fixed(number / 1000000f, 1) + "[gray]mil[]"; }else if(number >= 10000){ return number / 1000 + "[gray]k[]"; }else if(number >= 1000){ - return Strings.toFixed(number / 1000f, 1) + "[gray]k[]"; + return Strings.fixed(number / 1000f, 1) + "[gray]k[]"; }else{ return number + ""; } diff --git a/core/src/io/anuke/mindustry/core/World.java b/core/src/io/anuke/mindustry/core/World.java index 822cb3d357..af3ac67537 100644 --- a/core/src/io/anuke/mindustry/core/World.java +++ b/core/src/io/anuke/mindustry/core/World.java @@ -1,19 +1,14 @@ package io.anuke.mindustry.core; -import io.anuke.arc.ApplicationListener; -import io.anuke.arc.Core; -import io.anuke.arc.Events; +import io.anuke.annotations.Annotations.Nullable; +import io.anuke.arc.*; import io.anuke.arc.collection.Array; 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.util.Log; -import io.anuke.arc.util.Structs; -import io.anuke.arc.util.Tmp; -import io.anuke.mindustry.ai.BlockIndexer; -import io.anuke.mindustry.ai.Pathfinder; -import io.anuke.mindustry.ai.WaveSpawner; +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.EntityQuery; @@ -21,16 +16,10 @@ 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.maps.Map; -import io.anuke.mindustry.maps.MapException; -import io.anuke.mindustry.maps.Maps; +import io.anuke.mindustry.maps.*; import io.anuke.mindustry.maps.generators.Generator; -import io.anuke.mindustry.type.ContentType; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.type.Zone; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Pos; -import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.type.*; +import io.anuke.mindustry.world.*; import static io.anuke.mindustry.Vars.*; @@ -96,11 +85,13 @@ public class World implements ApplicationListener{ return tiles == null ? 0 : tiles[0].length; } - public Tile tile(int pos){ + public @Nullable + Tile tile(int pos){ return tiles == null ? null : tile(Pos.x(pos), Pos.y(pos)); } - public Tile tile(int x, int y){ + public @Nullable + Tile tile(int x, int y){ if(tiles == null){ return null; } @@ -112,7 +103,8 @@ public class World implements ApplicationListener{ return tiles[x][y]; } - public Tile tileWorld(float x, float y){ + public @Nullable + Tile tileWorld(float x, float y){ return tile(Math.round(x / tilesize), Math.round(y / tilesize)); } @@ -160,7 +152,7 @@ public class World implements ApplicationListener{ generating = true; } - /**Call to signal the beginning of loading the map with a custom set of tiles.*/ + /** 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; @@ -184,7 +176,7 @@ public class World implements ApplicationListener{ addDarkness(tiles); - EntityQuery.resizeTree(-finalWorldBounds, -finalWorldBounds, tiles.length * tilesize + finalWorldBounds, tiles[0].length * tilesize + finalWorldBounds); + EntityQuery.resizeTree(-finalWorldBounds, -finalWorldBounds, tiles.length * tilesize + finalWorldBounds * 2, tiles[0].length * tilesize + finalWorldBounds * 2); generating = false; Events.fire(new WorldLoadEvent()); @@ -258,19 +250,24 @@ public class World implements ApplicationListener{ invalidMap = false; if(!headless){ - if(state.teams.get(players[0].getTeam()).cores.size == 0){ + if(state.teams.get(player.getTeam()).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 != players[0].getTeam()){ + if(state.teams.get(team).cores.size != 0 && team != player.getTeam()){ invalidMap = false; } } if(invalidMap){ ui.showError("$map.nospawn.pvp"); } + }else if(!state.rules.waves){ //pvp maps need two cores to be valid + invalidMap = state.teams.get(waveTeam).cores.isEmpty(); + if(invalidMap){ + ui.showError("$map.nospawn.attack"); + } } }else{ invalidMap = true; @@ -308,7 +305,11 @@ public class World implements ApplicationListener{ } public void setBlock(Tile tile, Block block, Team team){ - tile.setBlock(block, team); + setBlock(tile, block, team, 0); + } + + public void setBlock(Tile tile, Block block, Team team, int rotation){ + tile.setBlock(block, team, rotation); if(block.isMultiblock()){ int offsetx = -(block.size - 1) / 2; int offsety = -(block.size - 1) / 2; @@ -320,7 +321,7 @@ public class World implements ApplicationListener{ if(!(worldx == tile.x && worldy == tile.y)){ Tile toplace = world.tile(worldx, worldy); if(toplace != null){ - toplace.setLinked((byte) (dx + offsetx), (byte) (dy + offsety)); + toplace.setLinked((byte)(dx + offsetx), (byte)(dy + offsety)); toplace.setTeam(team); } } @@ -335,7 +336,7 @@ public class World implements ApplicationListener{ if(!Structs.inBounds(x, y, oldWidth, oldHeight)) return -1; x += shiftX; y += shiftY; - return y*newWidth + x; + return y * newWidth + x; } /** @@ -343,12 +344,11 @@ public class World implements ApplicationListener{ */ 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)); + 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){ @@ -416,7 +416,7 @@ public class World implements ApplicationListener{ } } - /**Loads raw map tile data into a Tile[][] array, setting up multiblocks, cliffs and ores. */ + /** Loads raw map tile data into a Tile[][] array, setting up multiblocks, cliffs and ores. */ void loadTileData(Tile[][] tiles){ prepareTiles(tiles); } @@ -451,9 +451,7 @@ public class World implements ApplicationListener{ } for(int x = 0; x < tiles.length; x++){ - for(int y = 0; y < tiles[0].length; y++){ - dark[x][y] = writeBuffer[x][y]; - } + System.arraycopy(writeBuffer[x], 0, dark[x], 0, tiles[0].length); } } @@ -467,10 +465,12 @@ public class World implements ApplicationListener{ } } - /**'Prepares' a tile array by:
+ /** + * 'Prepares' a tile array by:
* - setting up multiblocks
* - updating occlusion
- * Usually used before placing structures on a tile array.*/ + * Usually used before placing structures on a tile array. + */ public void prepareTiles(Tile[][] tiles){ //find multiblocks @@ -506,7 +506,7 @@ public class World implements ApplicationListener{ if(!(worldx == x && worldy == y)){ Tile toplace = world.tile(worldx, worldy); if(toplace != null){ - toplace.setLinked((byte) (dx + offsetx), (byte) (dy + offsety)); + toplace.setLinked((byte)(dx + offsetx), (byte)(dy + offsety)); toplace.setTeam(team); } } diff --git a/core/src/io/anuke/mindustry/editor/DrawOperation.java b/core/src/io/anuke/mindustry/editor/DrawOperation.java index 6bc964e465..ea26df6ea4 100755 --- a/core/src/io/anuke/mindustry/editor/DrawOperation.java +++ b/core/src/io/anuke/mindustry/editor/DrawOperation.java @@ -4,6 +4,7 @@ import io.anuke.annotations.Annotations.Struct; import io.anuke.arc.collection.LongArray; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.gen.TileOp; +import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Floor; @@ -39,13 +40,17 @@ public class DrawOperation{ if(type == OpType.floor.ordinal()){ tile.setFloor((Floor)content.block(to)); }else if(type == OpType.block.ordinal()){ - tile.setBlock(content.block(to)); + Block block = content.block(to); + tile.setBlock(block); + if(block.isMultiblock()){ + editor.updateLinks(block, tile.x, tile.y); + } }else if(type == OpType.rotation.ordinal()){ tile.setRotation(to); }else if(type == OpType.team.ordinal()){ tile.setTeam(Team.all[to]); }else if(type == OpType.ore.ordinal()){ - tile.setOreByte(to); + tile.setOverlayID(to); } }); editor.renderer().updatePoint(tile.x, tile.y); diff --git a/core/src/io/anuke/mindustry/editor/EditorTile.java b/core/src/io/anuke/mindustry/editor/EditorTile.java index b35ae191f6..2ac9c755b8 100644 --- a/core/src/io/anuke/mindustry/editor/EditorTile.java +++ b/core/src/io/anuke/mindustry/editor/EditorTile.java @@ -6,12 +6,8 @@ import io.anuke.mindustry.game.Team; import io.anuke.mindustry.gen.TileOp; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.Floor; -import io.anuke.mindustry.world.blocks.OreBlock; -import io.anuke.mindustry.world.modules.ConsumeModule; -import io.anuke.mindustry.world.modules.ItemModule; -import io.anuke.mindustry.world.modules.LiquidModule; -import io.anuke.mindustry.world.modules.PowerModule; +import io.anuke.mindustry.world.blocks.*; +import io.anuke.mindustry.world.modules.*; import static io.anuke.mindustry.Vars.ui; @@ -28,19 +24,19 @@ public class EditorTile extends Tile{ @Override public void setFloor(Floor type){ - if(type instanceof OreBlock){ + if(type instanceof OverlayFloor){ //don't place on liquids - if(!floor().isLiquid) setOreByte(type.id); + setOverlayID(type.id); return; } Block previous = floor(); - Block ore = ore(); + Block ore = overlay(); if(previous == type && ore == Blocks.air) return; super.setFloor(type); //ore may get nullified so make sure to save editrs - if(ore() != ore){ - op(TileOp.get(x, y, (byte)OpType.ore.ordinal(), ore.id, ore().id)); + if(overlay() != ore){ + op(TileOp.get(x, y, (byte)OpType.ore.ordinal(), ore.id, overlay().id)); } if(previous != type){ op(TileOp.get(x, y, (byte)OpType.floor.ordinal(), previous.id, type.id)); @@ -49,10 +45,15 @@ public class EditorTile extends Tile{ @Override public void setBlock(Block type){ - Block previous = block(); + Block previous = block; + byte pteam = getTeamID(); if(previous == type) return; super.setBlock(type); + if(pteam != getTeamID()){ + op(TileOp.get(x, y, (byte)OpType.team.ordinal(), pteam, getTeamID())); + } op(TileOp.get(x, y, (byte)OpType.block.ordinal(), previous.id, type.id)); + } @Override @@ -72,10 +73,10 @@ public class EditorTile extends Tile{ } @Override - public void setOreByte(byte ore){ - byte previous = getOreByte(); + public void setOverlayID(byte ore){ + byte previous = getOverlayID(); if(previous == ore) return; - super.setOreByte(ore); + super.setOverlayID(ore); op(TileOp.get(x, y, (byte)OpType.ore.ordinal(), previous, ore)); } @@ -88,6 +89,14 @@ public class EditorTile extends Tile{ protected void changed(){ entity = null; + if(block == null){ + block = Blocks.air; + } + + if(floor == null){ + floor = (Floor)Blocks.air; + } + Block block = block(); if(block.hasEntity()){ diff --git a/core/src/io/anuke/mindustry/editor/EditorTool.java b/core/src/io/anuke/mindustry/editor/EditorTool.java index 665d111c4f..56af578d06 100644 --- a/core/src/io/anuke/mindustry/editor/EditorTool.java +++ b/core/src/io/anuke/mindustry/editor/EditorTool.java @@ -7,12 +7,8 @@ import io.anuke.arc.input.KeyCode; import io.anuke.arc.util.Pack; import io.anuke.arc.util.Structs; import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Pos; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.BlockPart; -import io.anuke.mindustry.world.blocks.Floor; -import io.anuke.mindustry.world.blocks.OreBlock; +import io.anuke.mindustry.world.*; +import io.anuke.mindustry.world.blocks.*; public enum EditorTool{ pick{ @@ -23,7 +19,7 @@ public enum EditorTool{ byte link = tile.getLinkByte(); - if(tile.block() instanceof BlockPart && link != 0){ + if(tile.isLinked()){ x -= (Pack.leftByte(link) - 8); y -= (Pack.rightByte(link) - 8); @@ -31,11 +27,11 @@ public enum EditorTool{ } //do not. - if(tile.block() instanceof BlockPart){ + if(tile.isLinked()){ return; } - editor.drawBlock = tile.block() == Blocks.air ? tile.ore() == Blocks.air ? tile.floor() : tile.ore() : tile.block(); + editor.drawBlock = tile.block() == Blocks.air ? tile.overlay() == Blocks.air ? tile.floor() : tile.overlay() : tile.block(); } }, pencil{ @@ -104,12 +100,14 @@ public enum EditorTool{ boolean synth = editor.drawBlock.synthetic(); Block draw = editor.drawBlock; - dest = draw instanceof OreBlock ? tile.ore() : isfloor ? floor : block; + dest = draw instanceof OverlayFloor ? tile.overlay() : isfloor ? floor : block; if(dest == draw || block == Blocks.part || block.isMultiblock()){ return; } + boolean alt = isAlt(); + int width = editor.width(); int height = editor.height(); @@ -117,7 +115,13 @@ public enum EditorTool{ Tile write = editor.tile(px, py); if(isfloor){ - write.setFloor((Floor)draw); + if(alt && !(draw instanceof OverlayFloor)){ + Block ore = write.overlay(); + write.setFloor((Floor)draw); + write.setOverlay(ore); + }else{ + write.setFloor((Floor)draw); + } }else{ write.setBlock(draw); } @@ -193,7 +197,7 @@ public enum EditorTool{ boolean eq(int px, int py){ Tile tile = data.tile(px, py); - return (data.drawBlock instanceof OreBlock ? tile.ore() : isfloor ? tile.floor() : tile.block()) == dest && !(data.drawBlock instanceof OreBlock && tile.floor().isLiquid); + return (data.drawBlock instanceof OverlayFloor ? tile.overlay() : isfloor ? tile.floor() : tile.block()) == dest && !(data.drawBlock instanceof OverlayFloor && tile.floor().isLiquid); } }, zoom; diff --git a/core/src/io/anuke/mindustry/editor/MapEditor.java b/core/src/io/anuke/mindustry/editor/MapEditor.java index e53bb60117..e74128be2b 100644 --- a/core/src/io/anuke/mindustry/editor/MapEditor.java +++ b/core/src/io/anuke/mindustry/editor/MapEditor.java @@ -68,7 +68,7 @@ public class MapEditor{ //adds missing blockparts public void checkLinkedTiles(){ //clear block parts first - for(int x = 0; x < width(); x ++){ + for(int x = 0; x < width(); x++){ for(int y = 0; y < height(); y++){ if(tiles[x][y].block() == Blocks.part){ tiles[x][y].setBlock(Blocks.air); @@ -78,8 +78,8 @@ public class MapEditor{ } //set up missing blockparts - for(int x = 0; x < width(); x ++){ - for(int y = 0; y < height(); y ++){ + for(int x = 0; x < width(); x++){ + for(int y = 0; y < height(); y++){ Block drawBlock = tiles[x][y].block(); if(drawBlock.isMultiblock()){ int offsetx = -(drawBlock.size - 1) / 2; @@ -92,7 +92,7 @@ public class MapEditor{ if(Structs.inBounds(worldx, worldy, width(), height()) && !(dx + offsetx == 0 && dy + offsety == 0)){ Tile tile = tiles[worldx][worldy]; tile.setBlock(Blocks.part); - tile.setLinkByte(Pack.byteByte((byte) (dx + offsetx + 8), (byte) (dy + offsety + 8))); + tile.setLinkByte(Pack.byteByte((byte)(dx + offsetx + 8), (byte)(dy + offsety + 8))); } } } @@ -107,7 +107,7 @@ public class MapEditor{ loading = false; } - /**Creates a 2-D array of EditorTiles with stone as the floor block.*/ + /** Creates a 2-D array of EditorTiles with stone as the floor block. */ public Tile[][] createTiles(int width, int height){ tiles = new Tile[width][height]; @@ -146,6 +146,27 @@ public class MapEditor{ return tiles[0].length; } + public void updateLinks(Block block, int x, int y){ + int offsetx = -(block.size - 1) / 2; + int offsety = -(block.size - 1) / 2; + + for(int dx = 0; dx < block.size; dx++){ + for(int dy = 0; dy < block.size; dy++){ + int worldx = dx + offsetx + x; + int worldy = dy + offsety + y; + + if(Structs.inBounds(worldx, worldy, width(), height())){ + Tile tile = tiles[worldx][worldy]; + + if(!(worldx == x && worldy == y)){ + tile.setBlock(Blocks.part); + tile.setLinkByte(Pack.byteByte((byte)(dx + offsetx + 8), (byte)(dy + offsety + 8))); + } + } + } + } + } + public void draw(int x, int y, boolean paint){ draw(x, y, paint, drawBlock); } @@ -158,9 +179,9 @@ public class MapEditor{ boolean isfloor = drawBlock instanceof Floor && drawBlock != Blocks.air; 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); + + x = Mathf.clamp(x, (drawBlock.size - 1) / 2, width() - drawBlock.size / 2 - 1); + y = Mathf.clamp(y, (drawBlock.size - 1) / 2, height() - drawBlock.size / 2 - 1); int offsetx = -(drawBlock.size - 1) / 2; int offsety = -(drawBlock.size - 1) / 2; @@ -176,7 +197,7 @@ public class MapEditor{ if(i == 1){ tile.setBlock(Blocks.part); - tile.setLinkByte(Pack.byteByte((byte) (dx + offsetx + 8), (byte) (dy + offsety + 8))); + tile.setLinkByte(Pack.byteByte((byte)(dx + offsetx + 8), (byte)(dy + offsety + 8))); }else{ byte link = tile.getLinkByte(); Block block = tile.block(); @@ -258,7 +279,7 @@ public class MapEditor{ clearOp(); Tile[][] previous = tiles; - int offsetX = -(width - width())/2, offsetY = -(height - height())/2; + int offsetX = -(width - width()) / 2, offsetY = -(height - height()) / 2; loading = true; tiles = new Tile[width][height]; diff --git a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java index 966f979a92..5d7edd42c8 100644 --- a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java @@ -26,7 +26,7 @@ import io.anuke.mindustry.ui.dialogs.FloatingDialog; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block.Icon; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.OreBlock; +import io.anuke.mindustry.world.blocks.OverlayFloor; import io.anuke.mindustry.world.blocks.storage.CoreBlock; import static io.anuke.mindustry.Vars.*; @@ -85,49 +85,49 @@ public class MapEditorDialog extends Dialog implements Disposable{ t.row(); t.addImageTextButton("$editor.import", "icon-load-map", isize, () -> - createDialog("$editor.import", - "$editor.importmap", "$editor.importmap.description", "icon-load-map", (Runnable) loadDialog::show, - "$editor.importfile", "$editor.importfile.description", "icon-file", (Runnable) () -> - Platform.instance.showFileChooser("$editor.loadmap", "Map Files", file -> ui.loadAnd(() -> { - try{ - //TODO what if it's an image? users should be warned for their stupidity - editor.beginEdit(MapIO.readMap(file, true)); - }catch(Exception e){ - ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false))); - Log.err(e); - } - }), true, mapExtension), + createDialog("$editor.import", + "$editor.importmap", "$editor.importmap.description", "icon-load-map", (Runnable)loadDialog::show, + "$editor.importfile", "$editor.importfile.description", "icon-file", (Runnable)() -> + Platform.instance.showFileChooser("$editor.loadmap", "Map Files", file -> ui.loadAnd(() -> { + try{ + //TODO what if it's an image? users should be warned for their stupidity + editor.beginEdit(MapIO.readMap(file, true)); + }catch(Exception e){ + ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false))); + Log.err(e); + } + }), true, mapExtension), - "$editor.importimage", "$editor.importimage.description", "icon-file-image", (Runnable)() -> - Platform.instance.showFileChooser("$loadimage", "Image Files", file -> - ui.loadAnd(() -> { - try{ - Pixmap pixmap = new Pixmap(file); - Tile[][] tiles = editor.createTiles(pixmap.getWidth(), pixmap.getHeight()); - editor.load(() -> MapIO.readLegacyPixmap(pixmap, tiles)); - editor.beginEdit(tiles); - }catch (Exception e){ - ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false))); - Log.err(e); - } - }), true, "png"))); + "$editor.importimage", "$editor.importimage.description", "icon-file-image", (Runnable)() -> + Platform.instance.showFileChooser("$loadimage", "Image Files", file -> + ui.loadAnd(() -> { + try{ + Pixmap pixmap = new Pixmap(file); + Tile[][] tiles = editor.createTiles(pixmap.getWidth(), pixmap.getHeight()); + editor.load(() -> MapIO.readLegacyPixmap(pixmap, tiles)); + editor.beginEdit(tiles); + }catch(Exception e){ + ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false))); + Log.err(e); + } + }), true, "png"))); t.addImageTextButton("$editor.export", "icon-save-map", isize, () -> - Platform.instance.showFileChooser("$editor.savemap", "Map Files", file -> { - file = file.parent().child(file.nameWithoutExtension() + "." + mapExtension); - FileHandle result = file; - ui.loadAnd(() -> { - try{ - if(!editor.getTags().containsKey("name")){ - editor.getTags().put("name", result.nameWithoutExtension()); - } - MapIO.writeMap(result, editor.createMap(result), editor.tiles()); - }catch(Exception e){ - ui.showError(Core.bundle.format("editor.errorsave", Strings.parseException(e, false))); - Log.err(e); - } - }); - }, false, mapExtension)); + Platform.instance.showFileChooser("$editor.savemap", "Map Files", file -> { + file = file.parent().child(file.nameWithoutExtension() + "." + mapExtension); + FileHandle result = file; + ui.loadAnd(() -> { + try{ + if(!editor.getTags().containsKey("name")){ + editor.getTags().put("name", result.nameWithoutExtension()); + } + MapIO.writeMap(result, editor.createMap(result), editor.tiles()); + }catch(Exception e){ + ui.showError(Core.bundle.format("editor.errorsave", Strings.parseException(e, false))); + Log.err(e); + } + }); + }, false, mapExtension)); }); menu.cont.row(); @@ -146,14 +146,14 @@ public class MapEditorDialog extends Dialog implements Disposable{ }); loadDialog = new MapLoadDialog(map -> - ui.loadAnd(() -> { - try{ - editor.beginEdit(map); - }catch(Exception e){ - ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false))); - Log.err(e); - } - })); + ui.loadAnd(() -> { + try{ + editor.beginEdit(map); + }catch(Exception e){ + ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false))); + Log.err(e); + } + })); setFillParent(true); @@ -181,7 +181,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ shown(() -> { saved = true; - Platform.instance.beginForceLandscape(); + if(!Core.settings.getBool("landscape")) Platform.instance.beginForceLandscape(); editor.clearOp(); Core.scene.setScrollFocus(view); if(!shownWithMap){ @@ -195,7 +195,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ hidden(() -> { editor.clearOp(); Platform.instance.updateRPC(); - Platform.instance.endForceLandscape(); + if(!Core.settings.getBool("landscape")) Platform.instance.endForceLandscape(); }); } @@ -239,10 +239,10 @@ public class MapEditorDialog extends Dialog implements Disposable{ dialog.cont.defaults().size(360f, h).padBottom(5).padRight(5).padLeft(5); for(int i = 0; i < arguments.length; i += 4){ - String name = (String) arguments[i]; - String description = (String) arguments[i + 1]; - String iconname = (String) arguments[i + 2]; - Runnable listenable = (Runnable) arguments[i + 3]; + String name = (String)arguments[i]; + String description = (String)arguments[i + 1]; + String iconname = (String)arguments[i + 2]; + Runnable listenable = (Runnable)arguments[i + 3]; TextButton button = dialog.cont.addButton(name, () -> { listenable.run(); @@ -306,8 +306,8 @@ public class MapEditorDialog extends Dialog implements Disposable{ public void build(){ 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); + 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); clearChildren(); table(cont -> { @@ -374,7 +374,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ tools.row(); tools.table("underline", t -> t.add("$editor.teams")) - .colspan(3).height(40).width(size * 3f + 3f).padBottom(3); + .colspan(3).height(40).width(size * 3f + 3f).padBottom(3); tools.row(); @@ -401,7 +401,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ mid.table("underline", t -> { Slider slider = new Slider(0, MapEditor.brushSizes.length - 1, 1, false); - slider.moved(f -> editor.brushSize = MapEditor.brushSizes[(int) (float) f]); + slider.moved(f -> editor.brushSize = MapEditor.brushSizes[(int)(float)f]); t.top(); t.add("$editor.brush"); @@ -486,7 +486,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ if(core != 0) return core; int synth = Boolean.compare(b1.synthetic(), b2.synthetic()); if(synth != 0) return synth; - int ore = Boolean.compare(b1 instanceof OreBlock, b2 instanceof OreBlock); + int ore = Boolean.compare(b1 instanceof OverlayFloor, b2 instanceof OverlayFloor); if(ore != 0) return ore; return Integer.compare(b1.id, b2.id); }); diff --git a/core/src/io/anuke/mindustry/editor/MapGenerateDialog.java b/core/src/io/anuke/mindustry/editor/MapGenerateDialog.java index a662e4d6fd..32e74f59d2 100644 --- a/core/src/io/anuke/mindustry/editor/MapGenerateDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapGenerateDialog.java @@ -62,7 +62,7 @@ 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", 14 * 2, this::showAdd).height(64f).width(140f); } void setup(){ @@ -84,7 +84,7 @@ public class MapGenerateDialog extends FloatingDialog{ add(new Image("icon-refresh"){{ setScaling(Scaling.none); }}); - visible(() -> generating); + visible(() -> generating && !updateEditorOnChange); }}).size(mobile ? 300f : 400f).padRight(6); t.pane(p -> filterTable = p).width(300f).get().setScrollingDisabled(true, false); }).grow(); @@ -120,24 +120,24 @@ public class MapGenerateDialog extends FloatingDialog{ t.table(b -> { b.left(); b.defaults().size(50f); - b.addImageButton("icon-refresh", 14*2, () -> { + b.addImageButton("icon-refresh", 14 * 2, () -> { filter.randomize(); update(); }); - b.addImageButton("icon-arrow-up", 10*2, () -> { + 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, () -> { + b.addImageButton("icon-arrow-down", 10 * 2, () -> { int idx = filters.indexOf(filter); - filters.swap(idx, Math.min(filters.size-1, idx + 1)); + filters.swap(idx, Math.min(filters.size - 1, idx + 1)); rebuildFilters(); update(); }); - b.addImageButton("icon-trash", 14*2, () -> { + b.addImageButton("icon-trash", 14 * 2, () -> { filters.remove(filter); rebuildFilters(); update(); @@ -220,7 +220,7 @@ public class MapGenerateDialog extends FloatingDialog{ for(int x = 0; x < editor.width(); x++){ for(int y = 0; y < editor.height(); y++){ Tile tile = editor.tile(x, y); - input.begin(editor, x, y, tile.floor(), tile.block(), tile.ore()); + input.begin(editor, x, y, tile.floor(), tile.block(), tile.overlay()); filter.apply(input); writeTiles[x][y].set(input.floor, input.block, input.ore, tile.getTeam(), tile.getRotation()); } @@ -233,11 +233,11 @@ public class MapGenerateDialog extends FloatingDialog{ Tile tile = editor.tile(x, y); DummyTile write = writeTiles[x][y]; - tile.setRotation((byte)write.rotation); + tile.setRotation(write.rotation); tile.setFloor((Floor)content.block(write.floor)); tile.setBlock(content.block(write.block)); tile.setTeam(Team.all[write.team]); - tile.setOre(content.block(write.ore)); + tile.setOverlay(content.block(write.ore)); } } }); @@ -295,7 +295,7 @@ public class MapGenerateDialog extends FloatingDialog{ //get result from buffer1 if there's filters left, otherwise get from editor directly if(filters.isEmpty()){ Tile tile = editor.tile(px * scaling, py * scaling); - color = MapIO.colorFor(tile.floor(), tile.block(), tile.ore(), Team.none); + color = MapIO.colorFor(tile.floor(), tile.block(), tile.overlay(), Team.none); }else{ DummyTile tile = buffer1[px][py]; color = MapIO.colorFor(content.block(tile.floor), content.block(tile.block), content.block(tile.ore), Team.none); @@ -305,6 +305,9 @@ public class MapGenerateDialog extends FloatingDialog{ } Core.app.post(() -> { + if(pixmap == null || texture == null){ + return; + } texture.draw(pixmap, 0, 0); generating = false; }); @@ -336,7 +339,7 @@ public class MapGenerateDialog extends FloatingDialog{ } void set(Tile other){ - set(other.floor(), other.block(), other.ore(), other.getTeam(), other.getRotation()); + set(other.floor(), other.block(), other.overlay(), other.getTeam(), other.getRotation()); } } diff --git a/core/src/io/anuke/mindustry/editor/MapLoadDialog.java b/core/src/io/anuke/mindustry/editor/MapLoadDialog.java index edca8d7868..de02642f9c 100644 --- a/core/src/io/anuke/mindustry/editor/MapLoadDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapLoadDialog.java @@ -1,14 +1,12 @@ package io.anuke.mindustry.editor; +import io.anuke.arc.function.Consumer; +import io.anuke.arc.scene.ui.*; +import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.util.Scaling; import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.ui.BorderImage; import io.anuke.mindustry.ui.dialogs.FloatingDialog; -import io.anuke.arc.function.Consumer; -import io.anuke.arc.scene.ui.ButtonGroup; -import io.anuke.arc.scene.ui.ScrollPane; -import io.anuke.arc.scene.ui.TextButton; -import io.anuke.arc.scene.ui.layout.Table; import static io.anuke.mindustry.Vars.world; diff --git a/core/src/io/anuke/mindustry/editor/MapRenderer.java b/core/src/io/anuke/mindustry/editor/MapRenderer.java index 65aa4fa56a..1488f8e0c6 100644 --- a/core/src/io/anuke/mindustry/editor/MapRenderer.java +++ b/core/src/io/anuke/mindustry/editor/MapRenderer.java @@ -40,7 +40,7 @@ public class MapRenderer implements Disposable{ } } - chunks = new IndexedRenderer[(int) Math.ceil((float) width / chunksize)][(int) Math.ceil((float) height / chunksize)]; + chunks = new IndexedRenderer[(int)Math.ceil((float)width / chunksize)][(int)Math.ceil((float)height / chunksize)]; for(int x = 0; x < chunks.length; x++){ for(int y = 0; y < chunks[0].length; y++){ @@ -72,8 +72,7 @@ public class MapRenderer implements Disposable{ IndexedRenderer mesh = chunks[x][y]; if(mesh == null){ - chunks[x][y] = new IndexedRenderer(chunksize * chunksize * 2); - mesh = chunks[x][y]; + continue; } mesh.getTransformMatrix().setToTranslation(tx, ty).scale(tw / (width * tilesize), th / (height * tilesize)); @@ -116,38 +115,38 @@ public class MapRenderer implements Disposable{ if(wall.rotate){ mesh.draw(idxWall, region, - wx * tilesize + wall.offset(), wy * tilesize + wall.offset(), - region.getWidth() * Draw.scl, region.getHeight() * Draw.scl, tile.getRotation() * 90 - 90); + wx * tilesize + wall.offset(), wy * tilesize + wall.offset(), + region.getWidth() * Draw.scl, region.getHeight() * Draw.scl, tile.getRotation() * 90 - 90); }else{ mesh.draw(idxWall, region, - wx * tilesize + wall.offset() + (tilesize - region.getWidth() * Draw.scl)/2f, - wy * tilesize + wall.offset() + (tilesize - region.getHeight() * Draw.scl)/2f, - region.getWidth() * Draw.scl, region.getHeight() * Draw.scl); + 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); } }else{ - region = floor.editorVariantRegions()[Mathf.randomSeed(idxWall, 0, floor.editorVariantRegions().length-1)]; + region = floor.editorVariantRegions()[Mathf.randomSeed(idxWall, 0, floor.editorVariantRegions().length - 1)]; mesh.draw(idxWall, region, wx * tilesize, wy * tilesize, 8, 8); } - float offsetX = -(wall.size/3)*tilesize, offsetY = -(wall.size/3) * tilesize; + float offsetX = -(wall.size / 3) * tilesize, offsetY = -(wall.size / 3) * tilesize; if(wall.update || wall.destructible){ mesh.setColor(team.color); region = Core.atlas.find("block-border-editor"); }else if(!wall.synthetic() && wall != Blocks.air){ region = !Core.atlas.isFound(wall.editorIcon()) ? Core.atlas.find("clear-editor") : wall.editorIcon(); - offsetX = tilesize/2f - region.getWidth()/2f * Draw.scl; - offsetY = tilesize/2f - region.getHeight()/2f * Draw.scl; - }else if(wall == Blocks.air && tile.ore() != null){ - region = tile.ore().editorVariantRegions()[Mathf.randomSeed(idxWall, 0, tile.ore().editorVariantRegions().length-1)];; + offsetX = tilesize / 2f - region.getWidth() / 2f * Draw.scl; + offsetY = tilesize / 2f - region.getHeight() / 2f * Draw.scl; + }else if(wall == Blocks.air && tile.overlay() != null){ + region = tile.overlay().editorVariantRegions()[Mathf.randomSeed(idxWall, 0, tile.overlay().editorVariantRegions().length - 1)]; }else{ region = Core.atlas.find("clear-editor"); } mesh.draw(idxDecal, region, - wx * tilesize + offsetX, wy * tilesize + offsetY, - region.getWidth() * Draw.scl, region.getHeight() * Draw.scl); + wx * tilesize + offsetX, wy * tilesize + offsetY, + region.getWidth() * Draw.scl, region.getHeight() * Draw.scl); mesh.setColor(Color.WHITE); } diff --git a/core/src/io/anuke/mindustry/editor/MapSaveDialog.java b/core/src/io/anuke/mindustry/editor/MapSaveDialog.java index bcac2914e9..57ed966a0a 100644 --- a/core/src/io/anuke/mindustry/editor/MapSaveDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapSaveDialog.java @@ -1,11 +1,11 @@ package io.anuke.mindustry.editor; -import io.anuke.mindustry.core.Platform; -import io.anuke.mindustry.maps.Map; -import io.anuke.mindustry.ui.dialogs.FloatingDialog; import io.anuke.arc.function.Consumer; import io.anuke.arc.scene.ui.TextButton; import io.anuke.arc.scene.ui.TextField; +import io.anuke.mindustry.core.Platform; +import io.anuke.mindustry.maps.Map; +import io.anuke.mindustry.ui.dialogs.FloatingDialog; import static io.anuke.mindustry.Vars.ui; import static io.anuke.mindustry.Vars.world; diff --git a/core/src/io/anuke/mindustry/editor/MapView.java b/core/src/io/anuke/mindustry/editor/MapView.java index 9b4ccef3ff..4503304907 100644 --- a/core/src/io/anuke/mindustry/editor/MapView.java +++ b/core/src/io/anuke/mindustry/editor/MapView.java @@ -3,18 +3,14 @@ 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.Draw; -import io.anuke.arc.graphics.g2d.Lines; -import io.anuke.arc.graphics.g2d.ScissorStack; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.input.GestureDetector; import io.anuke.arc.input.GestureDetector.GestureListener; import io.anuke.arc.input.KeyCode; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.*; import io.anuke.arc.scene.Element; -import io.anuke.arc.scene.event.InputEvent; -import io.anuke.arc.scene.event.InputListener; -import io.anuke.arc.scene.event.Touchable; +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; @@ -69,6 +65,7 @@ public class MapView extends Element implements GestureListener{ return false; } + @Override public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button){ if(pointer != 0){ @@ -196,7 +193,7 @@ public class MapView extends Element implements GestureListener{ super.act(delta); if(Core.scene.getKeyboardFocus() == null || !(Core.scene.getKeyboardFocus() instanceof TextField) && - !Core.input.keyDown(KeyCode.CONTROL_LEFT)){ + !Core.input.keyDown(KeyCode.CONTROL_LEFT)){ float ax = Core.input.axis(Binding.move_x); float ay = Core.input.axis(Binding.move_y); offsetx -= ax * 15f / zoom; @@ -224,7 +221,7 @@ public class MapView extends Element implements GestureListener{ } private Point2 project(float x, float y){ - float ratio = 1f / ((float) editor.width() / editor.height()); + float ratio = 1f / ((float)editor.width() / editor.height()); float size = Math.min(width, height); float sclwidth = size * zoom; float sclheight = size * zoom * ratio; @@ -232,26 +229,26 @@ public class MapView extends Element implements GestureListener{ y = (y - getHeight() / 2 + sclheight / 2 - offsety * zoom) / sclheight * editor.height(); if(editor.drawBlock.size % 2 == 0 && tool != EditorTool.eraser){ - return Tmp.g1.set((int) (x - 0.5f), (int) (y - 0.5f)); + return Tmp.g1.set((int)(x - 0.5f), (int)(y - 0.5f)); }else{ - return Tmp.g1.set((int) x, (int) y); + return Tmp.g1.set((int)x, (int)y); } } private Vector2 unproject(int x, int y){ - float ratio = 1f / ((float) editor.width() / editor.height()); + float ratio = 1f / ((float)editor.width() / editor.height()); float size = Math.min(width, height); float sclwidth = size * zoom; float sclheight = size * zoom * ratio; - float px = ((float) x / editor.width()) * sclwidth + offsetx * zoom - sclwidth / 2 + getWidth() / 2; - float py = ((float) (y) / editor.height()) * sclheight - + offsety * zoom - sclheight / 2 + getHeight() / 2; + float px = ((float)x / editor.width()) * sclwidth + offsetx * zoom - sclwidth / 2 + getWidth() / 2; + float py = ((float)(y) / editor.height()) * sclheight + + offsety * zoom - sclheight / 2 + getHeight() / 2; return vec.set(px, py); } @Override public void draw(){ - float ratio = 1f / ((float) editor.width() / editor.height()); + float ratio = 1f / ((float)editor.width() / editor.height()); float size = Math.min(width, height); float sclwidth = size * zoom; float sclheight = size * zoom * ratio; @@ -317,9 +314,9 @@ public class MapView extends Element implements GestureListener{ Vector2 v = unproject(p.x, p.y).add(x, y); float offset = (editor.drawBlock.size % 2 == 0 ? scaling / 2f : 0f); Lines.square( - v.x + scaling / 2f + offset, - v.y + scaling / 2f + offset, - scaling * editor.drawBlock.size / 2f); + v.x + scaling / 2f + offset, + v.y + scaling / 2f + offset, + scaling * editor.drawBlock.size / 2f); } } @@ -334,9 +331,9 @@ public class MapView extends Element implements GestureListener{ private boolean active(){ return Core.scene.getKeyboardFocus() != null - && Core.scene.getKeyboardFocus().isDescendantOf(ui.editor) - && ui.editor.isShown() && tool == EditorTool.zoom && - Core.scene.hit(Core.input.mouse().x, Core.input.mouse().y, true) == this; + && Core.scene.getKeyboardFocus().isDescendantOf(ui.editor) + && ui.editor.isShown() && tool == EditorTool.zoom && + Core.scene.hit(Core.input.mouse().x, Core.input.mouse().y, true) == this; } @Override diff --git a/core/src/io/anuke/mindustry/editor/WaveInfoDialog.java b/core/src/io/anuke/mindustry/editor/WaveInfoDialog.java index 45eef72a81..f27aad6897 100644 --- a/core/src/io/anuke/mindustry/editor/WaveInfoDialog.java +++ b/core/src/io/anuke/mindustry/editor/WaveInfoDialog.java @@ -7,9 +7,7 @@ import io.anuke.arc.input.KeyCode; import io.anuke.arc.math.Mathf; import io.anuke.arc.scene.ui.TextField.TextFieldFilter; import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.arc.util.Align; -import io.anuke.arc.util.Strings; -import io.anuke.arc.util.Time; +import io.anuke.arc.util.*; import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.StatusEffects; import io.anuke.mindustry.content.UnitTypes; @@ -47,7 +45,7 @@ public class WaveInfoDialog extends FloatingDialog{ }); keyDown(key -> { - if(key == KeyCode.ESCAPE || key == KeyCode.BACK) { + if(key == KeyCode.ESCAPE || key == KeyCode.BACK){ Core.app.post(this::hide); } }); @@ -74,7 +72,7 @@ public class WaveInfoDialog extends FloatingDialog{ dialog.hide(); }).disabled(b -> Core.app.getClipboard().getContents() == null || Core.app.getClipboard().getContents().isEmpty()); dialog.cont.row(); - dialog.cont.addButton("$settings.reset", () -> ui.showConfirm("$confirm", "$settings.clear.confirm", () ->{ + dialog.cont.addButton("$settings.reset", () -> ui.showConfirm("$confirm", "$settings.clear.confirm", () -> { groups = null; buildGroups(); dialog.hide(); @@ -100,7 +98,8 @@ public class WaveInfoDialog extends FloatingDialog{ cont.table("clear", m -> { m.add("$waves.preview").color(Color.LIGHT_GRAY).growX().center().get().setAlignment(Align.center, Align.center); m.row(); - m.addButton("-", () -> {}).update(t -> { + m.addButton("-", () -> { + }).update(t -> { if(t.getClickListener().isPressed()){ updateTimer += Time.delta(); if(updateTimer >= updatePeriod){ @@ -113,11 +112,12 @@ public class WaveInfoDialog extends FloatingDialog{ m.row(); m.pane(t -> preview = t).grow().get().setScrollingDisabled(true, false); m.row(); - m.addButton("+", () -> {}).update(t -> { + m.addButton("+", () -> { + }).update(t -> { if(t.getClickListener().isPressed()){ updateTimer += Time.delta(); if(updateTimer >= updatePeriod){ - start ++; + start++; updateTimer = 0f; updateWaves(); } @@ -146,10 +146,10 @@ public class WaveInfoDialog extends FloatingDialog{ t.row(); t.table(spawns -> { spawns.addField("" + (group.begin + 1), TextFieldFilter.digitsOnly, text -> { - if(Strings.canParsePostiveInt(text)){ - group.begin = Strings.parseInt(text) - 1; - updateWaves(); - } + if(Strings.canParsePostiveInt(text)){ + group.begin = Strings.parseInt(text) - 1; + updateWaves(); + } }).width(100f); spawns.add("$waves.to").padLeft(4).padRight(4); spawns.addField(group.end == never ? "" : (group.end + 1) + "", TextFieldFilter.digitsOnly, text -> { @@ -166,7 +166,7 @@ public class WaveInfoDialog extends FloatingDialog{ t.table(p -> { p.add("$waves.every").padRight(4); p.addField(group.spacing + "", TextFieldFilter.digitsOnly, text -> { - if(Strings.canParsePostiveInt(text)){ + if(Strings.canParsePostiveInt(text) && Strings.parseInt(text) > 0){ group.spacing = Strings.parseInt(text); updateWaves(); } @@ -184,7 +184,7 @@ public class WaveInfoDialog extends FloatingDialog{ }).width(80f); a.add(" + "); - a.addField(Strings.toFixed(Math.max((Mathf.isZero(group.unitScaling) ? 0 : 1f/group.unitScaling), 0), 2), TextFieldFilter.floatsOnly, text -> { + a.addField(Strings.fixed(Math.max((Mathf.isZero(group.unitScaling) ? 0 : 1f / group.unitScaling), 0), 2), TextFieldFilter.floatsOnly, text -> { if(Strings.canParsePositiveFloat(text)){ group.unitScaling = 1f / Strings.parseFloat(text); updateWaves(); @@ -228,7 +228,7 @@ public class WaveInfoDialog extends FloatingDialog{ dialog.hide(); buildGroups(); }).pad(2).margin(12f).fillX(); - if(++i % 2 == 0)dialog.cont.row(); + if(++i % 3 == 0) dialog.cont.row(); } dialog.show(); } @@ -239,10 +239,10 @@ public class WaveInfoDialog extends FloatingDialog{ Array groups = (this.groups == null ? DefaultWaves.get() : this.groups); - for(int i = start; i < displayed + start; i ++){ + for(int i = start; i < displayed + start; i++){ int wave = i; preview.table("underline", table -> { - table.add((wave+1) + "").color(Pal.accent).center().colspan(2).get().setAlignment(Align.center, Align.center); + table.add((wave + 1) + "").color(Pal.accent).center().colspan(2).get().setAlignment(Align.center, Align.center); table.row(); int[] spawned = new int[Vars.content.getBy(ContentType.unit).size]; diff --git a/core/src/io/anuke/mindustry/editor/generation/DistortFilter.java b/core/src/io/anuke/mindustry/editor/generation/DistortFilter.java index ebd969845b..f2233be7bf 100644 --- a/core/src/io/anuke/mindustry/editor/generation/DistortFilter.java +++ b/core/src/io/anuke/mindustry/editor/generation/DistortFilter.java @@ -11,14 +11,14 @@ public class DistortFilter extends GenerateFilter{ { options( - new SliderOption("scale", () -> scl, f -> scl = f, 1f, 400f), - new SliderOption("mag", () -> mag, f -> mag = f, 0.5f, 100f) + new SliderOption("scale", () -> scl, f -> scl = f, 1f, 400f), + new SliderOption("mag", () -> mag, f -> mag = f, 0.5f, 100f) ); } @Override public void apply(){ - DummyTile tile = in.tile(in.x / (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); + DummyTile 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); diff --git a/core/src/io/anuke/mindustry/editor/generation/FilterOption.java b/core/src/io/anuke/mindustry/editor/generation/FilterOption.java index 8ebad34254..7034fb5467 100644 --- a/core/src/io/anuke/mindustry/editor/generation/FilterOption.java +++ b/core/src/io/anuke/mindustry/editor/generation/FilterOption.java @@ -9,18 +9,19 @@ import io.anuke.mindustry.Vars; import io.anuke.mindustry.ui.dialogs.FloatingDialog; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block.Icon; -import io.anuke.mindustry.world.blocks.Floor; -import io.anuke.mindustry.world.blocks.OreBlock; +import io.anuke.mindustry.world.blocks.*; import static io.anuke.mindustry.Vars.updateEditorOnChange; public abstract class FilterOption{ - public static final Predicate floorsOnly = b -> (b instanceof Floor && !(b instanceof OreBlock)) && Core.atlas.isFound(b.icon(Icon.full)); + public static final Predicate 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 oresOnly = b -> b instanceof OreBlock && Core.atlas.isFound(b.icon(Icon.full)); + public static final Predicate oresOnly = b -> b instanceof OverlayFloor && Core.atlas.isFound(b.icon(Icon.full)); public abstract void build(Table table); - public Runnable changed = () -> {}; + + public Runnable changed = () -> { + }; static class SliderOption extends FilterOption{ final String name; @@ -40,7 +41,7 @@ public abstract class FilterOption{ 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, (max - min) / 200f, setter).growX().get(); slider.setValue(getter.get()); if(updateEditorOnChange){ slider.changed(changed); @@ -65,14 +66,14 @@ 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().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.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/editor/generation/GenerateFilter.java index b6bde0d4de..bd8551b23a 100644 --- a/core/src/io/anuke/mindustry/editor/generation/GenerateFilter.java +++ b/core/src/io/anuke/mindustry/editor/generation/GenerateFilter.java @@ -5,13 +5,14 @@ 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.DummyTile; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.blocks.Floor; public abstract class GenerateFilter{ - protected float o = (float)(Math.random()*10000000.0); + protected float o = (float)(Math.random() * 10000000.0); protected long seed; protected GenerateInput in; @@ -20,15 +21,15 @@ public abstract class GenerateFilter{ protected abstract void apply(); protected float noise(float x, float y, float scl, float mag){ - return (float)in.noise.octaveNoise2D(1f, 0f, 1f/scl, x + o, y + o)*mag; + return (float)in.noise.octaveNoise2D(1f, 0f, 1f / scl, x + o, y + o) * mag; } protected float noise(float x, float y, float scl, float mag, float octaves, float persistence){ - return (float)in.noise.octaveNoise2D(octaves, persistence, 1f/scl, x + o, y + o)*mag; + return (float)in.noise.octaveNoise2D(octaves, persistence, 1f / scl, x + o, y + o) * mag; } protected float rnoise(float x, float y, float scl, float mag){ - return in.pnoise.getValue((int)(x + o), (int)(y + o), 1f/scl)*mag; + return in.pnoise.getValue((int)(x + o), (int)(y + o), 1f / scl) * mag; } public void randomize(){ @@ -50,6 +51,10 @@ public abstract class GenerateFilter{ public final void apply(GenerateInput in){ this.in = in; apply(); + //remove extra ores on liquids + if(((Floor)in.floor).isLiquid){ + in.ore = Blocks.air; + } } public static class GenerateInput{ diff --git a/core/src/io/anuke/mindustry/editor/generation/NoiseFilter.java b/core/src/io/anuke/mindustry/editor/generation/NoiseFilter.java index 580c6331a2..6a6871df91 100644 --- a/core/src/io/anuke/mindustry/editor/generation/NoiseFilter.java +++ b/core/src/io/anuke/mindustry/editor/generation/NoiseFilter.java @@ -14,12 +14,12 @@ public class NoiseFilter extends GenerateFilter{ { options( - new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f), - new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f), - new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f), - new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f), - new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly), - new BlockOption("wall", () -> block, b -> block = b, wallsOnly) + new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f), + new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f), + new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f), + new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f), + new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly), + new BlockOption("wall", () -> block, b -> block = b, wallsOnly) ); } diff --git a/core/src/io/anuke/mindustry/editor/generation/OreFilter.java b/core/src/io/anuke/mindustry/editor/generation/OreFilter.java index 976878f958..c5af869165 100644 --- a/core/src/io/anuke/mindustry/editor/generation/OreFilter.java +++ b/core/src/io/anuke/mindustry/editor/generation/OreFilter.java @@ -1,11 +1,11 @@ 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.*; +import static io.anuke.mindustry.editor.generation.FilterOption.BlockOption; +import static io.anuke.mindustry.editor.generation.FilterOption.oresOnly; public class OreFilter extends GenerateFilter{ float scl = 40, threshold = 0.8f, octaves = 3f, falloff = 0.5f; @@ -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 && !in.srcfloor.isLiquid){ + if(noise > threshold){ in.ore = ore; } } diff --git a/core/src/io/anuke/mindustry/editor/generation/RiverNoiseFilter.java b/core/src/io/anuke/mindustry/editor/generation/RiverNoiseFilter.java index 2920ee7ad3..2cfb256b41 100644 --- a/core/src/io/anuke/mindustry/editor/generation/RiverNoiseFilter.java +++ b/core/src/io/anuke/mindustry/editor/generation/RiverNoiseFilter.java @@ -6,18 +6,20 @@ 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 RiverNoiseFilter extends GenerateFilter{ float scl = 40, threshold = 0f, threshold2 = 0.1f; - Block floor = Blocks.water, floor2 = Blocks.deepwater; + Block floor = Blocks.water, floor2 = Blocks.deepwater, block = Blocks.sandRocks; { options( - new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f), - new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f), - new SliderOption("threshold2", () -> threshold2, f -> threshold2 = f, 0f, 1f), - new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly), - new BlockOption("floor2", () -> floor2, b -> floor2 = b, floorsOnly) + new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f), + new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f), + new SliderOption("threshold2", () -> threshold2, f -> threshold2 = f, 0f, 1f), + new BlockOption("block", () -> block, b -> block = b, wallsOnly), + new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly), + new BlockOption("floor2", () -> floor2, b -> floor2 = b, floorsOnly) ); } @@ -28,6 +30,10 @@ public class RiverNoiseFilter extends GenerateFilter{ if(noise >= threshold){ in.floor = floor; + if(in.srcblock.solid){ + in.block = block; + } + if(noise >= threshold2){ in.floor = floor2; } diff --git a/core/src/io/anuke/mindustry/editor/generation/ScatterFilter.java b/core/src/io/anuke/mindustry/editor/generation/ScatterFilter.java index af6b09822e..4c05603006 100644 --- a/core/src/io/anuke/mindustry/editor/generation/ScatterFilter.java +++ b/core/src/io/anuke/mindustry/editor/generation/ScatterFilter.java @@ -14,16 +14,16 @@ public class ScatterFilter extends GenerateFilter{ { 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) + 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){ + if(in.srcfloor == floor && in.srcblock == Blocks.air && chance() <= chance){ in.block = block; } } diff --git a/core/src/io/anuke/mindustry/editor/generation/TerrainFilter.java b/core/src/io/anuke/mindustry/editor/generation/TerrainFilter.java index e0bf3234f3..ab8e07c3cb 100644 --- a/core/src/io/anuke/mindustry/editor/generation/TerrainFilter.java +++ b/core/src/io/anuke/mindustry/editor/generation/TerrainFilter.java @@ -15,20 +15,20 @@ public class TerrainFilter extends GenerateFilter{ { options( - new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f), - new SliderOption("mag", () -> magnitude, f -> magnitude = f, 0f, 2f), - new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f), - new SliderOption("circle-scale", () -> circleScl, f -> circleScl = f, 0f, 3f), - new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f), - new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f), - new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly), - new BlockOption("wall", () -> block, b -> block = b, wallsOnly) + new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f), + new SliderOption("mag", () -> magnitude, f -> magnitude = f, 0f, 2f), + new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f), + new SliderOption("circle-scale", () -> circleScl, f -> circleScl = f, 0f, 3f), + new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f), + new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f), + new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly), + new BlockOption("wall", () -> block, b -> block = b, wallsOnly) ); } @Override public void apply(){ - float noise = noise(in.x, in.y, scl, magnitude, octaves, falloff) + Mathf.dst((float) in.x / in.editor.width(), (float) in.y / in.editor.height(), 0.5f, 0.5f) * circleScl; + float noise = noise(in.x, in.y, scl, magnitude, octaves, falloff) + Mathf.dst((float)in.x / in.editor.width(), (float)in.y / in.editor.height(), 0.5f, 0.5f) * circleScl; in.floor = floor; in.ore = Blocks.air; diff --git a/core/src/io/anuke/mindustry/entities/Damage.java b/core/src/io/anuke/mindustry/entities/Damage.java index 093c3f7b14..91631ccad4 100644 --- a/core/src/io/anuke/mindustry/entities/Damage.java +++ b/core/src/io/anuke/mindustry/entities/Damage.java @@ -1,46 +1,50 @@ package io.anuke.mindustry.entities; -import io.anuke.mindustry.entities.Effects.Effect; +import io.anuke.annotations.Annotations.Struct; +import io.anuke.arc.collection.GridBits; +import io.anuke.arc.collection.IntQueue; import io.anuke.arc.function.Consumer; import io.anuke.arc.function.Predicate; import io.anuke.arc.graphics.Color; import io.anuke.arc.math.Mathf; -import io.anuke.arc.math.geom.Geometry; -import io.anuke.arc.math.geom.Rectangle; -import io.anuke.arc.math.geom.Vector2; +import io.anuke.arc.math.geom.*; import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Bullets; import io.anuke.mindustry.content.Fx; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.effect.Fire; import io.anuke.mindustry.entities.effect.Lightning; import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.gen.Call; +import io.anuke.mindustry.gen.PropCell; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.world.Tile; import static io.anuke.mindustry.Vars.*; -/**Utility class for damaging in an area.*/ +/** Utility class for damaging in an area. */ public class Damage{ private static Rectangle rect = new Rectangle(); private static Rectangle hitrect = new Rectangle(); private static Vector2 tr = new Vector2(); + private static GridBits bits = new GridBits(30, 30); + private static IntQueue propagation = new IntQueue(); - /**Creates a dynamic explosion based on specified parameters.*/ + /** Creates a dynamic explosion based on specified parameters. */ public static void dynamicExplosion(float x, float y, float flammability, float explosiveness, float power, float radius, Color color){ for(int i = 0; i < Mathf.clamp(power / 20, 0, 6); i++){ - int branches = 5 + Mathf.clamp((int) (power / 30), 1, 20); + int branches = 5 + Mathf.clamp((int)(power / 30), 1, 20); Time.run(i * 2f + Mathf.random(4f), () -> Lightning.create(Team.none, Pal.power, 3, - x, y, Mathf.random(360f), branches + Mathf.range(2))); + x, y, Mathf.random(360f), branches + Mathf.range(2))); } for(int i = 0; i < Mathf.clamp(flammability / 4, 0, 30); i++){ Time.run(i / 2f, () -> Call.createBullet(Bullets.fireball, x, y, Mathf.random(360f))); } - int waves = Mathf.clamp((int) (explosiveness / 4), 0, 30); + int waves = Mathf.clamp((int)(explosiveness / 4), 0, 30); for(int i = 0; i < waves; i++){ int f = i; @@ -60,7 +64,7 @@ public class Damage{ float shake = Math.min(explosiveness / 4f + 3f, 9f); Effects.shake(shake, shake, x, y); - Effects.effect(Fx.dynamicExplosion, x, y, radius/8f); + Effects.effect(Fx.dynamicExplosion, x, y, radius / 8f); } public static void createIncend(float x, float y, float range, int amount){ @@ -129,7 +133,7 @@ public class Damage{ Units.getNearbyEnemies(team, rect, cons); } - /**Damages all entities and blocks in a radius that are enemies of the team.*/ + /** Damages all entities and blocks in a radius that are enemies of the team. */ public static void damageUnits(Team team, float x, float y, float size, float damage, Predicate predicate, Consumer acceptor){ Consumer cons = entity -> { if(!predicate.test(entity)) return; @@ -150,13 +154,18 @@ public class Damage{ } } - /**Damages everything in a radius.*/ + /** Damages everything in a radius. */ public static void damage(float x, float y, float radius, float damage){ - damage(null, x, y, radius, damage); + damage(null, x, y, radius, damage, false); } - /**Damages all entities and blocks in a radius that are enemies of the team.*/ + /** Damages all entities and blocks in a radius that are enemies of the team. */ public static void damage(Team team, float x, float y, float radius, float damage){ + damage(team, x, y, radius, damage, false); + } + + /** Damages all entities and blocks in a radius that are enemies of the team. */ + public static void damage(Team team, float x, float y, float radius, float damage, boolean complete){ Consumer cons = entity -> { if(entity.getTeam() == team || entity.dst(x, y) > radius){ return; @@ -175,17 +184,72 @@ public class Damage{ Units.getNearby(rect, cons); } - int trad = (int) (radius / tilesize); - for(int dx = -trad; dx <= trad; dx++){ - for(int dy = -trad; dy <= trad; dy++){ - Tile tile = world.tile(Math.round(x / tilesize) + dx, Math.round(y / tilesize) + dy); - if(tile != null && tile.entity != null && (team == null || state.teams.areEnemies(team, tile.getTeam())) && Mathf.dst(dx, dy, 0, 0) <= trad){ - float amount = calculateDamage(x, y, tile.worldx(), tile.worldy(), radius, damage); - tile.entity.damage(amount); + if(!complete){ + int trad = (int)(radius / tilesize); + Tile tile = world.tileWorld(x, y); + if(tile != null){ + tileDamage(team, tile.x, tile.y, trad, damage); + } + }else{ + completeDamage(team, x, y, radius, damage); + } + } + + public static void tileDamage(Team team, int startx, int starty, int radius, float baseDamage){ + bits.clear(); + propagation.clear(); + int bitOffset = bits.width() / 2; + + propagation.addFirst(PropCell.get((byte)0, (byte)0, (short)baseDamage)); + //clamp radius to fit bits + radius = Math.min(radius, bits.width() / 2); + + while(!propagation.isEmpty()){ + int prop = propagation.removeLast(); + int x = PropCell.x(prop); + int y = PropCell.y(prop); + int damage = PropCell.damage(prop); + //manhattan distance used for calculating falloff, results in a diamond pattern + int dst = Math.abs(x) + Math.abs(y); + + int scaledDamage = (int)(damage * (1f - (float)dst / radius)); + + bits.set(bitOffset + x, bitOffset + y); + Tile tile = world.tile(startx + x, starty + y); + + if(scaledDamage <= 0 || tile == null) continue; + + tile = tile.target(); + + //apply damage to entity if needed + if(tile.entity != null && tile.getTeam() != team){ + int health = (int)tile.entity.health; + if(tile.entity.health > 0){ + tile.entity.damage(scaledDamage); + scaledDamage -= health; + + if(scaledDamage <= 0) continue; + } + } + + for(Point2 p : Geometry.d4){ + if(!bits.get(bitOffset + x + p.x, bitOffset + y + p.y)){ + propagation.addFirst(PropCell.get((byte)(x + p.x), (byte)(y + p.y), (short)scaledDamage)); } } } + } + private static void completeDamage(Team team, float x, float y, float radius, float damage){ + int trad = (int)(radius / tilesize); + for(int dx = -trad; dx <= trad; dx++){ + for(int dy = -trad; dy <= trad; dy++){ + Tile tile = world.tile(Math.round(x / tilesize) + dx, Math.round(y / tilesize) + dy); + if(tile != null && tile.entity != null && (team == null || state.teams.areEnemies(team, tile.getTeam())) && Mathf.dst(dx, dy) <= trad){ + tile.entity.damage(damage); + } + } + } } private static float calculateDamage(float x, float y, float tx, float ty, float radius, float damage){ @@ -194,4 +258,11 @@ public class Damage{ float scaled = Mathf.lerp(1f - dist / radius, 1f, falloff); return damage * scaled; } + + @Struct + class PropCellStruct{ + byte x; + byte y; + short damage; + } } diff --git a/core/src/io/anuke/mindustry/entities/Effects.java b/core/src/io/anuke/mindustry/entities/Effects.java index 576d5cc56e..4a2f964b61 100644 --- a/core/src/io/anuke/mindustry/entities/Effects.java +++ b/core/src/io/anuke/mindustry/entities/Effects.java @@ -156,11 +156,11 @@ public class Effects{ } } - public static interface EffectProvider{ + public interface EffectProvider{ void createEffect(Effect effect, Color color, float x, float y, float rotation, Object data); } - public static interface EffectRenderer{ + public interface EffectRenderer{ void render(EffectContainer effect); } } diff --git a/core/src/io/anuke/mindustry/entities/EntityCollisions.java b/core/src/io/anuke/mindustry/entities/EntityCollisions.java index 62e5e214d6..dec2fd2291 100644 --- a/core/src/io/anuke/mindustry/entities/EntityCollisions.java +++ b/core/src/io/anuke/mindustry/entities/EntityCollisions.java @@ -3,16 +3,13 @@ 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.Geometry; -import io.anuke.arc.math.geom.QuadTree; -import io.anuke.arc.math.geom.Rectangle; -import io.anuke.arc.math.geom.Vector2; +import io.anuke.arc.math.geom.*; import io.anuke.mindustry.entities.traits.Entity; import io.anuke.mindustry.entities.traits.SolidTrait; public class EntityCollisions{ //range for tile collision scanning - private static final int r = 2; + private static final int r = 1; //move in 1-unit chunks private static final float seg = 1f; @@ -135,7 +132,7 @@ public class EntityCollisions{ for(Entity entity : group.all()){ if(entity instanceof SolidTrait){ - SolidTrait s = (SolidTrait) entity; + SolidTrait s = (SolidTrait)entity; s.lastPosition().set(s.getX(), s.getY()); tree.insert(s); } @@ -144,8 +141,8 @@ public class EntityCollisions{ private void checkCollide(Entity entity, Entity other){ - SolidTrait a = (SolidTrait) entity; - SolidTrait b = (SolidTrait) other; + SolidTrait a = (SolidTrait)entity; + SolidTrait b = (SolidTrait)other; a.hitbox(this.r1); b.hitbox(this.r2); @@ -228,7 +225,7 @@ public class EntityCollisions{ if(!(entity instanceof SolidTrait) || collided.contains(entity.getID())) continue; - SolidTrait solid = (SolidTrait) entity; + SolidTrait solid = (SolidTrait)entity; solid.hitbox(r1); r1.x += (solid.lastPosition().x - solid.getX()); diff --git a/core/src/io/anuke/mindustry/entities/EntityDraw.java b/core/src/io/anuke/mindustry/entities/EntityDraw.java index e0a95627c2..1308b4dd64 100644 --- a/core/src/io/anuke/mindustry/entities/EntityDraw.java +++ b/core/src/io/anuke/mindustry/entities/EntityDraw.java @@ -6,6 +6,7 @@ import io.anuke.arc.function.Predicate; import io.anuke.arc.graphics.Camera; import io.anuke.arc.math.geom.Rectangle; import io.anuke.mindustry.entities.traits.DrawTrait; +import io.anuke.mindustry.entities.traits.Entity; public class EntityDraw{ private static final Rectangle viewport = new Rectangle(); @@ -42,15 +43,12 @@ public class EntityDraw{ viewport.set(cam.position.x - cam.width / 2, cam.position.y - cam.height / 2, cam.width, cam.height); } - group.forEach(e -> { - if(!(e instanceof DrawTrait)) return; - T t = (T) e; + for(Entity e : group.all()){ + if(!(e instanceof DrawTrait) || !toDraw.test((T)e) || !e.isAdded()) continue; - if(!toDraw.test(t) || !e.isAdded()) return; - - if(!clip || rect.setSize(((DrawTrait) e).drawSize()).setCenter(e.getX(), e.getY()).overlaps(viewport)){ - cons.accept(t); + if(!clip || rect.setSize(((DrawTrait)e).drawSize()).setCenter(e.getX(), e.getY()).overlaps(viewport)){ + cons.accept((T)e); } - }); + } } } diff --git a/core/src/io/anuke/mindustry/entities/EntityGroup.java b/core/src/io/anuke/mindustry/entities/EntityGroup.java index 2050535843..212bd6dfa8 100644 --- a/core/src/io/anuke/mindustry/entities/EntityGroup.java +++ b/core/src/io/anuke/mindustry/entities/EntityGroup.java @@ -180,7 +180,7 @@ public class EntityGroup{ return null; } - /**Returns the logic-only array for iteration.*/ + /** Returns the logic-only array for iteration. */ public Array all(){ return entityArray; } diff --git a/core/src/io/anuke/mindustry/entities/EntityQuery.java b/core/src/io/anuke/mindustry/entities/EntityQuery.java index 8e25527400..9358ca4f06 100644 --- a/core/src/io/anuke/mindustry/entities/EntityQuery.java +++ b/core/src/io/anuke/mindustry/entities/EntityQuery.java @@ -74,7 +74,7 @@ public class EntityQuery{ float cdist = 0f; Array entities = getNearby(group, x, y, range * 2f); for(int i = 0; i < entities.size; i++){ - T e = (T) entities.get(i); + T e = (T)entities.get(i); if(!pred.test(e)) continue; diff --git a/core/src/io/anuke/mindustry/entities/Predict.java b/core/src/io/anuke/mindustry/entities/Predict.java index 71b95ee7f2..e4e103a64e 100644 --- a/core/src/io/anuke/mindustry/entities/Predict.java +++ b/core/src/io/anuke/mindustry/entities/Predict.java @@ -14,7 +14,6 @@ public class Predict{ /** * Calculates of intercept of a stationary and moving target. Do not call from multiple threads! - * * @param srcx X of shooter * @param srcy Y of shooter * @param dstx X of target @@ -28,7 +27,7 @@ public class Predict{ dstvx /= Time.delta(); dstvy /= Time.delta(); float tx = dstx - srcx, - ty = dsty - srcy; + ty = dsty - srcy; // Get quadratic equation components float a = dstvx * dstvx + dstvy * dstvy - v * v; @@ -39,7 +38,7 @@ public class Predict{ Vector2 ts = quad(a, b, c); // Find smallest positive solution - Vector2 sol = vresult.set(0, 0); + Vector2 sol = vresult.set(dstx, dsty); if(ts != null){ float t0 = ts.x, t1 = ts.y; float t = Math.min(t0, t1); @@ -57,8 +56,8 @@ public class Predict{ */ public static Vector2 intercept(TargetTrait src, TargetTrait dst, float v){ return intercept(src.getX(), src.getY(), dst.getX(), dst.getY(), - dst.getTargetVelocityX() - src.getTargetVelocityX(), - dst.getTargetVelocityY() - src.getTargetVelocityY(), v); + dst.getTargetVelocityX() - src.getTargetVelocityX(), + dst.getTargetVelocityY() - src.getTargetVelocityY(), v); } private static Vector2 quad(float a, float b, float c){ diff --git a/core/src/io/anuke/mindustry/entities/Units.java b/core/src/io/anuke/mindustry/entities/Units.java index 7c72ad9492..c913a6db6f 100644 --- a/core/src/io/anuke/mindustry/entities/Units.java +++ b/core/src/io/anuke/mindustry/entities/Units.java @@ -7,10 +7,7 @@ import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Geometry; import io.anuke.arc.math.geom.Rectangle; import io.anuke.mindustry.entities.traits.TargetTrait; -import io.anuke.mindustry.entities.type.Player; -import io.anuke.mindustry.entities.type.TileEntity; -import io.anuke.mindustry.entities.type.BaseUnit; -import io.anuke.mindustry.entities.type.Unit; +import io.anuke.mindustry.entities.type.*; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -29,7 +26,6 @@ public class Units{ /** * Validates a target. - * * @param target The target to validate * @param team The team of the thing doing tha targeting * @param x The X position of the thing doign the targeting @@ -41,17 +37,17 @@ public class Units{ return target == null || (range != Float.MAX_VALUE && target.dst(x, y) > range) || target.getTeam() == team || !target.isValid(); } - /**See {@link #invalidateTarget(TargetTrait, Team, float, float, float)}*/ + /** See {@link #invalidateTarget(TargetTrait, Team, float, float, float)} */ public static boolean invalidateTarget(TargetTrait target, Team team, float x, float y){ return invalidateTarget(target, team, x, y, Float.MAX_VALUE); } - /**See {@link #invalidateTarget(TargetTrait, Team, float, float, float)}*/ + /** See {@link #invalidateTarget(TargetTrait, Team, float, float, float)} */ public static boolean invalidateTarget(TargetTrait target, Unit targeter){ return invalidateTarget(target, targeter.getTeam(), targeter.x, targeter.y, targeter.getWeapon().bullet.range()); } - /**Returns whether there are any entities on this tile.*/ + /** Returns whether there are any entities on this tile. */ public static boolean anyEntities(Tile tile){ Block type = tile.block(); rect.setSize(type.size * tilesize, type.size * tilesize); @@ -60,7 +56,7 @@ public class Units{ return anyEntities(rect); } - /**Can be called from any thread.*/ + /** Can be called from any thread. */ public static boolean anyEntities(Rectangle rect){ boolResult = false; @@ -78,7 +74,7 @@ public class Units{ return boolResult; } - /**Returns whether there are any entities on this tile, with the hitbox expanded.*/ + /** Returns whether there are any entities on this tile, with the hitbox expanded. */ public static boolean anyEntities(Tile tile, float expansion, Predicate pred){ Block type = tile.block(); rect.setSize(type.size * tilesize + expansion, type.size * tilesize + expansion); @@ -100,18 +96,18 @@ public class Units{ return value[0]; } - /**Returns the neareset damaged tile.*/ + /** Returns the neareset damaged tile. */ public static TileEntity findDamagedTile(Team team, float x, float y){ Tile tile = Geometry.findClosest(x, y, world.indexer.getDamaged(team)); return tile == null ? null : tile.entity; } - /**Returns the neareset ally tile in a range.*/ + /** Returns the neareset ally tile in a range. */ public static TileEntity findAllyTile(Team team, float x, float y, float range, Predicate pred){ return world.indexer.findTile(team, x, y, range, pred); } - /**Returns the neareset enemy tile in a range.*/ + /** Returns the neareset enemy tile in a range. */ public static TileEntity findEnemyTile(Team team, float x, float y, float range, Predicate pred){ if(team == Team.none) return null; @@ -124,7 +120,7 @@ public class Units{ return null; } - /**Iterates over all units on all teams, including players.*/ + /** Iterates over all units on all teams, including players. */ public static void allUnits(Consumer cons){ //check all unit groups first for(EntityGroup group : unitGroups){ @@ -141,17 +137,17 @@ public class Units{ } } - /**Returns the closest target enemy. First, units are checked, then tile entities.*/ + /** Returns the closest target enemy. First, units are checked, then tile entities. */ public static TargetTrait getClosestTarget(Team team, float x, float y, float range){ return getClosestTarget(team, x, y, range, Unit::isValid); } - /**Returns the closest target enemy. First, units are checked, then tile entities.*/ + /** Returns the closest target enemy. First, units are checked, then tile entities. */ public static TargetTrait getClosestTarget(Team team, float x, float y, float range, Predicate unitPred){ return getClosestTarget(team, x, y, range, unitPred, t -> true); } - /**Returns the closest target enemy. First, units are checked, then tile entities.*/ + /** Returns the closest target enemy. First, units are checked, then tile entities. */ public static TargetTrait getClosestTarget(Team team, float x, float y, float range, Predicate unitPred, Predicate tilePred){ Unit unit = getClosestEnemy(team, x, y, range, unitPred); if(unit != null){ @@ -161,7 +157,7 @@ public class Units{ } } - /**Returns the closest enemy of this team. Filter by predicate.*/ + /** Returns the closest enemy of this team. Filter by predicate. */ public static Unit getClosestEnemy(Team team, float x, float y, float range, Predicate predicate){ if(team == Team.none) return null; @@ -186,7 +182,7 @@ public class Units{ return result; } - /**Returns the closest ally of this team. Filter by predicate.*/ + /** Returns the closest ally of this team. Filter by predicate. */ public static Unit getClosest(Team team, float x, float y, float range, Predicate predicate){ result = null; cdist = 0f; @@ -209,21 +205,21 @@ public class Units{ return result; } - /**Iterates over all units in a rectangle.*/ + /** Iterates over all units in a rectangle. */ public static void getNearby(Team team, Rectangle rect, Consumer cons){ EntityGroup group = unitGroups[team.ordinal()]; if(!group.isEmpty()){ - EntityQuery.getNearby(group, rect, entity -> cons.accept((Unit) entity)); + EntityQuery.getNearby(group, rect, entity -> cons.accept((Unit)entity)); } //now check all players EntityQuery.getNearby(playerGroup, rect, player -> { - if(((Unit) player).getTeam() == team) cons.accept((Unit) player); + if(((Unit)player).getTeam() == team) cons.accept((Unit)player); }); } - /**Iterates over all units in a circle around this position.*/ + /** Iterates over all units in a circle around this position. */ public static void getNearby(Team team, float x, float y, float radius, Consumer cons){ rect.setSize(radius * 2).setCenter(x, y); @@ -231,53 +227,53 @@ public class Units{ if(!group.isEmpty()){ EntityQuery.getNearby(group, rect, entity -> { if(entity.dst(x, y) <= radius){ - cons.accept((Unit) entity); + cons.accept((Unit)entity); } }); } //now check all players EntityQuery.getNearby(playerGroup, rect, player -> { - if(((Unit) player).getTeam() == team && player.dst(x, y) <= radius){ - cons.accept((Unit) player); + if(((Unit)player).getTeam() == team && player.dst(x, y) <= radius){ + cons.accept((Unit)player); } }); } - /**Iterates over all units in a rectangle.*/ + /** Iterates over all units in a rectangle. */ public static void getNearby(Rectangle rect, Consumer cons){ for(Team team : Team.all){ EntityGroup group = unitGroups[team.ordinal()]; if(!group.isEmpty()){ - EntityQuery.getNearby(group, rect, entity -> cons.accept((Unit) entity)); + EntityQuery.getNearby(group, rect, entity -> cons.accept((Unit)entity)); } } //now check all enemy players - EntityQuery.getNearby(playerGroup, rect, player -> cons.accept((Unit) player)); + EntityQuery.getNearby(playerGroup, rect, player -> cons.accept((Unit)player)); } - /**Iterates over all units that are enemies of this team.*/ + /** Iterates over all units that are enemies of this team. */ public static void getNearbyEnemies(Team team, Rectangle rect, Consumer cons){ EnumSet targets = state.teams.enemiesOf(team); for(Team other : targets){ EntityGroup group = unitGroups[other.ordinal()]; if(!group.isEmpty()){ - EntityQuery.getNearby(group, rect, entity -> cons.accept((Unit) entity)); + EntityQuery.getNearby(group, rect, entity -> cons.accept((Unit)entity)); } } //now check all enemy players EntityQuery.getNearby(playerGroup, rect, player -> { - if(targets.contains(((Player) player).getTeam())){ - cons.accept((Unit) player); + if(targets.contains(((Player)player).getTeam())){ + cons.accept((Unit)player); } }); } - /**Iterates over all units.*/ + /** Iterates over all units. */ public static void getAllUnits(Consumer cons){ for(Team team : Team.all){ diff --git a/core/src/io/anuke/mindustry/entities/bullet/ArtilleryBulletType.java b/core/src/io/anuke/mindustry/entities/bullet/ArtilleryBulletType.java index 5c74a9f9f7..cbe7cae4fd 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/ArtilleryBulletType.java +++ b/core/src/io/anuke/mindustry/entities/bullet/ArtilleryBulletType.java @@ -1,9 +1,9 @@ package io.anuke.mindustry.entities.bullet; -import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.mindustry.content.Fx; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; //TODO scale velocity depending on fslope() public class ArtilleryBulletType extends BasicBulletType{ diff --git a/core/src/io/anuke/mindustry/entities/bullet/BasicBulletType.java b/core/src/io/anuke/mindustry/entities/bullet/BasicBulletType.java index b1127b6581..86b96ba7a8 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/BasicBulletType.java +++ b/core/src/io/anuke/mindustry/entities/bullet/BasicBulletType.java @@ -4,44 +4,18 @@ 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.math.Angles; -import io.anuke.arc.math.Mathf; -import io.anuke.mindustry.entities.Damage; -import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.Units; -import io.anuke.mindustry.entities.effect.Lightning; -import io.anuke.mindustry.entities.traits.TargetTrait; import io.anuke.mindustry.graphics.Pal; -/**An extended BulletType for most ammo-based bullets shot from turrets and units.*/ +/** An extended BulletType for most ammo-based bullets shot from turrets and units. */ public class BasicBulletType extends BulletType{ public Color backColor = Pal.bulletYellowBack, frontColor = Pal.bulletYellow; public float bulletWidth = 5f, bulletHeight = 7f; public float bulletShrink = 0.5f; public String bulletSprite; - public int fragBullets = 9; - public float fragVelocityMin = 0.2f, fragVelocityMax = 1f; - public BulletType fragBullet = null; - - /**Use a negative value to disable splash damage.*/ - public float splashDamageRadius = -1f; - - public int incendAmount = 0; - public float incendSpread = 8f; - public float incendChance = 1f; - - public float homingPower = 0f; - public float homingRange = 50f; - - public int lightining; - public int lightningLength = 5; - public TextureRegion backRegion; public TextureRegion frontRegion; - public float hitShake = 0f; - public BasicBulletType(float speed, float damage, String bulletSprite){ super(speed, damage); this.bulletSprite = bulletSprite; @@ -63,51 +37,4 @@ public class BasicBulletType extends BulletType{ Draw.rect(frontRegion, b.x, b.y, bulletWidth, height, b.rot() - 90); Draw.color(); } - - @Override - public void update(Bullet b){ - super.update(b); - - if(homingPower > 0.0001f){ - TargetTrait target = Units.getClosestTarget(b.getTeam(), b.x, b.y, homingRange); - if(target != null){ - b.velocity().setAngle(Mathf.slerpDelta(b.velocity().angle(), b.angleTo(target), 0.08f)); - } - } - } - - @Override - public void hit(Bullet b, float x, float y){ - super.hit(b, x, y); - - Effects.shake(hitShake, hitShake, b); - - if(fragBullet != null){ - for(int i = 0; i < fragBullets; i++){ - float len = Mathf.random(1f, 7f); - float a = Mathf.random(360f); - Bullet.create(fragBullet, b, x + Angles.trnsx(a, len), y + Angles.trnsy(a, len), a, Mathf.random(fragVelocityMin, fragVelocityMax)); - } - } - - if(Mathf.chance(incendChance)){ - Damage.createIncend(x, y, incendSpread, incendAmount); - } - - if(splashDamageRadius > 0){ - Damage.damage(b.getTeam(), x, y, splashDamageRadius, splashDamage); - } - } - - @Override - public void despawned(Bullet b){ - super.despawned(b); - if(fragBullet != null || splashDamageRadius > 0){ - hit(b); - } - - for (int i = 0; i < lightining; i++) { - Lightning.create(b.getTeam(), Pal.surge, damage, b.x, b.y, Mathf.random(360f), lightningLength); - } - } } diff --git a/core/src/io/anuke/mindustry/entities/bullet/Bullet.java b/core/src/io/anuke/mindustry/entities/bullet/Bullet.java index ae61553586..590e3b1635 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/Bullet.java +++ b/core/src/io/anuke/mindustry/entities/bullet/Bullet.java @@ -5,9 +5,7 @@ import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.math.geom.Vector2; -import io.anuke.arc.util.Interval; -import io.anuke.arc.util.Time; -import io.anuke.arc.util.Tmp; +import io.anuke.arc.util.*; import io.anuke.arc.util.pooling.Pool.Poolable; import io.anuke.arc.util.pooling.Pools; import io.anuke.mindustry.entities.EntityGroup; @@ -18,9 +16,7 @@ import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.world.Tile; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.*; @@ -36,7 +32,7 @@ public class Bullet extends SolidEntity implements DamageTrait, ScaleTrait, Pool protected Entity owner; protected float time; - /**Internal use only!*/ + /** Internal use only! */ public Bullet(){ } @@ -64,7 +60,7 @@ public class Bullet extends SolidEntity implements DamageTrait, ScaleTrait, Pool bullet.velocity.set(0, type.speed).setAngle(angle).scl(velocityScl); if(type.keepVelocity){ - bullet.velocity.add(owner instanceof VelocityTrait ? ((VelocityTrait) owner).velocity() : Vector2.ZERO); + bullet.velocity.add(owner instanceof VelocityTrait ? ((VelocityTrait)owner).velocity() : Vector2.ZERO); } bullet.team = team; @@ -85,13 +81,13 @@ public class Bullet extends SolidEntity implements DamageTrait, ScaleTrait, Pool return create(type, parent.owner, parent.team, x, y, angle, velocityScl); } - /**Internal use only.*/ + /** Internal use only. */ @Remote(called = Loc.server, unreliable = true) public static void createBullet(BulletType type, float x, float y, float angle){ create(type, null, Team.none, x, y, angle); } - /**ok*/ + /** ok */ @Remote(called = Loc.server, unreliable = true) public static void createBullet(BulletType type, Team team, float x, float y, float angle){ create(type, null, team, x, y, angle); @@ -131,6 +127,13 @@ public class Bullet extends SolidEntity implements DamageTrait, ScaleTrait, Pool this.data = data; } + public float damageMultiplier(){ + if(owner instanceof Unit){ + return ((Unit)owner).getDamageMultipler(); + } + return 1f; + } + @Override public void absorb(){ supressCollision = true; @@ -144,16 +147,10 @@ public class Bullet extends SolidEntity implements DamageTrait, ScaleTrait, Pool @Override public float damage(){ - //todo hacky way to get damage, refactor - if(owner instanceof Unit){ - return type.damage * ((Unit) owner).getDamageMultipler(); - } - if(owner instanceof Lightning && data instanceof Float){ return (Float)data; } - - return type.damage; + return type.damage * damageMultiplier(); } @Override @@ -193,7 +190,7 @@ public class Bullet extends SolidEntity implements DamageTrait, ScaleTrait, Pool @Override public boolean collides(SolidTrait other){ - return type.collides && (other != owner && !(other instanceof DamageTrait)) && !supressCollision && !(other instanceof Unit && ((Unit) other).isFlying() && !type.collidesAir); + return type.collides && (other != owner && !(other instanceof DamageTrait)) && !supressCollision && !(other instanceof Unit && ((Unit)other).isFlying() && !type.collidesAir); } @Override @@ -202,7 +199,7 @@ public class Bullet extends SolidEntity implements DamageTrait, ScaleTrait, Pool type.hit(this, x, y); if(other instanceof Unit){ - Unit unit = (Unit) other; + Unit unit = (Unit)other; unit.velocity().add(Tmp.v3.set(other.getX(), other.getY()).sub(x, y).setLength(type.knockback / unit.mass())); unit.applyEffect(type.status, type.statusDuration); } @@ -217,7 +214,7 @@ public class Bullet extends SolidEntity implements DamageTrait, ScaleTrait, Pool velocity.scl(Mathf.clamp(1f - type.drag * Time.delta())); - time += Time.delta() * 1f/(lifeScl); + time += Time.delta() * 1f / (lifeScl); time = Mathf.clamp(time, 0, type.lifetime); if(time >= type.lifetime){ @@ -335,12 +332,12 @@ public class Bullet extends SolidEntity implements DamageTrait, ScaleTrait, Pool velocity.limit(f); } - /** Sets the bullet's rotation in degrees.*/ + /** Sets the bullet's rotation in degrees. */ public void rot(float angle){ velocity.setAngle(angle); } - /** @return the bullet's rotation.*/ + /** @return the bullet's rotation. */ public float rot(){ float angle = Mathf.atan2(velocity.x, velocity.y) * Mathf.radiansToDegrees; if(angle < 0) angle += 360; diff --git a/core/src/io/anuke/mindustry/entities/bullet/BulletType.java b/core/src/io/anuke/mindustry/entities/bullet/BulletType.java index 198adaaf37..45cbc8aa8a 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/BulletType.java +++ b/core/src/io/anuke/mindustry/entities/bullet/BulletType.java @@ -1,10 +1,15 @@ package io.anuke.mindustry.entities.bullet; -import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.Effects.Effect; -import io.anuke.mindustry.content.StatusEffects; +import io.anuke.arc.math.Angles; +import io.anuke.arc.math.Mathf; import io.anuke.mindustry.content.Fx; +import io.anuke.mindustry.content.StatusEffects; +import io.anuke.mindustry.entities.*; +import io.anuke.mindustry.entities.Effects.Effect; +import io.anuke.mindustry.entities.effect.Lightning; +import io.anuke.mindustry.entities.traits.TargetTrait; import io.anuke.mindustry.game.Content; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.StatusEffect; import io.anuke.mindustry.world.Tile; @@ -19,43 +24,62 @@ public abstract class BulletType extends Content{ public boolean pierce; public Effect hitEffect, despawnEffect; - /**Effect created when shooting.*/ + /** Effect created when shooting. */ public Effect shootEffect = Fx.shootSmall; - /**Extra smoke effect created when shooting.*/ + /** Extra smoke effect created when shooting. */ public Effect smokeEffect = Fx.shootSmallSmoke; - /**Extra inaccuracy when firing.*/ + /** Extra inaccuracy when firing. */ public float inaccuracy = 0f; - /**How many bullets get created per ammo item/liquid.*/ + /** How many bullets get created per ammo item/liquid. */ public float ammoMultiplier = 1f; - /**Multiplied by turret reload speed to get final shoot speed.*/ + /** Multiplied by turret reload speed to get final shoot speed. */ public float reloadMultiplier = 1f; - /**Recoil from shooter entities.*/ + /** Recoil from shooter entities. */ public float recoil; public float splashDamage = 0f; - /**Knockback in velocity.*/ + /** Knockback in velocity. */ public float knockback; - /**Whether this bullet hits tiles.*/ + /** Whether this bullet hits tiles. */ public boolean hitTiles = true; - /**Status effect applied on hit.*/ + /** Status effect applied on hit. */ public StatusEffect status = StatusEffects.none; - /**Intensity of applied status effect in terms of duration.*/ + /** Intensity of applied status effect in terms of duration. */ public float statusDuration = 60 * 1f; - /**What fraction of armor is pierced, 0-1*/ - public float armorPierce = 0f; - /**Whether to sync this bullet to clients.*/ + /** Whether to sync this bullet to clients. */ public boolean syncable; - /**Whether this bullet type collides with tiles.*/ + /** Whether this bullet type collides with tiles. */ public boolean collidesTiles = true; - /**Whether this bullet type collides with tiles that are of the same team.*/ + /** Whether this bullet type collides with tiles that are of the same team. */ public boolean collidesTeam = false; - /**Whether this bullet type collides with air units.*/ + /** Whether this bullet type collides with air units. */ public boolean collidesAir = true; - /**Whether this bullet types collides with anything at all.*/ + /** Whether this bullet types collides with anything at all. */ public boolean collides = true; - /**Whether velocity is inherited from the shooter.*/ + /** Whether velocity is inherited from the shooter. */ public boolean keepVelocity = true; + //additional effects + + public int fragBullets = 9; + public float fragVelocityMin = 0.2f, fragVelocityMax = 1f; + public BulletType fragBullet = null; + + /** Use a negative value to disable splash damage. */ + public float splashDamageRadius = -1f; + + public int incendAmount = 0; + public float incendSpread = 8f; + public float incendChance = 1f; + + public float homingPower = 0f; + public float homingRange = 50f; + + public int lightining; + public int lightningLength = 5; + + public float hitShake = 0f; + public BulletType(float speed, float damage){ this.speed = speed; this.damage = damage; @@ -64,7 +88,7 @@ public abstract class BulletType extends Content{ despawnEffect = Fx.hitBulletSmall; } - /**Returns maximum distance the bullet this bullet type has can travel.*/ + /** Returns maximum distance the bullet this bullet type has can travel. */ public float range(){ return speed * lifetime * (1f - drag); } @@ -81,12 +105,38 @@ public abstract class BulletType extends Content{ hit(b, b.x, b.y); } - public void hit(Bullet b, float hitx, float hity){ - Effects.effect(hitEffect, hitx, hity, b.rot()); + public void hit(Bullet b, float x, float y){ + Effects.effect(hitEffect, x, y, b.rot()); + + Effects.shake(hitShake, hitShake, b); + + if(fragBullet != null){ + for(int i = 0; i < fragBullets; i++){ + float len = Mathf.random(1f, 7f); + float a = Mathf.random(360f); + Bullet.create(fragBullet, b, x + Angles.trnsx(a, len), y + Angles.trnsy(a, len), a, Mathf.random(fragVelocityMin, fragVelocityMax)); + } + } + + if(Mathf.chance(incendChance)){ + Damage.createIncend(x, y, incendSpread, incendAmount); + } + + if(splashDamageRadius > 0){ + Damage.damage(b.getTeam(), x, y, splashDamageRadius, splashDamage * b.damageMultiplier()); + } } public void despawned(Bullet b){ Effects.effect(despawnEffect, b.x, b.y, b.rot()); + + if(fragBullet != null || splashDamageRadius > 0){ + hit(b); + } + + for(int i = 0; i < lightining; i++){ + Lightning.create(b.getTeam(), Pal.surge, damage, b.x, b.y, Mathf.random(360f), lightningLength); + } } public void draw(Bullet b){ @@ -96,6 +146,13 @@ public abstract class BulletType extends Content{ } public void update(Bullet b){ + + if(homingPower > 0.0001f){ + TargetTrait target = Units.getClosestTarget(b.getTeam(), b.x, b.y, homingRange); + if(target != null){ + b.velocity().setAngle(Mathf.slerpDelta(b.velocity().angle(), b.angleTo(target), 0.08f)); + } + } } @Override diff --git a/core/src/io/anuke/mindustry/entities/bullet/FlakBulletType.java b/core/src/io/anuke/mindustry/entities/bullet/FlakBulletType.java index 908bd3f17b..227191470a 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/FlakBulletType.java +++ b/core/src/io/anuke/mindustry/entities/bullet/FlakBulletType.java @@ -1,9 +1,9 @@ package io.anuke.mindustry.entities.bullet; import io.anuke.arc.math.geom.Rectangle; +import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.entities.Units; -import io.anuke.arc.util.Time; public abstract class FlakBulletType extends BasicBulletType{ protected static Rectangle rect = new Rectangle(); @@ -24,7 +24,7 @@ public abstract class FlakBulletType extends BasicBulletType{ if(b.getData() instanceof Integer) return; if(b.timer.get(2, 6)){ - Units.getNearbyEnemies(b.getTeam(), rect.setSize(explodeRange*2f).setCenter(b.x, b.y), unit -> { + Units.getNearbyEnemies(b.getTeam(), rect.setSize(explodeRange * 2f).setCenter(b.x, b.y), unit -> { if(b.getData() instanceof Float) return; if(unit.dst(b) < explodeRange){ diff --git a/core/src/io/anuke/mindustry/entities/bullet/LiquidBulletType.java b/core/src/io/anuke/mindustry/entities/bullet/LiquidBulletType.java index 6b4c7d8bb9..e3fe41f828 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/LiquidBulletType.java +++ b/core/src/io/anuke/mindustry/entities/bullet/LiquidBulletType.java @@ -1,6 +1,5 @@ package io.anuke.mindustry.entities.bullet; -import io.anuke.mindustry.entities.Effects; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Fill; @@ -8,6 +7,7 @@ import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Geometry; import io.anuke.arc.math.geom.Point2; import io.anuke.mindustry.content.Fx; +import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.effect.Fire; import io.anuke.mindustry.entities.effect.Puddle; import io.anuke.mindustry.type.Liquid; @@ -20,7 +20,7 @@ public class LiquidBulletType extends BulletType{ Liquid liquid; public LiquidBulletType(Liquid liquid){ - super(2.8f, 0); + super(3.5f, 0); this.liquid = liquid; lifetime = 74f; @@ -35,11 +35,11 @@ public class LiquidBulletType extends BulletType{ @Override public float range(){ - return speed * lifetime /2f; + return speed * lifetime / 2f; } @Override - public void update(Bullet b) { + public void update(Bullet b){ super.update(b); if(liquid.canExtinguish()){ diff --git a/core/src/io/anuke/mindustry/entities/bullet/MassDriverBolt.java b/core/src/io/anuke/mindustry/entities/bullet/MassDriverBolt.java index 237aa09a15..01902bd9bc 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/MassDriverBolt.java +++ b/core/src/io/anuke/mindustry/entities/bullet/MassDriverBolt.java @@ -1,11 +1,11 @@ package io.anuke.mindustry.entities.bullet; -import io.anuke.mindustry.entities.Effects; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.math.Angles; import io.anuke.arc.math.Mathf; import io.anuke.mindustry.content.Fx; +import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.world.blocks.distribution.MassDriver.DriverBulletData; @@ -45,7 +45,7 @@ public class MassDriverBolt extends BulletType{ float hitDst = 7f; - DriverBulletData data = (DriverBulletData) b.getData(); + DriverBulletData data = (DriverBulletData)b.getData(); //if the target is dead, just keep flying until the bullet explodes if(data.to.isDead()){ @@ -87,7 +87,7 @@ public class MassDriverBolt extends BulletType{ if(!(b.getData() instanceof DriverBulletData)) return; - DriverBulletData data = (DriverBulletData) b.getData(); + DriverBulletData data = (DriverBulletData)b.getData(); data.to.isRecieving = false; for(int i = 0; i < data.items.length; i++){ diff --git a/core/src/io/anuke/mindustry/entities/bullet/MissileBulletType.java b/core/src/io/anuke/mindustry/entities/bullet/MissileBulletType.java index 351078866d..56a6b5ae7f 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/MissileBulletType.java +++ b/core/src/io/anuke/mindustry/entities/bullet/MissileBulletType.java @@ -1,11 +1,11 @@ package io.anuke.mindustry.entities.bullet; import io.anuke.arc.graphics.Color; -import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.graphics.Pal; -import io.anuke.mindustry.entities.Effects; -import io.anuke.arc.util.Time; import io.anuke.arc.math.Mathf; +import io.anuke.arc.util.Time; +import io.anuke.mindustry.content.Fx; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.graphics.Pal; public class MissileBulletType extends BasicBulletType{ protected Color trailColor = Pal.missileYellowBack; diff --git a/core/src/io/anuke/mindustry/entities/effect/Decal.java b/core/src/io/anuke/mindustry/entities/effect/Decal.java index 1cb773a3cc..72d251d9be 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Decal.java +++ b/core/src/io/anuke/mindustry/entities/effect/Decal.java @@ -1,12 +1,12 @@ package io.anuke.mindustry.entities.effect; import io.anuke.arc.graphics.Color; -import io.anuke.mindustry.entities.traits.BelowLiquidTrait; -import io.anuke.mindustry.entities.EntityGroup; -import io.anuke.mindustry.entities.impl.TimedEntity; -import io.anuke.mindustry.entities.traits.DrawTrait; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.math.Mathf; +import io.anuke.mindustry.entities.EntityGroup; +import io.anuke.mindustry.entities.impl.TimedEntity; +import io.anuke.mindustry.entities.traits.BelowLiquidTrait; +import io.anuke.mindustry.entities.traits.DrawTrait; import static io.anuke.mindustry.Vars.groundEffectGroup; diff --git a/core/src/io/anuke/mindustry/entities/effect/Fire.java b/core/src/io/anuke/mindustry/entities/effect/Fire.java index e4b1731661..18c5c48ebe 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Fire.java +++ b/core/src/io/anuke/mindustry/entities/effect/Fire.java @@ -3,9 +3,6 @@ package io.anuke.mindustry.entities.effect; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.collection.IntMap; -import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.EntityGroup; -import io.anuke.mindustry.entities.impl.TimedEntity; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Geometry; import io.anuke.arc.math.geom.Point2; @@ -13,22 +10,17 @@ import io.anuke.arc.util.Structs; import io.anuke.arc.util.Time; import io.anuke.arc.util.pooling.Pool.Poolable; import io.anuke.arc.util.pooling.Pools; -import io.anuke.mindustry.content.Bullets; -import io.anuke.mindustry.content.StatusEffects; -import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.Damage; -import io.anuke.mindustry.entities.type.TileEntity; +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.gen.Call; import io.anuke.mindustry.net.Net; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Pos; -import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.*; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.*; @@ -42,10 +34,11 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{ private float baseFlammability = -1, puddleFlammability; private float lifetime; - /**Deserialization use only!*/ - public Fire(){} + /** Deserialization use only! */ + public Fire(){ + } - /**Start a fire on the tile. If there already is a file there, refreshes its lifetime.*/ + /** Start a fire on the tile. If there already is a file there, refreshes its lifetime. */ public static void create(Tile tile){ if(Net.client() || tile == null) return; //not clientside. @@ -153,8 +146,8 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{ entity.damage(0.4f); } Damage.damageUnits(null, tile.worldx(), tile.worldy(), tilesize, 3f, - unit -> !unit.isFlying() && !unit.isImmune(StatusEffects.burning), - unit -> unit.applyEffect(StatusEffects.burning, 60 * 5)); + unit -> !unit.isFlying() && !unit.isImmune(StatusEffects.burning), + unit -> unit.applyEffect(StatusEffects.burning, 60 * 5)); } } @@ -175,14 +168,17 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{ @Override public void write(DataOutput data) throws IOException{ - data.writeFloat(x); - data.writeFloat(y); + data.writeInt(tile.pos()); + data.writeFloat(lifetime); } @Override public void read(DataInput data) throws IOException{ - x = data.readFloat(); - y = data.readFloat(); + int pos = data.readInt(); + this.lifetime = data.readFloat(); + + x = Pos.x(pos) * tilesize; + y = Pos.y(pos) * tilesize; } @Override diff --git a/core/src/io/anuke/mindustry/entities/effect/GroundEffectEntity.java b/core/src/io/anuke/mindustry/entities/effect/GroundEffectEntity.java index bc98f1619a..54094c4a87 100644 --- a/core/src/io/anuke/mindustry/entities/effect/GroundEffectEntity.java +++ b/core/src/io/anuke/mindustry/entities/effect/GroundEffectEntity.java @@ -1,12 +1,12 @@ package io.anuke.mindustry.entities.effect; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.util.Time; +import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.mindustry.entities.Effects.EffectRenderer; import io.anuke.mindustry.entities.impl.EffectEntity; -import io.anuke.arc.math.Mathf; -import io.anuke.arc.util.Time; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.world.Tile; /** @@ -17,7 +17,7 @@ public class GroundEffectEntity extends EffectEntity{ @Override public void update(){ - GroundEffect effect = (GroundEffect) this.effect; + GroundEffect effect = (GroundEffect)this.effect; if(effect.isStatic){ time += Time.delta(); @@ -41,7 +41,7 @@ public class GroundEffectEntity extends EffectEntity{ @Override public void draw(){ - GroundEffect effect = (GroundEffect) this.effect; + GroundEffect effect = (GroundEffect)this.effect; if(once && effect.isStatic) Effects.renderEffect(id, effect, color, lifetime(), rotation, x, y, data); diff --git a/core/src/io/anuke/mindustry/entities/effect/ItemTransfer.java b/core/src/io/anuke/mindustry/entities/effect/ItemTransfer.java index 5083897a33..2cb7f567e1 100644 --- a/core/src/io/anuke/mindustry/entities/effect/ItemTransfer.java +++ b/core/src/io/anuke/mindustry/entities/effect/ItemTransfer.java @@ -2,18 +2,16 @@ package io.anuke.mindustry.entities.effect; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; -import io.anuke.mindustry.entities.EntityGroup; -import io.anuke.mindustry.entities.impl.TimedEntity; -import io.anuke.mindustry.entities.traits.DrawTrait; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Fill; -import io.anuke.arc.graphics.g2d.Lines; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Interpolation; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Position; import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.util.Time; import io.anuke.arc.util.pooling.Pools; +import io.anuke.mindustry.entities.EntityGroup; +import io.anuke.mindustry.entities.impl.TimedEntity; +import io.anuke.mindustry.entities.traits.DrawTrait; import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.type.Item; diff --git a/core/src/io/anuke/mindustry/entities/effect/Lightning.java b/core/src/io/anuke/mindustry/entities/effect/Lightning.java index 7a89b29f9d..3358d64cd7 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Lightning.java +++ b/core/src/io/anuke/mindustry/entities/effect/Lightning.java @@ -4,27 +4,18 @@ import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.collection.Array; import io.anuke.arc.collection.IntSet; -import io.anuke.arc.graphics.g2d.Fill; -import io.anuke.arc.graphics.g2d.Lines; -import io.anuke.mindustry.entities.EntityGroup; -import io.anuke.mindustry.entities.impl.TimedEntity; -import io.anuke.mindustry.entities.traits.DrawTrait; -import io.anuke.mindustry.entities.traits.TimeTrait; import io.anuke.arc.graphics.Color; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.math.Angles; -import io.anuke.arc.math.Mathf; -import io.anuke.arc.math.RandomXS128; -import io.anuke.arc.math.geom.Geometry; -import io.anuke.arc.math.geom.Position; -import io.anuke.arc.math.geom.Rectangle; -import io.anuke.arc.math.geom.Vector2; +import io.anuke.arc.graphics.g2d.*; +import io.anuke.arc.math.*; +import io.anuke.arc.math.geom.*; import io.anuke.arc.util.pooling.Pools; import io.anuke.mindustry.content.Bullets; -import io.anuke.mindustry.entities.type.Unit; +import io.anuke.mindustry.entities.EntityGroup; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.bullet.Bullet; -import io.anuke.mindustry.entities.traits.SyncTrait; +import io.anuke.mindustry.entities.impl.TimedEntity; +import io.anuke.mindustry.entities.traits.*; +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; @@ -48,16 +39,16 @@ public class Lightning extends TimedEntity implements DrawTrait, SyncTrait, Time private Array lines = new Array<>(); private Color color = Pal.lancerLaser; - /**For pooling use only. Do not call directly!*/ + /** For pooling use only. Do not call directly! */ public Lightning(){ } - /**Create a lighting branch at a location. Use Team.none to damage everyone.*/ + /** Create a lighting branch at a location. Use Team.none to damage everyone. */ public static void create(Team team, Color color, float damage, float x, float y, float targetAngle, int length){ Call.createLighting(lastSeed++, team, color, damage, x, y, targetAngle, length); } - /**Do not invoke!*/ + /** Do not invoke! */ @Remote(called = Loc.server) public static void createLighting(int seed, Team team, Color color, float damage, float x, float y, float rotation, int length){ @@ -72,7 +63,7 @@ public class Lightning extends TimedEntity implements DrawTrait, SyncTrait, Time random.setSeed(seed); hit.clear(); - for (int i = 0; i < length/2; i++) { + for(int i = 0; i < length / 2; i++){ Bullet.create(Bullets.damageLightning, l, team, x, y, 0f, 1f, 1f, dmg); l.lines.add(new Vector2(x + Mathf.range(3f), y + Mathf.range(3f))); @@ -94,8 +85,8 @@ public class Lightning extends TimedEntity implements DrawTrait, SyncTrait, Time y = furthest.y; }else{ rotation += random.range(20f); - x += Angles.trnsx(rotation, hitRange/2f); - y += Angles.trnsy(rotation, hitRange/2f); + x += Angles.trnsx(rotation, hitRange / 2f); + y += Angles.trnsy(rotation, hitRange / 2f); } } } @@ -106,10 +97,12 @@ public class Lightning extends TimedEntity implements DrawTrait, SyncTrait, Time } @Override - public void write(DataOutput data){} + public void write(DataOutput data){ + } @Override - public void read(DataInput data){} + public void read(DataInput data){ + } @Override public float lifetime(){ @@ -144,7 +137,7 @@ public class Lightning extends TimedEntity implements DrawTrait, SyncTrait, Time int i = 0; for(Position p : lines){ - Fill.square(p.getX(), p.getY(), (5f - (float)i++/lines.size*2f) * fout(), 45); + Fill.square(p.getX(), p.getY(), (5f - (float)i++ / lines.size * 2f) * fout(), 45); } Draw.reset(); } diff --git a/core/src/io/anuke/mindustry/entities/effect/Puddle.java b/core/src/io/anuke/mindustry/entities/effect/Puddle.java index 8c3eb67ff7..f07800844c 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Puddle.java +++ b/core/src/io/anuke/mindustry/entities/effect/Puddle.java @@ -3,36 +3,25 @@ package io.anuke.mindustry.entities.effect; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.collection.IntMap; -import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.EntityGroup; -import io.anuke.mindustry.entities.impl.SolidEntity; -import io.anuke.mindustry.entities.traits.DrawTrait; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Fill; import io.anuke.arc.math.Angles; import io.anuke.arc.math.Mathf; -import io.anuke.arc.math.geom.Geometry; -import io.anuke.arc.math.geom.Point2; -import io.anuke.arc.math.geom.Rectangle; +import io.anuke.arc.math.geom.*; import io.anuke.arc.util.Time; import io.anuke.arc.util.pooling.Pool.Poolable; import io.anuke.arc.util.pooling.Pools; -import io.anuke.mindustry.content.Liquids; -import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.content.Bullets; -import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.Units; -import io.anuke.mindustry.entities.traits.SaveTrait; -import io.anuke.mindustry.entities.traits.SyncTrait; +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.gen.Call; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Tile; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.*; @@ -55,21 +44,21 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai private float accepting; private byte generation; - /**Deserialization use only!*/ + /** Deserialization use only! */ public Puddle(){ } - /**Deposists a puddle between tile and source.*/ + /** Deposists a puddle between tile and source. */ public static void deposit(Tile tile, Tile source, Liquid liquid, float amount){ deposit(tile, source, liquid, amount, 0); } - /**Deposists a puddle at a tile.*/ + /** Deposists a puddle at a tile. */ public static void deposit(Tile tile, Liquid liquid, float amount){ deposit(tile, tile, liquid, amount, 0); } - /**Returns the puddle on the specified tile. May return null.*/ + /** Returns the puddle on the specified tile. May return null. */ public static Puddle getPuddle(Tile tile){ return map.get(tile.pos()); } @@ -79,13 +68,13 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai if(tile.floor().isLiquid && !canStayOn(liquid, tile.floor().liquidDrop)){ reactPuddle(tile.floor().liquidDrop, liquid, amount, tile, - (tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f); + (tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f); Puddle p = map.get(tile.pos()); if(generation == 0 && p != null && p.lastRipple <= Time.time() - 40f){ Effects.effect(Fx.ripple, tile.floor().liquidDrop.color, - (tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f); + (tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f); p.lastRipple = Time.time(); } return; @@ -99,14 +88,14 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai puddle.tile = tile; puddle.liquid = liquid; puddle.amount = amount; - puddle.generation = (byte) generation; + puddle.generation = (byte)generation; puddle.set((tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f); puddle.add(); map.put(tile.pos(), puddle); }else if(p.liquid == liquid){ p.accepting = Math.max(amount, p.accepting); - if(generation == 0 && p.lastRipple <= Time.time() - 40f && p.amount >= maxLiquid / 2f){ + if(generation == 0 && p.lastRipple <= Time.time() - 40f && p.amount >= maxLiquid / 2f){ Effects.effect(Fx.ripple, p.liquid.color, (tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f); p.lastRipple = Time.time(); } @@ -123,10 +112,10 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai return liquid == Liquids.oil && other == Liquids.water; } - /**Reacts two liquids together at a location.*/ + /** Reacts two liquids together at a location. */ private static float reactPuddle(Liquid dest, Liquid liquid, float amount, Tile tile, float x, float y){ if((dest.flammability > 0.3f && liquid.temperature > 0.7f) || - (liquid.flammability > 0.3f && dest.temperature > 0.7f)){ //flammable liquid + hot liquid + (liquid.flammability > 0.3f && dest.temperature > 0.7f)){ //flammable liquid + hot liquid Fire.create(tile); if(Mathf.chance(0.006 * amount)){ Call.createBullet(Bullets.fireball, x, y, Mathf.random(360f)); @@ -234,7 +223,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai Fill.circle(x + Mathf.sin(Time.time() + seeds * 532, sscl, smag), y + Mathf.sin(Time.time() + seeds * 53, sscl, smag), f * 8f); Angles.randLenVectors(id, 3, f * 6f, (ex, ey) -> { Fill.circle(x + ex + Mathf.sin(Time.time() + seeds * 532, sscl, smag), - y + ey + Mathf.sin(Time.time() + seeds * 53, sscl, smag), f * 5f); + y + ey + Mathf.sin(Time.time() + seeds * 53, sscl, smag), f * 5f); seeds++; }); Draw.color(); @@ -295,7 +284,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai data.writeFloat(x); data.writeFloat(y); data.writeByte(liquid.id); - data.writeShort((short) (amount * 4)); + data.writeShort((short)(amount * 4)); data.writeInt(tile.pos()); } @@ -305,9 +294,10 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai y = data.readFloat(); liquid = content.liquid(data.readByte()); targetAmount = data.readShort() / 4f; - tile = world.tile(data.readInt()); + int pos = data.readInt(); + tile = world.tile(pos); - map.put(tile.pos(), this); + map.put(pos, this); } @Override diff --git a/core/src/io/anuke/mindustry/entities/effect/RubbleDecal.java b/core/src/io/anuke/mindustry/entities/effect/RubbleDecal.java index bc94ecbec9..eb5e4b01ab 100644 --- a/core/src/io/anuke/mindustry/entities/effect/RubbleDecal.java +++ b/core/src/io/anuke/mindustry/entities/effect/RubbleDecal.java @@ -11,7 +11,7 @@ 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.*/ + /** 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; diff --git a/core/src/io/anuke/mindustry/entities/effect/ScorchDecal.java b/core/src/io/anuke/mindustry/entities/effect/ScorchDecal.java index eba584b76b..5de0a894a2 100644 --- a/core/src/io/anuke/mindustry/entities/effect/ScorchDecal.java +++ b/core/src/io/anuke/mindustry/entities/effect/ScorchDecal.java @@ -40,10 +40,10 @@ public class ScorchDecal extends Decal{ float space = 1.5f + Mathf.randomSeed(id + i + 1, 0, 20) / 10f; Draw.rect(region, x + Angles.trnsx(rotation, space), - y + Angles.trnsy(rotation, space) + region.getHeight()/2f*Draw.scl, + y + Angles.trnsy(rotation, space) + region.getHeight() / 2f * Draw.scl, region.getWidth() * Draw.scl, region.getHeight() * Draw.scl, - region.getWidth()/2f*Draw.scl, 0, rotation - 90); + region.getWidth() / 2f * Draw.scl, 0, rotation - 90); } } } diff --git a/core/src/io/anuke/mindustry/entities/impl/DestructibleEntity.java b/core/src/io/anuke/mindustry/entities/impl/DestructibleEntity.java index fdb22094c6..dce6f3dae5 100644 --- a/core/src/io/anuke/mindustry/entities/impl/DestructibleEntity.java +++ b/core/src/io/anuke/mindustry/entities/impl/DestructibleEntity.java @@ -1,9 +1,7 @@ package io.anuke.mindustry.entities.impl; -import io.anuke.mindustry.entities.traits.DamageTrait; -import io.anuke.mindustry.entities.traits.HealthTrait; -import io.anuke.mindustry.entities.traits.SolidTrait; +import io.anuke.mindustry.entities.traits.*; public abstract class DestructibleEntity extends SolidEntity implements HealthTrait{ public transient boolean dead; @@ -18,7 +16,7 @@ public abstract class DestructibleEntity extends SolidEntity implements HealthTr public void collision(SolidTrait other, float x, float y){ if(other instanceof DamageTrait){ onHit(other); - damage(((DamageTrait) other).damage()); + damage(((DamageTrait)other).damage()); } } diff --git a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java index 248fadfee1..ec745b67c3 100644 --- a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java @@ -5,9 +5,7 @@ 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.Draw; -import io.anuke.arc.graphics.g2d.Fill; -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.Vector2; @@ -16,58 +14,57 @@ 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.Player; -import io.anuke.mindustry.entities.type.TileEntity; -import io.anuke.mindustry.entities.type.Unit; +import io.anuke.mindustry.entities.type.*; 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.Block; -import io.anuke.mindustry.world.Build; -import io.anuke.mindustry.world.Pos; -import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.blocks.BuildBlock; import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import java.util.Arrays; 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. */ public interface BuilderTrait extends Entity, TeamTrait{ //these are not instance variables! - Vector2[] tmptr = new Vector2[]{new Vector2(), new Vector2(), new Vector2(), new Vector2()}; float placeDistance = 220f; float mineDistance = 70f; - Array removal = new Array<>(); - /**Returns the queue for storing build requests.*/ + //due to iOS wierdness + class BuildDataStatic{ + static Array removal = new Array<>(); + static Vector2[] tmptr = new Vector2[]{new Vector2(), new Vector2(), new Vector2(), new Vector2()}; + } + + /** Returns the queue for storing build requests. */ Queue getPlaceQueue(); - /**Returns the tile this builder is currently mining.*/ + /** Returns the tile this builder is currently mining. */ Tile getMineTile(); - /**Sets the tile this builder is currently mining.*/ + /** 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.*/ + /** Returns the minining speed of this miner. 1 = standard, 0.5 = half speed, 2 = double speed, etc. */ float getMinePower(); - /**Build power, can be any float. 1 = builds recipes in normal time, 0 = doesn't build at all.*/ + /** 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.*/ + /** 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.*/ + /** Whether this type of builder can begin creating new blocks. */ default boolean canCreateBlocks(){ return true; } @@ -101,13 +98,13 @@ public interface BuilderTrait extends Entity, TeamTrait{ float progress = input.readFloat(); BuildRequest request; - if(type == 1){ //remove - request = new BuildRequest(Pos.x(position), Pos.y(position)); - }else{ //place - byte block = input.readByte(); - byte rotation = input.readByte(); - request = new BuildRequest(Pos.x(position), Pos.y(position), rotation, content.block(block)); - } + if(type == 1){ //remove + request = new BuildRequest(Pos.x(position), Pos.y(position)); + }else{ //place + byte block = input.readByte(); + byte rotation = input.readByte(); + request = new BuildRequest(Pos.x(position), Pos.y(position), rotation, content.block(block)); + } request.progress = progress; @@ -119,17 +116,17 @@ public interface BuilderTrait extends Entity, TeamTrait{ } } - /**Return whether this builder's place queue contains items.*/ + /** Return whether this builder's place queue contains items. */ default boolean isBuilding(){ return getPlaceQueue().size != 0; } - /**Clears the placement queue.*/ + /** Clears the placement queue. */ default void clearBuilding(){ getPlaceQueue().clear(); } - /**Add another build requests to the tail of the queue, if it doesn't exist there yet.*/ + /** 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()){ if(request.x == place.x && request.y == place.y){ @@ -167,8 +164,8 @@ public interface BuilderTrait extends Entity, TeamTrait{ for(BuildRequest request : removal){ if(!((request.breaking && world.tile(request.x, request.y).block() == Blocks.air) || - (!request.breaking && (world.tile(request.x, request.y).getRotation() == request.rotation || !request.block.rotate) - && world.tile(request.x, request.y).block() == request.block))){ + (!request.breaking && (world.tile(request.x, request.y).getRotation() == request.rotation || !request.block.rotate) + && world.tile(request.x, request.y).block() == request.block))){ getPlaceQueue().addLast(request); } } @@ -197,9 +194,9 @@ public interface BuilderTrait extends Entity, TeamTrait{ if(!(tile.block() instanceof BuildBlock)){ if(canCreateBlocks() && !current.breaking && Build.validPlace(getTeam(), current.x, current.y, current.block, current.rotation)){ - Build.beginPlace(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)){ - Build.beginBreak(getTeam(), current.x, current.y); + Call.beginBreak(getTeam(), current.x, current.y); }else{ getPlaceQueue().removeFirst(); return; @@ -208,8 +205,8 @@ public interface BuilderTrait extends Entity, TeamTrait{ TileEntity core = unit.getClosestCore(); - //if there is no core to build with, stop building! - if(core == null){ + //if there is no core to build with or no build entity, stop building! + if(core == null || !(tile.entity instanceof BuildEntity)){ return; } @@ -217,7 +214,6 @@ public interface BuilderTrait extends Entity, TeamTrait{ BuildEntity entity = tile.entity(); if(entity == null){ - getPlaceQueue().removeFirst(); return; } @@ -229,9 +225,9 @@ public interface BuilderTrait extends Entity, TeamTrait{ if(!Net.client()){ //deconstructing is 2x as fast if(current.breaking){ - entity.deconstruct(unit, core, 2f / entity.buildCost * Time.delta() * getBuildPower(tile)); + entity.deconstruct(unit, core, 2f / entity.buildCost * Time.delta() * getBuildPower(tile) * state.rules.buildSpeedMultiplier); }else{ - entity.construct(unit, core, 1f / entity.buildCost * Time.delta() * getBuildPower(tile)); + entity.construct(unit, core, 1f / entity.buildCost * Time.delta() * getBuildPower(tile) * state.rules.buildSpeedMultiplier); } current.progress = entity.progress(); @@ -245,14 +241,14 @@ public interface BuilderTrait extends Entity, TeamTrait{ } } - /**Do not call directly.*/ + /** 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())){ + || tile.drop() == null || !unit.acceptsItem(tile.drop()) || !canMine(tile.drop())){ setMineTile(null); }else{ Item item = tile.drop(); @@ -262,25 +258,25 @@ public interface BuilderTrait extends Entity, TeamTrait{ 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); + 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); + 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); + 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. This includes mining */ default void drawBuilding(){ Unit unit = (Unit)this; BuildRequest request; @@ -313,10 +309,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); @@ -328,7 +324,7 @@ public interface BuilderTrait extends Entity, TeamTrait{ Draw.color(); } - /**Internal use only.*/ + /** Internal use only. */ default void drawMining(){ Unit unit = (Unit)this; Tile tile = getMineTile(); @@ -349,7 +345,7 @@ public interface BuilderTrait extends Entity, TeamTrait{ Shapes.laser("minelaser", "minelaser-end", px, py, ex, ey, 0.75f); - if(unit instanceof Player && ((Player) unit).isLocal){ + 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()); } @@ -357,7 +353,7 @@ public interface BuilderTrait extends Entity, TeamTrait{ Draw.color(); } - /**Class for storing build requests. Can be either a place or remove request.*/ + /** Class for storing build requests. Can be either a place or remove request. */ class BuildRequest{ public final int x, y, rotation; public final Block block; @@ -366,7 +362,7 @@ public interface BuilderTrait extends Entity, TeamTrait{ public float progress; public boolean initialized; - /**This creates a build request.*/ + /** This creates a build request. */ public BuildRequest(int x, int y, int rotation, Block block){ this.x = x; this.y = y; @@ -375,7 +371,7 @@ public interface BuilderTrait extends Entity, TeamTrait{ this.breaking = false; } - /**This creates a remove request.*/ + /** This creates a remove request. */ public BuildRequest(int x, int y){ this.x = x; this.y = y; diff --git a/core/src/io/anuke/mindustry/entities/traits/Saveable.java b/core/src/io/anuke/mindustry/entities/traits/Saveable.java index 6f3950bcb0..b3b3bc5914 100644 --- a/core/src/io/anuke/mindustry/entities/traits/Saveable.java +++ b/core/src/io/anuke/mindustry/entities/traits/Saveable.java @@ -1,8 +1,6 @@ package io.anuke.mindustry.entities.traits; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; public interface Saveable{ void writeSave(DataOutput stream) throws IOException; diff --git a/core/src/io/anuke/mindustry/entities/traits/SolidTrait.java b/core/src/io/anuke/mindustry/entities/traits/SolidTrait.java index 83f5a70524..9321c6fcc1 100644 --- a/core/src/io/anuke/mindustry/entities/traits/SolidTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/SolidTrait.java @@ -1,11 +1,9 @@ package io.anuke.mindustry.entities.traits; -import io.anuke.mindustry.entities.EntityQuery; -import io.anuke.arc.math.geom.Position; +import io.anuke.arc.math.geom.*; import io.anuke.arc.math.geom.QuadTree.QuadTreeObject; -import io.anuke.arc.math.geom.Rectangle; -import io.anuke.arc.math.geom.Vector2; +import io.anuke.mindustry.entities.EntityQuery; public interface SolidTrait extends QuadTreeObject, MoveTrait, VelocityTrait, Entity, Position{ @@ -35,7 +33,8 @@ public interface SolidTrait extends QuadTreeObject, MoveTrait, VelocityTrait, En return true; } - default void collision(SolidTrait other, float x, float y){} + default void collision(SolidTrait other, float x, float y){ + } default void move(float x, float y){ EntityQuery.collisions().move(this, x, y); diff --git a/core/src/io/anuke/mindustry/entities/traits/SyncTrait.java b/core/src/io/anuke/mindustry/entities/traits/SyncTrait.java index 81e5419014..f41bc0381b 100644 --- a/core/src/io/anuke/mindustry/entities/traits/SyncTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/SyncTrait.java @@ -1,17 +1,12 @@ package io.anuke.mindustry.entities.traits; -import io.anuke.mindustry.core.NetClient; import io.anuke.mindustry.net.Interpolator; -import io.anuke.arc.Core; -import io.anuke.arc.util.Tmp; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; public interface SyncTrait extends Entity, TypeTrait{ - /**Sets the position of this entity and updated the interpolator.*/ + /** Sets the position of this entity and updated the interpolator. */ default void setNet(float x, float y){ set(x, y); @@ -24,40 +19,29 @@ public interface SyncTrait extends Entity, TypeTrait{ } } - /**Interpolate entity position only. Override if you need to interpolate rotations or other values.*/ + /** Interpolate entity position only. Override if you need to interpolate rotations or other values. */ default void interpolate(){ if(getInterpolator() == null){ throw new RuntimeException("This entity must have an interpolator to interpolate()!"); } - if(isClipped()){ - //move off screen when no longer in bounds - Tmp.r1.setSize(Core.camera.width * NetClient.viewScale, Core.camera.height * NetClient.viewScale) - .setCenter(Core.camera.position.x, Core.camera.position.y); - - if(!Tmp.r1.contains(getX(), getY()) && !Tmp.r1.contains(getInterpolator().last.x, getInterpolator().last.y)){ - set(-99999f, -99999f); - return; - } - } - getInterpolator().update(); setX(getInterpolator().pos.x); setY(getInterpolator().pos.y); } - /**Return the interpolator used for smoothing the position. Optional.*/ + /** Return the interpolator used for smoothing the position. Optional. */ default Interpolator getInterpolator(){ return null; } - /**Whether syncing is enabled for this entity; true by default.*/ + /** Whether syncing is enabled for this entity; true by default. */ default boolean isSyncing(){ return true; } - /**Whether this entity is clipped and not synced when out of viewport.*/ + /** Whether this entity is clipped and not synced when out of viewport. */ default boolean isClipped(){ return true; } diff --git a/core/src/io/anuke/mindustry/entities/traits/TargetTrait.java b/core/src/io/anuke/mindustry/entities/traits/TargetTrait.java index dcc7a876b9..819e9dbcdc 100644 --- a/core/src/io/anuke/mindustry/entities/traits/TargetTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/TargetTrait.java @@ -14,14 +14,14 @@ public interface TargetTrait extends Position, VelocityTrait{ default float getTargetVelocityX(){ if(this instanceof SolidTrait){ - return ((SolidTrait) this).getDeltaX(); + return ((SolidTrait)this).getDeltaX(); } return velocity().x; } default float getTargetVelocityY(){ if(this instanceof SolidTrait){ - return ((SolidTrait) this).getDeltaY(); + return ((SolidTrait)this).getDeltaY(); } return velocity().y; } diff --git a/core/src/io/anuke/mindustry/entities/traits/VelocityTrait.java b/core/src/io/anuke/mindustry/entities/traits/VelocityTrait.java index c836154f9c..e5bddaed43 100644 --- a/core/src/io/anuke/mindustry/entities/traits/VelocityTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/VelocityTrait.java @@ -28,7 +28,7 @@ public interface VelocityTrait extends MoveTrait{ velocity().scl(1f - drag() * Time.delta()); if(this instanceof SolidTrait){ - ((SolidTrait) this).move(velocity().x * Time.delta(), velocity().y * Time.delta()); + ((SolidTrait)this).move(velocity().x * Time.delta(), velocity().y * Time.delta()); }else{ moveBy(velocity().x * Time.delta(), velocity().y * Time.delta()); } diff --git a/core/src/io/anuke/mindustry/entities/type/BaseUnit.java b/core/src/io/anuke/mindustry/entities/type/BaseUnit.java index 2542e79bdd..54553c2036 100644 --- a/core/src/io/anuke/mindustry/entities/type/BaseUnit.java +++ b/core/src/io/anuke/mindustry/entities/type/BaseUnit.java @@ -17,9 +17,7 @@ import io.anuke.mindustry.entities.EntityGroup; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.traits.ShooterTrait; import io.anuke.mindustry.entities.traits.TargetTrait; -import io.anuke.mindustry.entities.units.StateMachine; -import io.anuke.mindustry.entities.units.UnitDrops; -import io.anuke.mindustry.entities.units.UnitState; +import io.anuke.mindustry.entities.units.*; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.net.Net; @@ -27,18 +25,17 @@ import io.anuke.mindustry.type.*; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockFlag; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.*; -/**Base class for AI units.*/ +/** Base class for AI units. */ public abstract class BaseUnit extends Unit implements ShooterTrait{ protected static int timerIndex = 0; protected static final int timerTarget = timerIndex++; + protected static final int timerTarget2 = timerIndex++; protected static final int timerShootLeft = timerIndex++; protected static final int timerShootRight = timerIndex++; @@ -49,7 +46,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ protected int spawner = noSpawner; - /**internal constructor used for deserialization, DO NOT USE*/ + /** internal constructor used for deserialization, DO NOT USE */ public BaseUnit(){ } @@ -63,6 +60,16 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ unit.onSuperDeath(); + //visual only. + if(Net.client()){ + Tile tile = world.tile(unit.spawner); + if(tile != null && !Net.client()){ + tile.block().unitRemoved(tile, unit); + } + + unit.spawner = noSpawner; + } + //must run afterwards so the unit's group is not null when sending the removal packet Core.app.post(unit::remove); } @@ -72,7 +79,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ return type.drag; } - /**Initialize the type and team of this unit. Only call once!*/ + /** 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!"); @@ -93,7 +100,7 @@ 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); } public void setState(UnitState state){ @@ -106,14 +113,14 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ } } - /**Only runs when the unit has a target.*/ + /** Only runs when the unit has a target. */ public void behavior(){ } public void updateTargeting(){ if(target == null || (target instanceof Unit && (target.isDead() || target.getTeam() == team)) - || (target instanceof TileEntity && ((TileEntity) target).tile.entity == null)){ + || (target instanceof TileEntity && ((TileEntity)target).tile.entity == null)){ target = null; } } @@ -129,7 +136,10 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ } public void targetClosest(){ - target = Units.getClosestTarget(team, x, y, Math.max(getWeapon().bullet.range(), type.range), u -> type.targetAir || !u.isFlying()); + TargetTrait newTarget = Units.getClosestTarget(team, x, y, Math.max(getWeapon().bullet.range(), type.range), u -> type.targetAir || !u.isFlying()); + if(newTarget != null){ + target = newTarget; + } } public TileEntity getClosestEnemyCore(){ @@ -157,9 +167,9 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ float angT = i == 0 ? 0 : Mathf.randomSeedRange(i + 2, 60f); float lenT = i == 0 ? 0 : Mathf.randomSeedRange(i + 3, 1f) - 1f; Draw.rect(item.item.icon(Item.Icon.large), - x + Angles.trnsx(rotation + 180f + angT, backTrns + lenT), - y + Angles.trnsy(rotation + 180f + angT, backTrns + lenT), - itemSize, itemSize, rotation); + x + Angles.trnsx(rotation + 180f + angT, backTrns + lenT), + y + Angles.trnsy(rotation + 180f + angT, backTrns + lenT), + itemSize, itemSize, rotation); } } } @@ -168,6 +178,11 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ return hasEffect(StatusEffects.boss); } + @Override + public float getDamageMultipler(){ + return status.getDamageMultiplier() * Vars.state.rules.unitDamageMultiplier; + } + @Override public boolean isImmune(StatusEffect effect){ return type.immunities.contains(effect); @@ -214,7 +229,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ @Override public float maxHealth(){ - return type.health; + return type.health * Vars.state.rules.unitHealthMultiplier; } @Override @@ -275,8 +290,9 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ @Override public void removed(){ + super.removed(); Tile tile = world.tile(spawner); - if(tile != null){ + if(tile != null && !Net.client()){ tile.block().unitRemoved(tile, this); } @@ -353,6 +369,8 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ interpolator.read(lastx, lasty, x, y, rotation); rotation = lastrot; + x = lastx; + y = lasty; } public void onSuperDeath(){ diff --git a/core/src/io/anuke/mindustry/entities/type/FlyingUnit.java b/core/src/io/anuke/mindustry/entities/type/FlyingUnit.java index ff628a98b8..854cd51c3d 100644 --- a/core/src/io/anuke/mindustry/entities/type/FlyingUnit.java +++ b/core/src/io/anuke/mindustry/entities/type/FlyingUnit.java @@ -47,7 +47,7 @@ public abstract class FlyingUnit extends BaseUnit{ attack(type.attackLength); if((Angles.near(angleTo(target), rotation, type.shootCone) || getWeapon().ignoreRotation) //bombers and such don't care about rotation - && dst(target) < Math.max(getWeapon().bullet.range(), type.range)){ + && dst(target) < getWeapon().bullet.range()){ BulletType ammo = getWeapon().bullet; if(type.rotateWeapon){ @@ -75,8 +75,9 @@ public abstract class FlyingUnit extends BaseUnit{ targetClosest(); targetClosestEnemyFlag(BlockFlag.target); - if(target != null){ + if(target != null && !Units.invalidateTarget(target, team, x, y)){ setState(attack); + return; } target = getClosestCore(); @@ -126,11 +127,11 @@ public abstract class FlyingUnit extends BaseUnit{ public void drawEngine(){ Draw.color(Pal.engine); Fill.circle(x + Angles.trnsx(rotation + 180, type.engineOffset), y + Angles.trnsy(rotation + 180, type.engineOffset), - type.engineSize + Mathf.absin(Time.time(), 2f, type.engineSize/4f)); + type.engineSize + Mathf.absin(Time.time(), 2f, type.engineSize / 4f)); Draw.color(Color.WHITE); - Fill.circle(x + Angles.trnsx(rotation + 180, type.engineOffset-1f), y + Angles.trnsy(rotation + 180, type.engineOffset-1f), - (type.engineSize + Mathf.absin(Time.time(), 2f, type.engineSize/4f)) / 2f); + Fill.circle(x + Angles.trnsx(rotation + 180, type.engineOffset - 1f), y + Angles.trnsy(rotation + 180, type.engineOffset - 1f), + (type.engineSize + Mathf.absin(Time.time(), 2f, type.engineSize / 4f)) / 2f); Draw.color(); } @@ -140,7 +141,7 @@ public abstract class FlyingUnit extends BaseUnit{ if(Units.invalidateTarget(target, this)){ for(boolean left : Mathf.booleans){ int wi = Mathf.num(left); - weaponAngles[wi] = Mathf.slerpDelta(weaponAngles[wi],rotation, 0.1f); + weaponAngles[wi] = Mathf.slerpDelta(weaponAngles[wi], rotation, 0.1f); } } } @@ -153,8 +154,8 @@ public abstract class FlyingUnit extends BaseUnit{ protected void wobble(){ if(Net.client()) return; - x += Mathf.sin(Time.time() + id * 999, 25f, 0.05f)*Time.delta(); - y += Mathf.cos(Time.time() + id * 999, 25f, 0.05f)*Time.delta(); + x += Mathf.sin(Time.time() + id * 999, 25f, 0.05f) * Time.delta(); + y += Mathf.cos(Time.time() + id * 999, 25f, 0.05f) * Time.delta(); if(velocity.len() <= 0.05f){ //rotation += Mathf.sin(Time.time() + id * 99, 10f, 2f * type.speed)*Time.delta(); diff --git a/core/src/io/anuke/mindustry/entities/type/GroundUnit.java b/core/src/io/anuke/mindustry/entities/type/GroundUnit.java index 2982057316..062231d760 100644 --- a/core/src/io/anuke/mindustry/entities/type/GroundUnit.java +++ b/core/src/io/anuke/mindustry/entities/type/GroundUnit.java @@ -54,10 +54,11 @@ public abstract class GroundUnit extends BaseUnit{ patrol = new UnitState(){ public void update(){ TileEntity target = getClosestCore(); + if(target != null){ if(dst(target) > 400f){ moveAwayFromCore(); - }else{ + }else if(!(!Units.invalidateTarget(GroundUnit.this.target, GroundUnit.this) && dst(GroundUnit.this.target) < getWeapon().bullet.range())){ patrol(); } } @@ -110,23 +111,23 @@ public abstract class GroundUnit extends BaseUnit{ public void draw(){ Draw.mixcol(Color.WHITE, hitTime / hitDuration); - float ft = Mathf.sin(walkTime * type.speed*5f, 6f, 2f + type.hitsize/15f); + float ft = Mathf.sin(walkTime * type.speed * 5f, 6f, 2f + type.hitsize / 15f); Floor floor = getFloorOn(); if(floor.isLiquid){ - Draw.color(Color.WHITE, floor.liquidColor, 0.5f); + Draw.color(Color.WHITE, floor.color, 0.5f); } for(int i : Mathf.signs){ Draw.rect(type.legRegion, - x + Angles.trnsx(baseRotation, ft * i), - y + Angles.trnsy(baseRotation, ft * i), - type.legRegion.getWidth() * i * Draw.scl, type.legRegion.getHeight() * Draw.scl - Mathf.clamp(ft * i, 0, 2), baseRotation - 90); + x + Angles.trnsx(baseRotation, ft * i), + y + Angles.trnsy(baseRotation, ft * i), + type.legRegion.getWidth() * i * Draw.scl, type.legRegion.getHeight() * Draw.scl - Mathf.clamp(ft * i, 0, 2), baseRotation - 90); } if(floor.isLiquid){ - Draw.color(Color.WHITE, floor.liquidColor, drownTime * 0.4f); + Draw.color(Color.WHITE, floor.color, drownTime * 0.4f); }else{ Draw.color(Color.WHITE); } @@ -137,10 +138,10 @@ public abstract class GroundUnit extends BaseUnit{ for(int i : Mathf.signs){ float tra = rotation - 90, trY = -type.weapon.getRecoil(this, i > 0) + type.weaponOffsetY; - float w = - i * type.weapon.region.getWidth() * Draw.scl; + float w = -i * type.weapon.region.getWidth() * Draw.scl; Draw.rect(type.weapon.region, - x + Angles.trnsx(tra, getWeapon().width * i, trY), - y + Angles.trnsy(tra, getWeapon().width * i, trY), w, type.weapon.region.getHeight() * Draw.scl, rotation - 90); + x + Angles.trnsx(tra, getWeapon().width * i, trY), + y + Angles.trnsy(tra, getWeapon().width * i, trY), w, type.weapon.region.getHeight() * Draw.scl, rotation - 90); } drawItems(); @@ -210,11 +211,9 @@ public abstract class GroundUnit extends BaseUnit{ if(tile == targetTile) return; - float angle = angleTo(targetTile); - - velocity.add(vec.trns(angleTo(targetTile), type.speed*Time.delta())); + velocity.add(vec.trns(angleTo(targetTile), type.speed * Time.delta())); if(Units.invalidateTarget(target, this)){ - rotation = Mathf.slerpDelta(rotation, angle, type.rotatespeed); + rotation = Mathf.slerpDelta(rotation, baseRotation, type.rotatespeed); } } @@ -236,9 +235,7 @@ public abstract class GroundUnit extends BaseUnit{ if(tile == targetTile || core == null || dst(core) < 90f) return; - float angle = angleTo(targetTile); - - velocity.add(vec.trns(angleTo(targetTile), type.speed*Time.delta())); - rotation = Mathf.slerpDelta(rotation, angle, type.rotatespeed); + velocity.add(vec.trns(angleTo(targetTile), type.speed * Time.delta())); + rotation = Mathf.slerpDelta(rotation, baseRotation, type.rotatespeed); } } diff --git a/core/src/io/anuke/mindustry/entities/type/Player.java b/core/src/io/anuke/mindustry/entities/type/Player.java index 7598bfd03c..922d4bd4ce 100644 --- a/core/src/io/anuke/mindustry/entities/type/Player.java +++ b/core/src/io/anuke/mindustry/entities/type/Player.java @@ -8,22 +8,14 @@ import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Angles; import io.anuke.arc.math.Mathf; -import io.anuke.arc.math.geom.Geometry; -import io.anuke.arc.math.geom.Point2; -import io.anuke.arc.math.geom.Rectangle; -import io.anuke.arc.math.geom.Vector2; -import io.anuke.arc.util.Align; -import io.anuke.arc.util.Interval; -import io.anuke.arc.util.Pack; -import io.anuke.arc.util.Time; +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.entities.*; -import io.anuke.mindustry.entities.traits.BuilderTrait; -import io.anuke.mindustry.entities.traits.ShooterTrait; -import io.anuke.mindustry.entities.traits.SpawnerTrait; -import io.anuke.mindustry.entities.traits.TargetTrait; +import io.anuke.mindustry.entities.traits.*; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Pal; @@ -37,9 +29,7 @@ import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Floor; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.*; @@ -58,7 +48,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ public float pointerX, pointerY; public String name = "name"; public String uuid, usid; - public boolean isAdmin, isTransferring, isShooting, isBoosting, isMobile; + public boolean isAdmin, isTransferring, isShooting, isBoosting, isMobile, isTyping; public float boostHeat, shootHeat, destructTime; public boolean achievedFlight; public Color color = new Color(); @@ -66,12 +56,14 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ public SpawnerTrait spawner, lastSpawner; public NetConnection con; - public int playerIndex = 0; public boolean isLocal = false; public Interval timer = new Interval(4); public TargetTrait target; public TargetTrait moveTarget; + public String lastText; + public float textFadeTime; + private float walktime; private Queue placeQueue = new Queue<>(); private Tile mining; @@ -92,6 +84,11 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ player.mech = (player.isMobile ? Mechs.starterMobile : Mechs.starterDesktop); } + @Override + public float getDamageMultipler(){ + return status.getDamageMultiplier() * state.rules.playerDamageMultiplier; + } + @Override public void hitbox(Rectangle rectangle){ rectangle.setSize(mech.hitsize).setCenter(x, y); @@ -178,7 +175,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ @Override public float maxHealth(){ - return mech.health; + return mech.health * state.rules.playerHealthMultiplier; } @Override @@ -279,7 +276,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ if(dead) return; if(!movement.isZero() && moved && !state.isPaused()){ - walktime += movement.len() / 1f * getFloorOn().speedMultiplier; + walktime += movement.len() * getFloorOn().speedMultiplier * 2f; baseRotation = Mathf.slerpDelta(baseRotation, movement.angle(), 0.13f); } @@ -292,7 +289,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ if(!mech.flying){ if(floor.isLiquid){ - Draw.color(Color.WHITE, floor.liquidColor, 0.5f); + Draw.color(Color.WHITE, floor.color, 0.5f); } float boostTrnsY = -boostHeat * 3f; @@ -312,7 +309,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ } if(floor.isLiquid){ - Draw.color(Color.WHITE, floor.liquidColor, drownTime); + Draw.color(Color.WHITE, floor.color, drownTime); }else{ Draw.color(Color.WHITE); } @@ -371,35 +368,52 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ float size = mech.engineSize * (mech.flying ? 1f : boostHeat); Draw.color(mech.engineColor); Fill.circle(x + Angles.trnsx(rotation + 180, mech.engineOffset), y + Angles.trnsy(rotation + 180, mech.engineOffset), - size + Mathf.absin(Time.time(), 2f, size/4f)); + size + Mathf.absin(Time.time(), 2f, size / 4f)); Draw.color(Color.WHITE); - Fill.circle(x + Angles.trnsx(rotation + 180, mech.engineOffset-1f), y + Angles.trnsy(rotation + 180, mech.engineOffset-1f), - (size + Mathf.absin(Time.time(), 2f, size/4f)) / 2f); + Fill.circle(x + Angles.trnsx(rotation + 180, mech.engineOffset - 1f), y + Angles.trnsy(rotation + 180, mech.engineOffset - 1f), + (size + Mathf.absin(Time.time(), 2f, size / 4f)) / 2f); Draw.color(); } public void drawName(){ BitmapFont font = Core.scene.skin.getFont("default-font"); GlyphLayout layout = Pools.obtain(GlyphLayout.class, GlyphLayout::new); + final float nameHeight = 11; + final float textHeight = 15; boolean ints = font.usesIntegerPositions(); font.setUseIntegerPositions(false); font.getData().setScale(0.25f / io.anuke.arc.scene.ui.layout.Unit.dp.scl(1f)); layout.setText(font, name); Draw.color(0f, 0f, 0f, 0.3f); - Fill.rect(x, y + 8 - layout.height / 2, layout.width + 2, layout.height + 3); + Fill.rect(x, y + nameHeight - layout.height / 2, layout.width + 2, layout.height + 3); Draw.color(); font.setColor(color); - font.draw(name, x, y + 8, 0, Align.center, false); + font.draw(name, x, y + nameHeight, 0, Align.center, false); if(isAdmin){ float s = 3f; Draw.color(color.r * 0.5f, color.g * 0.5f, color.b * 0.5f, 1f); - Draw.rect(Core.atlas.find("icon-admin-small"), x + layout.width / 2f + 2 + 1, y + 6.5f, s, s); + Draw.rect(Core.atlas.find("icon-admin-small"), x + layout.width / 2f + 2 + 1, y + nameHeight - 1.5f, s, s); Draw.color(color); - Draw.rect(Core.atlas.find("icon-admin-small"), x + layout.width / 2f + 2 + 1, y + 7f, s, s); + Draw.rect(Core.atlas.find("icon-admin-small"), x + layout.width / 2f + 2 + 1, y + nameHeight - 1f, s, s); + } + + if(Core.settings.getBool("playerchat") && ((textFadeTime > 0 && lastText != null) || isTyping)){ + String text = textFadeTime <= 0 || lastText == null ? "[LIGHT_GRAY]" + Strings.animated(Time.time(), 4, 15f, ".") : lastText; + float width = 100f; + float visualFadeTime = 1f - Mathf.curve(1f - textFadeTime, 0.9f); + font.setColor(1f, 1f, 1f, textFadeTime <= 0 || lastText == null ? 1f : visualFadeTime); + + layout.setText(font, text, Color.WHITE, width, Align.bottom, true); + + Draw.color(0f, 0f, 0f, 0.3f * (textFadeTime <= 0 || lastText == null ? 1f : visualFadeTime)); + Fill.rect(x, y + textHeight + layout.height - layout.height/2f, layout.width + 2, layout.height + 3); + font.draw(text, x - width/2f, y + textHeight + layout.height, width, Align.center, true); + + textFadeTime -= Time.delta() / (60 * 5); } Draw.reset(); @@ -449,15 +463,16 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ TextureRegion region = draw.region; Draw.rect(region, - request.x * tilesize + request.block.offset(), request.y * tilesize + request.block.offset(), - region.getWidth() * 1f * Draw.scl * draw.scalex, - region.getHeight() * 1f * Draw.scl * draw.scaley, request.block.rotate ? draw.rotation * 90 : 0); + request.x * tilesize + request.block.offset(), request.y * tilesize + request.block.offset(), + region.getWidth() * 1f * Draw.scl * draw.scalex, + region.getHeight() * 1f * Draw.scl * draw.scaley, request.block.rotate ? draw.rotation * 90 : 0); Draw.color(Pal.accent); for(int i = 0; i < 4; i++){ Point2 p = Geometry.d8edge[i]; - float offset = -Math.max(request.block.size-1, 0)/2f * tilesize; - if(i % 2 == 0) Draw.rect("block-select", request.x * tilesize + request.block.offset() + offset * p.x, request.y * tilesize + request.block.offset() + offset * p.y, i * 90); + float offset = -Math.max(request.block.size - 1, 0) / 2f * tilesize; + if(i % 2 == 0) + Draw.rect("block-select", request.x * tilesize + request.block.offset() + offset * p.x, request.y * tilesize + request.block.offset() + offset * p.y, i * 90); } Draw.color(); @@ -524,7 +539,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ if(mech.shake > 1f){ Effects.shake(mech.shake, mech.shake, this); } - Effects.effect(Fx.unitLand, tile.floor().liquidColor == null ? tile.floor().color : tile.floor().color, x, y, tile.floor().isLiquid ? 1f : 0.5f); + Effects.effect(Fx.unitLand, tile.floor().color, x, y, tile.floor().isLiquid ? 1f : 0.5f); } mech.onLand(this); achievedFlight = false; @@ -551,6 +566,8 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ updateMech(); } + isTyping = ui.chatfrag.chatOpen(); + updateBuilding(); if(!mech.flying){ @@ -585,7 +602,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ movement.x += xa * speed; } - Vector2 vec = Core.input.mouseWorld(control.input(playerIndex).getMouseX(), control.input(playerIndex).getMouseY()); + Vector2 vec = Core.input.mouseWorld(control.input().getMouseX(), control.input().getMouseY()); pointerX = vec.x; pointerY = vec.y; updateShooting(); @@ -608,7 +625,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ rotation = Mathf.slerpDelta(rotation, mech.flying ? velocity.angle() : movement.angle(), 0.13f * baseLerp); } }else{ - float angle = control.input(playerIndex).mouseAngle(x, y); + float angle = control.input().mouseAngle(x, y); this.rotation = Mathf.slerpDelta(this.rotation, angle, 0.1f * baseLerp); } } @@ -621,8 +638,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ } protected void updateFlying(){ - if(Units.invalidateTarget(target, this) && !(target instanceof TileEntity && ((TileEntity) target).damaged() && target.getTeam() == team && - mech.canHeal && dst(target) < getWeapon().bullet.range())){ + if(Units.invalidateTarget(target, this) && !(target instanceof TileEntity && ((TileEntity)target).damaged() && target.isValid() && ((TileEntity)target).isAdded() && target.getTeam() == team && mech.canHeal && dst(target) < getWeapon().bullet.range())){ target = null; } @@ -641,7 +657,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ if(dst(moveTarget) < 2f){ if(tapping){ - Tile tile = ((TileEntity) moveTarget).tile; + Tile tile = ((TileEntity)moveTarget).tile; tile.block().tapped(tile, this); } @@ -701,7 +717,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ if(target != null && dst(target) > getWeapon().bullet.range()){ target = null; }else if(target != null){ - target = ((Tile) target).entity; + target = ((Tile)target).entity; } } @@ -709,7 +725,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ setMineTile(null); } } - }else if(target.isValid() || (target instanceof TileEntity && ((TileEntity) target).damaged() && target.getTeam() == team && + }else if(target.isValid() || (target instanceof TileEntity && ((TileEntity)target).damaged() && target.getTeam() == team && mech.canHeal && dst(target) < getWeapon().bullet.range())){ //rotate toward and shoot the target if(mech.turnCursor){ @@ -727,8 +743,8 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ } }else if(isShooting()){ - Vector2 vec = Core.input.mouseWorld(control.input(playerIndex).getMouseX(), - control.input(playerIndex).getMouseY()); + Vector2 vec = Core.input.mouseWorld(control.input().getMouseX(), + control.input().getMouseY()); pointerX = vec.x; pointerY = vec.y; @@ -759,10 +775,14 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ spawner = lastSpawner = null; health = maxHealth(); boostHeat = drownTime = hitTime = 0f; - mech = (isMobile ? Mechs.starterMobile : Mechs.starterDesktop); + mech = getStarterMech(); placeQueue.clear(); } + public Mech getStarterMech(){ + return (isMobile ? Mechs.starterMobile : Mechs.starterDesktop); + } + public boolean isShooting(){ return isShooting && (!isBoosting || mech.flying); } @@ -808,7 +828,6 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ if(isLocal){ stream.writeByte(mech.id); - stream.writeByte(playerIndex); stream.writeInt(lastSpawner == null ? noSpawner : lastSpawner.getTile().pos()); super.writeSave(stream, false); } @@ -818,23 +837,17 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ public void readSave(DataInput stream) throws IOException{ boolean local = stream.readBoolean(); - if(local && !headless){ + if(local){ byte mechid = stream.readByte(); - int index = stream.readByte(); int spawner = stream.readInt(); - if(world.tile(spawner) != null && world.tile(spawner).entity != null && world.tile(spawner).entity instanceof SpawnerTrait){ - lastSpawner = (SpawnerTrait)(world.tile(spawner).entity); + Tile stile = world.tile(spawner); + if(stile != null && stile.entity instanceof SpawnerTrait){ + lastSpawner = (SpawnerTrait)stile.entity; } - players[index].readSaveSuper(stream); - players[index].mech = content.getByID(ContentType.mech, mechid); - players[index].dead = false; - }else if(local){ - byte mechid = stream.readByte(); - stream.readByte(); - stream.readInt(); - readSaveSuper(stream); - mech = content.getByID(ContentType.mech, mechid); - dead = false; + Player player = headless ? this : Vars.player; + player.readSaveSuper(stream); + player.mech = content.getByID(ContentType.mech, mechid); + player.dead = false; } } @@ -848,12 +861,12 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ public void write(DataOutput buffer) throws IOException{ super.writeSave(buffer, !isLocal); TypeIO.writeStringData(buffer, name); //TODO writing strings is very inefficient - buffer.writeByte(Pack.byteValue(isAdmin) | (Pack.byteValue(dead) << 1) | (Pack.byteValue(isBoosting) << 2)); + buffer.writeByte(Pack.byteValue(isAdmin) | (Pack.byteValue(dead) << 1) | (Pack.byteValue(isBoosting) << 2) | (Pack.byteValue(isTyping) << 3)); buffer.writeInt(Color.rgba8888(color)); buffer.writeByte(mech.id); buffer.writeInt(mining == null ? noSpawner : mining.pos()); buffer.writeInt(spawner == null ? noSpawner : spawner.getTile().pos()); - buffer.writeShort((short) (baseRotation * 2)); + buffer.writeShort((short)(baseRotation * 2)); writeBuilding(buffer); } @@ -867,6 +880,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ isAdmin = (bools & 1) != 0; dead = (bools & 2) != 0; boolean boosting = (bools & 4) != 0; + isTyping = (bools & 8) != 0; color.set(buffer.readInt()); mech = content.getByID(ContentType.mech, buffer.readByte()); int mine = buffer.readInt(); @@ -877,10 +891,10 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ interpolator.read(lastx, lasty, x, y, rotation, baseRotation); rotation = lastrot; + x = lastx; + y = lasty; if(isLocal){ - x = lastx; - y = lasty; velocity.x = lastvx; velocity.y = lastvy; }else{ diff --git a/core/src/io/anuke/mindustry/entities/type/TileEntity.java b/core/src/io/anuke/mindustry/entities/type/TileEntity.java index fa302ada5f..2fb3bb1d81 100644 --- a/core/src/io/anuke/mindustry/entities/type/TileEntity.java +++ b/core/src/io/anuke/mindustry/entities/type/TileEntity.java @@ -5,34 +5,26 @@ import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.Events; import io.anuke.arc.collection.Array; import io.anuke.arc.collection.ObjectSet; -import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.EntityGroup; -import io.anuke.mindustry.entities.impl.BaseEntity; -import io.anuke.mindustry.entities.traits.HealthTrait; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Point2; import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.util.Interval; import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Fx; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.EntityGroup; import io.anuke.mindustry.entities.bullet.Bullet; +import io.anuke.mindustry.entities.impl.BaseEntity; +import io.anuke.mindustry.entities.traits.HealthTrait; import io.anuke.mindustry.entities.traits.TargetTrait; import io.anuke.mindustry.game.EventType.BlockDestroyEvent; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Edges; -import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.blocks.defense.Wall; -import io.anuke.mindustry.world.consumers.Consume; -import io.anuke.mindustry.world.modules.ConsumeModule; -import io.anuke.mindustry.world.modules.ItemModule; -import io.anuke.mindustry.world.modules.LiquidModule; -import io.anuke.mindustry.world.modules.PowerModule; +import io.anuke.mindustry.world.modules.*; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.tileGroup; import static io.anuke.mindustry.Vars.world; @@ -40,10 +32,11 @@ import static io.anuke.mindustry.Vars.world; public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ public static final float timeToSleep = 60f * 4; //4 seconds to fall asleep private static final ObjectSet tmpTiles = new ObjectSet<>(); - /**This value is only used for debugging.*/ + /** This value is only used for debugging. */ public static int sleepingEntities = 0; public Tile tile; + public Block block; public Interval timer; public float health; public float timeScale = 1f, timeScaleDuration; @@ -53,7 +46,7 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ public LiquidModule liquids; public ConsumeModule cons; - /**List of (cached) tiles with entities in proximity, used for outputting to*/ + /** List of (cached) tiles with entities in proximity, used for outputting to */ private Array proximity = new Array<>(8); private boolean dead = false; private boolean sleeping; @@ -63,6 +56,10 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ public static void onTileDamage(Tile tile, float health){ if(tile.entity != null){ tile.entity.health = health; + + if(tile.entity.damaged()){ + world.indexer.notifyTileDamaged(tile.entity); + } } } @@ -72,15 +69,15 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ tile.entity.onDeath(); } - /**Sets this tile entity data to this tile, and adds it if necessary.*/ + /** Sets this tile entity data to this tile, and adds it if necessary. */ public TileEntity init(Tile tile, boolean shouldAdd){ this.tile = tile; x = tile.drawx(); y = tile.drawy(); + block = tile.block(); - health = tile.block().health; - - timer = new Interval(tile.block().timers); + health = block.health; + timer = new Interval(block.timers); if(shouldAdd){ add(); @@ -89,12 +86,12 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ return this; } - /**Scaled delta.*/ + /** Scaled delta. */ public float delta(){ return Time.delta() * timeScale; } - /**Call when nothing is happening to the entity. This increments the internal sleep timer.*/ + /** Call when nothing is happening to the entity. This increments the internal sleep timer. */ public void sleep(){ sleepTime += Time.delta(); if(!sleeping && sleepTime >= timeToSleep){ @@ -104,7 +101,7 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ } } - /**Call when this entity is updating. This wakes it up.*/ + /** Call when this entity is updating. This wakes it up. */ public void noSleep(){ sleepTime = 0f; if(sleeping){ @@ -122,20 +119,24 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ return dead || tile.entity != this; } - public void write(DataOutput stream) throws IOException{} + public void write(DataOutput stream) throws IOException{ + } - public void writeConfig(DataOutput stream) throws IOException{} + public void writeConfig(DataOutput stream) throws IOException{ + } - public void read(DataInput stream) throws IOException{} + public void read(DataInput stream) throws IOException{ + } - public void readConfig(DataInput stream) throws IOException{} + public void readConfig(DataInput stream) throws IOException{ + } public boolean collide(Bullet other){ return true; } public void collision(Bullet other){ - tile.block().handleBulletHit(this, other); + block.handleBulletHit(this, other); } public void kill(){ @@ -147,11 +148,13 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ float preHealth = health; - Call.onTileDamage(tile, health - tile.block().handleDamage(tile, damage)); + Call.onTileDamage(tile, health - block.handleDamage(tile, damage)); if(health <= 0){ Call.onTileDestroyed(tile); - }else if(preHealth >= maxHealth() - 0.00001f && health < maxHealth() && world != null){ //when just damaged + } + + if(preHealth >= maxHealth() - 0.00001f && health < maxHealth() && world != null){ //when just damaged world.indexer.notifyTileDamaged(this); } } @@ -164,14 +167,10 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ return tile; } - public boolean consumed(Class type){ - return tile.block().consumes.get(type).valid(tile.block(), this); - } - public void removeFromProximity(){ - tile.block().onProximityRemoved(tile); + block.onProximityRemoved(tile); - Point2[] nearby = Edges.getEdges(tile.block().size); + Point2[] nearby = Edges.getEdges(block.size); for(Point2 point : nearby){ Tile other = world.tile(tile.x + point.x, tile.y + point.y); //remove this tile from all nearby tile's proximities @@ -189,7 +188,7 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ tmpTiles.clear(); proximity.clear(); - Point2[] nearby = Edges.getEdges(tile.block().size); + Point2[] nearby = Edges.getEdges(block.size); for(Point2 point : nearby){ Tile other = world.tile(tile.x + point.x, tile.y + point.y); @@ -212,8 +211,8 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ proximity.add(tile); } - tile.block().onProximityAdded(tile); - tile.block().onProximityUpdate(tile); + block.onProximityAdded(tile); + block.onProximityUpdate(tile); } public Array proximity(){ @@ -232,7 +231,7 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ @Override public float maxHealth(){ - return tile.block().health; + return block.health; } @Override @@ -244,7 +243,6 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ public void onDeath(){ if(!dead){ dead = true; - Block block = tile.block(); Events.fire(new BlockDestroyEvent(tile)); block.onDestroyed(tile); @@ -267,24 +265,30 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ @Override public void update(){ //TODO better smoke effect, this one is awful - if(health != 0 && health < tile.block().health && !(tile.block() instanceof Wall) && - Mathf.chance(0.009f * Time.delta() * (1f - health / tile.block().health))){ + if(health != 0 && health < block.health && !(block instanceof Wall) && + Mathf.chance(0.009f * Time.delta() * (1f - health / block.health))){ Effects.effect(Fx.smoke, x + Mathf.range(4), y + Mathf.range(4)); } timeScaleDuration -= Time.delta(); - if(timeScaleDuration <= 0f || !tile.block().canOverdrive){ + if(timeScaleDuration <= 0f || !block.canOverdrive){ timeScale = 1f; } if(health <= 0){ onDeath(); + return; //no need to update anymore } - Block previous = tile.block(); - tile.block().update(tile); - if(tile.block() == previous && cons != null){ + + Block previous = block; + block.update(tile); + if(block == previous && cons != null){ cons.update(); } + + if(block == previous && power != null){ + power.graph.update(); + } } @Override diff --git a/core/src/io/anuke/mindustry/entities/type/Unit.java b/core/src/io/anuke/mindustry/entities/type/Unit.java index 2312d36612..910f8299ab 100644 --- a/core/src/io/anuke/mindustry/entities/type/Unit.java +++ b/core/src/io/anuke/mindustry/entities/type/Unit.java @@ -7,7 +7,6 @@ import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Geometry; -import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.util.Time; import io.anuke.arc.util.Tmp; @@ -15,7 +14,6 @@ import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.entities.Damage; import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.effect.ScorchDecal; import io.anuke.mindustry.entities.impl.DestructibleEntity; import io.anuke.mindustry.entities.traits.*; @@ -26,32 +24,29 @@ import io.anuke.mindustry.game.Teams.TeamData; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.net.Interpolator; import io.anuke.mindustry.net.Net; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.type.StatusEffect; -import io.anuke.mindustry.type.Weapon; +import io.anuke.mindustry.type.*; import io.anuke.mindustry.world.Pos; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Floor; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.*; public abstract class Unit extends DestructibleEntity implements SaveTrait, TargetTrait, SyncTrait, DrawTrait, TeamTrait{ - /**Total duration of hit flash effect*/ + /** Total duration of hit flash effect */ public static final float hitDuration = 9f; - /**Percision divisor of velocity, used when writing. For example a value of '2' would mean the percision is 1/2 = 0.5-size chunks.*/ + /** Percision divisor of velocity, used when writing. For example a value of '2' would mean the percision is 1/2 = 0.5-size chunks. */ public static final float velocityPercision = 8f; - /**Maximum absolute value of a velocity vector component.*/ + /** Maximum absolute value of a velocity vector component. */ public static final float maxAbsVelocity = 127f / velocityPercision; public static final int noSpawner = Pos.get(-1, 1); - private static final Rectangle queryRect = new Rectangle(); private static final Vector2 moveVector = new Vector2(); + private int lastWeightTile = Pos.invalid, lastWeightDelta; + private boolean wasFlying = false; + public float rotation; protected final Interpolator interpolator = new Interpolator(); @@ -95,7 +90,9 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ @Override public void damage(float amount){ - super.damage(calculateDamage(amount)); + if(!Net.client()){ + super.damage(calculateDamage(amount)); + } hitTime = hitDuration; } @@ -104,9 +101,9 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ if(isDead()) return false; if(other instanceof DamageTrait){ - return other instanceof TeamTrait && state.teams.areEnemies((((TeamTrait) other).getTeam()), team); + return other instanceof TeamTrait && state.teams.areEnemies((((TeamTrait)other).getTeam()), team); }else{ - return other instanceof Unit && ((Unit) other).isFlying() == isFlying(); + return other instanceof Unit && ((Unit)other).isFlying() == isFlying(); } } @@ -140,6 +137,22 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ } } + @Override + public void removed(){ + if(lastWeightTile != Pos.invalid){ + Tile tile = world.tile(lastWeightTile); + + if(tile != null){ + int dec = Math.min(lastWeightDelta, wasFlying ? tile.airWeight : tile.weight); + if(!wasFlying){ + tile.weight -= dec; + }else{ + tile.airWeight -= dec; + } + } + } + } + @Override public boolean isValid(){ return !isDead() && isAdded(); @@ -180,18 +193,18 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ stream.writeBoolean(isDead()); stream.writeFloat(net ? interpolator.target.x : x); stream.writeFloat(net ? interpolator.target.y : y); - stream.writeByte((byte) (Mathf.clamp(velocity.x, -maxAbsVelocity, maxAbsVelocity) * velocityPercision)); - stream.writeByte((byte) (Mathf.clamp(velocity.y, -maxAbsVelocity, maxAbsVelocity) * velocityPercision)); - stream.writeShort((short) (rotation * 2)); - stream.writeShort((short) health); + stream.writeByte((byte)(Mathf.clamp(velocity.x, -maxAbsVelocity, maxAbsVelocity) * velocityPercision)); + stream.writeByte((byte)(Mathf.clamp(velocity.y, -maxAbsVelocity, maxAbsVelocity) * velocityPercision)); + stream.writeShort((short)(rotation * 2)); + stream.writeShort((short)health); stream.writeByte(item.item.id); stream.writeShort((short)item.amount); status.writeSave(stream); } protected void clampPosition(){ - x = Mathf.clamp(x, tilesize, world.width() * tilesize - tilesize); - y = Mathf.clamp(y, tilesize, world.height() * tilesize - tilesize); + x = Mathf.clamp(x, 0, world.width() * tilesize - tilesize); + y = Mathf.clamp(y, 0, world.height() * tilesize - tilesize); } public void kill(){ @@ -219,17 +232,55 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ return status.hasEffect(effect); } - //TODO optimize public void avoidOthers(float scaling){ - hitbox(queryRect); - queryRect.setSize(queryRect.getWidth() * scaling); + boolean flying = isFlying(); - Units.getNearby(queryRect, t -> { - if(t == this || t.isFlying() != isFlying()) return; - float dst = dst(t); - moveVector.set(x, y).sub(t.getX(), t.getY()).setLength(1f * (1f - (dst / queryRect.getWidth()))); - applyImpulse(moveVector.x, moveVector.y); - }); + if(lastWeightTile != Pos.invalid){ + Tile tile = world.tile(lastWeightTile); + + if(tile != null){ + int dec = Math.min(lastWeightDelta, wasFlying ? tile.airWeight : tile.weight); + if(!wasFlying){ + tile.weight -= dec; + }else{ + tile.airWeight -= dec; + } + } + } + + final int rad = 2; + + moveVector.setZero(); + for(int cx = -rad; cx <= rad; cx++){ + for(int cy = -rad; cy <= rad; cy++){ + Tile tile = world.tileWorld(x + cx * tilesize, y + cy * tilesize); + if(tile == null) continue; + int weight = flying ? tile.airWeight : tile.weight; + float scl = (rad - Mathf.dst(tile.worldx(), tile.worldy(), x, y) / (8f * 1.2f * Mathf.sqrt2)) * 0.1f; + + moveVector.add(Mathf.sign(x - tile.worldx()) * scaling * weight * scl, Mathf.sign(y - tile.worldy()) * scaling * weight * scl); + } + } + + moveVector.limit(flying ? 0.1f : 0.2f); + + velocity.add(moveVector.x / mass() * Time.delta(), moveVector.y / mass() * Time.delta()); + + Tile tile = world.tileWorld(x, y); + + if(tile != null){ + int tw = flying ? tile.airWeight : tile.weight; + lastWeightDelta = Math.min((int)(mass()), 127 - tw); + lastWeightTile = tile.pos(); + if(!flying){ + tile.weight += lastWeightDelta; + }else{ + tile.airWeight += lastWeightDelta; + } + }else{ + lastWeightTile = Pos.invalid; + } + wasFlying = flying; } public TileEntity getClosestCore(){ @@ -245,12 +296,13 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ public Floor getFloorOn(){ Tile tile = world.tileWorld(x, y); - return tile == null ? (Floor) Blocks.air : tile.floor(); + return tile == null ? (Floor)Blocks.air : tile.floor(); } - public void onRespawn(Tile tile){} + public void onRespawn(Tile tile){ + } - /**Updates velocity and status effects.*/ + /** Updates velocity and status effects. */ public void updateVelocityStatus(){ Floor floor = getFloorOn(); @@ -258,7 +310,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ status.update(this); - velocity.limit(maxVelocity()).scl(1f + (status.getSpeedMultiplier()-1f) * Time.delta()); + velocity.limit(maxVelocity()).scl(1f + (status.getSpeedMultiplier() - 1f) * Time.delta()); if(x < -finalWorldBounds || y < -finalWorldBounds || x >= world.width() * tilesize + finalWorldBounds || y >= world.height() * tilesize + finalWorldBounds){ kill(); @@ -278,7 +330,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ } if(onLiquid && velocity.len() > 0.4f && Mathf.chance((velocity.len() * floor.speedMultiplier) * 0.06f * Time.delta())){ - Effects.effect(floor.walkEffect, floor.liquidColor, x, y); + Effects.effect(floor.walkEffect, floor.color, x, y); } if(onLiquid){ @@ -292,7 +344,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ if(onLiquid && floor.drownTime > 0){ drownTime += Time.delta() * 1f / floor.drownTime; if(Mathf.chance(Time.delta() * 0.05f)){ - Effects.effect(floor.drownUpdateEffect, floor.liquidColor, x, y); + Effects.effect(floor.drownUpdateEffect, floor.color, x, y); } }else{ drownTime = Mathf.lerpDelta(drownTime, 0f, 0.03f); @@ -364,7 +416,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ } public void drawStats(){ - Draw.color(Color.BLACK, team.color, healthf() + Mathf.absin(Time.time(), healthf()*5f, 1f - healthf())); + Draw.color(Color.BLACK, team.color, healthf() + Mathf.absin(Time.time(), healthf() * 5f, 1f - healthf())); Draw.rect(getPowerCellRegion(), x, y, rotation - 90); Draw.color(); } diff --git a/core/src/io/anuke/mindustry/entities/type/base/Drone.java b/core/src/io/anuke/mindustry/entities/type/base/Drone.java index 384d302d84..5d6fe4c1e1 100644 --- a/core/src/io/anuke/mindustry/entities/type/base/Drone.java +++ b/core/src/io/anuke/mindustry/entities/type/base/Drone.java @@ -2,36 +2,31 @@ package io.anuke.mindustry.entities.type.base; import io.anuke.arc.Events; import io.anuke.arc.collection.Queue; -import io.anuke.mindustry.entities.EntityGroup; 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.type.Player; -import io.anuke.mindustry.entities.type.TileEntity; +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.BaseUnit; -import io.anuke.mindustry.entities.type.FlyingUnit; +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.ItemStack; 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.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; -import static io.anuke.mindustry.Vars.unitGroups; -import static io.anuke.mindustry.Vars.world; +import static io.anuke.mindustry.Vars.*; public class Drone extends FlyingUnit implements BuilderTrait{ + + protected Item targetItem; protected Tile mineTile; protected Queue placeQueue = new Queue<>(); @@ -48,7 +43,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{ } public void update(){ - BuildEntity entity = (BuildEntity) target; + BuildEntity entity = (BuildEntity)target; TileEntity core = getClosestCore(); if(entity == null){ @@ -58,24 +53,12 @@ public class Drone extends FlyingUnit implements BuilderTrait{ if(core == null) return; - if((entity.progress() < 1f || entity.progress() > 0f) && entity.tile.block() instanceof BuildBlock){ //building is valid + 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.getRotation(), entity.block)); - } - } - - //if it's missing requirements, try and mine them - if(entity.block != null){ - for(ItemStack stack : entity.block.buildRequirements){ - if(!core.items.has(stack.item, stack.amount) && type.toMine.contains(stack.item)){ - targetItem = stack.item; - getPlaceQueue().clear(); - setState(mine); - return; - } + getPlaceQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y, entity.tile.getRotation(), entity.cblock)); } } @@ -105,7 +88,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{ if(target == null) return; if(target.dst(Drone.this) > type.range){ - circle(type.range*0.9f); + circle(type.range * 0.9f); }else{ getWeapon().update(Drone.this, target.getX(), target.getY()); } @@ -127,7 +110,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{ } //core full - if(targetItem != null && entity.tile.block().acceptStack(targetItem, 1, entity.tile, Drone.this) == 0){ + if(targetItem != null && entity.block.acceptStack(targetItem, 1, entity.tile, Drone.this) == 0){ setState(repair); return; } @@ -155,10 +138,10 @@ public class Drone extends FlyingUnit implements BuilderTrait{ moveTo(type.range / 1.5f); if(dst(target) < type.range && mineTile != target){ - setMineTile((Tile) target); + setMineTile((Tile)target); } - if(((Tile) target).block() != Blocks.air){ + if(((Tile)target).block() != Blocks.air){ setState(drop); } } @@ -190,7 +173,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{ if(target == null) return; - TileEntity tile = (TileEntity) target; + TileEntity tile = (TileEntity)target; if(dst(target) < type.range){ if(tile.tile.block().acceptStack(item.item, item.amount, tile.tile, Drone.this) == item.amount){ @@ -229,7 +212,6 @@ public class Drone extends FlyingUnit implements BuilderTrait{ EntityGroup group = unitGroups[event.team.ordinal()]; if(!(event.builder instanceof Player) || !(event.tile.entity instanceof BuildEntity)) return; - BuildEntity entity = event.tile.entity(); for(BaseUnit unit : group.all()){ if(unit instanceof Drone){ @@ -242,23 +224,11 @@ public class Drone extends FlyingUnit implements BuilderTrait{ drone.setState(drone.repair); } } - - drone.notifyPlaced(entity, event.breaking); } } }); } - private void notifyPlaced(BuildEntity entity, boolean isBreaking){ - float dist = Math.min(entity.dst(x, y) - placeDistance, 0); - - if(!state.is(build) && dist / type.maxVelocity < entity.buildCost * 0.9f){ - target = entity; - this.isBreaking = isBreaking; - setState(build); - } - } - @Override public boolean canMine(Item item){ return type.toMine.contains(item); @@ -297,6 +267,25 @@ public class Drone extends FlyingUnit implements BuilderTrait{ 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(); } @@ -312,7 +301,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{ @Override public void behavior(){ if(health <= health * type.retreatPercent && - Geometry.findClosest(x, y, world.indexer.getAllied(team, BlockFlag.repair)) != null){ + Geometry.findClosest(x, y, world.indexer.getAllied(team, BlockFlag.repair)) != null){ setState(retreat); } } @@ -337,7 +326,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{ if(entity == null){ return; } - targetItem = Structs.findMin(type.toMine, (a, b) -> -Integer.compare(entity.items.get(a), entity.items.get(b))); + targetItem = Structs.findMin(type.toMine, world.indexer::hasOre, (a, b) -> -Integer.compare(entity.items.get(a), entity.items.get(b))); } @Override diff --git a/core/src/io/anuke/mindustry/entities/type/base/Fortress.java b/core/src/io/anuke/mindustry/entities/type/base/Fortress.java index 06033fcf66..992948fa79 100644 --- a/core/src/io/anuke/mindustry/entities/type/base/Fortress.java +++ b/core/src/io/anuke/mindustry/entities/type/base/Fortress.java @@ -1,21 +1,6 @@ package io.anuke.mindustry.entities.type.base; -import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.type.GroundUnit; public class Fortress extends GroundUnit{ - - @Override - protected void patrol(){ - if(Units.invalidateTarget(target, this)){ - super.patrol(); - } - } - - @Override - protected void moveToCore(){ - if(Units.invalidateTarget(target, this)){ - super.moveToCore(); - } - } } diff --git a/core/src/io/anuke/mindustry/entities/type/base/Revenant.java b/core/src/io/anuke/mindustry/entities/type/base/Revenant.java index 9f3c5f2c6e..03233dbb5d 100644 --- a/core/src/io/anuke/mindustry/entities/type/base/Revenant.java +++ b/core/src/io/anuke/mindustry/entities/type/base/Revenant.java @@ -14,7 +14,7 @@ public class Revenant extends FlyingUnit{ float tra = rotation - 90, trY = -getWeapon().getRecoil(this, i > 0) + type.weaponOffsetY; float w = i > 0 ? -12 : 12; float wx = x + Angles.trnsx(tra, getWeapon().width * i, trY), wy = y + Angles.trnsy(tra, getWeapon().width * i, trY); - int wi = (i + 1)/2; + int wi = (i + 1) / 2; Draw.rect(getWeapon().region, wx, wy, w, 12, weaponAngles[wi] - 90); } } diff --git a/core/src/io/anuke/mindustry/entities/units/Statuses.java b/core/src/io/anuke/mindustry/entities/units/Statuses.java index ffc4fe8278..b8d0116ce3 100644 --- a/core/src/io/anuke/mindustry/entities/units/Statuses.java +++ b/core/src/io/anuke/mindustry/entities/units/Statuses.java @@ -12,12 +12,11 @@ import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.StatusEffect; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.content; -/** Class for controlling status effects on an entity.*/ + +/** Class for controlling status effects on an entity. */ public class Statuses implements Saveable{ private static final StatusEntry globalResult = new StatusEntry(); private static final Array removals = new Array<>(); diff --git a/core/src/io/anuke/mindustry/entities/units/UnitDrops.java b/core/src/io/anuke/mindustry/entities/units/UnitDrops.java index 84c47a4457..fb18a9b9fb 100644 --- a/core/src/io/anuke/mindustry/entities/units/UnitDrops.java +++ b/core/src/io/anuke/mindustry/entities/units/UnitDrops.java @@ -1,12 +1,12 @@ package io.anuke.mindustry.entities.units; +import io.anuke.arc.math.Mathf; import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Items; import io.anuke.mindustry.entities.type.BaseUnit; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.type.Item; -import io.anuke.arc.math.Mathf; public class UnitDrops{ private static Item[] dropTable; @@ -37,7 +37,8 @@ public class UnitDrops{ if(Mathf.chance(0.03)){ int amount = Mathf.random(20, 40); amount = core.tile.block().acceptStack(item, amount, core.tile, null); - if (amount > 0) Call.transferItemTo(item, amount, unit.x + Mathf.range(2f), unit.y + Mathf.range(2f), core.tile); + if(amount > 0) + Call.transferItemTo(item, amount, unit.x + Mathf.range(2f), unit.y + Mathf.range(2f), core.tile); } } } diff --git a/core/src/io/anuke/mindustry/game/Content.java b/core/src/io/anuke/mindustry/game/Content.java index 34ec10b4dd..4da406e960 100644 --- a/core/src/io/anuke/mindustry/game/Content.java +++ b/core/src/io/anuke/mindustry/game/Content.java @@ -4,7 +4,7 @@ import io.anuke.mindustry.Vars; import io.anuke.mindustry.type.ContentType; -/**Base class for a content type that is loaded in {@link io.anuke.mindustry.core.ContentLoader}.*/ +/** Base class for a content type that is loaded in {@link io.anuke.mindustry.core.ContentLoader}. */ public abstract class Content{ public final byte id; @@ -19,7 +19,7 @@ public abstract class Content{ */ public abstract ContentType getContentType(); - /**Called after all content is created. Do not use to load regions or texture data!*/ + /** Called after all content is created. Do not use to load regions or texture data! */ public void init(){ } diff --git a/core/src/io/anuke/mindustry/game/ContentList.java b/core/src/io/anuke/mindustry/game/ContentList.java index 8fc59c8bf2..82406a9880 100644 --- a/core/src/io/anuke/mindustry/game/ContentList.java +++ b/core/src/io/anuke/mindustry/game/ContentList.java @@ -1,7 +1,7 @@ package io.anuke.mindustry.game; -/**Interface for a list of content to be loaded in {@link io.anuke.mindustry.core.ContentLoader}.*/ +/** Interface for a list of content to be loaded in {@link io.anuke.mindustry.core.ContentLoader}. */ public interface ContentList{ - /**This method should create all the content.*/ + /** This method should create all the content. */ void load(); } diff --git a/core/src/io/anuke/mindustry/game/DefaultWaves.java b/core/src/io/anuke/mindustry/game/DefaultWaves.java index 8880c2996d..a2bee78936 100644 --- a/core/src/io/anuke/mindustry/game/DefaultWaves.java +++ b/core/src/io/anuke/mindustry/game/DefaultWaves.java @@ -1,9 +1,7 @@ package io.anuke.mindustry.game; import io.anuke.arc.collection.Array; -import io.anuke.mindustry.content.Items; -import io.anuke.mindustry.content.StatusEffects; -import io.anuke.mindustry.content.UnitTypes; +import io.anuke.mindustry.content.*; import io.anuke.mindustry.type.ItemStack; public class DefaultWaves{ @@ -12,155 +10,158 @@ public class DefaultWaves{ public static Array get(){ if(spawns == null && UnitTypes.dagger != null){ spawns = Array.with( - new SpawnGroup(UnitTypes.dagger){{ - end = 8; - unitScaling = 2; - }}, + new SpawnGroup(UnitTypes.dagger){{ + end = 8; + unitScaling = 1.5f; + }}, - new SpawnGroup(UnitTypes.wraith){{ - begin = 12; - end = 14; - unitScaling = 2; - }}, + new SpawnGroup(UnitTypes.wraith){{ + begin = 12; + end = 14; + unitScaling = 1f; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 11; - unitScaling = 2; - spacing = 2; - max = 4; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 11; + unitScaling = 1.7f; + spacing = 2; + max = 4; + }}, - new SpawnGroup(UnitTypes.titan){{ - begin = 9; - spacing = 3; - unitScaling = 2; + new SpawnGroup(UnitTypes.titan){{ + begin = 9; + spacing = 3; + unitScaling = 2; - end = 30; - }}, + end = 30; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 8; - unitScaling = 1; - unitAmount = 1; - spacing = 2; - end = 30; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 8; + unitScaling = 1; + unitAmount = 1; + spacing = 2; + }}, - new SpawnGroup(UnitTypes.titan){{ - begin = 28; - spacing = 3; - unitScaling = 1; - end = 40; - }}, + new SpawnGroup(UnitTypes.titan){{ + begin = 28; + spacing = 3; + unitScaling = 1; + end = 40; + }}, - new SpawnGroup(UnitTypes.titan){{ - begin = 45; - spacing = 3; - unitScaling = 2; - effect = StatusEffects.overdrive; - }}, + new SpawnGroup(UnitTypes.titan){{ + begin = 45; + spacing = 3; + unitScaling = 2; + effect = StatusEffects.overdrive; + }}, - new SpawnGroup(UnitTypes.titan){{ - begin = 120; - spacing = 2; - unitScaling = 3; - unitAmount = 5; - effect = StatusEffects.overdrive; - }}, + new SpawnGroup(UnitTypes.titan){{ + begin = 120; + spacing = 2; + unitScaling = 3; + unitAmount = 5; + effect = StatusEffects.overdrive; + }}, - new SpawnGroup(UnitTypes.wraith){{ - begin = 16; - unitScaling = 1; - spacing = 2; + new SpawnGroup(UnitTypes.wraith){{ + begin = 16; + unitScaling = 1; + spacing = 2; - max = 7; - }}, + max = 12; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 82; - spacing = 3; - unitAmount = 4; - unitScaling = 3; - effect = StatusEffects.overdrive; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 82; + spacing = 3; + unitAmount = 4; + unitScaling = 3; + effect = StatusEffects.overdrive; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 41; - spacing = 5; - unitAmount = 1; - unitScaling = 3; - effect = StatusEffects.shielded; - max = 10; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 41; + spacing = 5; + unitAmount = 1; + unitScaling = 3; + effect = StatusEffects.shielded; + }}, - new SpawnGroup(UnitTypes.fortress){{ - begin = 40; - spacing = 5; - unitAmount = 2; - unitScaling = 3; - max = 10; - }}, + new SpawnGroup(UnitTypes.fortress){{ + begin = 40; + spacing = 5; + unitAmount = 2; + unitScaling = 2; + max = 20; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 35; - spacing = 3; - unitAmount = 4; - effect = StatusEffects.overdrive; - items = new ItemStack(Items.blastCompound, 60); - end = 60; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 35; + spacing = 3; + unitAmount = 4; + effect = StatusEffects.overdrive; + items = new ItemStack(Items.blastCompound, 60); + end = 60; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 42; - spacing = 3; - unitAmount = 4; - effect = StatusEffects.overdrive; - items = new ItemStack(Items.pyratite, 100); - end = 130; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 42; + spacing = 3; + unitAmount = 4; + effect = StatusEffects.overdrive; + items = new ItemStack(Items.pyratite, 100); + end = 130; + }}, - new SpawnGroup(UnitTypes.ghoul){{ - begin = 40; - unitAmount = 2; - spacing = 2; - unitScaling = 3; - max = 8; - }}, + new SpawnGroup(UnitTypes.ghoul){{ + begin = 40; + unitAmount = 2; + spacing = 2; + unitScaling = 3; + max = 8; + }}, - new SpawnGroup(UnitTypes.wraith){{ - begin = 50; - unitAmount = 4; - unitScaling = 3; - spacing = 5; - effect = StatusEffects.overdrive; - max = 8; - }}, + new SpawnGroup(UnitTypes.wraith){{ + begin = 50; + unitAmount = 4; + unitScaling = 3; + spacing = 5; + effect = StatusEffects.overdrive; + max = 8; + }}, - new SpawnGroup(UnitTypes.revenant){{ - begin = 50; - unitAmount = 2; - unitScaling = 3; - spacing = 5; - max = 8; - }}, + new SpawnGroup(UnitTypes.revenant){{ + begin = 50; + unitAmount = 2; + unitScaling = 3; + spacing = 5; + max = 8; + }}, - new SpawnGroup(UnitTypes.ghoul){{ - begin = 53; - unitAmount = 2; - unitScaling = 3; - spacing = 4; - max = 8; - end = 74; - }}, + new SpawnGroup(UnitTypes.ghoul){{ + begin = 53; + unitAmount = 2; + unitScaling = 3; + spacing = 4; + max = 8; + }}, - new SpawnGroup(UnitTypes.ghoul){{ - begin = 53; - unitAmount = 2; - unitScaling = 3; - spacing = 4; - max = 8; - end = 74; - }} + new SpawnGroup(UnitTypes.eruptor){{ + begin = 31; + unitAmount = 4; + unitScaling = 1; + spacing = 3; + }}, + + new SpawnGroup(UnitTypes.ghoul){{ + begin = 90; + unitAmount = 2; + unitScaling = 3; + spacing = 4; + max = 8; + }} ); } return spawns == null ? new Array<>() : spawns; diff --git a/core/src/io/anuke/mindustry/game/Difficulty.java b/core/src/io/anuke/mindustry/game/Difficulty.java index ae19a30f49..8dc4a79269 100644 --- a/core/src/io/anuke/mindustry/game/Difficulty.java +++ b/core/src/io/anuke/mindustry/game/Difficulty.java @@ -2,15 +2,17 @@ package io.anuke.mindustry.game; import io.anuke.arc.Core; -/**Presets for time between waves. - * TODO specify correct time*/ +/** + * Presets for time between waves. + * TODO specify correct time + */ public enum Difficulty{ easy(1.4f), normal(1f), hard(0.5f), insane(0.25f); - /**Multiplier of the time between waves.*/ + /** Multiplier of the time between waves. */ public final float waveTime; private String value; diff --git a/core/src/io/anuke/mindustry/game/EventType.java b/core/src/io/anuke/mindustry/game/EventType.java index c5dc0ba433..f55079b0c0 100644 --- a/core/src/io/anuke/mindustry/game/EventType.java +++ b/core/src/io/anuke/mindustry/game/EventType.java @@ -2,23 +2,24 @@ package io.anuke.mindustry.game; import io.anuke.arc.Events.Event; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.entities.traits.BuilderTrait; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.type.Zone; import io.anuke.mindustry.world.Tile; public class EventType{ - /**Called when a zone's requirements are met.*/ - public static class ZoneCompleteEvent implements Event{ - public final Zone zone; + /** Called when a zone's requirements are met. */ + public static class ZoneRequireCompleteEvent implements Event{ + public final Zone zone, required; - public ZoneCompleteEvent(Zone zone){ + public ZoneRequireCompleteEvent(Zone zone, Zone required){ this.zone = zone; + this.required = required; } } - /**Called when a zone's requirements are met.*/ + /** Called when a zone's requirements are met. */ public static class ZoneConfigureCompleteEvent implements Event{ public final Zone zone; @@ -27,7 +28,7 @@ public class EventType{ } } - /**Called when the game is first loaded.*/ + /** Called when the game is first loaded. */ public static class GameLoadEvent implements Event{ } @@ -52,12 +53,12 @@ public class EventType{ } } - /**Called when a game begins and the world is loaded.*/ + /** Called when a game begins and the world is loaded. */ public static class WorldLoadEvent implements Event{ } - /**Called from the logic thread. Do not access graphics here!*/ + /** Called from the logic thread. Do not access graphics here! */ public static class TileChangeEvent implements Event{ public final Tile tile; @@ -83,8 +84,10 @@ public class EventType{ } } - /**Called when block building begins by placing down the BuildBlock. - * The tile's block will nearly always be a BuildBlock.*/ + /** + * Called when block building begins by placing down the BuildBlock. + * The tile's block will nearly always be a BuildBlock. + */ public static class BlockBuildBeginEvent implements Event{ public final Tile tile; public final Team team; @@ -109,8 +112,10 @@ public class EventType{ } } - /**Called when a player or drone begins building something. - * This does not necessarily happen when a new BuildBlock is created.*/ + /** + * Called when a player or drone begins building something. + * This does not necessarily happen when a new BuildBlock is created. + */ public static class BuildSelectEvent implements Event{ public final Tile tile; public final Team team; diff --git a/core/src/io/anuke/mindustry/game/GlobalData.java b/core/src/io/anuke/mindustry/game/GlobalData.java index 6726f6fd7f..11dabeb994 100644 --- a/core/src/io/anuke/mindustry/game/GlobalData.java +++ b/core/src/io/anuke/mindustry/game/GlobalData.java @@ -2,20 +2,16 @@ package io.anuke.mindustry.game; import io.anuke.arc.Core; import io.anuke.arc.Events; -import io.anuke.arc.collection.ObjectIntMap; -import io.anuke.arc.collection.ObjectMap; -import io.anuke.arc.collection.ObjectSet; +import io.anuke.arc.collection.*; import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Items; import io.anuke.mindustry.game.EventType.UnlockEvent; -import io.anuke.mindustry.type.ContentType; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.ItemStack; +import io.anuke.mindustry.type.*; import static io.anuke.mindustry.Vars.content; import static io.anuke.mindustry.Vars.state; -/**Stores player unlocks. Clientside only.*/ +/** Stores player unlocks. Clientside only. */ public class GlobalData{ private ObjectMap> unlocked = new ObjectMap<>(); private ObjectIntMap items = new ObjectIntMap<>(); @@ -74,7 +70,7 @@ public class GlobalData{ return items; } - /** Returns whether or not this piece of content is unlocked yet.*/ + /** Returns whether or not this piece of content is unlocked yet. */ public boolean isUnlocked(UnlockableContent content){ return content.alwaysUnlocked() || unlocked.getOr(content.getContentType(), ObjectSet::new).contains(content.name); } @@ -95,7 +91,7 @@ public class GlobalData{ } } - /** Clears all unlocked content. Automatically saves.*/ + /** Clears all unlocked content. Automatically saves. */ public void reset(){ save(); } @@ -116,7 +112,7 @@ public class GlobalData{ //set up default values if(!Core.settings.has("item-" + Items.copper.name)){ - addItem(Items.copper, 50); + addItem(Items.copper, 50); } } diff --git a/core/src/io/anuke/mindustry/game/MappableContent.java b/core/src/io/anuke/mindustry/game/MappableContent.java index 9b1e7bbc36..3253975085 100644 --- a/core/src/io/anuke/mindustry/game/MappableContent.java +++ b/core/src/io/anuke/mindustry/game/MappableContent.java @@ -1,6 +1,6 @@ package io.anuke.mindustry.game; -public abstract class MappableContent extends Content { +public abstract class MappableContent extends Content{ public final String name; public MappableContent(String name){ diff --git a/core/src/io/anuke/mindustry/game/RulePreset.java b/core/src/io/anuke/mindustry/game/RulePreset.java index 2fb2fbe504..4968f24db3 100644 --- a/core/src/io/anuke/mindustry/game/RulePreset.java +++ b/core/src/io/anuke/mindustry/game/RulePreset.java @@ -3,7 +3,7 @@ package io.anuke.mindustry.game; import io.anuke.arc.Core; import io.anuke.arc.function.Supplier; -/**Defines preset rule sets..*/ +/** Defines preset rule sets.. */ public enum RulePreset{ survival(() -> new Rules(){{ waveTimer = true; @@ -15,6 +15,7 @@ public enum RulePreset{ infiniteResources = true; waves = true; waveTimer = false; + respawnTime = 0f; spawns = DefaultWaves.get(); }}), attack(() -> new Rules(){{ @@ -25,6 +26,12 @@ public enum RulePreset{ pvp = true; enemyCoreBuildRadius = 600f; respawnTime = 60 * 10; + buildCostMultiplier = 0.5f; + buildSpeedMultiplier = 2f; + playerDamageMultiplier = 0.45f; + playerHealthMultiplier = 0.8f; + unitBuildSpeedMultiplier = 3f; + unitHealthMultiplier = 2f; }}); private final Supplier rules; diff --git a/core/src/io/anuke/mindustry/game/Rules.java b/core/src/io/anuke/mindustry/game/Rules.java index cf31cce7e0..44db4aabdf 100644 --- a/core/src/io/anuke/mindustry/game/Rules.java +++ b/core/src/io/anuke/mindustry/game/Rules.java @@ -3,30 +3,46 @@ package io.anuke.mindustry.game; import io.anuke.annotations.Annotations.Serialize; import io.anuke.arc.collection.Array; -/**Defines current rules on how the game should function. - * Does not store game state, just configuration.*/ +/** + * Defines current rules on how the game should function. + * Does not store game state, just configuration. + */ @Serialize public class Rules{ - /**Whether the player has infinite resources.*/ + /** Whether the player has infinite resources. */ public boolean infiniteResources; - /**Whether the waves come automatically on a timer. If not, waves come when the play button is pressed.*/ + /** Whether the waves come automatically on a timer. If not, waves come when the play button is pressed. */ public boolean waveTimer = true; - /**Whether waves are spawnable at all.*/ + /** Whether waves are spawnable at all. */ public boolean waves; - /**Whether the enemy AI has infinite resources in most of their buildings and turrets.*/ + /** Whether the enemy AI has infinite resources in most of their buildings and turrets. */ public boolean enemyCheat; - /**Whether the game objective is PvP. Note that this enables automatic hosting.*/ + /** Whether the game objective is PvP. Note that this enables automatic hosting. */ public boolean pvp; - /**Whether enemy units drop random items on death.*/ + /** Whether enemy units drop random items on death. */ public boolean unitDrops; - /**No-build zone around enemy core radius.*/ + /** How fast unit pads build units. */ + public float unitBuildSpeedMultiplier = 1f; + /** How much health units start with. */ + public float unitHealthMultiplier = 1f; + /** How much health players start with. */ + public float playerHealthMultiplier = 1f; + /** How much damage player mechs deal. */ + public float playerDamageMultiplier = 1f; + /** How much damage any other units deal. */ + public float unitDamageMultiplier = 1f; + /** Multiplier for buildings for the player. */ + public float buildCostMultiplier = 1f; + /** Multiplier for building speed. */ + public float buildSpeedMultiplier = 1f; + /** No-build zone around enemy core radius. */ public float enemyCoreBuildRadius = 400f; - /**Player respawn time in ticks.*/ + /** Player respawn time in ticks. */ public float respawnTime = 60 * 4; - /**Time between waves in ticks.*/ + /** Time between waves in ticks. */ public float waveSpacing = 60 * 60 * 2; - /**Zone ID, -1 for invalid zone.*/ + /** Zone ID, -1 for invalid zone. */ public byte zone = -1; - /**Spawn layout. Since only zones modify this, it should be assigned on save load.*/ + /** Spawn layout. Since only zones modify this, it should be assigned on save load. */ public transient Array spawns = DefaultWaves.get(); } diff --git a/core/src/io/anuke/mindustry/game/Saves.java b/core/src/io/anuke/mindustry/game/Saves.java index 0142f194f7..3078637c01 100644 --- a/core/src/io/anuke/mindustry/game/Saves.java +++ b/core/src/io/anuke/mindustry/game/Saves.java @@ -2,9 +2,7 @@ package io.anuke.mindustry.game; import io.anuke.arc.Core; import io.anuke.arc.Events; -import io.anuke.arc.collection.Array; -import io.anuke.arc.collection.IntArray; -import io.anuke.arc.collection.IntMap; +import io.anuke.arc.collection.*; import io.anuke.arc.files.FileHandle; import io.anuke.arc.util.Strings; import io.anuke.arc.util.Time; @@ -48,7 +46,7 @@ public class Saves{ saves.clear(); IntArray slots = Core.settings.getObject("save-slots", IntArray.class, IntArray::new); - for(int i = 0; i < slots.size; i ++){ + for(int i = 0; i < slots.size; i++){ int index = slots.get(i); if(SaveIO.isSaveValid(index)){ SaveSlot slot = new SaveSlot(index); @@ -68,7 +66,7 @@ public class Saves{ SaveSlot current = this.current; if(current != null && !state.is(State.menu) - && !(state.isPaused() && Core.scene.hasDialog())){ + && !(state.isPaused() && Core.scene.hasDialog())){ if(lastTimestamp != 0){ totalPlaytime += Time.timeSinceMillis(lastTimestamp); } diff --git a/core/src/io/anuke/mindustry/game/SpawnGroup.java b/core/src/io/anuke/mindustry/game/SpawnGroup.java index 6847b9a116..d6cc11f243 100644 --- a/core/src/io/anuke/mindustry/game/SpawnGroup.java +++ b/core/src/io/anuke/mindustry/game/SpawnGroup.java @@ -4,10 +4,7 @@ import io.anuke.arc.util.serialization.Json; import io.anuke.arc.util.serialization.Json.Serializable; import io.anuke.arc.util.serialization.JsonValue; import io.anuke.mindustry.entities.type.BaseUnit; -import io.anuke.mindustry.type.ContentType; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.type.StatusEffect; -import io.anuke.mindustry.type.UnitType; +import io.anuke.mindustry.type.*; import static io.anuke.mindustry.Vars.content; @@ -19,23 +16,23 @@ import static io.anuke.mindustry.Vars.content; public class SpawnGroup implements Serializable{ public static final int never = Integer.MAX_VALUE; - /**The unit type spawned*/ + /** The unit type spawned */ public UnitType type; - /**When this spawn should end*/ + /** When this spawn should end */ public int end = never; - /**When this spawn should start*/ + /** When this spawn should start */ public int begin; - /**The spacing, in waves, of spawns. For example, 2 = spawns every other wave*/ + /** The spacing, in waves, of spawns. For example, 2 = spawns every other wave */ public int spacing = 1; - /**Maximum amount of units that spawn*/ - public int max = 40; - /**How many waves need to pass before the amount of units spawned increases by 1*/ + /** Maximum amount of units that spawn */ + public int max = 100; + /** How many waves need to pass before the amount of units spawned increases by 1 */ public float unitScaling = never; - /**Amount of enemies spawned initially, with no scaling*/ + /** Amount of enemies spawned initially, with no scaling */ public int unitAmount = 1; - /**Status effect applied to the spawned unit. Null to disable.*/ + /** Status effect applied to the spawned unit. Null to disable. */ public StatusEffect effect; - /**Items this unit spawns with. Null to disable.*/ + /** Items this unit spawns with. Null to disable. */ public ItemStack items; public SpawnGroup(UnitType type){ @@ -46,14 +43,14 @@ public class SpawnGroup implements Serializable{ //serialization use only } - /**Returns the amount of units spawned on a specific wave.*/ + /** Returns the amount of units spawned on a specific wave. */ public int getUnitsSpawned(int wave){ if(wave < begin || wave > end || (wave - begin) % spacing != 0){ return 0; } float scaling = this.unitScaling; - return Math.min(unitAmount - 1 + Math.max((int) (((wave - begin) / spacing) / scaling), 1), max); + return Math.min(unitAmount - 1 + Math.max((int)(((wave - begin + 1) / spacing) / scaling), 1), max); } /** @@ -75,24 +72,24 @@ public class SpawnGroup implements Serializable{ } @Override - public void write (Json json) { + public void write(Json json){ json.writeValue("type", type.name); if(begin != 0) json.writeValue("begin", begin); if(end != never) json.writeValue("end", end); if(spacing != 1) json.writeValue("spacing", spacing); - if(max != 40) json.writeValue("max", max); + //if(max != 40) json.writeValue("max", max); if(unitScaling != never) json.writeValue("scaling", unitScaling); if(unitAmount != 1) json.writeValue("amount", unitAmount); if(effect != null) json.writeValue("effect", effect.id); } @Override - public void read (Json json, JsonValue data) { + public void read(Json json, JsonValue data){ type = content.getByName(ContentType.unit, data.getString("type", "dagger")); begin = data.getInt("begin", 0); end = data.getInt("end", never); spacing = data.getInt("spacing", 1); - max = data.getInt("spacing", 40); + //max = data.getInt("max", 40); unitScaling = data.getFloat("scaling", never); unitAmount = data.getInt("amount", 1); effect = content.getByID(ContentType.status, data.getInt("effect", -1)); diff --git a/core/src/io/anuke/mindustry/game/Stats.java b/core/src/io/anuke/mindustry/game/Stats.java index 05917231c5..7e00d05d44 100644 --- a/core/src/io/anuke/mindustry/game/Stats.java +++ b/core/src/io/anuke/mindustry/game/Stats.java @@ -4,25 +4,23 @@ import io.anuke.annotations.Annotations.Serialize; import io.anuke.arc.collection.Array; import io.anuke.arc.collection.ObjectIntMap; import io.anuke.arc.math.Mathf; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.ItemType; -import io.anuke.mindustry.type.Zone; +import io.anuke.mindustry.type.*; @Serialize public class Stats{ - /**Items delivered to global resoure counter. Zones only.*/ + /** Items delivered to global resoure counter. Zones only. */ public ObjectIntMap itemsDelivered = new ObjectIntMap<>(); - /**Enemy (red team) units destroyed.*/ + /** Enemy (red team) units destroyed. */ public int enemyUnitsDestroyed; - /**Total waves lasted.*/ + /** Total waves lasted. */ public int wavesLasted; - /**Total (ms) time lasted in this save/zone.*/ + /** Total (ms) time lasted in this save/zone. */ public long timeLasted; - /**Friendly buildings fully built.*/ + /** Friendly buildings fully built. */ public int buildingsBuilt; - /**Friendly buildings fully deconstructed.*/ + /** Friendly buildings fully deconstructed. */ public int buildingsDeconstructed; - /**Friendly buildings destroyed.*/ + /** Friendly buildings destroyed. */ public int buildingsDestroyed; public RankResult calculateRank(Zone zone, boolean launched){ @@ -30,7 +28,7 @@ public class Stats{ //each new launch period adds onto the rank 'points' if(wavesLasted >= zone.conditionWave){ - score += (float)((wavesLasted - zone.conditionWave) / zone.launchPeriod + 1) * 1.2f; + score += (float)((wavesLasted - zone.conditionWave) / zone.launchPeriod + 1) * 1.2f; } int capacity = zone.loadout.core().itemCapacity; @@ -42,13 +40,13 @@ public class Stats{ frac += Mathf.clamp((float)itemsDelivered.get(item, 0) / capacity) / (float)obtainable.size; } - score += frac*1.6f; + score += frac * 1.6f; if(!launched){ score *= 0.5f; } - int rankIndex = Mathf.clamp((int)(score), 0, Rank.values().length-1); + int rankIndex = Mathf.clamp((int)(score), 0, Rank.values().length - 1); Rank rank = Rank.values()[rankIndex]; String sign = Math.abs((rankIndex + 0.5f) - score) < 0.2f || rank.name().contains("S") ? "" : (rankIndex + 0.5f) < score ? "-" : "+"; @@ -57,7 +55,7 @@ public class Stats{ public static class RankResult{ public final Rank rank; - /**+ or -*/ + /** + or - */ public final String modifier; public RankResult(Rank rank, String modifier){ diff --git a/core/src/io/anuke/mindustry/game/Team.java b/core/src/io/anuke/mindustry/game/Team.java index 429e6e970a..a5193e48b2 100644 --- a/core/src/io/anuke/mindustry/game/Team.java +++ b/core/src/io/anuke/mindustry/game/Team.java @@ -5,7 +5,7 @@ import io.anuke.arc.graphics.Color; public enum Team{ none(Color.valueOf("4d4e58")), - blue(Color.ROYAL), + blue(Color.valueOf("4169e1")), red(Color.valueOf("e84737")), green(Color.valueOf("1dc645")), purple(Color.valueOf("ba5bd9")), diff --git a/core/src/io/anuke/mindustry/game/Teams.java b/core/src/io/anuke/mindustry/game/Teams.java index 28ffdfc2a2..1dc52906f1 100644 --- a/core/src/io/anuke/mindustry/game/Teams.java +++ b/core/src/io/anuke/mindustry/game/Teams.java @@ -1,18 +1,15 @@ package io.anuke.mindustry.game; -import io.anuke.arc.collection.Array; -import io.anuke.arc.collection.EnumSet; -import io.anuke.arc.collection.ObjectSet; +import io.anuke.arc.collection.*; import io.anuke.mindustry.Vars; import io.anuke.mindustry.world.Tile; -/**Class for various team-based utilities.*/ +/** Class for various team-based utilities. */ public class Teams{ private TeamData[] map = new TeamData[Team.all.length]; /** * Register a team. - * * @param team The team type enum. * @param enemies The array of enemies of this team. Any team not in this array is considered neutral. */ @@ -20,7 +17,7 @@ public class Teams{ map[team.ordinal()] = new TeamData(team, EnumSet.of(enemies)); } - /**Returns team data by type.*/ + /** Returns team data by type. */ public TeamData get(Team team){ if(map[team.ordinal()] == null){ add(team, Array.with(Team.all).select(t -> t != team).toArray(Team.class)); @@ -28,18 +25,18 @@ public class Teams{ return map[team.ordinal()]; } - /**Returns whether a team is active, e.g. whether it has any cores remaining.*/ + /** Returns whether a team is active, e.g. whether it has any cores remaining. */ public boolean isActive(Team team){ //the enemy wave team is always active return (Vars.state.rules.waves && team == Vars.waveTeam) || get(team).cores.size > 0; } - /**Returns a set of all teams that are enemies of this team.*/ + /** Returns a set of all teams that are enemies of this team. */ public EnumSet enemiesOf(Team team){ return get(team).enemies; } - /**Returns whether {@param other} is an enemy of {@param #team}.*/ + /** Returns whether {@param other} is an enemy of {@param #team}. */ public boolean areEnemies(Team team, Team other){ return enemiesOf(team).contains(other); } diff --git a/core/src/io/anuke/mindustry/game/UnlockableContent.java b/core/src/io/anuke/mindustry/game/UnlockableContent.java index 7a843ecdfc..24edd13949 100644 --- a/core/src/io/anuke/mindustry/game/UnlockableContent.java +++ b/core/src/io/anuke/mindustry/game/UnlockableContent.java @@ -5,11 +5,11 @@ import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.Vars; -/**Base interface for an unlockable content type.*/ +/** Base interface for an unlockable content type. */ public abstract class UnlockableContent extends MappableContent{ - /**Localized, formal name. Never null. Set to block name if not found in bundle.*/ + /** Localized, formal name. Never null. Set to block name if not found in bundle. */ public String localizedName; - /**Localized description. May be null.*/ + /** Localized description. May be null. */ public String description; public UnlockableContent(String name){ @@ -19,24 +19,24 @@ public abstract class UnlockableContent extends MappableContent{ this.description = Core.bundle.getOrNull(getContentType() + "." + name + ".description"); } - /**Returns the localized name of this content.*/ + /** Returns the localized name of this content. */ public abstract String localizedName(); public abstract TextureRegion getContentIcon(); - /**This should show all necessary info about this content in the specified table.*/ + /** This should show all necessary info about this content in the specified table. */ public abstract void displayInfo(Table table); - /**Called when this content is unlocked. Use this to unlock other related content.*/ + /** Called when this content is unlocked. Use this to unlock other related content. */ public void onUnlock(){ } - /**Whether this content is always hidden in the content info dialog.*/ + /** Whether this content is always hidden in the content info dialog. */ public boolean isHidden(){ return false; } - /**Override to make content always unlocked.*/ + /** Override to make content always unlocked. */ public boolean alwaysUnlocked(){ return false; } diff --git a/core/src/io/anuke/mindustry/game/Version.java b/core/src/io/anuke/mindustry/game/Version.java index 276dd04354..5349306321 100644 --- a/core/src/io/anuke/mindustry/game/Version.java +++ b/core/src/io/anuke/mindustry/game/Version.java @@ -9,15 +9,15 @@ import io.anuke.arc.util.io.PropertiesUtils; import java.io.IOException; public class Version{ - /**Build type. 'official' for official releases; 'custom' or 'bleeding edge' are also used.*/ + /** Build type. 'official' for official releases; 'custom' or 'bleeding edge' are also used. */ public static String type; - /**Build modifier, e.g. 'alpha' or 'release'*/ + /** Build modifier, e.g. 'alpha' or 'release' */ public static String modifier; - /**Number specifying the major version, e.g. '4'*/ + /** Number specifying the major version, e.g. '4' */ public static int number; - /**Build number, e.g. '43'. set to '-1' for custom builds.*/ + /** Build number, e.g. '43'. set to '-1' for custom builds. */ public static int build = 0; - /**Revision number. Used for hotfixes. Does not affect server compatibility.*/ + /** Revision number. Used for hotfixes. Does not affect server compatibility. */ public static int revision = 0; public static void init(){ diff --git a/core/src/io/anuke/mindustry/graphics/BlockRenderer.java b/core/src/io/anuke/mindustry/graphics/BlockRenderer.java index a12ccd624d..524d1df00a 100644 --- a/core/src/io/anuke/mindustry/graphics/BlockRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/BlockRenderer.java @@ -4,8 +4,6 @@ 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.mindustry.entities.EntityDraw; -import io.anuke.mindustry.entities.EntityGroup; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.Texture.TextureFilter; import io.anuke.arc.graphics.g2d.Draw; @@ -13,7 +11,6 @@ import io.anuke.arc.graphics.g2d.Fill; import io.anuke.arc.graphics.glutils.FrameBuffer; import io.anuke.arc.util.Tmp; import io.anuke.mindustry.content.Blocks; -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.game.Team; @@ -26,8 +23,7 @@ import static io.anuke.mindustry.Vars.*; public class BlockRenderer{ private final static int initialRequests = 32 * 32; private final static int expandr = 9; - private final static boolean disableShadows = false; - private final static Color shadowColor = new Color(0, 0, 0, 0.19f); + private final static Color shadowColor = new Color(0, 0, 0, 0.71f); public final FloorRenderer floor = new FloorRenderer(); @@ -38,6 +34,7 @@ public class BlockRenderer{ private FrameBuffer shadows = new FrameBuffer(2, 2); private FrameBuffer fog = new FrameBuffer(2, 2); private Array outArray = new Array<>(); + private Array shadowEvents = new Array<>(); public BlockRenderer(){ @@ -46,21 +43,41 @@ public class BlockRenderer{ } Events.on(WorldLoadEvent.class, event -> { + shadowEvents.clear(); lastCamY = lastCamX = -99; //invalidate camera position so blocks get updated + shadows.getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear); + shadows.resize(world.width(), world.height()); + shadows.begin(); + Core.graphics.clear(Color.WHITE); + Draw.proj().setOrtho(0, 0, shadows.getWidth(), shadows.getHeight()); + + Draw.color(shadowColor); + + for(int x = 0; x < world.width(); x++){ + for(int y = 0; y < world.height(); y++){ + Tile tile = world.rawTile(x, y); + if(tile.block().hasShadow){ + Fill.rect(tile.x + 0.5f, tile.y + 0.5f, 1, 1); + } + } + } + + Draw.flush(); + Draw.color(); + shadows.end(); + fog.getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear); fog.resize(world.width(), world.height()); fog.begin(); Core.graphics.clear(Color.WHITE); Draw.proj().setOrtho(0, 0, fog.getWidth(), fog.getHeight()); - //TODO highly inefficient, width*height rectangles isn't great - //TODO handle shadow rotation generation with GPU blur/erode algorithm for(int x = 0; x < world.width(); x++){ for(int y = 0; y < world.height(); y++){ Tile tile = world.rawTile(x, y); if(tile.getRotation() > 0 && tile.block().solid && tile.block().fillsTile && !tile.block().synthetic()){ - Draw.color(0f, 0f, 0f, Math.min((tile.getRotation() + 0.5f)/4f, 1f)); + Draw.color(0f, 0f, 0f, Math.min((tile.getRotation() + 0.5f) / 4f, 1f)); Fill.rect(tile.x + 0.5f, tile.y + 0.5f, 1, 1); } } @@ -72,10 +89,12 @@ public class BlockRenderer{ }); Events.on(TileChangeEvent.class, event -> { + shadowEvents.add(event.tile); + int avgx = (int)(camera.position.x / tilesize); - int avgy = (int)(camera.position. y/ tilesize); - int rangex = (int) (camera.width / tilesize / 2) + 2; - int rangey = (int) (camera.height / tilesize / 2) + 2; + int avgy = (int)(camera.position.y / tilesize); + int rangex = (int)(camera.width / tilesize / 2) + 2; + int rangey = (int)(camera.height / tilesize / 2) + 2; if(Math.abs(avgx - event.tile.x) <= rangex && Math.abs(avgy - event.tile.y) <= rangey){ lastCamY = lastCamX = -99; //invalidate camera position so blocks get updated @@ -85,11 +104,11 @@ public class BlockRenderer{ public void drawFog(){ float ww = world.width() * tilesize, wh = world.height() * tilesize; - float x = camera.position.x + tilesize/2f, y = camera.position.y + tilesize/2f; - float u = (x - camera.width/2f) / ww, - v = (y - camera.height/2f) / wh, - u2 = (x + camera.width/2f) / ww, - v2 = (y + camera.height/2f) / wh; + float x = camera.position.x + tilesize / 2f, y = camera.position.y + tilesize / 2f; + float u = (x - camera.width / 2f) / ww, + v = (y - camera.height / 2f) / wh, + u2 = (x + camera.width / 2f) / ww, + v2 = (y + camera.height / 2f) / wh; Tmp.tr1.set(fog.getTexture()); Tmp.tr1.set(u, v2, u2, v); @@ -100,55 +119,54 @@ public class BlockRenderer{ } public void drawShadows(){ - if(disableShadows) return; + if(!shadowEvents.isEmpty()){ + Draw.flush(); - Draw.color(); + shadows.begin(); + Draw.proj().setOrtho(0, 0, shadows.getWidth(), shadows.getHeight()); - if(!Core.graphics.isHidden() && (shadows.getWidth() != Core.graphics.getWidth() || shadows.getHeight() != Core.graphics.getHeight())){ - shadows.resize(Core.graphics.getWidth(), Core.graphics.getHeight()); + for(Tile tile : shadowEvents){ + //clear it first + Draw.color(Color.WHITE); + Fill.rect(tile.x + 0.5f, tile.y + 0.5f, 1, 1); + //then draw the shadow + Draw.color(!tile.block().hasShadow ? Color.WHITE : shadowColor); + Fill.rect(tile.x + 0.5f, tile.y + 0.5f, 1, 1); + } + + Draw.flush(); + Draw.color(); + shadows.end(); + shadowEvents.clear(); + + Draw.proj(camera.projection()); + renderer.pixelator.rebind(); } + float ww = world.width() * tilesize, wh = world.height() * tilesize; + float x = camera.position.x + tilesize / 2f, y = camera.position.y + tilesize / 2f; + float u = (x - camera.width / 2f) / ww, + v = (y - camera.height / 2f) / wh, + u2 = (x + camera.width / 2f) / ww, + v2 = (y + camera.height / 2f) / wh; + Tmp.tr1.set(shadows.getTexture()); - Shaders.shadow.color.set(shadowColor); - Shaders.shadow.scl = renderer.cameraScale()/3f; - Shaders.shadow.region = Tmp.tr1; + Tmp.tr1.set(u, v2, u2, v); - Draw.flush(); - shadows.begin(); - Core.graphics.clear(Color.CLEAR); - - floor.beginDraw(); - floor.drawLayer(CacheLayer.walls); - floor.endDraw(); - - drawBlocks(Layer.shadow); - - EntityDraw.drawWith(playerGroup, player -> !player.isDead(), Unit::draw); - for(EntityGroup group : unitGroups){ - EntityDraw.drawWith(group, unit -> !unit.isDead(), Unit::draw); - } - - Draw.color(); - Draw.flush(); - shadows.end(); - - Draw.shader(Shaders.shadow); - Draw.rect(Draw.wrap(shadows.getTexture()), - camera.position.x, - camera.position.y, - camera.width, -camera.height); + Draw.shader(Shaders.fog); + Draw.rect(Tmp.tr1, camera.position.x, camera.position.y, camera.width, camera.height); Draw.shader(); } - /**Process all blocks to draw.*/ + /** Process all blocks to draw. */ public void processBlocks(){ iterateidx = 0; int avgx = (int)(camera.position.x / tilesize); int avgy = (int)(camera.position.y / tilesize); - int rangex = (int) (camera.width / tilesize / 2) + 3; - int rangey = (int) (camera.height / tilesize / 2) + 3; + int rangex = (int)(camera.width / tilesize / 2) + 3; + int rangey = (int)(camera.height / tilesize / 2) + 3; if(avgx == lastCamX && avgy == lastCamY && lastRangeX == rangex && lastRangeY == rangey){ return; @@ -174,7 +192,6 @@ public class BlockRenderer{ } if(block.expanded || !expanded){ - addRequest(tile, Layer.shadow); if(block.layer != null && block.isLayer(tile)){ addRequest(tile, block.layer); @@ -215,11 +232,9 @@ public class BlockRenderer{ BlockRequest req = requests.get(iterateidx); Block block = req.tile.block(); - if(req.layer == Layer.shadow){ - block.drawShadow(req.tile); - }else if(req.layer == Layer.block){ + if(req.layer == Layer.block){ block.draw(req.tile); - if(block.synthetic() && req.tile.getTeam() != players[0].getTeam()){ + if(block.synthetic() && req.tile.getTeam() != player.getTeam()){ block.drawTeam(req.tile); } }else if(req.layer == block.layer){ diff --git a/core/src/io/anuke/mindustry/graphics/FloorRenderer.java b/core/src/io/anuke/mindustry/graphics/FloorRenderer.java index 7bc7acc202..b3276147dc 100644 --- a/core/src/io/anuke/mindustry/graphics/FloorRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/FloorRenderer.java @@ -2,20 +2,13 @@ package io.anuke.mindustry.graphics; import io.anuke.arc.Core; import io.anuke.arc.Events; -import io.anuke.arc.collection.IntArray; -import io.anuke.arc.collection.IntSet; +import io.anuke.arc.collection.*; import io.anuke.arc.collection.IntSet.IntSetIterator; -import io.anuke.arc.collection.ObjectSet; import io.anuke.arc.graphics.Camera; import io.anuke.arc.graphics.GL20; -import io.anuke.arc.graphics.g2d.CacheBatch; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.SpriteBatch; -import io.anuke.arc.graphics.g2d.SpriteCache; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Mathf; -import io.anuke.arc.util.Log; -import io.anuke.arc.util.Structs; -import io.anuke.arc.util.Time; +import io.anuke.arc.util.*; import io.anuke.mindustry.game.EventType.WorldLoadEvent; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Floor; @@ -45,8 +38,8 @@ public class FloorRenderer{ Camera camera = Core.camera; - int crangex = (int) (camera.width / (chunksize * tilesize)) + 1; - int crangey = (int) (camera.height / (chunksize * tilesize)) + 1; + int crangex = (int)(camera.width / (chunksize * tilesize)) + 1; + int crangey = (int)(camera.height / (chunksize * tilesize)) + 1; int camx = (int)(camera.position.x / (chunksize * tilesize)); int camy = (int)(camera.position.y / (chunksize * tilesize)); @@ -129,8 +122,8 @@ public class FloorRenderer{ Camera camera = Core.camera; - int crangex = (int) (camera.width / (chunksize * tilesize)) + 1; - int crangey = (int) (camera.height / (chunksize * tilesize)) + 1; + int crangex = (int)(camera.width / (chunksize * tilesize)) + 1; + int crangey = (int)(camera.height / (chunksize * tilesize)) + 1; layer.begin(); @@ -183,7 +176,7 @@ public class FloorRenderer{ for(int tilex = cx * chunksize; tilex < (cx + 1) * chunksize; tilex++){ for(int tiley = cy * chunksize; tiley < (cy + 1) * chunksize; tiley++){ - Tile tile = world.tile(tilex , tiley); + Tile tile = world.tile(tilex, tiley); Floor floor; if(tile == null){ @@ -194,7 +187,7 @@ public class FloorRenderer{ if(tile.block().cacheLayer == layer && layer == CacheLayer.walls){ tile.block().draw(tile); - }else if(floor.cacheLayer == layer && (world.isAccessible(tile.x,tile.y) || tile.block().cacheLayer != CacheLayer.walls || !tile.block().fillsTile)){ + }else if(floor.cacheLayer == layer && (world.isAccessible(tile.x, tile.y) || tile.block().cacheLayer != CacheLayer.walls || !tile.block().fillsTile)){ floor.draw(tile); }else if(floor.cacheLayer.ordinal() < layer.ordinal() && layer != CacheLayer.walls){ floor.drawNonLayer(tile); @@ -208,10 +201,10 @@ public class FloorRenderer{ public void clearTiles(){ if(cbatch != null) cbatch.dispose(); - int chunksx = Mathf.ceil((float) (world.width()) / chunksize), - chunksy = Mathf.ceil((float) (world.height()) / chunksize) ; + int chunksx = Mathf.ceil((float)(world.width()) / chunksize), + chunksy = Mathf.ceil((float)(world.height()) / chunksize); cache = new Chunk[chunksx][chunksy]; - SpriteCache sprites = new SpriteCache(world.width() * world.height() * 5, (world.width() / chunksize) * (world.height() / chunksize) * 2, false); + SpriteCache sprites = new SpriteCache(world.width() * world.height() * 6, (world.width() / chunksize) * (world.height() / chunksize) * 2, false); cbatch = new CacheBatch(sprites); Time.mark(); diff --git a/core/src/io/anuke/mindustry/graphics/IndexedRenderer.java b/core/src/io/anuke/mindustry/graphics/IndexedRenderer.java index ca2e9787b4..b4165dbe63 100644 --- a/core/src/io/anuke/mindustry/graphics/IndexedRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/IndexedRenderer.java @@ -16,35 +16,35 @@ public class IndexedRenderer implements Disposable{ private final static int vsize = 5; private Shader program = new Shader( - Strings.join("\n", - "attribute vec4 " + Shader.POSITION_ATTRIBUTE + ";", - "attribute vec4 " + Shader.COLOR_ATTRIBUTE + ";", - "attribute vec2 " + Shader.TEXCOORD_ATTRIBUTE + "0;", - "uniform mat4 u_projTrans;", - "varying vec4 v_color;", - "varying vec2 v_texCoords;", - "", - "void main(){", - " v_color = " + Shader.COLOR_ATTRIBUTE + ";", - " v_color.a = v_color.a * (255.0/254.0);", - " v_texCoords = " + Shader.TEXCOORD_ATTRIBUTE + "0;", - " gl_Position = u_projTrans * " + Shader.POSITION_ATTRIBUTE + ";", - "}"), - Strings.join("\n", - "#ifdef GL_ES", - "#define LOWP lowp", - "precision mediump float;", - "#else", - "#define LOWP ", - "#endif", - "", - "varying LOWP vec4 v_color;", - "varying vec2 v_texCoords;", - "uniform sampler2D u_texture;", - "", - "void main(){", - " gl_FragColor = v_color * texture2D(u_texture, v_texCoords);", - "}" + Strings.join("\n", + "attribute vec4 " + Shader.POSITION_ATTRIBUTE + ";", + "attribute vec4 " + Shader.COLOR_ATTRIBUTE + ";", + "attribute vec2 " + Shader.TEXCOORD_ATTRIBUTE + "0;", + "uniform mat4 u_projTrans;", + "varying vec4 v_color;", + "varying vec2 v_texCoords;", + "", + "void main(){", + " v_color = " + Shader.COLOR_ATTRIBUTE + ";", + " v_color.a = v_color.a * (255.0/254.0);", + " v_texCoords = " + Shader.TEXCOORD_ATTRIBUTE + "0;", + " gl_Position = u_projTrans * " + Shader.POSITION_ATTRIBUTE + ";", + "}"), + Strings.join("\n", + "#ifdef GL_ES", + "#define LOWP lowp", + "precision mediump float;", + "#else", + "#define LOWP ", + "#endif", + "", + "varying LOWP vec4 v_color;", + "varying vec2 v_texCoords;", + "uniform sampler2D u_texture;", + "", + "void main(){", + " gl_FragColor = v_color * texture2D(u_texture, v_texCoords);", + "}" )); private Mesh mesh; private float[] tmpVerts = new float[vsize * 6]; @@ -226,9 +226,9 @@ public class IndexedRenderer implements Disposable{ if(mesh != null) mesh.dispose(); mesh = new Mesh(true, 6 * sprites, 0, - new VertexAttribute(Usage.Position, 2, "a_position"), - new VertexAttribute(Usage.ColorPacked, 4, "a_color"), - new VertexAttribute(Usage.TextureCoordinates, 2, "a_texCoord0")); + new VertexAttribute(Usage.Position, 2, "a_position"), + new VertexAttribute(Usage.ColorPacked, 4, "a_color"), + new VertexAttribute(Usage.TextureCoordinates, 2, "a_texCoord0")); vertices = new float[6 * sprites * vsize]; mesh.setVertices(vertices); } diff --git a/core/src/io/anuke/mindustry/graphics/Layer.java b/core/src/io/anuke/mindustry/graphics/Layer.java index 493a13deba..f84f6aa3c2 100644 --- a/core/src/io/anuke/mindustry/graphics/Layer.java +++ b/core/src/io/anuke/mindustry/graphics/Layer.java @@ -1,18 +1,16 @@ package io.anuke.mindustry.graphics; public enum Layer{ - /**Drawn under everything.*/ - shadow, - /**Base block layer.*/ + /** Base block layer. */ block, - /**for placement*/ + /** for placement */ placement, - /**First overlay. Stuff like conveyor items.*/ + /** First overlay. Stuff like conveyor items. */ overlay, - /**"High" blocks, like turrets.*/ + /** "High" blocks, like turrets. */ turret, - /**Power lasers.*/ + /** Power lasers. */ power, - /**Extra lasers, like healing turrets.*/ + /** Extra lasers, like healing turrets. */ laser } diff --git a/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java b/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java index 7eac43461c..c14c49b6e8 100644 --- a/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java @@ -3,19 +3,14 @@ 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.graphics.Pixmap; +import io.anuke.arc.graphics.*; import io.anuke.arc.graphics.Pixmap.Format; -import io.anuke.arc.graphics.Pixmaps; -import io.anuke.arc.graphics.Texture; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Fill; -import io.anuke.arc.graphics.g2d.ScissorStack; -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.Rectangle; import io.anuke.arc.util.Disposable; -import io.anuke.mindustry.entities.type.Unit; 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; @@ -25,13 +20,13 @@ import static io.anuke.mindustry.Vars.tilesize; import static io.anuke.mindustry.Vars.world; public class MinimapRenderer implements Disposable{ - private static final int baseSize = 16; + private static final float baseSize = 16f; private final Array units = new Array<>(); private Pixmap pixmap; private Texture texture; private TextureRegion region; private Rectangle rect = new Rectangle(), scissor = new Rectangle(); - private int zoom = 4; + private float zoom = 4; public MinimapRenderer(){ Events.on(WorldLoadEvent.class, event -> { @@ -49,7 +44,11 @@ public class MinimapRenderer implements Disposable{ public void zoomBy(float amount){ zoom += amount; - zoom = Mathf.clamp(zoom, 1, Math.min(world.width(), world.height()) / baseSize / 2); + setZoom(zoom); + } + + public void setZoom(float amount){ + zoom = Mathf.clamp(amount, 1f, Math.min(world.width(), world.height()) / baseSize / 2f); } public float getZoom(){ @@ -69,33 +68,27 @@ public class MinimapRenderer implements Disposable{ public void drawEntities(float x, float y, float w, float h){ updateUnitArray(); - int sz = baseSize * zoom; + float sz = baseSize * zoom; float dx = (Core.camera.position.x / tilesize); float dy = (Core.camera.position.y / tilesize); dx = Mathf.clamp(dx, sz, world.width() - sz); dy = Mathf.clamp(dy, sz, world.height() - sz); - if(!ScissorStack.pushScissors(scissor.set(x, y, w, h))){ - return; - } - rect.set((dx - sz) * tilesize, (dy - sz) * tilesize, sz * 2 * tilesize, sz * 2 * tilesize); for(Unit unit : units){ float rx = (unit.x - rect.x) / rect.width * w, ry = (unit.y - rect.y) / rect.width * h; Draw.color(unit.getTeam().color); - Fill.crect(x + rx, y + ry, w / (sz * 2), h / (sz * 2)); + Fill.rect(x + rx, y + ry, baseSize / 2f, baseSize / 2f); } Draw.color(); - - ScissorStack.popScissors(); } public TextureRegion getRegion(){ if(texture == null) return null; - int sz = Mathf.clamp(baseSize * zoom, baseSize, Math.min(world.width(), world.height())); + float sz = Mathf.clamp(baseSize * zoom, baseSize, Math.min(world.width(), world.height())); float dx = (Core.camera.position.x / tilesize); float dy = (Core.camera.position.y / tilesize); dx = Mathf.clamp(dx, sz, world.width() - sz); @@ -124,7 +117,7 @@ public class MinimapRenderer implements Disposable{ } public void updateUnitArray(){ - int sz = baseSize * zoom; + float sz = baseSize * zoom; float dx = (Core.camera.position.x / tilesize); float dy = (Core.camera.position.y / tilesize); dx = Mathf.clamp(dx, sz, world.width() - sz); @@ -137,7 +130,7 @@ public class MinimapRenderer implements Disposable{ private int colorFor(Tile tile){ tile = tile.target(); - return MapIO.colorFor(tile.floor(), tile.block(), tile.ore(), tile.getTeam()); + return MapIO.colorFor(tile.floor(), tile.block(), tile.overlay(), tile.getTeam()); } @Override diff --git a/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java b/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java index c0975f3b79..a08d9d1788 100644 --- a/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java @@ -9,6 +9,7 @@ import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.util.Time; import io.anuke.arc.util.Tmp; +import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.type.Player; @@ -25,20 +26,18 @@ public class OverlayRenderer{ private float buildFadeTime; public void drawBottom(){ - for(Player player : players){ - InputHandler input = control.input(player.playerIndex); + InputHandler input = control.input(); - if(!input.isDrawing() || player.isDead()) continue; + if(!input.isDrawing() || player.isDead()) return; - input.drawOutlined(); - } + input.drawOutlined(); } public void drawTop(){ if(Core.settings.getBool("indicators")){ for(Player player : playerGroup.all()){ - if(player != players[0] && player.getTeam() == players[0].getTeam()){ + if(Vars.player != player && Vars.player.getTeam() == player.getTeam()){ if(!rect.setSize(Core.camera.width * 0.9f, Core.camera.height * 0.9f) .setCenter(Core.camera.position.x, Core.camera.position.y).contains(player.x, player.y)){ @@ -52,7 +51,7 @@ public class OverlayRenderer{ } Units.allUnits(unit -> { - if(unit != players[0] && unit.getTeam() != players[0].getTeam() && !rect.setSize(Core.camera.width * 0.9f, Core.camera.height * 0.9f).setCenter(Core.camera.position.x, Core.camera.position.y).contains(unit.x, unit.y)){ + if(unit != player && unit.getTeam() != player.getTeam() && !rect.setSize(Core.camera.width * 0.9f, Core.camera.height * 0.9f).setCenter(Core.camera.position.x, Core.camera.position.y).contains(unit.x, unit.y)){ Tmp.v1.set(unit.x, unit.y).sub(Core.camera.position.x, Core.camera.position.y).setLength(indicatorLength); Lines.stroke(1f, unit.getTeam().color); @@ -62,67 +61,66 @@ public class OverlayRenderer{ }); } - for(Player player : players){ - if(player.isDead()) continue; //dead players don't draw + if(player.isDead()) return; //dead players don't draw - InputHandler input = control.input(player.playerIndex); + InputHandler input = control.input(); - //draw config selected block - if(input.frag.config.isShown()){ - Tile tile = input.frag.config.getSelectedTile(); - tile.block().drawConfigure(tile); - } + //draw config selected block + if(input.frag.config.isShown()){ + Tile tile = input.frag.config.getSelectedTile(); + tile.block().drawConfigure(tile); + } - input.drawTop(); + input.drawTop(); - buildFadeTime = Mathf.lerpDelta(buildFadeTime, input.isPlacing() ? 1f : 0f, 0.06f); + buildFadeTime = Mathf.lerpDelta(buildFadeTime, input.isPlacing() ? 1f : 0f, 0.06f); - Draw.reset(); - Lines.stroke(buildFadeTime*2f); + Draw.reset(); + Lines.stroke(buildFadeTime * 2f); - if(buildFadeTime > 0.005f){ - for(Team enemy : state.teams.enemiesOf(player.getTeam())){ - for(Tile core : state.teams.get(enemy).cores){ - float dst = Mathf.dst(player.x, player.y, core.drawx(), core.drawy()); - if(dst < state.rules.enemyCoreBuildRadius * 1.5f){ - Draw.color(Color.DARK_GRAY); - Lines.poly(core.drawx(), core.drawy() - 2, 200, state.rules.enemyCoreBuildRadius); - Draw.color(Pal.accent, enemy.color, 0.5f + Mathf.absin(Time.time(), 10f, 0.5f)); - Lines.poly(core.drawx(), core.drawy(), 200, state.rules.enemyCoreBuildRadius); - } + if(buildFadeTime > 0.005f){ + for(Team enemy : state.teams.enemiesOf(player.getTeam())){ + for(Tile core : state.teams.get(enemy).cores){ + float dst = Mathf.dst(player.x, player.y, core.drawx(), core.drawy()); + if(dst < state.rules.enemyCoreBuildRadius * 1.5f){ + Draw.color(Color.DARK_GRAY); + Lines.poly(core.drawx(), core.drawy() - 2, 200, state.rules.enemyCoreBuildRadius); + Draw.color(Pal.accent, enemy.color, 0.5f + Mathf.absin(Time.time(), 10f, 0.5f)); + Lines.poly(core.drawx(), core.drawy(), 200, state.rules.enemyCoreBuildRadius); } } } + } + Draw.reset(); + + //draw selected block bars and info + if(input.block == null && !Core.scene.hasMouse()){ + Vector2 vec = Core.input.mouseWorld(input.getMouseX(), input.getMouseY()); + Tile tile = world.tileWorld(vec.x, vec.y); + + if(tile != null && tile.block() != Blocks.air && tile.target().getTeam() == player.getTeam()){ + Tile target = tile.target(); + target.block().drawSelect(target); + } + } + + if(input.isDroppingItem()){ + Vector2 v = Core.input.mouseWorld(input.getMouseX(), input.getMouseY()); + float size = 8; + Draw.rect(player.item().item.icon(Item.Icon.large), v.x, v.y, size, size); + Draw.color(Pal.accent); + Lines.circle(v.x, v.y, 6 + Mathf.absin(Time.time(), 5f, 1f)); Draw.reset(); - //draw selected block bars and info - if(input.block == null && !Core.scene.hasMouse()){ - Vector2 vec = Core.input.mouseWorld(input.getMouseX(), input.getMouseY()); - Tile tile = world.tileWorld(vec.x, vec.y); - - if(tile != null && tile.block() != Blocks.air && tile.target().getTeam() == players[0].getTeam()){ - Tile target = tile.target(); - target.block().drawSelect(target); - } - } - - if(input.isDroppingItem()){ - Vector2 v = Core.input.mouseWorld(input.getMouseX(), input.getMouseY()); - float size = 8; - Draw.rect(player.item().item.icon(Item.Icon.large), v.x, v.y, size, size); - Draw.color(Pal.accent); - Lines.circle(v.x, v.y, 6 + Mathf.absin(Time.time(), 5f, 1f)); - Draw.reset(); - - Tile tile = world.tileWorld(v.x, v.y); - if(tile != null) tile = tile.target(); - if(tile != null && tile.interactable(player.getTeam()) && tile.block().acceptStack(player.item().item, player.item().amount, tile, player) > 0){ - Draw.color(Pal.place); - Lines.square(tile.drawx(), tile.drawy(), tile.block().size * tilesize / 2f + 1 + Mathf.absin(Time.time(), 5f, 1f)); - Draw.color(); - } + Tile tile = world.tileWorld(v.x, v.y); + if(tile != null) tile = tile.target(); + if(tile != null && tile.interactable(player.getTeam()) && tile.block().acceptStack(player.item().item, player.item().amount, tile, player) > 0){ + Draw.color(Pal.place); + Lines.square(tile.drawx(), tile.drawy(), tile.block().size * tilesize / 2f + 1 + Mathf.absin(Time.time(), 5f, 1f)); + Draw.color(); } } } + } diff --git a/core/src/io/anuke/mindustry/graphics/Pal.java b/core/src/io/anuke/mindustry/graphics/Pal.java index 37de7b50b0..e13ed16723 100644 --- a/core/src/io/anuke/mindustry/graphics/Pal.java +++ b/core/src/io/anuke/mindustry/graphics/Pal.java @@ -22,6 +22,9 @@ public class Pal{ lightFlame = Color.valueOf("ffdd55"), darkFlame = Color.valueOf("db401c"), + lightPyraFlame = Color.valueOf("ffb855"), + darkPyraFlame = Color.valueOf("db661c"), + turretHeat = Color.valueOf("ab3400"), lightOrange = Color.valueOf("f68021"), @@ -45,6 +48,7 @@ public class Pal{ heal = Color.valueOf("98ffa9"), bar = Color.SLATE, accent = Color.valueOf("ffd37f"), + stat = Color.valueOf("ffd37f"), locked = Color.valueOf("989aa4"), accentBack = Color.valueOf("d4816b"), place = Color.valueOf("6335f8"), diff --git a/core/src/io/anuke/mindustry/graphics/Pixelator.java b/core/src/io/anuke/mindustry/graphics/Pixelator.java new file mode 100644 index 0000000000..afc4b91cd8 --- /dev/null +++ b/core/src/io/anuke/mindustry/graphics/Pixelator.java @@ -0,0 +1,75 @@ +package io.anuke.mindustry.graphics; + +import io.anuke.arc.Core; +import io.anuke.arc.graphics.Blending; +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.glutils.FrameBuffer; +import io.anuke.arc.util.Disposable; +import io.anuke.mindustry.entities.type.Player; + +import static io.anuke.arc.Core.camera; +import static io.anuke.arc.Core.graphics; +import static io.anuke.mindustry.Vars.playerGroup; +import static io.anuke.mindustry.Vars.renderer; + +public class Pixelator implements Disposable{ + private FrameBuffer buffer = new FrameBuffer(2, 2); + + public void drawPixelate(){ + float pre = renderer.getScale(); + float scale = renderer.getScale(); + scale = (int)scale; + renderer.setScale(scale); + camera.width = (int)camera.width; + camera.height = (int)camera.height; + + boolean hadShields = Core.settings.getBool("animatedshields"); + boolean hadWater = Core.settings.getBool("animatedwater"); + Core.settings.put("animatedwater", false); + Core.settings.put("animatedshields", false); + graphics.clear(0f, 0f, 0f, 1f); + + float px = Core.camera.position.x, py = Core.camera.position.y; + Core.camera.position.set((int)px + ((int)(camera.width) % 2 == 0 ? 0 : 0.5f), (int)py + ((int)(camera.height) % 2 == 0 ? 0 : 0.5f)); + + int w = (int)(Core.camera.width); + int h = (int)(Core.camera.height); + + if(!graphics.isHidden() && (buffer.getWidth() != w || buffer.getHeight() != h)){ + buffer.resize(w, h); + } + + Draw.flush(); + buffer.begin(); + renderer.draw(); + + Draw.flush(); + buffer.end(); + + Draw.blend(Blending.disabled); + 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); + + Core.camera.position.set(px, py); + Core.settings.put("animatedwater", hadWater); + Core.settings.put("animatedshields", hadShields); + renderer.setScale(pre); + } + + public void rebind(){ + if(enabled()){ + buffer.begin(); + } + } + + public boolean enabled(){ + return Core.settings.getBool("pixelate"); + } + + @Override + public void dispose(){ + buffer.dispose(); + } +} diff --git a/core/src/io/anuke/mindustry/graphics/Shaders.java b/core/src/io/anuke/mindustry/graphics/Shaders.java index 7839716f71..e253818f1f 100644 --- a/core/src/io/anuke/mindustry/graphics/Shaders.java +++ b/core/src/io/anuke/mindustry/graphics/Shaders.java @@ -120,10 +120,10 @@ public class Shaders{ setUniformf("u_dp", Unit.dp.scl(1f)); setUniformf("u_time", Time.time() / Unit.dp.scl(1f)); setUniformf("u_offset", - Core.camera.position.x - Core.camera.width / 2 , - Core.camera.position.y - Core.camera.height / 2 ); - setUniformf("u_texsize", Core.camera.width , - Core.camera.height ); + Core.camera.position.x - Core.camera.width / 2, + Core.camera.position.y - Core.camera.height / 2); + setUniformf("u_texsize", Core.camera.width, + Core.camera.height); } } @@ -140,10 +140,10 @@ public class Shaders{ setUniformf("time", Time.time()); } } - + public static class LoadShader extends Shader{ public LoadShader(String frag, String vert){ - super(Core.files.internal("shaders/" + vert + ".vertex"), Core.files.internal("shaders/" + frag + ".fragment")); + super(Core.files.internal("shaders/" + vert + ".vertex.glsl"), Core.files.internal("shaders/" + frag + ".fragment.glsl")); } } } diff --git a/core/src/io/anuke/mindustry/graphics/Shapes.java b/core/src/io/anuke/mindustry/graphics/Shapes.java index 899ed2ae8d..4918d5dd1b 100644 --- a/core/src/io/anuke/mindustry/graphics/Shapes.java +++ b/core/src/io/anuke/mindustry/graphics/Shapes.java @@ -1,10 +1,7 @@ package io.anuke.mindustry.graphics; import io.anuke.arc.Core; -import io.anuke.arc.graphics.g2d.CapStyle; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Lines; -import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Tmp; @@ -34,6 +31,6 @@ public class Shapes{ public static void tri(float x, float y, float width, float length, float rotation){ float oy = 17f / 63f * length; - Draw.rect(Core.atlas.find("shape-3"), x, y - oy + length/2f, width, length, width / 2f, oy, rotation - 90); + Draw.rect(Core.atlas.find("shape-3"), x, y - oy + length / 2f, width, length, width / 2f, oy, rotation - 90); } } diff --git a/core/src/io/anuke/mindustry/input/Binding.java b/core/src/io/anuke/mindustry/input/Binding.java index dc23e9f7dd..d135f1f528 100644 --- a/core/src/io/anuke/mindustry/input/Binding.java +++ b/core/src/io/anuke/mindustry/input/Binding.java @@ -2,9 +2,7 @@ package io.anuke.mindustry.input; import io.anuke.arc.Application.ApplicationType; import io.anuke.arc.Core; -import io.anuke.arc.KeyBinds.Axis; -import io.anuke.arc.KeyBinds.KeyBind; -import io.anuke.arc.KeyBinds.KeybindValue; +import io.anuke.arc.KeyBinds.*; import io.anuke.arc.input.InputDevice.DeviceType; import io.anuke.arc.input.KeyCode; @@ -25,6 +23,7 @@ public enum Binding implements KeyBind{ menu(Core.app.getType() == ApplicationType.Android ? KeyCode.BACK : KeyCode.ESCAPE), pause(KeyCode.SPACE), toggle_menus(KeyCode.C), + screenshot(KeyCode.P), player_list(KeyCode.TAB, "multiplayer"), chat(KeyCode.ENTER), chat_history_prev(KeyCode.UP), @@ -36,9 +35,22 @@ public enum Binding implements KeyBind{ private final KeybindValue defaultValue; private final String category; - Binding(KeybindValue defaultValue, String category){ this.defaultValue = defaultValue; this.category = category; } - Binding(KeybindValue defaultValue){ this(defaultValue, null); } + Binding(KeybindValue defaultValue, String category){ + this.defaultValue = defaultValue; + this.category = category; + } - @Override public KeybindValue defaultValue(DeviceType type){ return defaultValue; } - @Override public String category(){ return category; } + Binding(KeybindValue defaultValue){ + this(defaultValue, null); + } + + @Override + public KeybindValue defaultValue(DeviceType type){ + return defaultValue; + } + + @Override + public String category(){ + return category; + } } diff --git a/core/src/io/anuke/mindustry/input/DesktopInput.java b/core/src/io/anuke/mindustry/input/DesktopInput.java index eeda4020d1..bc3ef2533c 100644 --- a/core/src/io/anuke/mindustry/input/DesktopInput.java +++ b/core/src/io/anuke/mindustry/input/DesktopInput.java @@ -10,7 +10,6 @@ import io.anuke.arc.math.geom.Geometry; import io.anuke.arc.math.geom.Point2; import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.input.PlaceUtils.NormalizeDrawResult; import io.anuke.mindustry.input.PlaceUtils.NormalizeResult; @@ -22,38 +21,35 @@ import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.input.PlaceMode.*; public class DesktopInput extends InputHandler{ - /**Current cursor type.*/ + /** Current cursor type. */ private Cursor cursorType = SystemCursor.arrow; - /**Position where the player started dragging a line.*/ + /** Position where the player started dragging a line. */ private int selectX, selectY; - /**Whether selecting mode is active.*/ + /** Whether selecting mode is active. */ private PlaceMode mode; - /**Animation scale for line.*/ + /** Animation scale for line. */ private float selectScale; private int prevX, prevY, prevRotation; - public DesktopInput(Player player){ - super(player); - } - - /**Draws a placement icon for a specific block.*/ + /** Draws a placement icon for a specific block. */ void drawPlace(int x, int y, Block block, int rotation, int prevX, int prevY, int prevRotation){ if(validPlace(x, y, block, rotation)){ block.getPlaceDraw(placeDraw, rotation, prevX, prevY, prevRotation); Draw.color(); Draw.rect(placeDraw.region, x * tilesize + block.offset(), y * tilesize + block.offset(), - placeDraw.region.getWidth() * selectScale * Draw.scl * placeDraw.scalex, - placeDraw.region.getHeight() * selectScale * Draw.scl * placeDraw.scaley, - block.rotate ? placeDraw.rotation * 90 : 0); + placeDraw.region.getWidth() * selectScale * Draw.scl * placeDraw.scalex, + placeDraw.region.getHeight() * selectScale * Draw.scl * placeDraw.scaley, + block.rotate ? placeDraw.rotation * 90 : 0); Draw.color(Pal.accent); for(int i = 0; i < 4; i++){ Point2 p = Geometry.d8edge[i]; - float offset = -Math.max(block.size-1, 0)/2f * tilesize; - if(i % 2 == 0)Draw.rect("block-select", x * tilesize + block.offset() + offset * p.x, y * tilesize + block.offset() + offset * p.y, i * 90); + float offset = -Math.max(block.size - 1, 0) / 2f * tilesize; + if(i % 2 == 0) + Draw.rect("block-select", x * tilesize + block.offset() + offset * p.x, y * tilesize + block.offset() + offset * p.y, i * 90); } Draw.color(); }else{ @@ -103,7 +99,7 @@ public class DesktopInput extends InputHandler{ tile = tile.target(); Draw.color(Pal.removeBack); - Lines.square(tile.drawx(), tile.drawy()-1, tile.block().size * tilesize / 2f - 1); + Lines.square(tile.drawx(), tile.drawy() - 1, tile.block().size * tilesize / 2f - 1); Draw.color(Pal.remove); Lines.square(tile.drawx(), tile.drawy(), tile.block().size * tilesize / 2f - 1); } @@ -166,7 +162,7 @@ public class DesktopInput extends InputHandler{ selectScale = 0f; } - rotation = Mathf.mod(rotation + (int) Core.input.axisTap(Binding.rotate), 4); + rotation = Mathf.mod(rotation + (int)Core.input.axisTap(Binding.rotate), 4); Tile cursor = tileAt(Core.input.mouseX(), Core.input.mouseY()); @@ -211,8 +207,8 @@ 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 && - !tryBeginMine(selected) && player.getMineTile() == null && !ui.chatfrag.chatOpen()) { + if(!tileTapped(selected) && !tryTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y) && player.getPlaceQueue().size == 0 && !droppingItem && + !tryBeginMine(selected) && player.getMineTile() == null && !ui.chatfrag.chatOpen()){ player.isShooting = true; } }else if(!ui.chatfrag.chatOpen()){ //if it's out of bounds, shooting is just fine @@ -277,9 +273,10 @@ public class DesktopInput extends InputHandler{ @Override public void updateController(){ - if(state.is(State.menu)){ droppingItem = false; + mode = none; + block = null; } } } diff --git a/core/src/io/anuke/mindustry/input/InputHandler.java b/core/src/io/anuke/mindustry/input/InputHandler.java index 46e442a818..8a073e1f4b 100644 --- a/core/src/io/anuke/mindustry/input/InputHandler.java +++ b/core/src/io/anuke/mindustry/input/InputHandler.java @@ -29,22 +29,19 @@ import io.anuke.mindustry.net.ValidateException; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.ui.fragments.OverlayFragment; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Build; -import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.*; import static io.anuke.mindustry.Vars.*; public abstract class InputHandler implements InputProcessor{ - /**Used for dropping items.*/ + /** Used for dropping items. */ final static float playerSelectRange = mobile ? 17f : 11f; - /**Maximum line length.*/ + /** Maximum line length. */ final static int maxLength = 100; final static Vector2 stackTrns = new Vector2(); - /**Distance on the back from where items originate.*/ + /** Distance on the back from where items originate. */ final static float backTrns = 3f; - public final Player player; public final OverlayFragment frag = new OverlayFragment(this); public Block block; @@ -54,10 +51,6 @@ public abstract class InputHandler implements InputProcessor{ protected PlaceDraw placeDraw = new PlaceDraw(); private PlaceLine line = new PlaceLine(); - public InputHandler(Player player){ - this.player = player; - } - //methods to override @Remote(targets = Loc.client, called = Loc.server) @@ -96,17 +89,17 @@ public abstract class InputHandler implements InputProcessor{ tile.block().getStackOffset(item, tile, stackTrns); ItemTransfer.create(item, - player.x + Angles.trnsx(player.rotation + 180f, backTrns), player.y + Angles.trnsy(player.rotation + 180f, backTrns), - new Vector2(tile.drawx() + stackTrns.x, tile.drawy() + stackTrns.y), () -> { - if(tile.block() != block || tile.entity == null || tile.entity.items == null) return; + player.x + Angles.trnsx(player.rotation + 180f, backTrns), player.y + Angles.trnsy(player.rotation + 180f, backTrns), + new Vector2(tile.drawx() + stackTrns.x, tile.drawy() + stackTrns.y), () -> { + if(tile.block() != block || tile.entity == null || tile.entity.items == null) return; - tile.block().handleStack(item, removed, tile, player); - remaining[1] -= removed; + tile.block().handleStack(item, removed, tile, player); + remaining[1] -= removed; - if(end && remaining[1] > 0){ - tile.block().handleStack(item, remaining[1], tile, player); - } - }); + if(end && remaining[1] > 0){ + tile.block().handleStack(item, remaining[1], tile, player); + } + }); remaining[0] -= removed; @@ -159,7 +152,7 @@ public abstract class InputHandler implements InputProcessor{ return false; } - /**Handles tile tap events that are not platform specific.*/ + /** Handles tile tap events that are not platform specific. */ boolean tileTapped(Tile tile){ tile = tile.target(); @@ -169,8 +162,8 @@ public abstract class InputHandler implements InputProcessor{ if(tile.block().configurable && tile.interactable(player.getTeam())){ consumed = true; if(((!frag.config.isShown() && tile.block().shouldShowConfigure(tile, player)) //if the config fragment is hidden, show - //alternatively, the current selected block can 'agree' to switch config tiles - || (frag.config.isShown() && frag.config.getSelectedTile().block().onConfigureTileTapped(frag.config.getSelectedTile(), tile)))){ + //alternatively, the current selected block can 'agree' to switch config tiles + || (frag.config.isShown() && frag.config.getSelectedTile().block().onConfigureTileTapped(frag.config.getSelectedTile(), tile)))){ frag.config.showConfig(tile); } //otherwise... @@ -215,7 +208,7 @@ public abstract class InputHandler implements InputProcessor{ return consumed; } - /**Tries to select the player to drop off items, returns true if successful.*/ + /** Tries to select the player to drop off items, returns true if successful. */ boolean tryTapPlayer(float x, float y){ if(canTapPlayer(x, y)){ droppingItem = true; @@ -228,7 +221,7 @@ public abstract class InputHandler implements InputProcessor{ return Mathf.dst(x, y, player.x, player.y) <= playerSelectRange && player.item().amount > 0; } - /**Tries to begin mining a tile, returns true if successful.*/ + /** Tries to begin mining a tile, returns true if successful. */ boolean tryBeginMine(Tile tile){ if(canMine(tile)){ //if a block is clicked twice, reset it @@ -240,13 +233,13 @@ public abstract class InputHandler implements InputProcessor{ boolean canMine(Tile tile){ return !Core.scene.hasMouse() - && tile.drop() != null && tile.drop().hardness <= player.mech.drillPower - && !tile.floor().playerUnmineable - && player.acceptsItem(tile.drop()) - && tile.block() == Blocks.air && player.dst(tile.worldx(), tile.worldy()) <= Player.mineDistance; + && tile.drop() != null && tile.drop().hardness <= player.mech.drillPower + && !(tile.floor().playerUnmineable && tile.overlay().itemDrop == null) + && player.acceptsItem(tile.drop()) + && tile.block() == Blocks.air && player.dst(tile.worldx(), tile.worldy()) <= Player.mineDistance; } - /**Returns the tile at the specified MOUSE coordinates.*/ + /** Returns the tile at the specified MOUSE coordinates. */ Tile tileAt(float x, float y){ return world.tile(tileX(x), tileY(y)); } @@ -313,25 +306,20 @@ public abstract class InputHandler implements InputProcessor{ } } - public boolean cursorNear(){ - return true; - } - public void tryPlaceBlock(int x, int y){ - if(block != null && validPlace(x, y, block, rotation) && cursorNear()){ + if(block != null && validPlace(x, y, block, rotation)){ placeBlock(x, y, block, rotation); } } public void tryBreakBlock(int x, int y){ - if(cursorNear() && validBreak(x, y)){ + if(validBreak(x, y)){ breakBlock(x, y); } } public boolean validPlace(int x, int y, Block type, int rotation){ - return Build.validPlace(player.getTeam(), x, y, type, rotation) && - Mathf.dst(player.x, player.y, x * tilesize, y * tilesize) < Player.placeDistance; + return Build.validPlace(player.getTeam(), x, y, type, rotation); } public boolean validBreak(int x, int y){ @@ -384,7 +372,7 @@ public abstract class InputHandler implements InputProcessor{ for(int i = 0; i < points.size; i++){ Point2 point = points.get(i); - if(block != null && Tmp.r2.setSize(block.size * tilesize).setCenter(point.x*tilesize + block.offset(), point.y*tilesize + block.offset()).overlaps(Tmp.r3)){ + if(block != null && Tmp.r2.setSize(block.size * tilesize).setCenter(point.x * tilesize + block.offset(), point.y * tilesize + block.offset()).overlaps(Tmp.r3)){ continue; } @@ -395,7 +383,7 @@ public abstract class InputHandler implements InputProcessor{ line.last = next == null; cons.accept(line); - Tmp.r3.setSize(block.size * tilesize).setCenter(point.x*tilesize + block.offset(), point.y*tilesize + block.offset()); + Tmp.r3.setSize(block.size * tilesize).setCenter(point.x * tilesize + block.offset(), point.y * tilesize + block.offset()); } } diff --git a/core/src/io/anuke/mindustry/input/MobileInput.java b/core/src/io/anuke/mindustry/input/MobileInput.java index 554cf9af09..ab33b78716 100644 --- a/core/src/io/anuke/mindustry/input/MobileInput.java +++ b/core/src/io/anuke/mindustry/input/MobileInput.java @@ -4,31 +4,23 @@ import io.anuke.arc.Core; import io.anuke.arc.collection.Array; import io.anuke.arc.function.BooleanProvider; import io.anuke.arc.graphics.Color; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Lines; -import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.input.GestureDetector; import io.anuke.arc.input.GestureDetector.GestureListener; import io.anuke.arc.input.KeyCode; import io.anuke.arc.math.Interpolation; import io.anuke.arc.math.Mathf; -import io.anuke.arc.math.geom.Geometry; -import io.anuke.arc.math.geom.Point2; -import io.anuke.arc.math.geom.Rectangle; -import io.anuke.arc.math.geom.Vector2; +import io.anuke.arc.math.geom.*; import io.anuke.arc.scene.actions.Actions; import io.anuke.arc.scene.event.Touchable; import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.arc.util.Align; -import io.anuke.arc.util.Time; -import io.anuke.arc.util.Tmp; +import io.anuke.arc.util.*; import io.anuke.mindustry.content.Blocks; 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.TargetTrait; -import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.graphics.Pal; @@ -61,7 +53,7 @@ public class MobileInput extends InputHandler implements GestureListener{ /** Animation data for crosshair. */ private float crosshairScale; private TargetTrait lastTarget; - /** Used for shifting build requests.*/ + /** Used for shifting build requests. */ private float shiftDeltaX, shiftDeltaY; /** List of currently selected tiles to place. */ @@ -81,8 +73,7 @@ public class MobileInput extends InputHandler implements GestureListener{ private int prevX, prevY, prevRotation; - public MobileInput(Player player){ - super(player); + public MobileInput(){ Core.input.addProcessor(new GestureDetector(20, 0.5f, 0.4f, 0.15f, this)); } @@ -175,7 +166,7 @@ public class MobileInput extends InputHandler implements GestureListener{ Core.scene.table("guideDim", t -> { t.margin(10f); t.touchable(Touchable.disabled); - t.top().table("button", s -> s.add("$"+type).growX().wrap().labelAlign(Align.center, Align.center)).growX(); + t.top().table("button", s -> s.add("$" + type).growX().wrap().labelAlign(Align.center, Align.center)).growX(); t.update(() -> { if((done.get() || state.is(State.menu)) && t.getUserObject() == null){ t.actions(Actions.delay(1f), Actions.fadeOut(1f, Interpolation.fade), Actions.remove()); @@ -189,11 +180,11 @@ public class MobileInput extends InputHandler implements GestureListener{ } boolean isLinePlacing(){ - return mode == placing && lineMode && Mathf.dst(lineStartX * tilesize, lineStartY * tilesize, Core.input.mouseWorld().x, Core.input.mouseWorld().y) >= 3*tilesize; + return mode == placing && lineMode && Mathf.dst(lineStartX * tilesize, lineStartY * tilesize, Core.input.mouseWorld().x, Core.input.mouseWorld().y) >= 3 * tilesize; } boolean isAreaBreaking(){ - return mode == breaking && lineMode && Mathf.dst(lineStartX * tilesize, lineStartY * tilesize, Core.input.mouseWorld().x, Core.input.mouseWorld().y) >= 2*tilesize; + return mode == breaking && lineMode && Mathf.dst(lineStartX * tilesize, lineStartY * tilesize, Core.input.mouseWorld().x, Core.input.mouseWorld().y) >= 2 * tilesize; } //endregion @@ -224,24 +215,27 @@ public class MobileInput extends InputHandler implements GestureListener{ Draw.mixcol(Pal.accent, 1f); for(int i = 0; i < 4; i++){ Point2 p = Geometry.d8edge[i]; - float poffset = -Math.max(request.block.size-1, 0)/2f * tilesize; + float poffset = -Math.max(request.block.size - 1, 0) / 2f * tilesize; TextureRegion find = Core.atlas.find("block-select"); - if(i%2 == 0) Draw.rect("block-select", request.tile().x * tilesize + request.block.offset() + poffset * p.x, request.tile().y * tilesize + request.block.offset() + poffset * p.y, - find.getWidth() * Draw.scl * request.scale, find.getHeight() * Draw.scl * request.scale, i * 90); + if(i % 2 == 0) + Draw.rect("block-select", request.tile().x * tilesize + request.block.offset() + poffset * p.x, request.tile().y * tilesize + request.block.offset() + poffset * p.y, + find.getWidth() * Draw.scl * request.scale, find.getHeight() * Draw.scl * request.scale, i * 90); } Draw.color(); }else{ - float rad = (tile.block().size * tilesize / 2f - 1) * request.scale; + float rad = Math.max((tile.block().size * tilesize / 2f - 1) * request.scale, 1f); + + if(rad <= 1.01f) return; Draw.mixcol(); //draw removing request Draw.tint(Pal.removeBack); - Lines.square(tile.drawx(), tile.drawy()-1, rad); + Lines.square(tile.drawx(), tile.drawy() - 1, rad); Draw.tint(Pal.remove); Lines.square(tile.drawx(), tile.drawy(), rad); } } - /**Draws a placement icon for a specific block.*/ + /** Draws a placement icon for a specific block. */ void drawPlace(int x, int y, Block block, int rotation, int prevX, int prevY, int prevRotation){ if(validPlace(x, y, block, rotation)){ block.getPlaceDraw(placeDraw, rotation, prevX, prevY, prevRotation); @@ -255,8 +249,9 @@ public class MobileInput extends InputHandler implements GestureListener{ Draw.color(Pal.accent); for(int i = 0; i < 4; i++){ Point2 p = Geometry.d8edge[i]; - float offset = -Math.max(block.size-1, 0)/2f * tilesize; - if(i % 2 == 0)Draw.rect("block-select", x * tilesize + block.offset() + offset * p.x, y * tilesize + block.offset() + offset * p.y, i * 90); + float offset = -Math.max(block.size - 1, 0) / 2f * tilesize; + if(i % 2 == 0) + Draw.rect("block-select", x * tilesize + block.offset() + offset * p.x, y * tilesize + block.offset() + offset * p.y, i * 90); } Draw.color(); }else{ @@ -353,7 +348,7 @@ public class MobileInput extends InputHandler implements GestureListener{ if(tile == null) continue; if((!request.remove && validPlace(tile.x, tile.y, request.block, request.rotation)) - || (request.remove && validBreak(tile.x, tile.y))){ + || (request.remove && validBreak(tile.x, tile.y))){ request.scale = Mathf.lerpDelta(request.scale, 1f, 0.2f); request.redness = Mathf.lerpDelta(request.redness, 0f, 0.2f); }else{ @@ -365,7 +360,7 @@ public class MobileInput extends InputHandler implements GestureListener{ if(!request.remove && request == lastPlaced && request.block != null){ Draw.mixcol(); - drawArrow(request.block, tile.x, tile.y, request.rotation); + if(request.block.rotate) drawArrow(request.block, tile.x, tile.y, request.rotation); } Draw.mixcol(Tmp.c1, 1f); @@ -401,6 +396,7 @@ public class MobileInput extends InputHandler implements GestureListener{ } drawPlace(l.x, l.y, block, l.rotation, prevX - l.x, prevY - l.y, prevRotation); + rotation = l.rotation; prevX = l.x; prevY = l.y; prevRotation = l.rotation; @@ -417,7 +413,7 @@ public class MobileInput extends InputHandler implements GestureListener{ other = other.target(); Draw.color(Pal.removeBack); - Lines.square(other.drawx(), other.drawy()-1, other.block().size * tilesize / 2f - 1); + Lines.square(other.drawx(), other.drawy() - 1, other.block().size * tilesize / 2f - 1); Draw.color(Pal.remove); Lines.square(other.drawx(), other.drawy(), other.block().size * tilesize / 2f - 1); } @@ -492,6 +488,11 @@ public class MobileInput extends InputHandler implements GestureListener{ if(mode == placing && isPlacing()){ iterateLine(lineStartX, lineStartY, tileX, tileY, l -> { + Tile tile = world.tile(l.x, l.y); + if(tile != null && hasRequest(tile)){ + return; + } + PlaceRequest request = new PlaceRequest(l.x, l.y, block, l.rotation); request.scale = 1f; selection.add(request); @@ -652,7 +653,7 @@ public class MobileInput extends InputHandler implements GestureListener{ panY = (screenY - Core.graphics.getHeight()) + edgePan; } - vector.set(panX, panY).scl((Core.camera.width ) / Core.graphics.getWidth()); + vector.set(panX, panY).scl((Core.camera.width) / Core.graphics.getWidth()); vector.limit(maxPanSpeed); //pan view @@ -723,7 +724,7 @@ public class MobileInput extends InputHandler implements GestureListener{ public boolean zoom(float initialDistance, float distance){ if(lastDistance == -1) lastDistance = initialDistance; - float amount = (Mathf.sign(distance > lastDistance) * 0.07f) * Time.delta(); + float amount = (Mathf.sign(distance > lastDistance) * 0.04f) * Time.delta(); renderer.scaleCamera(io.anuke.arc.scene.ui.layout.Unit.dp.scl(amount)); lastDistance = distance; return true; diff --git a/core/src/io/anuke/mindustry/input/PlaceUtils.java b/core/src/io/anuke/mindustry/input/PlaceUtils.java index 1a36c24608..52e06e518b 100644 --- a/core/src/io/anuke/mindustry/input/PlaceUtils.java +++ b/core/src/io/anuke/mindustry/input/PlaceUtils.java @@ -15,26 +15,26 @@ public class PlaceUtils{ private static Bresenham2 bres = new Bresenham2(); private static Array points = new Array<>(); - /**Normalize a diagonal line into points. */ + /** Normalize a diagonal line into points. */ public static Array normalizeDiagonal(int startX, int startY, int endX, int endY){ Pools.freeAll(points); points.clear(); return bres.lineNoDiagonal(startX, startY, endX, endY, Pools.get(Point2.class, Point2::new), points); } - /**Normalize two points into one straight line, no diagonals.*/ + /** Normalize two points into one straight line, no diagonals. */ public static Array normalizeLine(int startX, int startY, int endX, int endY){ Pools.freeAll(points); points.clear(); if(Math.abs(startX - endX) > Math.abs(startY - endY)){ //go width for(int i = 0; i <= Math.abs(startX - endX); i++){ - points.add(Pools.obtain(Point2.class, Point2::new).set(startX + i*Mathf.sign(endX - startX), startY)); + points.add(Pools.obtain(Point2.class, Point2::new).set(startX + i * Mathf.sign(endX - startX), startY)); } }else{ //go height for(int i = 0; i <= Math.abs(startY - endY); i++){ - points.add(Pools.obtain(Point2.class, Point2::new).set(startX, startY + i*Mathf.sign(endY - startY))); + points.add(Pools.obtain(Point2.class, Point2::new).set(startX, startY + i * Mathf.sign(endY - startY))); } } return points; @@ -43,7 +43,6 @@ public class PlaceUtils{ /** * Normalizes a placement area and returns the result, ready to be used for drawing a rectangle. * Returned x2 and y2 will always be greater than x and y. - * * @param block block that will be drawn * @param startx starting X coordinate * @param starty starting Y coordinate @@ -80,7 +79,6 @@ public class PlaceUtils{ /** * Normalizes a placement area and returns the result. * Returned x2 and y2 will always be greater than x and y. - * * @param tilex starting X coordinate * @param tiley starting Y coordinate * @param endx ending X coordinate diff --git a/core/src/io/anuke/mindustry/io/BundleLoader.java b/core/src/io/anuke/mindustry/io/BundleLoader.java index ba11207bf1..14cb5e3e67 100644 --- a/core/src/io/anuke/mindustry/io/BundleLoader.java +++ b/core/src/io/anuke/mindustry/io/BundleLoader.java @@ -2,10 +2,8 @@ package io.anuke.mindustry.io; import io.anuke.arc.Core; import io.anuke.arc.files.FileHandle; -import io.anuke.arc.util.I18NBundle; +import io.anuke.arc.util.*; import io.anuke.mindustry.Vars; -import io.anuke.arc.util.Time; -import io.anuke.arc.util.Log; import io.anuke.mindustry.input.Binding; import java.util.Locale; diff --git a/core/src/io/anuke/mindustry/io/Changelogs.java b/core/src/io/anuke/mindustry/io/Changelogs.java index 6dfcf6ce3c..33d888be47 100644 --- a/core/src/io/anuke/mindustry/io/Changelogs.java +++ b/core/src/io/anuke/mindustry/io/Changelogs.java @@ -44,11 +44,11 @@ public class Changelogs{ @Override public String toString(){ return "VersionInfo{" + - "name='" + name + '\'' + - ", description='" + description + '\'' + - ", id=" + id + - ", build=" + build + - '}'; + "name='" + name + '\'' + + ", description='" + description + '\'' + + ", id=" + id + + ", build=" + build + + '}'; } } } diff --git a/core/src/io/anuke/mindustry/io/Contributors.java b/core/src/io/anuke/mindustry/io/Contributors.java index 9924e8e44c..13e3a3dad1 100644 --- a/core/src/io/anuke/mindustry/io/Contributors.java +++ b/core/src/io/anuke/mindustry/io/Contributors.java @@ -36,8 +36,8 @@ public class Contributors{ @Override public String toString(){ return "Contributor{" + - "login='" + login + '\'' + - '}'; + "login='" + login + '\'' + + '}'; } } } diff --git a/core/src/io/anuke/mindustry/io/MapIO.java b/core/src/io/anuke/mindustry/io/MapIO.java index 6db9e18a2f..5d925a8899 100644 --- a/core/src/io/anuke/mindustry/io/MapIO.java +++ b/core/src/io/anuke/mindustry/io/MapIO.java @@ -10,17 +10,12 @@ import io.anuke.arc.graphics.Pixmap.Format; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.*; import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.game.MappableContent; -import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.game.Version; +import io.anuke.mindustry.game.*; import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.CachedTile; -import io.anuke.mindustry.world.LegacyColorMapper; +import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.LegacyColorMapper.LegacyBlock; -import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.BlockPart; import io.anuke.mindustry.world.blocks.Floor; @@ -32,7 +27,7 @@ import java.util.zip.InflaterInputStream; import static io.anuke.mindustry.Vars.bufferSize; import static io.anuke.mindustry.Vars.content; -/** Reads and writes map files.*/ +/** Reads and writes map files. */ public class MapIO{ public static final int version = 1; @@ -44,13 +39,13 @@ public class MapIO{ //stainedRocks, stainedRocksRed, stainedRocksYellow, stainedStoneYellow, stainedBoulder, missingBlocks = ObjectMap.of( - "stained-stone", Blocks.shale, - "stained-stone-red", Blocks.shale, - "stained-stone-yellow", Blocks.shale, - "stained-rocks", Blocks.shaleRocks, - "stained-boulder", Blocks.shaleBoulder, - "stained-rocks-red", Blocks.shaleRocks, - "stained-rocks-yellow", Blocks.shaleRocks + "stained-stone", Blocks.shale, + "stained-stone-red", Blocks.shale, + "stained-stone-yellow", Blocks.shale, + "stained-rocks", Blocks.shaleRocks, + "stained-boulder", Blocks.shaleBoulder, + "stained-rocks-red", Blocks.shaleRocks, + "stained-rocks-yellow", Blocks.shaleRocks ); } @@ -69,25 +64,30 @@ public class MapIO{ public static Pixmap generatePreview(Map map) throws IOException{ Time.mark(); - Pixmap floor = new Pixmap(map.width, map.height, Format.RGBA8888); - Pixmap wall = new Pixmap(map.width, map.height, Format.RGBA8888); + Pixmap floors = new Pixmap(map.width, map.height, Format.RGBA8888); + Pixmap walls = new Pixmap(map.width, map.height, Format.RGBA8888); int black = Color.rgba8888(Color.BLACK); + int shade = Color.rgba8888(0f, 0f, 0f, 0.5f); CachedTile tile = new CachedTile(){ @Override public void setFloor(Floor type){ - floor.drawPixel(x, floor.getHeight() - 1 - y, colorFor(type, Blocks.air, Blocks.air, getTeam())); + floors.drawPixel(x, floors.getHeight() - 1 - y, colorFor(type, Blocks.air, Blocks.air, getTeam())); } @Override - public void setOreByte(byte b){ - if(b != 0) floor.drawPixel(x, floor.getHeight() - 1 - y, colorFor(floor(), Blocks.air, content.block(b), getTeam())); + public void setOverlayID(byte b){ + if(b != 0) + floors.drawPixel(x, floors.getHeight() - 1 - y, colorFor(floor(), Blocks.air, content.block(b), getTeam())); } @Override protected void changed(){ super.changed(); int c = colorFor(Blocks.air, block(), Blocks.air, getTeam()); - if(c != black) wall.drawPixel(x, floor.getHeight() - 1 - y, c); + if(c != black){ + walls.drawPixel(x, floors.getHeight() - 1 - y, c); + floors.drawPixel(x, floors.getHeight() - 1 - y + 1, shade); + } } }; readTiles(map, (x, y) -> { @@ -95,9 +95,9 @@ public class MapIO{ tile.y = (short)y; return tile; }); - floor.drawPixmap(wall, 0, 0); - wall.dispose(); - return floor; + floors.drawPixmap(walls, 0, 0); + walls.dispose(); + return floors; } public static Pixmap generatePreview(Tile[][] tiles){ @@ -105,7 +105,7 @@ public class MapIO{ for(int x = 0; x < pixmap.getWidth(); x++){ for(int y = 0; y < pixmap.getHeight(); y++){ Tile tile = tiles[x][y]; - pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, colorFor(tile.floor(), tile.block(), tile.ore(), tile.getTeam())); + pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, colorFor(tile.floor(), tile.block(), tile.overlay(), tile.getTeam())); } } return pixmap; @@ -144,13 +144,13 @@ public class MapIO{ for(int i = 0; i < tiles.length * tiles[0].length; i++){ Tile tile = tiles[i % width][i / width]; stream.writeByte(tile.getFloorID()); - stream.writeByte(tile.getOreByte()); + stream.writeByte(tile.getOverlayID()); int consecutives = 0; for(int j = i + 1; j < width * height && consecutives < 255; j++){ Tile nextTile = tiles[j % width][j / width]; - if(nextTile.getFloorID() != tile.getFloorID() || nextTile.block() != Blocks.air || nextTile.getOreByte() != tile.getOreByte()){ + if(nextTile.getFloorID() != tile.getFloorID() || nextTile.block() != Blocks.air || nextTile.getOverlayID() != tile.getOverlayID()){ break; } @@ -167,7 +167,7 @@ public class MapIO{ stream.writeByte(tile.getBlockID()); if(tile.block() instanceof BlockPart){ - stream.writeByte(tile.link); + stream.writeByte(tile.getLinkByte()); }else if(tile.entity != null){ stream.writeByte(Pack.byteByte(tile.getTeamID(), tile.getRotation())); //team + rotation stream.writeShort(/*(short)tile.entity.health*/tile.block().health); //health @@ -216,12 +216,12 @@ public class MapIO{ } } - /**Reads tiles from a map, version-agnostic.*/ + /** Reads tiles from a map, version-agnostic. */ public static void readTiles(Map map, Tile[][] tiles) throws IOException{ readTiles(map, (x, y) -> tiles[x][y]); } - /**Reads tiles from a map, version-agnostic.*/ + /** Reads tiles from a map, version-agnostic. */ public static void readTiles(Map map, TileProvider tiles) throws IOException{ if(map.version == 0){ readLegacyMmapTiles(map.file, tiles); @@ -232,12 +232,12 @@ public class MapIO{ } } - /**Reads tiles from a map in the new build-65 format.*/ + /** Reads tiles from a map in the new build-65 format. */ private static void readTiles(FileHandle file, int width, int height, Tile[][] tiles) throws IOException{ readTiles(file, width, height, (x, y) -> tiles[x][y]); } - /**Reads tiles from a map in the new build-65 format.*/ + /** Reads tiles from a map in the new build-65 format. */ private static void readTiles(FileHandle file, int width, int height, TileProvider tiles) throws IOException{ try(BufferedInputStream input = file.read(bufferSize)){ @@ -272,13 +272,13 @@ public class MapIO{ Tile tile = tiles.get(x, y); tile.setFloor((Floor)content.block(floorid)); - tile.setOre(content.block(oreid)); + tile.setOverlay(content.block(oreid)); for(int j = i + 1; j < i + 1 + consecutives; j++){ int newx = j % width, newy = j / width; Tile newTile = tiles.get(newx, newy); newTile.setFloor((Floor)content.block(floorid)); - newTile.setOre(content.block(oreid)); + newTile.setOverlay(content.block(oreid)); } i += consecutives; @@ -293,7 +293,7 @@ public class MapIO{ tile.setBlock(block); if(block == Blocks.part){ - tile.link = stream.readByte(); + tile.setLinkByte(stream.readByte()); }else if(tile.entity != null){ byte tr = stream.readByte(); short health = stream.readShort(); @@ -327,7 +327,7 @@ public class MapIO{ //region legacy IO - /**Reads a pixmap in the 3.5 pixmap format.*/ + /** Reads a pixmap in the 3.5 pixmap format. */ public static void readLegacyPixmap(Pixmap pixmap, Tile[][] tiles){ for(int x = 0; x < pixmap.getWidth(); x++){ for(int y = 0; y < pixmap.getHeight(); y++){ @@ -337,7 +337,7 @@ public class MapIO{ tile.setFloor(block.floor); tile.setBlock(block.wall); - if(block.ore != null) tile.setOre(block.ore); + if(block.ore != null) tile.setOverlay(block.ore); //place core if(color == Color.rgba8888(Color.GREEN)){ @@ -351,7 +351,7 @@ public class MapIO{ Tile write = tiles[worldx][worldy]; write.setBlock(Blocks.part); write.setTeam(Team.blue); - write.setLinkByte(Pack.byteByte((byte) (dx - 1 + 8), (byte) (dy - 1 + 8))); + write.setLinkByte(Pack.byteByte((byte)(dx - 1 + 8), (byte)(dy - 1 + 8))); } } } @@ -364,12 +364,12 @@ public class MapIO{ } } - /**Reads a pixmap in the old 4.0 .mmap format.*/ + /** Reads a pixmap in the old 4.0 .mmap format. */ private static void readLegacyMmapTiles(FileHandle file, Tile[][] tiles) throws IOException{ readLegacyMmapTiles(file, (x, y) -> tiles[x][y]); } - /**Reads a mmap in the old 4.0 .mmap format.*/ + /** Reads a mmap in the old 4.0 .mmap format. */ private static void readLegacyMmapTiles(FileHandle file, TileProvider tiles) throws IOException{ try(DataInputStream stream = new DataInputStream(file.read(bufferSize))){ stream.readInt(); //version @@ -437,7 +437,7 @@ public class MapIO{ } if(oreMap.containsKey(floorb)){ - tile.setOre(content.block(oreMap.get(floorb, 0))); + tile.setOverlay(content.block(oreMap.get(floorb, 0))); } } } diff --git a/core/src/io/anuke/mindustry/io/SaveFileVersion.java b/core/src/io/anuke/mindustry/io/SaveFileVersion.java index 289f7b85b1..0cbe383901 100644 --- a/core/src/io/anuke/mindustry/io/SaveFileVersion.java +++ b/core/src/io/anuke/mindustry/io/SaveFileVersion.java @@ -5,21 +5,14 @@ import io.anuke.arc.util.Pack; import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.entities.Entities; import io.anuke.mindustry.entities.EntityGroup; -import io.anuke.mindustry.entities.traits.Entity; -import io.anuke.mindustry.entities.traits.SaveTrait; -import io.anuke.mindustry.entities.traits.TypeTrait; -import io.anuke.mindustry.game.Content; -import io.anuke.mindustry.game.MappableContent; -import io.anuke.mindustry.game.Rules; -import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.entities.traits.*; +import io.anuke.mindustry.game.*; import io.anuke.mindustry.gen.Serialization; import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.content; import static io.anuke.mindustry.Vars.world; @@ -36,7 +29,7 @@ public abstract class SaveFileVersion{ long playtime = stream.readLong(); int build = stream.readInt(); - Rules rules = Serialization.readRules(stream); + Rules rules = Serialization.readRulesStreamJson(stream); String map = stream.readUTF(); int wave = stream.readInt(); return new SaveMeta(version, time, playtime, build, map, wave, rules); @@ -51,13 +44,13 @@ public abstract class SaveFileVersion{ for(int i = 0; i < world.width() * world.height(); i++){ Tile tile = world.tile(i % world.width(), i / world.width()); stream.writeByte(tile.getFloorID()); - stream.writeByte(tile.getOreByte()); + stream.writeByte(tile.getOverlayID()); int consecutives = 0; for(int j = i + 1; j < world.width() * world.height() && consecutives < 255; j++){ Tile nextTile = world.tile(j % world.width(), j / world.width()); - if(nextTile.getFloorID() != tile.getFloorID() || nextTile.getOreByte() != tile.getOreByte()){ + if(nextTile.getFloorID() != tile.getFloorID() || nextTile.getOverlayID() != tile.getOverlayID()){ break; } @@ -74,10 +67,10 @@ public abstract class SaveFileVersion{ stream.writeByte(tile.getBlockID()); if(tile.block() == Blocks.part){ - stream.writeByte(tile.link); + stream.writeByte(tile.getLinkByte()); }else if(tile.entity != null){ stream.writeByte(Pack.byteByte(tile.getTeamID(), tile.getRotation())); //team + rotation - stream.writeShort((short) tile.entity.health); //health + stream.writeShort((short)tile.entity.health); //health if(tile.entity.items != null) tile.entity.items.write(stream); if(tile.entity.power != null) tile.entity.power.write(stream); @@ -123,12 +116,12 @@ public abstract class SaveFileVersion{ Block ore = content.block(oreid); tiles[x][y] = new Tile(x, y, floorid, (byte)0); - tiles[x][y].setOre(ore); + tiles[x][y].setOverlay(ore); for(int j = i + 1; j < i + 1 + consecutives; j++){ int newx = j % width, newy = j / width; Tile newTile = new Tile(newx, newy, floorid, (byte)0); - newTile.setOre(ore); + newTile.setOverlay(ore); tiles[newx][newy] = newTile; } @@ -143,7 +136,7 @@ public abstract class SaveFileVersion{ tile.setBlock(block); if(block == Blocks.part){ - tile.link = stream.readByte(); + tile.setLinkByte(stream.readByte()); }else if(tile.entity != null){ byte tr = stream.readByte(); short health = stream.readShort(); @@ -193,8 +186,8 @@ public abstract class SaveFileVersion{ if(!group.isEmpty() && group.all().get(0) instanceof SaveTrait){ stream.writeInt(group.size()); for(Entity entity : group.all()){ - stream.writeByte(((SaveTrait) entity).getTypeID()); - ((SaveTrait) entity).writeSave(stream); + stream.writeByte(((SaveTrait)entity).getTypeID()); + ((SaveTrait)entity).writeSave(stream); } } } @@ -207,7 +200,7 @@ public abstract class SaveFileVersion{ int amount = stream.readInt(); for(int j = 0; j < amount; j++){ byte typeid = stream.readByte(); - SaveTrait trait = (SaveTrait) TypeTrait.getTypeByID(typeid).get(); + SaveTrait trait = (SaveTrait)TypeTrait.getTypeByID(typeid).get(); trait.readSave(stream); } } @@ -219,12 +212,12 @@ public abstract class SaveFileVersion{ MappableContent[][] map = new MappableContent[ContentType.values().length][0]; - for (int i = 0; i < mapped; i++) { + for(int i = 0; i < mapped; i++){ ContentType type = ContentType.values()[stream.readByte()]; short total = stream.readShort(); map[type.ordinal()] = new MappableContent[total]; - for (int j = 0; j < total; j++) { + for(int j = 0; j < total; j++){ String name = stream.readUTF(); map[type.ordinal()][j] = content.getByName(type, name); } @@ -249,7 +242,7 @@ public abstract class SaveFileVersion{ stream.writeByte(arr.first().getContentType().ordinal()); stream.writeShort(arr.size); for(Content c : arr){ - stream.writeUTF(((MappableContent) c).name); + stream.writeUTF(((MappableContent)c).name); } } } diff --git a/core/src/io/anuke/mindustry/io/SaveIO.java b/core/src/io/anuke/mindustry/io/SaveIO.java index f7c5b50320..ad6231d118 100644 --- a/core/src/io/anuke/mindustry/io/SaveIO.java +++ b/core/src/io/anuke/mindustry/io/SaveIO.java @@ -1,11 +1,9 @@ package io.anuke.mindustry.io; -import io.anuke.arc.collection.Array; -import io.anuke.arc.collection.IntArray; -import io.anuke.arc.collection.IntMap; +import io.anuke.arc.collection.*; import io.anuke.arc.files.FileHandle; import io.anuke.mindustry.Vars; -import io.anuke.mindustry.io.versions.Save16; +import io.anuke.mindustry.io.versions.Save1; import java.io.*; import java.util.zip.DeflaterOutputStream; @@ -17,9 +15,7 @@ import static io.anuke.mindustry.Vars.*; public class SaveIO{ public static final IntArray breakingVersions = IntArray.with(47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 63); public static final IntMap versions = new IntMap<>(); - public static final Array versionArray = Array.with( - new Save16() - ); + public static final Array versionArray = Array.with(new Save1()); static{ for(SaveFileVersion version : versionArray){ @@ -98,7 +94,7 @@ public class SaveIO{ write(new DeflaterOutputStream(file.write(false, bufferSize)){ byte[] tmp = {0}; - public void write(int var1) throws IOException { + public void write(int var1) throws IOException{ tmp[0] = (byte)(var1 & 255); this.write(tmp, 0, 1); } diff --git a/core/src/io/anuke/mindustry/io/TypeIO.java b/core/src/io/anuke/mindustry/io/TypeIO.java index c88bce34eb..367207d9b9 100644 --- a/core/src/io/anuke/mindustry/io/TypeIO.java +++ b/core/src/io/anuke/mindustry/io/TypeIO.java @@ -10,28 +10,19 @@ import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.bullet.BulletType; import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest; import io.anuke.mindustry.entities.traits.ShooterTrait; -import io.anuke.mindustry.entities.type.BaseUnit; -import io.anuke.mindustry.entities.type.Player; -import io.anuke.mindustry.entities.type.Unit; +import io.anuke.mindustry.entities.type.*; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.net.Packets.AdminAction; import io.anuke.mindustry.net.Packets.KickReason; -import io.anuke.mindustry.type.ContentType; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.Liquid; -import io.anuke.mindustry.type.Mech; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Pos; -import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.type.*; +import io.anuke.mindustry.world.*; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import java.nio.ByteBuffer; import static io.anuke.mindustry.Vars.*; -/** Class for specifying read/write methods for code generation.*/ +/** Class for specifying read/write methods for code generation. */ @SuppressWarnings("unused") public class TypeIO{ @@ -56,7 +47,7 @@ public class TypeIO{ buffer.put((byte)-1); return; } - buffer.put((byte) unit.getGroup().getID()); + buffer.put((byte)unit.getGroup().getID()); buffer.putInt(unit.getID()); } @@ -65,12 +56,12 @@ public class TypeIO{ byte gid = buffer.get(); if(gid == -1) return null; int id = buffer.getInt(); - return (Unit) Entities.getGroup(gid).getByID(id); + return (Unit)Entities.getGroup(gid).getByID(id); } @WriteClass(ShooterTrait.class) public static void writeShooter(ByteBuffer buffer, ShooterTrait trait){ - buffer.put((byte) trait.getGroup().getID()); + buffer.put((byte)trait.getGroup().getID()); buffer.putInt(trait.getID()); } @@ -78,7 +69,7 @@ public class TypeIO{ public static ShooterTrait readShooter(ByteBuffer buffer){ byte gid = buffer.get(); int id = buffer.getInt(); - return (ShooterTrait) Entities.getGroup(gid).getByID(id); + return (ShooterTrait)Entities.getGroup(gid).getByID(id); } @WriteClass(Bullet.class) @@ -94,7 +85,7 @@ 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)unitGroups[unit.getTeam().ordinal()].getID()); buffer.putInt(unit.getID()); } @@ -102,7 +93,7 @@ public class TypeIO{ public static BaseUnit writeBaseUnit(ByteBuffer buffer){ byte gid = buffer.get(); int id = buffer.getInt(); - return (BaseUnit) Entities.getGroup(gid).getByID(id); + return (BaseUnit)Entities.getGroup(gid).getByID(id); } @WriteClass(Tile.class) @@ -129,11 +120,11 @@ public class TypeIO{ public static void writeRequests(ByteBuffer buffer, BuildRequest[] requests){ buffer.putShort((short)requests.length); for(BuildRequest request : requests){ - buffer.put(request.breaking ? (byte) 1 : 0); + buffer.put(request.breaking ? (byte)1 : 0); buffer.putInt(Pos.get(request.x, request.y)); if(!request.breaking){ buffer.put(request.block.id); - buffer.put((byte) request.rotation); + buffer.put((byte)request.rotation); } } } @@ -163,7 +154,7 @@ public class TypeIO{ @WriteClass(KickReason.class) public static void writeKick(ByteBuffer buffer, KickReason reason){ - buffer.put((byte) reason.ordinal()); + buffer.put((byte)reason.ordinal()); } @ReadClass(KickReason.class) @@ -173,7 +164,7 @@ public class TypeIO{ @WriteClass(Team.class) public static void writeTeam(ByteBuffer buffer, Team reason){ - buffer.put((byte) reason.ordinal()); + buffer.put((byte)reason.ordinal()); } @ReadClass(Team.class) @@ -183,7 +174,7 @@ public class TypeIO{ @WriteClass(AdminAction.class) public static void writeAction(ByteBuffer buffer, AdminAction reason){ - buffer.put((byte) reason.ordinal()); + buffer.put((byte)reason.ordinal()); } @ReadClass(AdminAction.class) @@ -193,7 +184,7 @@ public class TypeIO{ @WriteClass(Effect.class) public static void writeEffect(ByteBuffer buffer, Effect effect){ - buffer.putShort((short) effect.id); + buffer.putShort((short)effect.id); } @ReadClass(Effect.class) @@ -256,10 +247,10 @@ public class TypeIO{ public static void writeString(ByteBuffer buffer, String string){ if(string != null){ byte[] bytes = string.getBytes(charset); - buffer.putShort((short) bytes.length); + buffer.putShort((short)bytes.length); buffer.put(bytes); }else{ - buffer.putShort((short) -1); + buffer.putShort((short)-1); } } @@ -277,7 +268,7 @@ public class TypeIO{ @WriteClass(byte[].class) public static void writeBytes(ByteBuffer buffer, byte[] bytes){ - buffer.putShort((short) bytes.length); + buffer.putShort((short)bytes.length); buffer.put(bytes); } @@ -292,10 +283,10 @@ public class TypeIO{ public static void writeStringData(DataOutput buffer, String string) throws IOException{ if(string != null){ byte[] bytes = string.getBytes(charset); - buffer.writeShort((short) bytes.length); + buffer.writeShort((short)bytes.length); buffer.write(bytes); }else{ - buffer.writeShort((short) -1); + buffer.writeShort((short)-1); } } diff --git a/core/src/io/anuke/mindustry/io/versions/Save16.java b/core/src/io/anuke/mindustry/io/versions/Save1.java similarity index 87% rename from core/src/io/anuke/mindustry/io/versions/Save16.java rename to core/src/io/anuke/mindustry/io/versions/Save1.java index 466da0d648..438da9feae 100644 --- a/core/src/io/anuke/mindustry/io/versions/Save16.java +++ b/core/src/io/anuke/mindustry/io/versions/Save1.java @@ -7,16 +7,14 @@ import io.anuke.mindustry.gen.Serialization; import io.anuke.mindustry.io.SaveFileVersion; import io.anuke.mindustry.maps.Map; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.*; -public class Save16 extends SaveFileVersion{ +public class Save1 extends SaveFileVersion{ - public Save16(){ - super(16); + public Save1(){ + super(1); } @Override @@ -26,7 +24,7 @@ public class Save16 extends SaveFileVersion{ stream.readInt(); //build //general state - state.rules = Serialization.readRules(stream); + state.rules = Serialization.readRulesStreamJson(stream); String mapname = stream.readUTF(); Map map = world.maps.all().find(m -> m.name().equals(mapname)); if(map == null) map = new Map(customMapDirectory.child(mapname), 1, 1, new ObjectMap<>(), true); @@ -56,7 +54,7 @@ public class Save16 extends SaveFileVersion{ stream.writeInt(Version.build); //build //--GENERAL STATE-- - Serialization.writeRules(stream, state.rules); + Serialization.writeRulesStreamJson(stream, state.rules); stream.writeUTF(world.getMap().name()); //map name stream.writeInt(state.wave); //wave diff --git a/core/src/io/anuke/mindustry/maps/Map.java b/core/src/io/anuke/mindustry/maps/Map.java index b97f30a91e..83f4d5f02d 100644 --- a/core/src/io/anuke/mindustry/maps/Map.java +++ b/core/src/io/anuke/mindustry/maps/Map.java @@ -14,19 +14,19 @@ import io.anuke.mindustry.io.MapIO; import static io.anuke.mindustry.Vars.world; public class Map implements Comparable{ - /** Whether this is a custom map.*/ + /** Whether this is a custom map. */ public final boolean custom; - /** Metadata. Author description, display name, etc.*/ + /** Metadata. Author description, display name, etc. */ public final ObjectMap tags; - /** Base file of this map. File can be named anything at all.*/ + /** Base file of this map. File can be named anything at all. */ public final FileHandle file; - /** Format version.*/ + /** Format version. */ public final int version; - /** Map width/height, shorts.*/ + /** Map width/height, shorts. */ public int width, height; - /** Preview texture.*/ + /** Preview texture. */ public Texture texture; - /** Build that this map was created in. -1 = unknown or custom build.*/ + /** Build that this map was created in. -1 = unknown or custom build. */ public int build; public Map(FileHandle file, int width, int height, ObjectMap tags, boolean custom, int version, int build){ @@ -83,7 +83,7 @@ public class Map implements Comparable{ } public String tag(String name){ - return tags.containsKey(name) && !tags.get(name).trim().isEmpty() ? tags.get(name): Core.bundle.get("unknown"); + return tags.containsKey(name) && !tags.get(name).trim().isEmpty() ? tags.get(name) : Core.bundle.get("unknown"); } public boolean hasTag(String name){ @@ -103,9 +103,9 @@ public class Map implements Comparable{ @Override public String toString(){ return "Map{" + - "file='" + file + '\'' + - ", custom=" + custom + - ", tags=" + tags + - '}'; + "file='" + file + '\'' + + ", custom=" + custom + + ", tags=" + tags + + '}'; } } diff --git a/core/src/io/anuke/mindustry/maps/Maps.java b/core/src/io/anuke/mindustry/maps/Maps.java index ff5fc523cb..72ecba7c64 100644 --- a/core/src/io/anuke/mindustry/maps/Maps.java +++ b/core/src/io/anuke/mindustry/maps/Maps.java @@ -7,7 +7,6 @@ import io.anuke.arc.files.FileHandle; import io.anuke.arc.graphics.Texture; import io.anuke.arc.util.Disposable; import io.anuke.arc.util.Log; -import io.anuke.arc.util.Time; import io.anuke.arc.util.serialization.Json; import io.anuke.mindustry.game.SpawnGroup; import io.anuke.mindustry.io.MapIO; @@ -19,11 +18,11 @@ import java.io.StringWriter; import static io.anuke.mindustry.Vars.*; public class Maps implements Disposable{ - /** List of all built-in maps. Filenames only.*/ + /** List of all built-in maps. Filenames only. */ private static final String[] defaultMapNames = {"fortress"}; /** All maps stored in an ordered array. */ private Array maps = new Array<>(); - /** Serializer for meta.*/ + /** Serializer for meta. */ private Json json = new Json(); public Maps(){ @@ -65,7 +64,6 @@ public class Maps implements Disposable{ /** Load all maps. Should be called at application start. */ public void load(){ - Time.mark(); try{ for(String name : defaultMapNames){ FileHandle file = Core.files.internal("maps/" + name + "." + mapExtension); @@ -76,11 +74,17 @@ public class Maps implements Disposable{ } loadCustomMaps(); - Log.info("Time to load maps: {0}", Time.elapsed()); } - /** Save a custom map to the directory. This updates all values and stored data necessary. - * The tags are copied to prevent mutation later.*/ + public void reload(){ + dispose(); + load(); + } + + /** + * Save a custom map to the directory. This updates all values and stored data necessary. + * The tags are copied to prevent mutation later. + */ public void saveMap(ObjectMap baseTags, Tile[][] data){ try{ @@ -160,12 +164,12 @@ public class Maps implements Disposable{ return str == null ? null : str.equals("[]") ? new Array<>() : Array.with(json.fromJson(SpawnGroup[].class, str)); } - /** Find a new filename to put a map to.*/ + /** Find a new filename to put a map to. */ private FileHandle findFile(){ //find a map name that isn't used. int i = maps.size; while(customMapDirectory.child("map_" + i + "." + mapExtension).exists()){ - i ++; + i++; } return customMapDirectory.child("map_" + i + "." + mapExtension); } diff --git a/core/src/io/anuke/mindustry/maps/generators/BasicGenerator.java b/core/src/io/anuke/mindustry/maps/generators/BasicGenerator.java index 26a9d62ace..ffa17cd671 100644 --- a/core/src/io/anuke/mindustry/maps/generators/BasicGenerator.java +++ b/core/src/io/anuke/mindustry/maps/generators/BasicGenerator.java @@ -1,18 +1,26 @@ package io.anuke.mindustry.maps.generators; -import io.anuke.arc.collection.Array; +import io.anuke.arc.collection.*; +import io.anuke.arc.function.IntPositionConsumer; 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.Structs; import io.anuke.arc.util.noise.Simplex; import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.*; +import io.anuke.mindustry.world.blocks.Floor; -public class BasicGenerator extends RandomGenerator{ - private Array ores; - private Simplex sim = new Simplex(); - private Simplex sim2 = new Simplex(); +import java.util.PriorityQueue; - public BasicGenerator(int width, int height, Item... ores){ +public abstract class BasicGenerator extends RandomGenerator{ + protected static final DistanceHeuristic manhattan = (x1, y1, x2, y2) -> Math.abs(x1 - x2) + Math.abs(y1 - y2); + + protected Array ores; + protected Simplex sim = new Simplex(); + protected Simplex sim2 = new Simplex(); + + public BasicGenerator(int width, int height, Block... ores){ super(width, height); this.ores = Array.with(ores); } @@ -25,33 +33,231 @@ public class BasicGenerator extends RandomGenerator{ super.generate(tiles); } - @Override - public void generate(int x, int y){ - floor = Blocks.stone; + public void ores(Tile[][] tiles){ + pass(tiles, (x, y) -> { + if(ores != null){ + int offsetX = x - 4, offsetY = y + 23; + for(int i = ores.size - 1; i >= 0; i--){ + Block entry = ores.get(i); + if(Math.abs(0.5f - sim.octaveNoise2D(2, 0.7, 1f / (50 + i * 2), offsetX, offsetY + i*999)) > 0.23f && + Math.abs(0.5f - sim2.octaveNoise2D(1, 1, 1f / (40 + i * 4), offsetX, offsetY - i*999)) > 0.32f){ + ore = entry; + break; + } + } + } + }); + } - if(ores != null){ - int offsetX = x - 4, offsetY = y + 23; - for(int i = ores.size - 1; i >= 0; i--){ - Item entry = ores.get(i); - if(Math.abs(0.5f - sim.octaveNoise2D(2, 0.7, 1f / (50 + i * 2), offsetX, offsetY)) > 0.23f && - Math.abs(0.5f - sim2.octaveNoise2D(1, 1, 1f / (40 + i * 4), offsetX, offsetY)) > 0.32f){ + public void terrain(Tile[][] tiles, Block dst, float scl, float mag, float cmag){ + pass(tiles, (x, y) -> { + double rocks = sim.octaveNoise2D(5, 0.5, 1f / scl, x, y) * mag + + Mathf.dst((float)x / width, (float)y / height, 0.5f, 0.5f) * cmag; - //floor = OreBlock.get(floor, entry); - break; + double edgeDist = Math.min(x, Math.min(y, Math.min(Math.abs(x - (width - 1)), Math.abs(y - (height - 1))))); + double transition = 5; + if(edgeDist < transition){ + rocks += (transition - edgeDist) / transition / 1.5; + } + + if(rocks > 0.9){ + block =dst; + } + }); + } + + public void noise(Tile[][] tiles, Block floor, Block block, int octaves, float falloff, float scl, float threshold){ + sim.setSeed(Mathf.random(99999)); + pass(tiles, (x, y) -> { + if(sim.octaveNoise2D(octaves, falloff, 1f / scl, x, y) > threshold){ + Tile tile = tiles[x][y]; + this.floor = floor; + if(tile.block().solid){ + this.block = block; + } + } + }); + } + + public void overlay(Tile[][] tiles, Block floor, Block block, float chance, int octaves, float falloff, float scl, float threshold){ + sim.setSeed(Mathf.random(99999)); + pass(tiles, (x, y) -> { + if(sim.octaveNoise2D(octaves, falloff, 1f / scl, x, y) > threshold && Mathf.chance(chance) && tiles[x][y].floor() == floor){ + ore = block; + } + }); + } + + public void tech(Tile[][] tiles){ + Block[] blocks = {Blocks.darkPanel3}; + int secSize = 20; + pass(tiles, (x, y) -> { + int mx = x % secSize, my = y % secSize; + int sclx = x / secSize, scly = y / secSize; + if(noise(sclx, scly, 10f, 1f) > 0.63f && (mx == 0 || my == 0 || mx == secSize - 1 || my == secSize - 1)){ + if(Mathf.chance(noise(x + 0x231523, y, 40f, 1f))){ + floor = Structs.random(blocks); + if(Mathf.dst(mx, my, secSize/2, secSize/2) > secSize/2f + 2){ + floor = Blocks.darkPanel4; + } + } + + if(block.solid && Mathf.chance(0.7)){ + block = Blocks.darkMetal; + } + } + }); + } + + public void distort(Tile[][] tiles, float scl, float mag){ + Block[][] blocks = new Block[width][height]; + Floor[][] floors = new Floor[width][height]; + + each((x, y) -> { + float cx = x + noise(x, y, scl, mag) - mag / 2f, cy = y + noise(x, y + 1525215f, scl, mag) - mag / 2f; + Tile other = tiles[Mathf.clamp((int)cx, 0, width-1)][Mathf.clamp((int)cy, 0, height-1)]; + blocks[x][y] = other.block(); + floors[x][y] = other.floor(); + }); + + pass(tiles, (x, y) -> { + floor = floors[x][y]; + block = blocks[x][y]; + }); + } + + public void scatter(Tile[][] tiles, Block target, Block dst, float chance){ + pass(tiles, (x, y) -> { + if(!Mathf.chance(chance)) return; + if(floor == target){ + floor = dst; + }else if(block == target){ + block = dst; + } + }); + } + + public void each(IntPositionConsumer r){ + for(int x = 0; x < width; x++){ + for(int y = 0; y < height; y++){ + r.accept(x, y); + } + } + } + + protected float noise(float x, float y, float scl, float mag){ + return (float)sim2.octaveNoise2D(1f, 0f, 1f / scl, x + 0x361266f, y + 0x251259f) * mag; + } + + public void pass(Tile[][] tiles, IntPositionConsumer r){ + for(int x = 0; x < width; x++){ + for(int y = 0; y < height; y++){ + floor = tiles[x][y].floor(); + block = tiles[x][y].block(); + ore = tiles[x][y].overlay(); + r.accept(x, y); + tiles[x][y] = new Tile(x, y, floor.id, block.id); + tiles[x][y].setOverlay(ore); + } + } + } + + public void brush(Tile[][] tiles, Array path, int rad){ + path.each(tile -> erase(tiles, tile.x, tile.y, rad)); + } + + public void erase(Tile[][] tiles, int cx, int cy, int rad){ + for(int x = -rad; x <= rad; x++){ + for(int y = -rad; y <= rad; y++){ + int wx = cx + x, wy = cy + y; + if(Structs.inBounds(wx, wy, width, height) && Mathf.dst(x, y, 0, 0) <= rad){ + Tile other = tiles[wx][wy]; + other.setBlock(Blocks.air); + } + } + } + } + + public Array pathfind(Tile[][] tiles, int startX, int startY, int endX, int endY, TileHueristic th, DistanceHeuristic dh){ + Tile start = tiles[startX][startY]; + Tile end = tiles[endX][endY]; + GridBits closed = new GridBits(width, height); + IntFloatMap costs = new IntFloatMap(); + PriorityQueue queue = new PriorityQueue<>((a, b) -> Float.compare(costs.get(a.pos(), 0f) + dh.cost(a.x, a.y, end.x, end.y), costs.get(b.pos(), 0f) + dh.cost(b.x, b.y, end.x, end.y))); + queue.add(start); + boolean found = false; + while(!queue.isEmpty()){ + Tile next = queue.poll(); + float baseCost = costs.get(next.pos(), 0f); + if(next == end){ + found = true; + break; + } + closed.set(next.x, next.y); + for(Point2 point : Geometry.d4){ + int newx = next.x + point.x, newy = next.y + point.y; + if(Structs.inBounds(newx, newy, width, height)){ + Tile child = tiles[newx][newy]; + if(!closed.get(child.x, child.y)){ + closed.set(child.x, child.y); + child.setRotation(child.relativeTo(next.x, next.y)); + costs.put(child.pos(), th.cost(child) + baseCost); + queue.add(child); + } } } } - //rock outcrops - double rocks = sim.octaveNoise2D(3, 0.7, 1f / 70f, x, y); - double edgeDist = Math.min(x, Math.min(y, Math.min(Math.abs(x - (width - 1)), Math.abs(y - (height - 1))))); - double transition = 8; - if(edgeDist < transition){ - rocks += (transition - edgeDist) / transition / 1.5; + Array out = new Array<>(); + + if(!found) return out; + + Tile current = end; + while(current != start){ + out.add(current); + Point2 p = Geometry.d4(current.getRotation()); + current = tiles[current.x + p.x][current.y + p.y]; } - if(rocks > 0.64){ - block = Blocks.rocks; + out.reverse(); + + return out; + } + + public void inverseFloodFill(Tile[][] tiles, Tile start, Block block){ + IntArray arr = new IntArray(); + arr.add(start.pos()); + while(!arr.isEmpty()){ + int i = arr.pop(); + int x = Pos.x(i), y = Pos.y(i); + tiles[x][y].cost = 2; + for(Point2 point : Geometry.d4){ + int newx = x + point.x, newy = y + point.y; + if(Structs.inBounds(newx, newy, width, height)){ + Tile child = tiles[newx][newy]; + if(child.block() == Blocks.air && child.cost != 2){ + child.cost = 2; + arr.add(child.pos()); + } + } + } + } + + for(int x = 0; x < width; x ++){ + for(int y = 0; y < height; y++){ + Tile tile = tiles[x][y]; + if(tile.cost != 2 && tile.block() == Blocks.air){ + tile.setBlock(block); + } + } } } + + public interface DistanceHeuristic{ + float cost(int x1, int y1, int x2, int y2); + } + + public interface TileHueristic{ + float cost(Tile tile); + } } diff --git a/core/src/io/anuke/mindustry/maps/generators/Generator.java b/core/src/io/anuke/mindustry/maps/generators/Generator.java index a9d31fe87c..965c6cf0e7 100644 --- a/core/src/io/anuke/mindustry/maps/generators/Generator.java +++ b/core/src/io/anuke/mindustry/maps/generators/Generator.java @@ -5,16 +5,18 @@ import io.anuke.mindustry.world.Tile; public abstract class Generator{ public int width, height; + protected Loadout loadout; public Generator(int width, int height){ this.width = width; this.height = height; } - public Generator(){} + public Generator(){ + } public void init(Loadout loadout){ - + this.loadout = loadout; } public abstract void generate(Tile[][] tiles); diff --git a/core/src/io/anuke/mindustry/maps/generators/MapGenerator.java b/core/src/io/anuke/mindustry/maps/generators/MapGenerator.java index 96a904fc8c..46811f808f 100644 --- a/core/src/io/anuke/mindustry/maps/generators/MapGenerator.java +++ b/core/src/io/anuke/mindustry/maps/generators/MapGenerator.java @@ -26,15 +26,16 @@ public class MapGenerator extends Generator{ private Map map; private String mapName; private Array decorations = Array.with(new Decoration(Blocks.stone, Blocks.rock, 0.003f)); - private Loadout loadout; - /**How much the landscape is randomly distorted.*/ + /** How much the landscape is randomly distorted. */ public float distortion = 3; - /**The amount of final enemy spawns used. -1 to use everything in the map. - * This amount of enemy spawns is selected randomly from the map.*/ + /** + * The amount of final enemy spawns used. -1 to use everything in the map. + * This amount of enemy spawns is selected randomly from the map. + */ public int enemySpawns = -1; - /**Whether floor is distorted along with blocks.*/ + /** Whether floor is distorted along with blocks. */ public boolean distortFloor = false; - /**Items randomly added to containers and vaults.*/ + /** Items randomly added to containers and vaults. */ public ItemStack[] storageDrops = ItemStack.with(Items.copper, 300, Items.lead, 300, Items.silicon, 200, Items.graphite, 200, Items.blastCompound, 200); public MapGenerator(String mapName){ @@ -95,7 +96,7 @@ public class MapGenerator extends Generator{ tiles[x][y].setBlock(Blocks.air); } - if(tiles[x][y].block() == Blocks.spawn){ + if(tiles[x][y].block() == Blocks.spawn && enemySpawns != -1){ enemies.add(new Point2(x, y)); tiles[x][y].setBlock(Blocks.air); } @@ -124,7 +125,7 @@ public class MapGenerator extends Generator{ if(distortFloor){ tile.setFloor(tiles[newX][newY].floor()); - tile.setOre(tiles[newX][newY].ore()); + tile.setOverlay(tiles[newX][newY].overlay()); } for(Decoration decor : decorations){ @@ -167,7 +168,7 @@ public class MapGenerator extends Generator{ double dst = Mathf.dst(x, y); if(dst < frad && Structs.inBounds(wx, wy, tiles) && (dst <= rad || Mathf.chance(0.5))){ Tile tile = tiles[wx][wy]; - tile.clearOre(); + tile.clearOverlay(); } } } diff --git a/core/src/io/anuke/mindustry/maps/generators/RandomGenerator.java b/core/src/io/anuke/mindustry/maps/generators/RandomGenerator.java index 9692f0dc54..bacb5cbaea 100644 --- a/core/src/io/anuke/mindustry/maps/generators/RandomGenerator.java +++ b/core/src/io/anuke/mindustry/maps/generators/RandomGenerator.java @@ -1,13 +1,18 @@ package io.anuke.mindustry.maps.generators; +import io.anuke.arc.collection.ObjectMap; import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; +import static io.anuke.mindustry.Vars.customMapDirectory; +import static io.anuke.mindustry.Vars.world; + public abstract class RandomGenerator extends Generator{ protected Block floor; protected Block block; + protected Block ore; public RandomGenerator(int width, int height){ super(width, height); @@ -19,16 +24,23 @@ public abstract class RandomGenerator extends Generator{ for(int y = 0; y < height; y++){ floor = Blocks.air; block = Blocks.air; + ore = Blocks.air; generate(x, y); tiles[x][y] = new Tile(x, y, floor.id, block.id); + tiles[x][y].setOverlay(ore); } } - tiles[width/2][height/2].setBlock(Blocks.coreShard, Team.blue); - tiles[width/2][height/2 - 6].setBlock(Blocks.launchPad, Team.blue); + decorate(tiles); + + world.setMap(new Map(customMapDirectory.child("generated"), 0, 0, new ObjectMap<>(), true)); } - /**Sets {@link #floor} and {@link #block} to the correct values as output. - * Before this method is called, both are set to {@link Blocks#air} as defaults.*/ + public abstract void decorate(Tile[][] tiles); + + /** + * Sets {@link #floor} and {@link #block} to the correct values as output. + * Before this method is called, both are set to {@link Blocks#air} as defaults. + */ public abstract void generate(int x, int y); } diff --git a/core/src/io/anuke/mindustry/maps/zonegen/DesertWastesGenerator.java b/core/src/io/anuke/mindustry/maps/zonegen/DesertWastesGenerator.java new file mode 100644 index 0000000000..95ee943df3 --- /dev/null +++ b/core/src/io/anuke/mindustry/maps/zonegen/DesertWastesGenerator.java @@ -0,0 +1,47 @@ +package io.anuke.mindustry.maps.zonegen; + +import io.anuke.arc.math.Mathf; +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.maps.generators.BasicGenerator; +import io.anuke.mindustry.world.Tile; + +public class DesertWastesGenerator extends BasicGenerator{ + + public DesertWastesGenerator(int width, int height){ + super(width, height, Blocks.oreCopper, Blocks.oreLead, Blocks.oreCoal, Blocks.oreCopper); + } + + @Override + public void generate(int x, int y){ + floor = Blocks.sand; + } + + @Override + public void decorate(Tile[][] tiles){ + ores(tiles); + terrain(tiles, Blocks.sandRocks, 60f, 1.5f, 0.9f); + + int rand = 40; + int border = 25; + int spawnX = Mathf.clamp(30 + Mathf.range(rand), border, width - border), spawnY = Mathf.clamp(30 + Mathf.range(rand), border, height - border); + int endX = Mathf.clamp(width - 30 + Mathf.range(rand), border, width - border), endY = Mathf.clamp(height - 30 + Mathf.range(rand), border, height - border); + + brush(tiles, pathfind(tiles, spawnX, spawnY, endX, endY, tile -> tile.solid() ? 5f : 0f, manhattan), 6); + brush(tiles, pathfind(tiles, spawnX, spawnY, endX, endY, tile -> tile.solid() ? 4f : 0f + (float)sim.octaveNoise2D(1, 1, 1f / 40f, tile.x, tile.y) * 20, manhattan), 5); + + erase(tiles, endX, endY, 10); + erase(tiles, spawnX, spawnY, 20); + distort(tiles, 20f, 4f); + inverseFloodFill(tiles, tiles[spawnX][spawnY], Blocks.sandRocks); + + noise(tiles, Blocks.salt, Blocks.saltRocks, 5, 0.6f, 200f, 0.55f); + noise(tiles, Blocks.darksand, Blocks.duneRocks, 5, 0.7f, 120f, 0.5f); + + tech(tiles); + overlay(tiles, Blocks.sand, Blocks.pebbles, 0.15f, 5, 0.8f, 30f, 0.62f); + //scatter(tiles, Blocks.sandRocks, Blocks.creeptree, 1f); + + tiles[endX][endY].setBlock(Blocks.spawn); + loadout.setup(spawnX, spawnY); + } +} diff --git a/core/src/io/anuke/mindustry/maps/zonegen/OvergrowthGenerator.java b/core/src/io/anuke/mindustry/maps/zonegen/OvergrowthGenerator.java new file mode 100644 index 0000000000..c5317ac011 --- /dev/null +++ b/core/src/io/anuke/mindustry/maps/zonegen/OvergrowthGenerator.java @@ -0,0 +1,43 @@ +package io.anuke.mindustry.maps.zonegen; + +import io.anuke.arc.math.Mathf; +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.maps.generators.BasicGenerator; +import io.anuke.mindustry.world.Tile; + +public class OvergrowthGenerator extends BasicGenerator{ + + public OvergrowthGenerator(int width, int height){ + super(width, height, Blocks.oreCopper, Blocks.oreLead, Blocks.oreCoal, Blocks.oreCopper); + } + + @Override + public void generate(int x, int y){ + floor = Blocks.moss; + } + + @Override + public void decorate(Tile[][] tiles){ + ores(tiles); + terrain(tiles, Blocks.sporePine, 70f, 1.4f, 1f); + + int rand = 40; + int border = 25; + int spawnX = Mathf.clamp(30 + Mathf.range(rand), border, width - border), spawnY = Mathf.clamp(30 + Mathf.range(rand), border, height - border); + int endX = Mathf.clamp(width - 30 + Mathf.range(rand), border, width - border), endY = Mathf.clamp(height - 30 + Mathf.range(rand), border, height - border); + + brush(tiles, pathfind(tiles, spawnX, spawnY, endX, endY, tile -> (tile.solid() ? 5f : 0f) + (float)sim.octaveNoise2D(1, 1, 1f / 50f, tile.x, tile.y) * 50, manhattan), 6); + brush(tiles, pathfind(tiles, spawnX, spawnY, endX, endY, tile -> (tile.solid() ? 4f : 0f) + (float)sim.octaveNoise2D(1, 1, 1f / 90f, tile.x+999, tile.y) * 70, manhattan), 5); + + erase(tiles, endX, endY, 10); + erase(tiles, spawnX, spawnY, 20); + distort(tiles, 20f, 4f); + inverseFloodFill(tiles, tiles[spawnX][spawnY], Blocks.sporerocks); + + noise(tiles, Blocks.darksandTaintedWater, Blocks.duneRocks, 4, 0.7f, 120f, 0.64f); + //scatter(tiles, Blocks.sporePine, Blocks.whiteTreeDead, 1f); + + tiles[endX][endY].setBlock(Blocks.spawn); + loadout.setup(spawnX, spawnY); + } +} diff --git a/core/src/io/anuke/mindustry/net/Administration.java b/core/src/io/anuke/mindustry/net/Administration.java index 52de0350f5..81f729fd67 100644 --- a/core/src/io/anuke/mindustry/net/Administration.java +++ b/core/src/io/anuke/mindustry/net/Administration.java @@ -2,21 +2,19 @@ package io.anuke.mindustry.net; import io.anuke.annotations.Annotations.Serialize; import io.anuke.arc.Core; -import io.anuke.arc.collection.Array; -import io.anuke.arc.collection.ObjectMap; -import io.anuke.arc.collection.ObjectSet; +import io.anuke.arc.collection.*; import static io.anuke.mindustry.Vars.headless; public class Administration{ - /**All player info. Maps UUIDs to info. This persists throughout restarts.*/ + /** All player info. Maps UUIDs to info. This persists throughout restarts. */ private ObjectMap playerInfo = new ObjectMap<>(); private Array bannedIPs = new Array<>(); public Administration(){ Core.settings.defaults( - "strict", true + "strict", true ); load(); @@ -40,7 +38,7 @@ public class Administration{ Core.settings.save(); } - /**Call when a player joins to update their information here.*/ + /** Call when a player joins to update their information here. */ public void updatePlayerJoined(String id, String ip, String name){ PlayerInfo info = getCreateInfo(id); info.lastName = name; @@ -74,7 +72,7 @@ public class Administration{ return true; } - /**Bans a player by UUID; returns whether this player was already banned.*/ + /** Bans a player by UUID; returns whether this player was already banned. */ public boolean banPlayerID(String id){ if(playerInfo.containsKey(id) && playerInfo.get(id).banned) return false; @@ -163,7 +161,7 @@ public class Administration{ public boolean adminPlayer(String id, String usid){ PlayerInfo info = getCreateInfo(id); - if(info.admin) + if(info.admin && info.adminUsid != null && info.adminUsid.equals(usid)) return false; info.adminUsid = usid; @@ -201,13 +199,13 @@ public class Administration{ return info.admin && usid.equals(info.adminUsid); } - /**Finds player info by IP, UUID and name.*/ + /** Finds player info by IP, UUID and name. */ public ObjectSet findByName(String name){ ObjectSet result = new ObjectSet<>(); for(PlayerInfo info : playerInfo.values()){ if(info.lastName.toLowerCase().equals(name.toLowerCase()) || (info.names.contains(name, false)) - || info.ips.contains(name, false) || info.id.equals(name)){ + || info.ips.contains(name, false) || info.id.equals(name)){ result.add(info); } } diff --git a/core/src/io/anuke/mindustry/net/Interpolator.java b/core/src/io/anuke/mindustry/net/Interpolator.java index b7b32b321a..0201f980ce 100644 --- a/core/src/io/anuke/mindustry/net/Interpolator.java +++ b/core/src/io/anuke/mindustry/net/Interpolator.java @@ -36,7 +36,6 @@ public class Interpolator{ } public void update(){ - if(lastUpdated != 0 && updateSpacing != 0){ float timeSinceUpdate = Time.timeSinceMillis(lastUpdated); float alpha = Math.min(timeSinceUpdate / updateSpacing, 2f); diff --git a/core/src/io/anuke/mindustry/net/Net.java b/core/src/io/anuke/mindustry/net/Net.java index e1a337c6d5..92448d9c90 100644 --- a/core/src/io/anuke/mindustry/net/Net.java +++ b/core/src/io/anuke/mindustry/net/Net.java @@ -1,12 +1,8 @@ package io.anuke.mindustry.net; import io.anuke.arc.Core; -import io.anuke.arc.Net.HttpRequest; -import io.anuke.arc.Net.HttpResponse; -import io.anuke.arc.Net.HttpResponseListener; -import io.anuke.arc.collection.Array; -import io.anuke.arc.collection.IntMap; -import io.anuke.arc.collection.ObjectMap; +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; @@ -15,9 +11,7 @@ import io.anuke.arc.util.Time; import io.anuke.arc.util.pooling.Pools; import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.net.Packets.KickReason; -import io.anuke.mindustry.net.Packets.StreamBegin; -import io.anuke.mindustry.net.Packets.StreamChunk; +import io.anuke.mindustry.net.Packets.*; import io.anuke.mindustry.net.Streamable.StreamBuilder; import java.io.IOException; @@ -47,7 +41,7 @@ public class Net{ return serverProvider != null; } - /**Display a network error. Call on the graphics thread.*/ + /** Display a network error. Call on the graphics thread. */ public static void showError(Throwable e){ if(!headless){ @@ -96,7 +90,6 @@ public class Net{ if(loaded){ //handle all packets that were skipped while loading for(int i = 0; i < packetQueue.size; i++){ - Log.info("Processing {0} packet post-load.", packetQueue.get(i).getClass()); handleClientReceived(packetQueue.get(i)); } } @@ -171,7 +164,7 @@ public class Net{ * Returns a list of all connections IDs. */ public static Array getConnections(){ - return (Array) serverProvider.getConnections(); + return (Array)serverProvider.getConnections(); } /** @@ -238,7 +231,7 @@ public class Net{ * Registers a server listener for when an object is recieved. */ public static void handleServer(Class type, BiConsumer listener){ - serverListeners.put(type, (BiConsumer) listener); + serverListeners.put(type, (BiConsumer)listener); } /** @@ -247,10 +240,10 @@ public class Net{ public static void handleClientReceived(Object object){ if(object instanceof StreamBegin){ - StreamBegin b = (StreamBegin) object; + StreamBegin b = (StreamBegin)object; streams.put(b.id, new StreamBuilder(b)); }else if(object instanceof StreamChunk){ - StreamChunk c = (StreamChunk) object; + StreamChunk c = (StreamChunk)object; StreamBuilder builder = streams.get(c.id); if(builder == null){ throw new RuntimeException("Recieved stream chunk without a StreamBegin beforehand!"); @@ -262,13 +255,12 @@ public class Net{ } }else if(clientListeners.get(object.getClass()) != null){ - if(clientLoaded || ((object instanceof Packet) && ((Packet) object).isImportant())){ + if(clientLoaded || ((object instanceof Packet) && ((Packet)object).isImportant())){ if(clientListeners.get(object.getClass()) != null) clientListeners.get(object.getClass()).accept(object); Pools.free(object); - }else if(!((object instanceof Packet) && ((Packet) object).isUnimportant())){ + }else if(!((object instanceof Packet) && ((Packet)object).isUnimportant())){ packetQueue.add(object); - Log.info("Queuing packet {0}", object); }else{ Pools.free(object); } @@ -371,24 +363,24 @@ public class Net{ tcp, udp } - /**Client implementation.*/ + /** Client implementation. */ public interface ClientProvider{ - /**Connect to a server.*/ + /** Connect to a server. */ void connect(String ip, int port, Runnable success) throws IOException; - /**Send an object to the server.*/ + /** Send an object to the server. */ void send(Object object, SendMode mode); - /**Update the ping. Should be done every second or so.*/ + /** Update the ping. Should be done every second or so. */ void updatePing(); - /**Get ping in milliseconds. Will only be valid after a call to updatePing.*/ + /** Get ping in milliseconds. Will only be valid after a call to updatePing. */ int getPing(); - /**Disconnect from the server.*/ + /** Disconnect from the server. */ void disconnect(); - /**Decompress an input snapshot byte array.*/ + /** Decompress an input snapshot byte array. */ byte[] decompressSnapshot(byte[] input, int size); /** @@ -398,43 +390,43 @@ public class Net{ */ void discover(Consumer callback, Runnable done); - /**Ping a host. If an error occured, failed() should be called with the exception.*/ + /** Ping a host. If an error occured, failed() should be called with the exception. */ void pingHost(String address, int port, Consumer valid, Consumer failed); - /**Close all connections.*/ + /** Close all connections. */ void dispose(); } - /**Server implementation.*/ + /** Server implementation. */ public interface ServerProvider{ - /**Host a server at specified port.*/ + /** Host a server at specified port. */ void host(int port) throws IOException; - /**Sends a large stream of data to a specific client.*/ + /** Sends a large stream of data to a specific client. */ void sendStream(int id, Streamable stream); - /**Send an object to everyone connected.*/ + /** Send an object to everyone connected. */ void send(Object object, SendMode mode); - /**Send an object to a specific client ID.*/ + /** Send an object to a specific client ID. */ void sendTo(int id, Object object, SendMode mode); - /**Send an object to everyone except a client ID.*/ + /** Send an object to everyone except a client ID. */ void sendExcept(int id, Object object, SendMode mode); - /**Close the server connection.*/ + /** Close the server connection. */ void close(); - /**Compress an input snapshot byte array.*/ + /** Compress an input snapshot byte array. */ byte[] compressSnapshot(byte[] input); - /**Return all connected users.*/ + /** Return all connected users. */ Array getConnections(); - /**Returns a connection by ID.*/ + /** Returns a connection by ID. */ NetConnection getByID(int id); - /**Close all connections.*/ + /** Close all connections. */ void dispose(); } } diff --git a/core/src/io/anuke/mindustry/net/NetConnection.java b/core/src/io/anuke/mindustry/net/NetConnection.java index d016c34442..2bb53fb9f7 100644 --- a/core/src/io/anuke/mindustry/net/NetConnection.java +++ b/core/src/io/anuke/mindustry/net/NetConnection.java @@ -9,9 +9,9 @@ public abstract class NetConnection{ public boolean modclient; public boolean mobile; - /**ID of last recieved client snapshot.*/ + /** ID of last recieved client snapshot. */ public int lastRecievedClientSnapshot = -1; - /**Timestamp of last recieved snapshot.*/ + /** Timestamp of last recieved snapshot. */ public long lastRecievedClientTime; public boolean hasConnected = false; diff --git a/core/src/io/anuke/mindustry/net/NetworkIO.java b/core/src/io/anuke/mindustry/net/NetworkIO.java index 45e46aae3b..19ca66cf53 100644 --- a/core/src/io/anuke/mindustry/net/NetworkIO.java +++ b/core/src/io/anuke/mindustry/net/NetworkIO.java @@ -6,10 +6,8 @@ import io.anuke.arc.collection.ObjectMap.Entry; import io.anuke.arc.util.Time; import io.anuke.mindustry.entities.Entities; import io.anuke.mindustry.entities.type.Player; -import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.game.Teams; +import io.anuke.mindustry.game.*; import io.anuke.mindustry.game.Teams.TeamData; -import io.anuke.mindustry.game.Version; import io.anuke.mindustry.gen.Serialization; import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.maps.Map; @@ -71,8 +69,6 @@ public class NetworkIO{ public static void loadWorld(InputStream is){ - Player player = players[0]; - try(DataInputStream stream = new DataInputStream(is)){ Time.clear(); @@ -127,7 +123,7 @@ public class NetworkIO{ state.teams.get(team).cores.add(world.tile(stream.readInt())); } - if(team == players[0].getTeam() && cores > 0){ + if(team == player.getTeam() && cores > 0){ Core.camera.position.set(state.teams.get(team).cores.first().drawx(), state.teams.get(team).cores.first().drawy()); } } @@ -140,7 +136,7 @@ public class NetworkIO{ public static ByteBuffer writeServerData(){ int maxlen = 32; - String host = (headless ? "Server" : players[0].name); + String host = (headless ? "Server" : player.name); String map = world.getMap() == null ? "None" : world.getMap().name(); host = host.substring(0, Math.min(host.length(), maxlen)); @@ -148,10 +144,10 @@ public class NetworkIO{ ByteBuffer buffer = ByteBuffer.allocate(128); - buffer.put((byte) host.getBytes(charset).length); + buffer.put((byte)host.getBytes(charset).length); buffer.put(host.getBytes(charset)); - buffer.put((byte) map.getBytes(charset).length); + buffer.put((byte)map.getBytes(charset).length); buffer.put(map.getBytes(charset)); buffer.putInt(playerGroup.size()); diff --git a/core/src/io/anuke/mindustry/net/Packets.java b/core/src/io/anuke/mindustry/net/Packets.java index 381df947c5..75d218cc11 100644 --- a/core/src/io/anuke/mindustry/net/Packets.java +++ b/core/src/io/anuke/mindustry/net/Packets.java @@ -76,7 +76,7 @@ public class Packets{ TypeIO.writeString(buffer, versionType); TypeIO.writeString(buffer, name); TypeIO.writeString(buffer, usid); - buffer.put(mobile ? (byte) 1 : 0); + buffer.put(mobile ? (byte)1 : 0); buffer.putInt(color); buffer.put(Base64Coder.decode(uuid)); } @@ -115,7 +115,7 @@ public class Packets{ public void write(ByteBuffer buffer){ buffer.put(type); buffer.put(priority); - buffer.putShort((short) writeLength); + buffer.putShort((short)writeLength); writeBuffer.position(0); for(int i = 0; i < writeLength; i++){ @@ -139,7 +139,7 @@ public class Packets{ } } - /**Marks the beginning of a stream.*/ + /** Marks the beginning of a stream. */ public static class StreamBegin implements Packet{ private static int lastid; @@ -169,7 +169,7 @@ public class Packets{ @Override public void write(ByteBuffer buffer){ buffer.putInt(id); - buffer.putShort((short) data.length); + buffer.putShort((short)data.length); buffer.put(data); } diff --git a/core/src/io/anuke/mindustry/net/Registrator.java b/core/src/io/anuke/mindustry/net/Registrator.java index 6430a686a9..cfbcffd163 100644 --- a/core/src/io/anuke/mindustry/net/Registrator.java +++ b/core/src/io/anuke/mindustry/net/Registrator.java @@ -6,11 +6,11 @@ import io.anuke.mindustry.net.Packets.*; public class Registrator{ private static ClassEntry[] classes = { - new ClassEntry(StreamBegin.class, StreamBegin::new), - new ClassEntry(StreamChunk.class, StreamChunk::new), - new ClassEntry(WorldStream.class, WorldStream::new), - new ClassEntry(ConnectPacket.class, ConnectPacket::new), - new ClassEntry(InvokePacket.class, InvokePacket::new) + new ClassEntry(StreamBegin.class, StreamBegin::new), + new ClassEntry(StreamChunk.class, StreamChunk::new), + new ClassEntry(WorldStream.class, WorldStream::new), + new ClassEntry(ConnectPacket.class, ConnectPacket::new), + new ClassEntry(InvokePacket.class, InvokePacket::new) }; private static ObjectIntMap ids = new ObjectIntMap<>(); @@ -26,7 +26,7 @@ public class Registrator{ } public static byte getID(Class type){ - return (byte) ids.get(type, -1); + return (byte)ids.get(type, -1); } public static ClassEntry[] getClasses(){ diff --git a/core/src/io/anuke/mindustry/net/Streamable.java b/core/src/io/anuke/mindustry/net/Streamable.java index 7ad7910149..9f2c3c0fbc 100644 --- a/core/src/io/anuke/mindustry/net/Streamable.java +++ b/core/src/io/anuke/mindustry/net/Streamable.java @@ -2,9 +2,7 @@ package io.anuke.mindustry.net; import io.anuke.mindustry.net.Packets.StreamBegin; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; +import java.io.*; public class Streamable implements Packet{ public transient ByteArrayInputStream stream; @@ -36,7 +34,7 @@ public class Streamable implements Packet{ } public Streamable build(){ - Streamable s = (Streamable) Registrator.getByID(type).constructor.get(); + Streamable s = (Streamable)Registrator.getByID(type).constructor.get(); s.stream = new ByteArrayInputStream(stream.toByteArray()); return s; } diff --git a/core/src/io/anuke/mindustry/type/Category.java b/core/src/io/anuke/mindustry/type/Category.java index 6e5f7a621a..a90bad9c64 100644 --- a/core/src/io/anuke/mindustry/type/Category.java +++ b/core/src/io/anuke/mindustry/type/Category.java @@ -1,24 +1,24 @@ package io.anuke.mindustry.type; public enum Category{ - /**Offensive turrets.*/ + /** Offensive turrets. */ turret, - /**Blocks that produce raw resources, such as drills.*/ + /** Blocks that produce raw resources, such as drills. */ production, - /**Blocks that move items around.*/ + /** Blocks that move items around. */ distribution, - /**Blocks that move liquids around.*/ + /** Blocks that move liquids around. */ liquid, - /**Blocks that generate or transport power.*/ + /** Blocks that generate or transport power. */ power, - /**Walls and other defensive structures.*/ + /** Walls and other defensive structures. */ defense, - /**Blocks that craft things.*/ + /** Blocks that craft things. */ crafting, - /**Blocks that create units.*/ + /** Blocks that create units. */ units, - /**Things that upgrade the player such as mech pads.*/ + /** Things that upgrade the player such as mech pads. */ upgrade, - /**Things for storage or passive effects.*/ + /** Things for storage or passive effects. */ effect } diff --git a/core/src/io/anuke/mindustry/type/ContentType.java b/core/src/io/anuke/mindustry/type/ContentType.java index c20ff0f310..125ccc8221 100644 --- a/core/src/io/anuke/mindustry/type/ContentType.java +++ b/core/src/io/anuke/mindustry/type/ContentType.java @@ -1,7 +1,7 @@ package io.anuke.mindustry.type; -/**Do not rearrange, ever!*/ -public enum ContentType { +/** Do not rearrange, ever! */ +public enum ContentType{ item, block, mech, diff --git a/core/src/io/anuke/mindustry/type/Item.java b/core/src/io/anuke/mindustry/type/Item.java index fea86c85bc..9c03431759 100644 --- a/core/src/io/anuke/mindustry/type/Item.java +++ b/core/src/io/anuke/mindustry/type/Item.java @@ -16,22 +16,22 @@ public class Item extends UnlockableContent implements Comparable{ public final Color color; private TextureRegion[] regions; - /**type of the item; used for tabs and core acceptance. default value is {@link ItemType#resource}.*/ + /** type of the item; used for tabs and core acceptance. default value is {@link ItemType#resource}. */ public ItemType type = ItemType.resource; - /**how explosive this item is.*/ + /** how explosive this item is. */ public float explosiveness = 0f; - /**flammability above 0.3 makes this eleigible for item burners.*/ + /** flammability above 0.3 makes this eleigible for item burners. */ public float flammability = 0f; - /**how radioactive this item is. 0=none, 1=chernobyl ground zero*/ + /** how radioactive this item is. 0=none, 1=chernobyl ground zero */ public float radioactivity; - /**drill hardness of the item*/ + /** drill hardness of the item */ public int hardness = 0; /** * base material cost of this item, used for calculating place times * 1 cost = 1 tick added to build time */ public float cost = 3f; - /**If true, item is always unlocked.*/ + /** If true, item is always unlocked. */ public boolean alwaysUnlocked = false; public Item(String name, Color color){ @@ -53,7 +53,7 @@ public class Item extends UnlockableContent implements Comparable{ } @Override - public boolean alwaysUnlocked() { + public boolean alwaysUnlocked(){ return alwaysUnlocked; } @@ -69,7 +69,7 @@ public class Item extends UnlockableContent implements Comparable{ @Override public TextureRegion getContentIcon(){ - return icon(Icon.large); + return icon(Icon.xlarge); } @Override @@ -88,10 +88,10 @@ public class Item extends UnlockableContent implements Comparable{ } public enum Icon{ - small(8*2), - medium(8*3), - large(8*4), - xlarge(8*5); + small(8 * 2), + medium(8 * 3), + large(8 * 4), + xlarge(8 * 5); public final int size; @@ -100,7 +100,7 @@ public class Item extends UnlockableContent implements Comparable{ } } - /**Allocates a new array containing all items the generate ores.*/ + /** Allocates a new array containing all items that generate ores. */ public static Array getAllOres(){ return content.blocks().select(b -> b instanceof OreBlock).map(b -> ((Floor)b).itemDrop); } diff --git a/core/src/io/anuke/mindustry/type/ItemStack.java b/core/src/io/anuke/mindustry/type/ItemStack.java index 47cfc87868..b99cf26069 100644 --- a/core/src/io/anuke/mindustry/type/ItemStack.java +++ b/core/src/io/anuke/mindustry/type/ItemStack.java @@ -16,16 +16,16 @@ public class ItemStack implements Comparable{ } public static ItemStack[] with(Object... items){ - ItemStack[] stacks = new ItemStack[items.length/2]; - for(int i = 0; i < items.length; i+= 2){ - stacks[i/2] = new ItemStack((Item)items[i], (Integer)items[i + 1]); + ItemStack[] stacks = new ItemStack[items.length / 2]; + for(int i = 0; i < items.length; i += 2){ + stacks[i / 2] = new ItemStack((Item)items[i], (Integer)items[i + 1]); } return stacks; } public static Array list(Object... items){ - Array stacks = new Array<>(items.length/2); - for(int i = 0; i < items.length; i+= 2){ + Array stacks = new Array<>(items.length / 2); + for(int i = 0; i < items.length; i += 2){ stacks.add(new ItemStack((Item)items[i], (Integer)items[i + 1])); } return stacks; diff --git a/core/src/io/anuke/mindustry/type/ItemType.java b/core/src/io/anuke/mindustry/type/ItemType.java index 320e0d0fce..40459f070e 100644 --- a/core/src/io/anuke/mindustry/type/ItemType.java +++ b/core/src/io/anuke/mindustry/type/ItemType.java @@ -1,8 +1,8 @@ package io.anuke.mindustry.type; public enum ItemType{ - /**Not used for anything besides crafting inside blocks.*/ + /** Not used for anything besides crafting inside blocks. */ resource, - /**Can be used for constructing blocks. Only materials are accepted into the core.*/ + /** Can be used for constructing blocks. Only materials are accepted into the core. */ material } diff --git a/core/src/io/anuke/mindustry/type/Liquid.java b/core/src/io/anuke/mindustry/type/Liquid.java index 2f04dfa787..bb3a0f363a 100644 --- a/core/src/io/anuke/mindustry/type/Liquid.java +++ b/core/src/io/anuke/mindustry/type/Liquid.java @@ -11,21 +11,21 @@ import io.anuke.mindustry.ui.ContentDisplay; public class Liquid extends UnlockableContent{ public final Color color; - /**0-1, 0 is completely inflammable, anything above that may catch fire when exposed to heat, 0.5+ is very flammable.*/ + /** 0-1, 0 is completely inflammable, anything above that may catch fire when exposed to heat, 0.5+ is very flammable. */ public float flammability; - /**temperature: 0.5 is 'room' temperature, 0 is very cold, 1 is molten hot*/ + /** temperature: 0.5 is 'room' temperature, 0 is very cold, 1 is molten hot */ public float temperature = 0.5f; - /**how much heat this liquid can store. 0.4=water (decent), anything lower is probably less dense and bad at cooling.*/ + /** how much heat this liquid can store. 0.4=water (decent), anything lower is probably less dense and bad at cooling. */ public float heatCapacity = 0.5f; - /**how thick this liquid is. 0.5=water (relatively viscous), 1 would be something like tar (very slow)*/ + /** how thick this liquid is. 0.5=water (relatively viscous), 1 would be something like tar (very slow) */ public float viscosity = 0.5f; - /**how prone to exploding this liquid is, when heated. 0 = nothing, 1 = nuke*/ + /** how prone to exploding this liquid is, when heated. 0 = nothing, 1 = nuke */ public float explosiveness; - /**the burning color of this liquid*/ + /** the burning color of this liquid */ public Color flameColor = Color.valueOf("ffb763"); - /**The associated status effect.*/ + /** The associated status effect. */ public StatusEffect effect = StatusEffects.none; - /**Displayed icon. TODO fix it by removing autogen, draw icons manually*/ + /** Displayed icon. TODO fix it by removing autogen, draw icons manually */ public TextureRegion iconRegion; public Liquid(String name, Color color){ diff --git a/core/src/io/anuke/mindustry/type/LiquidStack.java b/core/src/io/anuke/mindustry/type/LiquidStack.java new file mode 100644 index 0000000000..c4dcda7568 --- /dev/null +++ b/core/src/io/anuke/mindustry/type/LiquidStack.java @@ -0,0 +1,19 @@ +package io.anuke.mindustry.type; + +public class LiquidStack{ + public Liquid liquid; + public float amount; + + public LiquidStack(Liquid liquid, float amount){ + this.liquid = liquid; + this.amount = amount; + } + + @Override + public String toString(){ + return "LiquidStack{" + + "liquid=" + liquid + + ", amount=" + amount + + '}'; + } +} diff --git a/core/src/io/anuke/mindustry/type/Loadout.java b/core/src/io/anuke/mindustry/type/Loadout.java index 26303254b2..c322488fc4 100644 --- a/core/src/io/anuke/mindustry/type/Loadout.java +++ b/core/src/io/anuke/mindustry/type/Loadout.java @@ -4,9 +4,7 @@ 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.mindustry.world.Block; -import io.anuke.mindustry.world.Pos; -import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.blocks.storage.CoreBlock; import static io.anuke.mindustry.Vars.defaultTeam; @@ -34,7 +32,7 @@ public class Loadout extends Content{ int coreX = -1, coreY = -1; outer: - for(int y = 0; y < layout.length; y ++){ + for(int y = 0; y < layout.length; y++){ for(int x = 0; x < layout[0].length(); x++){ char c = layout[y].charAt(x); if(entries.get(c) != null && entries.get(c).block instanceof CoreBlock){ @@ -48,7 +46,7 @@ public class Loadout extends Content{ if(coreX == -1) throw new IllegalArgumentException("Schematic does not have a core."); - for(int y = 0; y < layout.length; y ++){ + for(int y = 0; y < layout.length; y++){ for(int x = 0; x < layout[0].length(); x++){ char c = layout[y].charAt(x); if(entries.containsKey(c)){ @@ -76,7 +74,7 @@ public class Loadout extends Content{ tile.setRotation((byte)entry.value.rotation); if(entry.value.ore != null){ for(Tile t : tile.getLinkedTiles(outArray)){ - t.setOre(entry.value.ore); + t.setOverlay(entry.value.ore); } } } diff --git a/core/src/io/anuke/mindustry/type/Mech.java b/core/src/io/anuke/mindustry/type/Mech.java index aa56ac67fc..1d9a7cb520 100644 --- a/core/src/io/anuke/mindustry/type/Mech.java +++ b/core/src/io/anuke/mindustry/type/Mech.java @@ -44,9 +44,11 @@ public class Mech extends UnlockableContent{ return Core.bundle.get("mech." + name + ".name"); } - public void updateAlt(Player player){} + public void updateAlt(Player player){ + } - public void draw(Player player){} + public void draw(Player player){ + } public float getExtraArmor(Player player){ return 0f; @@ -56,13 +58,16 @@ public class Mech extends UnlockableContent{ return 0f; } - public float getRotationAlpha(Player player){return 1f;} + public float getRotationAlpha(Player player){ + return 1f; + } public boolean canShoot(Player player){ return true; } - public void onLand(Player player){} + public void onLand(Player player){ + } @Override public void displayInfo(Table table){ diff --git a/core/src/io/anuke/mindustry/type/StatusEffect.java b/core/src/io/anuke/mindustry/type/StatusEffect.java index 3852f0a38e..785bcab946 100644 --- a/core/src/io/anuke/mindustry/type/StatusEffect.java +++ b/core/src/io/anuke/mindustry/type/StatusEffect.java @@ -2,15 +2,15 @@ package io.anuke.mindustry.type; import io.anuke.arc.collection.Array; import io.anuke.arc.collection.ObjectMap; -import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.arc.function.Supplier; import io.anuke.arc.graphics.Color; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.units.Statuses.StatusEntry; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.mindustry.entities.type.Unit; +import io.anuke.mindustry.entities.units.Statuses.StatusEntry; import io.anuke.mindustry.game.Content; public class StatusEffect extends Content{ @@ -19,29 +19,31 @@ public class StatusEffect extends Content{ public float speedMultiplier = 1f; //speed public Color color = Color.WHITE.cpy(); //tint color - /**Transition handler map.*/ + /** Transition handler map. */ private ObjectMap transitions = new ObjectMap<>(); - /**Transition initializer array. Since provided effects are only available after init(), this handles putting things - * in the transitions map.*/ + /** + * Transition initializer array. Since provided effects are only available after init(), this handles putting things + * in the transitions map. + */ private Array transInit = new Array<>(); - /**Damage per frame.*/ + /** Damage per frame. */ protected float damage; - /**Effect that happens randomly on top of the affected unit.*/ + /** Effect that happens randomly on top of the affected unit. */ protected Effect effect = Fx.none; @SuppressWarnings("unchecked") @Override public void init(){ for(Object[] pair : transInit){ - Supplier sup = (Supplier) pair[0]; - TransitionHandler handler = (TransitionHandler) pair[1]; + Supplier sup = (Supplier)pair[0]; + TransitionHandler handler = (TransitionHandler)pair[1]; transitions.put(sup.get(), handler); } transInit.clear(); } - /**Runs every tick on the affected unit while time is greater than 0.*/ + /** Runs every tick on the affected unit while time is greater than 0. */ public void update(Unit unit, float time){ if(damage > 0){ unit.damagePeriodic(damage); @@ -78,7 +80,6 @@ public class StatusEffect extends Content{ /** * Called when transitioning between two status effects. - * * @param to The state to transition to * @param time The current status effect time * @param newTime The time that the new status effect will last diff --git a/core/src/io/anuke/mindustry/type/Weapon.java b/core/src/io/anuke/mindustry/type/Weapon.java index 093eda0244..fceb8d22fc 100644 --- a/core/src/io/anuke/mindustry/type/Weapon.java +++ b/core/src/io/anuke/mindustry/type/Weapon.java @@ -22,38 +22,38 @@ import io.anuke.mindustry.net.Net; public class Weapon{ public final String name; - /**minimum cursor distance from player, fixes 'cross-eyed' shooting.*/ + /** minimum cursor distance from player, fixes 'cross-eyed' shooting. */ protected static float minPlayerDist = 20f; protected static int sequenceNum = 0; - /**bullet shot*/ + /** bullet shot */ public BulletType bullet; - /**shell ejection effect*/ + /** shell ejection effect */ public Effect ejectEffect = Fx.none; - /**weapon reload in frames*/ + /** weapon reload in frames */ public float reload; - /**amount of shots per fire*/ + /** amount of shots per fire */ public int shots = 1; - /**spacing in degrees between multiple shots, if applicable*/ + /** spacing in degrees between multiple shots, if applicable */ public float spacing = 12f; - /**inaccuracy of degrees of each shot*/ + /** inaccuracy of degrees of each shot */ public float inaccuracy = 0f; - /**intensity and duration of each shot's screen shake*/ + /** intensity and duration of each shot's screen shake */ public float shake = 0f; - /**visual weapon knockback.*/ + /** visual weapon knockback. */ public float recoil = 1.5f; - /**shoot barrel y offset*/ + /** shoot barrel y offset */ public float length = 3f; - /**shoot barrel x offset.*/ + /** shoot barrel x offset. */ public float width = 4f; - /**fraction of velocity that is random*/ + /** fraction of velocity that is random */ public float velocityRnd = 0f; - /**whether to shoot the weapons in different arms one after another, rather than all at once*/ + /** whether to shoot the weapons in different arms one after another, rather than all at once */ public boolean roundrobin = false; - /**randomization of shot length*/ + /** randomization of shot length */ public float lengthRand = 0f; - /**delay in ticks between shots*/ + /** delay in ticks between shots */ public float shotDelay = 0; - /**whether shooter rotation is ignored when shooting.*/ + /** whether shooter rotation is ignored when shooting. */ public boolean ignoreRotation = false; public TextureRegion region; @@ -72,7 +72,7 @@ public class Weapon{ if(player == null) return; //clients do not see their own shoot events: they are simulated completely clientside to prevent laggy visuals //messing with the firerate or any other stats does not affect the server (take that, script kiddies!) - if(Net.client() && player == Vars.players[0]){ + if(Net.client() && player == Vars.player){ return; } @@ -95,7 +95,7 @@ public class Weapon{ if(weapon.shotDelay > 0.01f){ Angles.shotgun(weapon.shots, weapon.spacing, rotation, f -> { Time.run(sequenceNum * weapon.shotDelay, () -> weapon.bullet(shooter, x, y, f + Mathf.range(weapon.inaccuracy))); - sequenceNum ++; + sequenceNum++; }); }else{ Angles.shotgun(weapon.shots, weapon.spacing, rotation, f -> weapon.bullet(shooter, x, y, f + Mathf.range(weapon.inaccuracy))); @@ -156,7 +156,7 @@ public class Weapon{ shootDirect(p, x, y, angle, left); }else{ if(p instanceof Player){ //players need special weapon handling logic - Call.onPlayerShootWeapon((Player) p, x, y, angle, left); + Call.onPlayerShootWeapon((Player)p, x, y, angle, left); }else{ Call.onGenericShootWeapon(p, x, y, angle, left); } @@ -168,6 +168,6 @@ public class Weapon{ Tmp.v1.trns(angle, 3f); Bullet.create(bullet, - owner, owner.getTeam(), x + Tmp.v1.x, y + Tmp.v1.y, angle, (1f - velocityRnd) + Mathf.random(velocityRnd)); + owner, owner.getTeam(), x + Tmp.v1.x, y + Tmp.v1.y, angle, (1f - velocityRnd) + Mathf.random(velocityRnd)); } } diff --git a/core/src/io/anuke/mindustry/type/Zone.java b/core/src/io/anuke/mindustry/type/Zone.java index 93b5208c67..e97bc11cf1 100644 --- a/core/src/io/anuke/mindustry/type/Zone.java +++ b/core/src/io/anuke/mindustry/type/Zone.java @@ -7,32 +7,29 @@ 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.content.StatusEffects; -import io.anuke.mindustry.game.EventType.ZoneCompleteEvent; 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.SpawnGroup; import io.anuke.mindustry.game.UnlockableContent; import io.anuke.mindustry.maps.generators.Generator; -import io.anuke.mindustry.maps.generators.MapGenerator; import io.anuke.mindustry.world.Block; import java.util.Arrays; -import static io.anuke.mindustry.Vars.data; -import static io.anuke.mindustry.Vars.state; +import static io.anuke.mindustry.Vars.*; public class Zone extends UnlockableContent{ public final Generator generator; public Block[] blockRequirements = {}; - public ItemStack[] itemRequirements = {}; - public Zone[] zoneRequirements = {}; + public ZoneRequirement[] zoneRequirements = {}; + //TODO debug verify resources. public Item[] resources = {}; public Supplier rules = Rules::new; public boolean alwaysUnlocked; public int conditionWave = Integer.MAX_VALUE; - public int configureWave = 40; + public int configureWave = 15; public int launchPeriod = 10; public Loadout loadout = Loadouts.basicShard; @@ -40,20 +37,11 @@ public class Zone extends UnlockableContent{ protected Array startingItems = new Array<>(); protected ItemStack[] launchCost = null; - public Zone(String name, MapGenerator generator){ + public Zone(String name, Generator generator){ super(name); this.generator = generator; } - protected SpawnGroup bossGroup(UnitType type){ - return new SpawnGroup(type){{ - begin = configureWave-1; - effect = StatusEffects.boss; - unitScaling = 1; - spacing = configureWave; - }}; - } - public boolean isBossWave(int wave){ return wave % configureWave == 0 && wave > 0; } @@ -79,8 +67,11 @@ public class Zone extends UnlockableContent{ Core.settings.put(name + "-wave", wave); data.modified(); - if(wave == conditionWave + 1){ - Events.fire(new ZoneCompleteEvent(this)); + for(Zone zone : content.zones()){ + ZoneRequirement req = Structs.find(zone.zoneRequirements, f -> f.zone == this); + if(req != null && wave == req.wave + 1){ + Events.fire(new ZoneRequireCompleteEvent(zone, this)); + } } if(wave == configureWave + 1){ @@ -123,7 +114,7 @@ public class Zone extends UnlockableContent{ data.modified(); } - /**Whether this zone has met its condition; if true, the player can leave.*/ + /** Whether this zone has met its condition; if true, the player can leave. */ public boolean metCondition(){ return state.wave >= conditionWave; } @@ -155,14 +146,17 @@ public class Zone extends UnlockableContent{ //neither of these are implemented, as zones are not displayed in a normal fashion... yet @Override - public void displayInfo(Table table){} + public void displayInfo(Table table){ + } @Override - public TextureRegion getContentIcon(){ return null; } + public TextureRegion getContentIcon(){ + return null; + } @Override public String localizedName(){ - return Core.bundle.get("zone."+name+".name"); + return Core.bundle.get("zone." + name + ".name"); } @Override @@ -170,4 +164,22 @@ public class Zone extends UnlockableContent{ return ContentType.zone; } + public static class ZoneRequirement{ + public final Zone zone; + public final int wave; + + public ZoneRequirement(Zone zone, int wave){ + this.zone = zone; + this.wave = wave; + } + + public static ZoneRequirement[] with(Object... objects){ + ZoneRequirement[] out = new ZoneRequirement[objects.length / 2]; + for(int i = 0; i < objects.length; i += 2){ + out[i / 2] = new ZoneRequirement((Zone)objects[i], (Integer)objects[i + 1]); + } + return out; + } + } + } diff --git a/core/src/io/anuke/mindustry/ui/Bar.java b/core/src/io/anuke/mindustry/ui/Bar.java index cbd2b7b0f9..4e9a87659d 100644 --- a/core/src/io/anuke/mindustry/ui/Bar.java +++ b/core/src/io/anuke/mindustry/ui/Bar.java @@ -4,10 +4,7 @@ import io.anuke.arc.Core; import io.anuke.arc.function.FloatProvider; import io.anuke.arc.function.Supplier; import io.anuke.arc.graphics.Color; -import io.anuke.arc.graphics.g2d.BitmapFont; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.GlyphLayout; -import io.anuke.arc.graphics.g2d.ScissorStack; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.scene.Element; @@ -79,7 +76,7 @@ public class Bar extends Element{ lay.setText(font, name); font.setColor(Color.WHITE); - font.draw(name, x + width/2f - lay.width/2f, y + height/2f + lay.height/2f + 1); + font.draw(name, x + width / 2f - lay.width / 2f, y + height / 2f + lay.height / 2f + 1); Pools.free(lay); } diff --git a/core/src/io/anuke/mindustry/ui/BorderImage.java b/core/src/io/anuke/mindustry/ui/BorderImage.java index 0db23da2ba..0e14960df0 100644 --- a/core/src/io/anuke/mindustry/ui/BorderImage.java +++ b/core/src/io/anuke/mindustry/ui/BorderImage.java @@ -1,12 +1,10 @@ package io.anuke.mindustry.ui; import io.anuke.arc.graphics.Texture; -import io.anuke.arc.graphics.g2d.TextureRegion; -import io.anuke.mindustry.graphics.Pal; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Lines; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.scene.ui.Image; import io.anuke.arc.scene.ui.layout.Unit; +import io.anuke.mindustry.graphics.Pal; public class BorderImage extends Image{ private float thickness = 3f; diff --git a/core/src/io/anuke/mindustry/ui/ContentDisplay.java b/core/src/io/anuke/mindustry/ui/ContentDisplay.java index 62e571449e..f00506202d 100644 --- a/core/src/io/anuke/mindustry/ui/ContentDisplay.java +++ b/core/src/io/anuke/mindustry/ui/ContentDisplay.java @@ -1,21 +1,16 @@ package io.anuke.mindustry.ui; import io.anuke.arc.Core; +import io.anuke.arc.collection.Array; import io.anuke.arc.collection.OrderedMap; import io.anuke.arc.graphics.Color; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.util.Strings; -import io.anuke.mindustry.type.UnitType; import io.anuke.mindustry.graphics.Pal; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.Liquid; -import io.anuke.mindustry.type.Mech; +import io.anuke.mindustry.type.*; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block.Icon; -import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.mindustry.world.meta.BlockStats; -import io.anuke.mindustry.world.meta.StatCategory; -import io.anuke.mindustry.world.meta.StatValue; +import io.anuke.mindustry.world.meta.*; public class ContentDisplay{ @@ -45,7 +40,7 @@ public class ContentDisplay{ BlockStats stats = block.stats; for(StatCategory cat : stats.toMap().keys()){ - OrderedMap map = stats.toMap().get(cat); + OrderedMap> map = stats.toMap().get(cat); if(map.size == 0) continue; @@ -56,7 +51,13 @@ public class ContentDisplay{ table.table(inset -> { inset.left(); inset.add("[LIGHT_GRAY]" + stat.localized() + ":[] "); - map.get(stat).display(inset); + Array arr = map.get(stat); + for(StatValue value : arr){ + value.display(inset); + inset.add().size(10f); + } + + //map.get(stat).display(inset); }).fillX().padLeft(10); table.row(); } @@ -86,11 +87,11 @@ public class ContentDisplay{ table.left().defaults().fillX(); - table.add(Core.bundle.format("item.explosiveness", (int) (item.explosiveness * 100))); + table.add(Core.bundle.format("item.explosiveness", (int)(item.explosiveness * 100))); table.row(); - table.add(Core.bundle.format("item.flammability", (int) (item.flammability * 100))); + table.add(Core.bundle.format("item.flammability", (int)(item.flammability * 100))); table.row(); - table.add(Core.bundle.format("item.radioactivity", (int) (item.radioactivity * 100))); + table.add(Core.bundle.format("item.radioactivity", (int)(item.radioactivity * 100))); table.row(); } @@ -117,15 +118,15 @@ public class ContentDisplay{ table.left().defaults().fillX(); - table.add(Core.bundle.format("item.explosiveness", (int) (liquid.explosiveness * 100))); + table.add(Core.bundle.format("item.explosiveness", (int)(liquid.explosiveness * 100))); table.row(); - table.add(Core.bundle.format("item.flammability", (int) (liquid.flammability * 100))); + table.add(Core.bundle.format("item.flammability", (int)(liquid.flammability * 100))); table.row(); - table.add(Core.bundle.format("liquid.heatcapacity", (int) (liquid.heatCapacity * 100))); + table.add(Core.bundle.format("liquid.heatcapacity", (int)(liquid.heatCapacity * 100))); table.row(); - table.add(Core.bundle.format("liquid.temperature", (int) (liquid.temperature * 100))); + table.add(Core.bundle.format("liquid.temperature", (int)(liquid.temperature * 100))); table.row(); - table.add(Core.bundle.format("liquid.viscosity", (int) (liquid.viscosity * 100))); + table.add(Core.bundle.format("liquid.viscosity", (int)(liquid.viscosity * 100))); table.row(); } @@ -134,6 +135,7 @@ public class ContentDisplay{ title.addImage(mech.getContentIcon()).size(8 * 6); title.add("[accent]" + mech.localizedName()).padLeft(5); }); + table.left().defaults().left(); table.row(); @@ -159,13 +161,17 @@ public class ContentDisplay{ table.add(Core.bundle.format("mech.ability", Core.bundle.get("mech." + mech.name + ".ability"))); table.row(); } + + table.add(Core.bundle.format("mech.buildspeed", (int)(mech.buildPower * 100f))); + table.row(); + table.add(Core.bundle.format("mech.health", (int)mech.health)); table.row(); table.add(Core.bundle.format("mech.itemcapacity", mech.itemCapacity)); table.row(); if(mech.drillPower > 0){ - table.add(Core.bundle.format("mech.minespeed", (int) (mech.mineSpeed * 10))); + table.add(Core.bundle.format("mech.minespeed", (int)(mech.mineSpeed * 100f))); table.row(); table.add(Core.bundle.format("mech.minepower", mech.drillPower)); table.row(); @@ -196,7 +202,7 @@ public class ContentDisplay{ table.add(Core.bundle.format("unit.health", unit.health)); table.row(); - table.add(Core.bundle.format("unit.speed", Strings.toFixed(unit.speed, 1))); + table.add(Core.bundle.format("unit.speed", Strings.fixed(unit.speed, 1))); table.row(); table.row(); } diff --git a/core/src/io/anuke/mindustry/ui/GridImage.java b/core/src/io/anuke/mindustry/ui/GridImage.java index fd164cc191..81916cba40 100644 --- a/core/src/io/anuke/mindustry/ui/GridImage.java +++ b/core/src/io/anuke/mindustry/ui/GridImage.java @@ -19,15 +19,15 @@ public class GridImage extends Element{ int minspace = 10; - int jumpx = (int) (Math.max(minspace, xspace) / xspace); - int jumpy = (int) (Math.max(minspace, yspace) / yspace); + int jumpx = (int)(Math.max(minspace, xspace) / xspace); + int jumpy = (int)(Math.max(minspace, yspace) / yspace); for(int x = 0; x <= imageWidth; x += jumpx){ - Fill.crect((int) (getX() + xspace * x - s), getY() - s, 2, getHeight() + (x == imageWidth ? 1 : 0)); + Fill.crect((int)(getX() + xspace * x - s), getY() - s, 2, getHeight() + (x == imageWidth ? 1 : 0)); } for(int y = 0; y <= imageHeight; y += jumpy){ - Fill.crect(getX() - s, (int) (getY() + y * yspace - s), getWidth(), 2); + Fill.crect(getX() - s, (int)(getY() + y * yspace - s), getWidth(), 2); } } diff --git a/core/src/io/anuke/mindustry/ui/ItemDisplay.java b/core/src/io/anuke/mindustry/ui/ItemDisplay.java index ff5b6153f3..1e7dd9fbbf 100644 --- a/core/src/io/anuke/mindustry/ui/ItemDisplay.java +++ b/core/src/io/anuke/mindustry/ui/ItemDisplay.java @@ -1,10 +1,10 @@ package io.anuke.mindustry.ui; +import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemStack; -import io.anuke.arc.scene.ui.layout.Table; -/**An item image with text.*/ +/** An item image with text. */ public class ItemDisplay extends Table{ public ItemDisplay(Item item){ @@ -12,7 +12,7 @@ public class ItemDisplay extends Table{ } public ItemDisplay(Item item, int amount){ - add(new ItemImage(new ItemStack(item, amount))).size(8*3); + add(new ItemImage(new ItemStack(item, amount))).size(8 * 4); add(item.localizedName()).padLeft(4); } } diff --git a/core/src/io/anuke/mindustry/ui/ItemImage.java b/core/src/io/anuke/mindustry/ui/ItemImage.java index 3e4692c270..6ef197b8d9 100644 --- a/core/src/io/anuke/mindustry/ui/ItemImage.java +++ b/core/src/io/anuke/mindustry/ui/ItemImage.java @@ -1,12 +1,12 @@ package io.anuke.mindustry.ui; -import io.anuke.arc.graphics.g2d.TextureRegion; -import io.anuke.mindustry.type.Item.Icon; -import io.anuke.mindustry.type.ItemStack; import io.anuke.arc.function.Supplier; +import io.anuke.arc.graphics.g2d.TextureRegion; 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.mindustry.type.Item.Icon; +import io.anuke.mindustry.type.ItemStack; public class ItemImage extends Stack{ @@ -27,7 +27,7 @@ public class ItemImage extends Stack{ } public ItemImage(ItemStack stack){ - add(new Image(stack.item.icon(Icon.medium))); + add(new Image(stack.item.icon(Icon.large))); if(stack.amount != 0){ Table t = new Table().left().bottom(); diff --git a/core/src/io/anuke/mindustry/ui/ItemsDisplay.java b/core/src/io/anuke/mindustry/ui/ItemsDisplay.java index 83a42a18b8..a4ca3d6d07 100644 --- a/core/src/io/anuke/mindustry/ui/ItemsDisplay.java +++ b/core/src/io/anuke/mindustry/ui/ItemsDisplay.java @@ -27,11 +27,13 @@ public class ItemsDisplay extends Table{ table("flat", t -> { t.margin(10).marginLeft(15).marginTop(15f); + t.add("$launcheditems").colspan(3).left().padBottom(5); + t.row(); ObjectIntMap items = data.items(); for(Item item : content.items()){ if(item.type == ItemType.material && data.isUnlocked(item)){ t.label(() -> format.format(items.get(item, 0))).left(); - t.addImage(item.icon(Icon.medium)).size(8*3).padLeft(4).padRight(4); + t.addImage(item.icon(Icon.medium)).size(8 * 3).padLeft(4).padRight(4); t.add(item.localizedName()).color(Color.LIGHT_GRAY).left(); t.row(); } diff --git a/core/src/io/anuke/mindustry/ui/Links.java b/core/src/io/anuke/mindustry/ui/Links.java index 5f47c61a5a..0348970890 100644 --- a/core/src/io/anuke/mindustry/ui/Links.java +++ b/core/src/io/anuke/mindustry/ui/Links.java @@ -8,13 +8,13 @@ public class 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", "http://mindustry.wikia.com/wiki/Mindustry_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("trello", "https://trello.com/b/aE2tcUwF", Color.valueOf("026aa7")), + new LinkEntry("wiki", "http://mindustry.wikia.com/wiki/Mindustry_Wiki", Color.valueOf("0f142f")), + new LinkEntry("itch.io", "https://anuke.itch.io/mindustry", Color.valueOf("fa5c5c")), + 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/LiquidDisplay.java b/core/src/io/anuke/mindustry/ui/LiquidDisplay.java index 442707408e..efa010f207 100644 --- a/core/src/io/anuke/mindustry/ui/LiquidDisplay.java +++ b/core/src/io/anuke/mindustry/ui/LiquidDisplay.java @@ -1,14 +1,31 @@ package io.anuke.mindustry.ui; -import io.anuke.mindustry.type.Liquid; +import io.anuke.arc.graphics.Color; 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.Strings; +import io.anuke.mindustry.type.Liquid; +import io.anuke.mindustry.world.meta.StatUnit; -/**An ItemDisplay, but for liquids.*/ +/** An ItemDisplay, but for liquids. */ public class LiquidDisplay extends Table{ - public LiquidDisplay(Liquid liquid){ - add(new Image(liquid.getContentIcon())).size(8*3); - add(liquid.localizedName()).padLeft(3); + public LiquidDisplay(Liquid liquid, float amount, boolean perSecond){ + add(new Stack(){{ + add(new Image(liquid.getContentIcon())); + + if(amount != 0){ + Table t = new Table().left().bottom(); + t.add(Strings.autoFixed(amount, 1)); + add(t); + } + }}).size(8 * 4).padRight(3); + + if(perSecond){ + add(StatUnit.perSecond.localized()).padLeft(2).padRight(5).color(Color.LIGHT_GRAY); + } + + add(liquid.localizedName()); } } diff --git a/core/src/io/anuke/mindustry/ui/MenuButton.java b/core/src/io/anuke/mindustry/ui/MenuButton.java index 9d5f34430e..80f577f4cf 100644 --- a/core/src/io/anuke/mindustry/ui/MenuButton.java +++ b/core/src/io/anuke/mindustry/ui/MenuButton.java @@ -1,8 +1,8 @@ package io.anuke.mindustry.ui; import io.anuke.arc.graphics.Color; -import io.anuke.arc.util.Align; import io.anuke.arc.scene.ui.TextButton; +import io.anuke.arc.util.Align; public class MenuButton extends TextButton{ diff --git a/core/src/io/anuke/mindustry/ui/Minimap.java b/core/src/io/anuke/mindustry/ui/Minimap.java index 243e8039da..e39e128e3e 100644 --- a/core/src/io/anuke/mindustry/ui/Minimap.java +++ b/core/src/io/anuke/mindustry/ui/Minimap.java @@ -2,23 +2,38 @@ package io.anuke.mindustry.ui; import io.anuke.arc.Core; 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.InputEvent; -import io.anuke.arc.scene.event.InputListener; +import io.anuke.arc.scene.event.*; import io.anuke.arc.scene.ui.layout.Container; +import io.anuke.arc.scene.ui.layout.Unit; -import static io.anuke.mindustry.Vars.renderer; +import static io.anuke.mindustry.Vars.*; public class Minimap extends Container{ public Minimap(){ - super(new Element(){ + background("pane"); + float margin = 5f; + touchable(Touchable.enabled); + + addChild(new Element(){ + { + setSize(Unit.dp.scl(140f)); + } + + @Override + public void act(float delta){ + setPosition(margin, margin); + + super.act(delta); + } @Override public void draw(){ if(renderer.minimap.getRegion() == null) return; - Draw.rect(renderer.minimap.getRegion(), x + width/2f, y + height/2f, width, height); + Draw.rect(renderer.minimap.getRegion(), x + width / 2f, y + height / 2f, width, height); if(renderer.minimap.getTexture() != null){ renderer.minimap.drawEntities(x, y, width, height); @@ -26,10 +41,8 @@ public class Minimap extends Container{ } }); - background("pane"); - size(140f); - margin(5f); + margin(margin); addListener(new InputListener(){ @Override @@ -39,6 +52,42 @@ public class Minimap extends Container{ } }); + addListener(new ClickListener(){ + { + tapSquareSize = Unit.dp.scl(11f); + } + + @Override + public void touchUp(InputEvent event, float x, float y, int pointer, KeyCode button){ + if(inTapSquare()){ + super.touchUp(event, x, y, pointer, button); + }else{ + pressed = false; + pressedPointer = -1; + pressedButton = null; + cancelled = false; + } + } + + @Override + public void touchDragged(InputEvent event, float x, float y, int pointer){ + if(!inTapSquare(x, y)){ + invalidateTapSquare(); + } + super.touchDragged(event, x, y, pointer); + + if(mobile){ + float max = Math.min(world.width(), world.height()) / 16f / 2f; + renderer.minimap.setZoom(1f + y / height * (max - 1f)); + } + } + + @Override + public void clicked(InputEvent event, float x, float y){ + ui.minimap.show(); + } + }); + update(() -> { Element e = Core.scene.hit(Core.input.mouseX(), Core.input.mouseY(), true); diff --git a/core/src/io/anuke/mindustry/ui/MobileButton.java b/core/src/io/anuke/mindustry/ui/MobileButton.java index 4d64eafe5c..102357e80c 100644 --- a/core/src/io/anuke/mindustry/ui/MobileButton.java +++ b/core/src/io/anuke/mindustry/ui/MobileButton.java @@ -1,7 +1,7 @@ package io.anuke.mindustry.ui; -import io.anuke.arc.util.Align; import io.anuke.arc.scene.ui.ImageButton; +import io.anuke.arc.util.Align; public class MobileButton extends ImageButton{ diff --git a/core/src/io/anuke/mindustry/ui/ReqImage.java b/core/src/io/anuke/mindustry/ui/ReqImage.java index 315ce91211..1b3da1c6a7 100644 --- a/core/src/io/anuke/mindustry/ui/ReqImage.java +++ b/core/src/io/anuke/mindustry/ui/ReqImage.java @@ -1,9 +1,7 @@ package io.anuke.mindustry.ui; import io.anuke.arc.function.BooleanProvider; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Lines; -import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.scene.Element; import io.anuke.arc.scene.ui.Image; import io.anuke.arc.scene.ui.layout.Stack; diff --git a/core/src/io/anuke/mindustry/ui/TreeLayout.java b/core/src/io/anuke/mindustry/ui/TreeLayout.java index d5f0db4e8e..1a7395f928 100644 --- a/core/src/io/anuke/mindustry/ui/TreeLayout.java +++ b/core/src/io/anuke/mindustry/ui/TreeLayout.java @@ -1,5 +1,3 @@ - - package io.anuke.mindustry.ui; import io.anuke.arc.collection.FloatArray; @@ -108,7 +106,7 @@ public class TreeLayout{ } private TreeNode getAncestor(TreeNode node){ - return node.ancestor != null ? node.ancestor : node; + return node.ancestor != null ? node.ancestor : node; } private float getDistance(TreeNode v, TreeNode w){ @@ -211,7 +209,7 @@ public class TreeLayout{ float shift = 0; float change = 0; - for(int i = v.children.length - 1; i >= 0; i --){ + for(int i = v.children.length - 1; i >= 0; i--){ TreeNode w = v.children[i]; change = change + w.change; w.prelim += shift; @@ -236,10 +234,9 @@ public class TreeLayout{ previousChild = w; } executeShifts(v); - float midpoint = (v.children[0].prelim + v.children[v.children.length-1].prelim) / 2f; - TreeNode w = leftSibling; - if(w != null){ - v.prelim = w.prelim + getDistance(v, w); + float midpoint = (v.children[0].prelim + v.children[v.children.length - 1].prelim) / 2f; + if(leftSibling != null){ + v.prelim = leftSibling.prelim + getDistance(v, leftSibling); v.mode = v.prelim - midpoint; }else{ v.prelim = midpoint; diff --git a/core/src/io/anuke/mindustry/ui/dialogs/AboutDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/AboutDialog.java index af6ddffe1b..a4297444fa 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/AboutDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/AboutDialog.java @@ -1,21 +1,19 @@ package io.anuke.mindustry.ui.dialogs; import io.anuke.arc.Core; -import io.anuke.arc.graphics.Color; import io.anuke.arc.collection.Array; import io.anuke.arc.collection.ObjectSet; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.scene.ui.ScrollPane; +import io.anuke.arc.scene.ui.layout.Cell; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.arc.scene.utils.UIUtils; +import io.anuke.arc.util.*; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.io.Contributors; import io.anuke.mindustry.io.Contributors.Contributor; import io.anuke.mindustry.ui.Links; import io.anuke.mindustry.ui.Links.LinkEntry; -import io.anuke.arc.util.Time; -import io.anuke.arc.scene.ui.ScrollPane; -import io.anuke.arc.scene.ui.layout.Cell; -import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.arc.scene.utils.UIUtils; -import io.anuke.arc.util.OS; -import io.anuke.arc.util.Strings; import static io.anuke.mindustry.Vars.ios; import static io.anuke.mindustry.Vars.ui; @@ -27,7 +25,9 @@ public class AboutDialog extends FloatingDialog{ public AboutDialog(){ super("$about.button"); - Contributors.getContributors(out -> contributors = out, Throwable::printStackTrace); + if(!ios){ + Contributors.getContributors(out -> contributors = out, Throwable::printStackTrace); + } shown(this::setup); onResize(this::setup); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/AdminsDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/AdminsDialog.java index 70a1e5abb3..42fed50472 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/AdminsDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/AdminsDialog.java @@ -1,8 +1,8 @@ package io.anuke.mindustry.ui.dialogs; -import io.anuke.mindustry.net.Administration.PlayerInfo; 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.*; diff --git a/core/src/io/anuke/mindustry/ui/dialogs/BansDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/BansDialog.java index 741ce3c983..be60408759 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/BansDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/BansDialog.java @@ -1,10 +1,11 @@ package io.anuke.mindustry.ui.dialogs; -import io.anuke.mindustry.net.Administration.PlayerInfo; 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.*; +import static io.anuke.mindustry.Vars.netServer; +import static io.anuke.mindustry.Vars.ui; public class BansDialog extends FloatingDialog{ diff --git a/core/src/io/anuke/mindustry/ui/dialogs/ColorPickDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/ColorPickDialog.java index 68ac658a9f..a737782b8e 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/ColorPickDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/ColorPickDialog.java @@ -7,8 +7,8 @@ import io.anuke.arc.scene.ui.Dialog; import io.anuke.arc.scene.ui.ImageButton; import io.anuke.arc.scene.ui.layout.Table; +import static io.anuke.mindustry.Vars.player; import static io.anuke.mindustry.Vars.playerColors; -import static io.anuke.mindustry.Vars.players; public class ColorPickDialog extends Dialog{ private Consumer cons; @@ -29,7 +29,7 @@ public class ColorPickDialog extends Dialog{ cons.accept(color); hide(); }).size(48).get(); - button.setChecked(players[0].color.equals(color)); + button.setChecked(player.color.equals(color)); button.getStyle().imageUpColor = color; if(i % 4 == 3){ diff --git a/core/src/io/anuke/mindustry/ui/dialogs/ContentInfoDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/ContentInfoDialog.java index 23f46045e8..f76bba6bbc 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/ContentInfoDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/ContentInfoDialog.java @@ -1,8 +1,8 @@ package io.anuke.mindustry.ui.dialogs; -import io.anuke.mindustry.game.UnlockableContent; import io.anuke.arc.scene.ui.ScrollPane; import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.game.UnlockableContent; public class ContentInfoDialog extends FloatingDialog{ diff --git a/core/src/io/anuke/mindustry/ui/dialogs/ControlsDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/ControlsDialog.java index 2a6db67316..aad28dc08e 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/ControlsDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/ControlsDialog.java @@ -16,7 +16,7 @@ public class ControlsDialog extends KeybindDialog{ title.setAlignment(Align.center); titleTable.row(); titleTable.add(new Image("white")) - .growX().height(3f).pad(4f).get().setColor(Pal.accent); + .growX().height(3f).pad(4f).get().setColor(Pal.accent); } @Override diff --git a/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java index 18f05306c8..aa0c22c37e 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java @@ -4,10 +4,7 @@ import io.anuke.arc.Core; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.arc.scene.event.Touchable; -import io.anuke.arc.scene.ui.ButtonGroup; -import io.anuke.arc.scene.ui.ImageButton; -import io.anuke.arc.scene.ui.ScrollPane; -import io.anuke.arc.scene.ui.TextButton; +import io.anuke.arc.scene.ui.*; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.util.Align; import io.anuke.arc.util.Scaling; @@ -21,6 +18,7 @@ import static io.anuke.mindustry.Vars.*; public class CustomGameDialog extends FloatingDialog{ Difficulty difficulty = Difficulty.normal; RulePreset lastPreset = RulePreset.survival; + CustomRulesDialog dialog = new CustomRulesDialog(); public CustomGameDialog(){ super("$customgame"); @@ -31,7 +29,9 @@ public class CustomGameDialog extends FloatingDialog{ } void setup(){ - state.rules = lastPreset.get(); + if(lastPreset == null){ + lastPreset = RulePreset.survival; + } cont.clear(); Table maps = new Table(); @@ -43,7 +43,8 @@ public class CustomGameDialog extends FloatingDialog{ Table selmode = new Table(); ButtonGroup group = new ButtonGroup<>(); - selmode.add("$level.mode").padRight(15f); + selmode.add("$level.mode").colspan(4); + selmode.row(); int i = 0; Table modes = new Table(); @@ -51,12 +52,17 @@ public class CustomGameDialog extends FloatingDialog{ for(RulePreset mode : RulePreset.values()){ modes.addButton(mode.toString(), "toggle", () -> { - state.rules = mode.get(); lastPreset = mode; }).update(b -> b.setChecked(lastPreset == mode)).group(group).size(140f, 54f); if(i++ % 2 == 1) modes.row(); } selmode.add(modes); + selmode.addButton("$mode.custom", "toggle", () -> { + }) + .update(b -> b.setChecked(lastPreset == null)).size(108f).group(group).get().tapped(() -> { + lastPreset = null; + dialog.show(); + }); selmode.addButton("?", this::displayGameModeHelp).width(50f).fillY().padLeft(18f); cont.add(selmode); @@ -68,14 +74,16 @@ public class CustomGameDialog extends FloatingDialog{ Table sdif = new Table(); - sdif.add("$setting.difficulty.name").padRight(15f); + 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("", () -> {}) + sdif.addButton("", () -> { + }) .update(t -> { t.setText(difficulty.toString()); t.touchable(Touchable.disabled); @@ -86,7 +94,7 @@ public class CustomGameDialog extends FloatingDialog{ state.wavetime = difficulty.waveTime; }).width(s); - cont.add(sdif); + cont.add(sdif).visible(() -> lastPreset != null); cont.row(); float images = 146f; @@ -114,7 +122,7 @@ public class CustomGameDialog extends FloatingDialog{ image.clicked(() -> { hide(); - control.playMap(map, lastPreset.get()); + control.playMap(map, lastPreset == null ? dialog.rules : lastPreset.get()); }); maps.add(image); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/CustomRulesDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/CustomRulesDialog.java new file mode 100644 index 0000000000..2b8073eff7 --- /dev/null +++ b/core/src/io/anuke/mindustry/ui/dialogs/CustomRulesDialog.java @@ -0,0 +1,67 @@ +package io.anuke.mindustry.ui.dialogs; + +import io.anuke.arc.function.FloatConsumer; +import io.anuke.arc.function.FloatProvider; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.arc.util.Strings; +import io.anuke.mindustry.core.Platform; +import io.anuke.mindustry.game.Rules; + +import static io.anuke.mindustry.Vars.tilesize; + +public class CustomRulesDialog extends FloatingDialog{ + public final Rules rules = new Rules(); + private Table main; + + public CustomRulesDialog(){ + super("$mode.custom"); + + rules.waves = true; + rules.waveTimer = true; + + setFillParent(true); + shown(this::setup); + addCloseButton(); + } + + void setup(){ + cont.clear(); + cont.pane(m -> main = m); + main.margin(10f); + + main.left().defaults().fillX().left().pad(5); + main.row(); + main.addCheck("$rules.infiniteresources", b -> rules.infiniteResources = b).checked(b -> rules.infiniteResources); + main.row(); + main.addCheck("$rules.wavetimer", b -> rules.waveTimer = b).checked(b -> rules.waveTimer); + main.row(); + main.addCheck("$rules.waves", b -> rules.waves = b).checked(b -> rules.waves); + main.row(); + main.addCheck("$rules.pvp", b -> rules.pvp = b).checked(b -> rules.pvp); + main.row(); + main.addCheck("$rules.unitdrops", b -> rules.unitDrops = b).checked(b -> rules.unitDrops); + main.row(); + number("$rules.buildcostmultiplier", f -> rules.buildCostMultiplier = f, () -> rules.buildCostMultiplier); + number("$rules.buildspeedmultiplier", f -> rules.buildSpeedMultiplier = f, () -> rules.buildSpeedMultiplier); + number("$rules.unitbuildspeedmultiplier", f -> rules.unitBuildSpeedMultiplier = f, () -> rules.unitBuildSpeedMultiplier); + number("$rules.unithealthmultiplier", f -> rules.unitHealthMultiplier = f, () -> rules.unitHealthMultiplier); + number("$rules.playerhealthmultiplier", f -> rules.playerHealthMultiplier = f, () -> rules.playerHealthMultiplier); + number("$rules.playerdamagemultiplier", f -> rules.playerDamageMultiplier = f, () -> rules.playerDamageMultiplier); + number("$rules.unitdamagemultiplier", f -> rules.unitDamageMultiplier = f, () -> rules.unitDamageMultiplier); + number("$rules.enemycorebuildradius", f -> rules.enemyCoreBuildRadius = f * tilesize, () -> Math.min(rules.enemyCoreBuildRadius / tilesize, 200)); + number("$rules.respawntime", f -> rules.respawnTime = f * 60f, () -> rules.respawnTime / 60f); + number("$rules.wavespacing", f -> rules.waveSpacing = f * 60f, () -> rules.waveSpacing / 60f); + } + + void number(String text, FloatConsumer cons, FloatProvider prov){ + main.table(t -> { + t.left(); + t.add(text).left().padRight(5); + Platform.instance.addDialog(t.addField(prov.get() + "", s -> cons.accept(Strings.parseFloat(s))) + .valid(Strings::canParsePositiveFloat).width(120f).left().get()); + }); + + 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 41adede89b..1c094e841e 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/DatabaseDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/DatabaseDialog.java @@ -2,9 +2,7 @@ package io.anuke.mindustry.ui.dialogs; import io.anuke.arc.collection.Array; import io.anuke.arc.scene.event.HandCursorListener; -import io.anuke.arc.scene.ui.Image; -import io.anuke.arc.scene.ui.ScrollPane; -import io.anuke.arc.scene.ui.Tooltip; +import io.anuke.arc.scene.ui.*; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.scene.utils.UIUtils; import io.anuke.mindustry.Vars; @@ -34,7 +32,7 @@ public class DatabaseDialog extends FloatingDialog{ Array[] allContent = Vars.content.getContentMap(); - for(int j = 0; j < allContent.length; j ++){ + for(int j = 0; j < allContent.length; j++){ ContentType type = ContentType.values()[j]; Array array = allContent[j].select(c -> c instanceof UnlockableContent && !((UnlockableContent)c).isHidden()); @@ -53,7 +51,7 @@ public class DatabaseDialog extends FloatingDialog{ int count = 0; for(int i = 0; i < array.size; i++){ - UnlockableContent unlock = (UnlockableContent) array.get(i); + UnlockableContent unlock = (UnlockableContent)array.get(i); Image image = unlocked(unlock) ? new Image(unlock.getContentIcon()) : new Image("icon-tree-locked"); image.addListener(new HandCursorListener()); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/DeployDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/DeployDialog.java index 617ad236dc..af0c8b34a2 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/DeployDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/DeployDialog.java @@ -10,13 +10,13 @@ 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; @@ -100,8 +100,8 @@ public class DeployDialog extends FloatingDialog{ } boolean hidden(Zone zone){ - for(Zone other : zone.zoneRequirements){ - if(!data.isUnlocked(other)){ + for(ZoneRequirement other : zone.zoneRequirements){ + if(!data.isUnlocked(other.zone)){ return true; } } @@ -137,7 +137,7 @@ public class DeployDialog extends FloatingDialog{ TextButton button = new TextButton("", "node"); button.setSize(node.width, node.height); button.update(() -> { - button.setPosition(node.x + panX + width/2f, node.y + panY + height/2f, Align.center); + button.setPosition(node.x + panX + width / 2f, node.y + panY + height / 2f, Align.center); }); button.clearChildren(); buildButton(node.zone, button); @@ -152,7 +152,7 @@ public class DeployDialog extends FloatingDialog{ @Override public void draw(){ - float offsetX = panX + width/2f + x, offsetY = panY + height/2f + y; + float offsetX = panX + width / 2f + x, offsetY = panY + height / 2f + y; for(ZoneNode node : nodes){ for(ZoneNode child : node.children){ @@ -177,7 +177,7 @@ public class DeployDialog extends FloatingDialog{ this.height /= 2f; nodes.add(this); - arr.selectFrom(content.zones(), other -> Structs.contains(other.zoneRequirements, zone)); + arr.selectFrom(content.zones(), other -> other.zoneRequirements.length > 0 && other.zoneRequirements[0].zone == zone); children = new ZoneNode[arr.size]; for(int i = 0; i < children.length; i++){ diff --git a/core/src/io/anuke/mindustry/ui/dialogs/DiscordDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/DiscordDialog.java index b21e875749..7ea5b5b683 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/DiscordDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/DiscordDialog.java @@ -2,8 +2,8 @@ package io.anuke.mindustry.ui.dialogs; import io.anuke.arc.Core; import io.anuke.arc.graphics.Color; -import io.anuke.mindustry.graphics.Pal; 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; diff --git a/core/src/io/anuke/mindustry/ui/dialogs/FileChooser.java b/core/src/io/anuke/mindustry/ui/dialogs/FileChooser.java index a6e42fa975..2bb98b5cd9 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/FileChooser.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/FileChooser.java @@ -11,9 +11,7 @@ import io.anuke.arc.scene.ui.*; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.scene.ui.layout.Unit; import io.anuke.arc.scene.utils.UIUtils; -import io.anuke.arc.util.Align; -import io.anuke.arc.util.OS; -import io.anuke.arc.util.Time; +import io.anuke.arc.util.*; import io.anuke.arc.util.pooling.Pools; import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.Platform; @@ -27,7 +25,7 @@ public class FileChooser extends FloatingDialog{ public static Predicate defaultFilter = file -> true; private Table files; private FileHandle homeDirectory = Core.files.absolute(OS.isMac ? OS.getProperty("user.home") + "/Downloads/" : - Core.files.getExternalStoragePath()); + Core.files.getExternalStoragePath()); private FileHandle directory = homeDirectory; private ScrollPane pane; private TextField navigation, filefield; @@ -241,7 +239,7 @@ public class FileChooser extends FloatingDialog{ button.add(image).padRight(4f).size(14 * 2f); button.getCells().reverse(); files.top().left().add(button).align(Align.topLeft).fillX().expandX() - .height(50).pad(2).padTop(0).padBottom(0).colspan(2); + .height(50).pad(2).padTop(0).padBottom(0).colspan(2); button.getLabel().setAlignment(Align.left); files.row(); } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/FloatingDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/FloatingDialog.java index 7e95935bef..967fda7db8 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/FloatingDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/FloatingDialog.java @@ -1,15 +1,15 @@ package io.anuke.mindustry.ui.dialogs; import io.anuke.arc.Core; +import io.anuke.arc.Events; import io.anuke.arc.input.KeyCode; +import io.anuke.arc.scene.ui.Dialog; +import io.anuke.arc.scene.ui.ScrollPane; import io.anuke.arc.util.Align; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.game.EventType.ResizeEvent; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.net.Net; -import io.anuke.arc.Events; -import io.anuke.arc.scene.ui.Dialog; -import io.anuke.arc.scene.ui.ScrollPane; import static io.anuke.mindustry.Vars.state; @@ -23,7 +23,7 @@ public class FloatingDialog extends Dialog{ this.title.setAlignment(Align.center); titleTable.row(); titleTable.addImage("white", Pal.accent) - .growX().height(3f).pad(4f); + .growX().height(3f).pad(4f); hidden(() -> { if(shouldPause && !state.is(State.menu)){ @@ -43,14 +43,14 @@ public class FloatingDialog extends Dialog{ boolean[] done = {false}; shown(() -> Core.app.post(() -> - forEach(child -> { - if(done[0]) return; + forEach(child -> { + if(done[0]) return; - if(child instanceof ScrollPane){ - Core.scene.setScrollFocus(child); - done[0] = true; - } - }))); + if(child instanceof ScrollPane){ + Core.scene.setScrollFocus(child); + done[0] = true; + } + }))); } protected void onResize(Runnable run){ @@ -66,7 +66,7 @@ public class FloatingDialog extends Dialog{ buttons.addImageTextButton("$back", "icon-arrow-left", 30f, this::hide).size(210f, 64f); keyDown(key -> { - if(key == KeyCode.ESCAPE || key == KeyCode.BACK) { + if(key == KeyCode.ESCAPE || key == KeyCode.BACK){ Core.app.post(this::hide); } }); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/GameOverDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/GameOverDialog.java index f20e225fe2..ca7cdcf5d7 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/GameOverDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/GameOverDialog.java @@ -14,7 +14,7 @@ public class GameOverDialog extends FloatingDialog{ public GameOverDialog(){ super("$gameover"); - setFillParent(false); + setFillParent(true); shown(this::rebuild); } @@ -31,7 +31,7 @@ public class GameOverDialog extends FloatingDialog{ buttons.margin(10); if(state.rules.pvp){ - cont.add(Core.bundle.format("gameover.pvp",winner.localized())).pad(6); + cont.add(Core.bundle.format("gameover.pvp", winner.localized())).pad(6); buttons.addButton("$menu", () -> { hide(); state.set(State.menu); @@ -43,36 +43,37 @@ public class GameOverDialog extends FloatingDialog{ cont.row(); } - cont.table(t -> { - cont.left().defaults().left(); - cont.add(Core.bundle.format("stat.wave", state.stats.wavesLasted)); - cont.row(); - cont.add(Core.bundle.format("stat.enemiesDestroyed", state.stats.enemyUnitsDestroyed)); - cont.row(); - cont.add(Core.bundle.format("stat.built", state.stats.buildingsBuilt)); - cont.row(); - cont.add(Core.bundle.format("stat.destroyed", state.stats.buildingsDestroyed)); - cont.row(); - cont.add(Core.bundle.format("stat.deconstructed", state.stats.buildingsDeconstructed)); - cont.row(); + cont.pane(t -> { + t.margin(13f); + t.left().defaults().left(); + t.add(Core.bundle.format("stat.wave", state.stats.wavesLasted)); + t.row(); + t.add(Core.bundle.format("stat.enemiesDestroyed", state.stats.enemyUnitsDestroyed)); + t.row(); + t.add(Core.bundle.format("stat.built", state.stats.buildingsBuilt)); + t.row(); + t.add(Core.bundle.format("stat.destroyed", state.stats.buildingsDestroyed)); + t.row(); + t.add(Core.bundle.format("stat.deconstructed", state.stats.buildingsDeconstructed)); + t.row(); if(world.isZone() && !state.stats.itemsDelivered.isEmpty()){ - cont.add("$stat.delivered"); - cont.row(); + t.add("$stat.delivered"); + t.row(); for(Item item : content.items()){ if(state.stats.itemsDelivered.get(item, 0) > 0){ - cont.table(items -> { + t.table(items -> { items.add(" [LIGHT_GRAY]" + state.stats.itemsDelivered.get(item, 0)); - items.addImage(item.icon(Icon.medium)).size(8 *3).pad(4); + items.addImage(item.icon(Icon.medium)).size(8 * 3).pad(4); }).left(); - cont.row(); + t.row(); } } } if(world.isZone()){ RankResult result = state.stats.calculateRank(world.getZone(), state.launched); - cont.add(Core.bundle.format("stat.rank", result.rank + result.modifier)); - cont.row(); + t.add(Core.bundle.format("stat.rank", result.rank + result.modifier)); + t.row(); } }).pad(12); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/HostDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/HostDialog.java index 8771012793..a8f40dc583 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/HostDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/HostDialog.java @@ -6,12 +6,11 @@ import io.anuke.arc.scene.ui.ImageButton; import io.anuke.arc.util.Strings; import io.anuke.arc.util.Time; import io.anuke.mindustry.Vars; -import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.net.Net; import java.io.IOException; -import static io.anuke.mindustry.Vars.players; +import static io.anuke.mindustry.Vars.player; import static io.anuke.mindustry.Vars.ui; public class HostDialog extends FloatingDialog{ @@ -20,8 +19,6 @@ public class HostDialog extends FloatingDialog{ public HostDialog(){ super("$hostserver"); - Player player = players[0]; - addCloseButton(); cont.table(t -> { diff --git a/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java index 91a263aa7c..3771f67ff7 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java @@ -14,7 +14,6 @@ import io.anuke.arc.util.Strings; import io.anuke.arc.util.Time; import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.Platform; -import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.game.Version; import io.anuke.mindustry.net.Host; import io.anuke.mindustry.net.Net; @@ -155,10 +154,10 @@ public class JoinDialog extends FloatingDialog{ 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, ""); + 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, ""); + Core.bundle.format("server.version", host.version, ""); }else{ versionString = Core.bundle.format("server.version", host.version, host.versionType); } @@ -168,12 +167,12 @@ public class JoinDialog extends FloatingDialog{ server.content.table(t -> { t.add(versionString).left(); t.row(); - t.add("[lightgray]" + Core.bundle.format("server.hostname", host.name)).left(); + t.add("[lightgray]" + Core.bundle.format("server.hostname", host.name)).width(targetWidth() - 10f).left().get().setEllipsis(true); t.row(); t.add("[lightgray]" + (host.players != 1 ? Core.bundle.format("players", host.players) : - Core.bundle.format("players.single", host.players))).left(); + 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)).left(); + 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 -> { @@ -185,8 +184,6 @@ public class JoinDialog extends FloatingDialog{ void setup(){ float w = targetWidth(); - Player player = players[0]; - hosts.clear(); hosts.add(remote).growX(); @@ -232,7 +229,7 @@ public class JoinDialog extends FloatingDialog{ pad = 6; } - Cell cell = ((Table) pane.getParent()).getCell(button); + Cell cell = ((Table)pane.getParent()).getCell(button); if(!Mathf.isEqual(cell.getMinWidth(), pw)){ cell.width(pw); @@ -259,7 +256,7 @@ public class JoinDialog extends FloatingDialog{ local.add().growX(); local.addImageButton("icon-loading", 16 * 2f, this::refreshLocal).pad(-12f).padLeft(0).size(70f); }else{ - local.background((Drawable) null); + local.background((Drawable)null); } } @@ -267,8 +264,8 @@ public class JoinDialog extends FloatingDialog{ if(totalHosts == 0){ local.clear(); } - local.background((Drawable) null); - totalHosts ++; + local.background((Drawable)null); + totalHosts++; float w = targetWidth(); local.row(); @@ -295,6 +292,7 @@ public class JoinDialog extends FloatingDialog{ }); Time.runTask(2f, () -> { + logic.reset(); Vars.netClient.beginConnecting(); Net.connect(ip, port, () -> { hide(); @@ -327,7 +325,7 @@ public class JoinDialog extends FloatingDialog{ void setIP(String ip){ //parse ip:port, if unsuccessful, use default values - if(ip.lastIndexOf(':') != -1 && ip.lastIndexOf(':') != ip.length()-1){ + if(ip.lastIndexOf(':') != -1 && ip.lastIndexOf(':') != ip.length() - 1){ try{ int idx = ip.lastIndexOf(':'); this.ip = ip.substring(0, idx); @@ -346,6 +344,7 @@ public class JoinDialog extends FloatingDialog{ return ip + (port != Vars.port ? ":" + port : ""); } - public Server(){} + public Server(){ + } } } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/LanguageDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/LanguageDialog.java index 53317eca9e..006b9c25d9 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/LanguageDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/LanguageDialog.java @@ -1,9 +1,7 @@ package io.anuke.mindustry.ui.dialogs; import io.anuke.arc.Core; -import io.anuke.arc.scene.ui.ButtonGroup; -import io.anuke.arc.scene.ui.ScrollPane; -import io.anuke.arc.scene.ui.TextButton; +import io.anuke.arc.scene.ui.*; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.util.Log; diff --git a/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java index 5b4b7f778c..01e1126217 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java @@ -1,19 +1,17 @@ package io.anuke.mindustry.ui.dialogs; import io.anuke.arc.Core; -import io.anuke.arc.files.FileHandle; import io.anuke.arc.collection.Array; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.core.Platform; -import io.anuke.mindustry.io.SaveIO; -import io.anuke.mindustry.game.Saves.SaveSlot; -import io.anuke.arc.util.Time; +import io.anuke.arc.files.FileHandle; import io.anuke.arc.scene.ui.ScrollPane; import io.anuke.arc.scene.ui.TextButton; import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.arc.util.Log; -import io.anuke.arc.util.Strings; +import io.anuke.arc.util.*; +import io.anuke.mindustry.Vars; +import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.core.Platform; +import io.anuke.mindustry.game.Saves.SaveSlot; +import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.io.SaveIO.SaveException; import java.io.IOException; diff --git a/core/src/io/anuke/mindustry/ui/dialogs/LocalPlayerDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/LocalPlayerDialog.java deleted file mode 100644 index 59f23e65ec..0000000000 --- a/core/src/io/anuke/mindustry/ui/dialogs/LocalPlayerDialog.java +++ /dev/null @@ -1,61 +0,0 @@ -package io.anuke.mindustry.ui.dialogs; - -import io.anuke.arc.Core; -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.mindustry.entities.type.Player; - -import static io.anuke.mindustry.Vars.control; -import static io.anuke.mindustry.Vars.players; - -public class LocalPlayerDialog extends FloatingDialog{ - - public LocalPlayerDialog(){ - super("$addplayers"); - - addCloseButton(); - shown(this::rebuild); - } - - private void rebuild(){ - float size = 140f; - - cont.clear(); - - if(players.length > 1){ - cont.addImageButton("icon-cancel", 14 * 2, () -> { - control.removePlayer(); - rebuild(); - }).size(50f, size).pad(5).bottom(); - }else{ - cont.add().size(50f, size); - } - - for(Player player : players){ - Table table = new Table(); - Stack stack = new Stack(); - - stack.add(new Image("button")); - - Image img = new Image(Core.atlas.find("icon-chat")); - img.setScaling(Scaling.fill); - - stack.add(img); - - table.add("Player " + (player.playerIndex + 1)).update(label -> label.setColor(player.color)); - table.row(); - table.add(stack).size(size); - - cont.add(table).pad(5); - } - - if(players.length < 4){ - cont.addImageButton("icon-add", 14 * 2, () -> { - control.addPlayer(players.length); - rebuild(); - }).size(50f, size).pad(5).bottom(); - } - } -} diff --git a/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java index a98770f023..87a6f4c805 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java @@ -3,14 +3,10 @@ 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.scene.ui.Image; -import io.anuke.arc.scene.ui.ScrollPane; -import io.anuke.arc.scene.ui.TextButton; +import io.anuke.arc.scene.ui.*; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.scene.utils.UIUtils; -import io.anuke.arc.util.Log; -import io.anuke.arc.util.Scaling; -import io.anuke.arc.util.Strings; +import io.anuke.arc.util.*; import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.io.MapIO; diff --git a/core/src/io/anuke/mindustry/ui/dialogs/MinimapDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/MinimapDialog.java new file mode 100644 index 0000000000..36f57dc608 --- /dev/null +++ b/core/src/io/anuke/mindustry/ui/dialogs/MinimapDialog.java @@ -0,0 +1,64 @@ +package io.anuke.mindustry.ui.dialogs; + +import io.anuke.arc.Core; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.input.KeyCode; +import io.anuke.arc.scene.event.InputEvent; +import io.anuke.arc.scene.event.InputListener; +import io.anuke.arc.scene.ui.layout.Unit; + +import static io.anuke.mindustry.Vars.mobile; +import static io.anuke.mindustry.Vars.renderer; + +public class MinimapDialog extends FloatingDialog{ + + public MinimapDialog(){ + super("$minimap"); + setFillParent(false); + + shown(this::setup); + + addCloseButton(); + shouldPause = true; + } + + void setup(){ + cont.clear(); + float size = Math.min(Core.graphics.getWidth(), Core.graphics.getHeight()) / Unit.dp.scl(1f) / 1.3f; + + cont.table("pane", t -> { + t.addRect((x, y, width, height) -> { + if(renderer.minimap.getRegion() == null) return; + Draw.color(Color.WHITE); + Draw.rect(renderer.minimap.getRegion(), x + width / 2f, y + height / 2f, width, height); + + if(renderer.minimap.getTexture() != null){ + renderer.minimap.drawEntities(x, y, width, height); + } + }).grow(); + }).size(size); + + cont.addListener(new InputListener(){ + @Override + public boolean scrolled(InputEvent event, float x, float y, float amountx, float amounty){ + renderer.minimap.zoomBy(amounty); + return true; + } + + @Override + public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button){ + return true; + } + + @Override + public void touchDragged(InputEvent event, float x, float y, int pointer){ + if(mobile){ + renderer.minimap.zoomBy(Core.input.deltaY(pointer) / 30f / Unit.dp.scl(1f)); + } + } + }); + + Core.app.post(() -> Core.scene.setScrollFocus(cont)); + } +} diff --git a/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java index 77e071c8a6..452c4e2627 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java @@ -18,7 +18,7 @@ public class PausedDialog extends FloatingDialog{ shown(this::rebuild); keyDown(key -> { - if(key == KeyCode.ESCAPE || key == KeyCode.BACK) { + if(key == KeyCode.ESCAPE || key == KeyCode.BACK){ hide(); } }); @@ -37,7 +37,7 @@ public class PausedDialog extends FloatingDialog{ float dw = 210f; cont.defaults().width(dw).height(50).pad(5f); - cont.addButton("$back", this::hide).colspan(2).width(dw*2 + 20f); + cont.addButton("$back", this::hide).colspan(2).width(dw * 2 + 20f); cont.row(); if(world.isZone()){ @@ -55,7 +55,7 @@ public class PausedDialog extends FloatingDialog{ cont.row(); - cont.addButton("$hostserver", ui.host::show).disabled(b -> Net.active()).colspan(2).width(dw*2 + 20f); + cont.addButton("$hostserver", ui.host::show).disabled(b -> Net.active()).colspan(2).width(dw * 2 + 20f); cont.row(); @@ -97,7 +97,7 @@ public class PausedDialog extends FloatingDialog{ public void runExitSave(){ if(control.saves.getCurrent() == null || - !control.saves.getCurrent().isAutosave()){ + !control.saves.getCurrent().isAutosave()){ state.set(State.menu); return; } @@ -107,7 +107,7 @@ public class PausedDialog extends FloatingDialog{ control.saves.getCurrent().save(); }catch(Throwable e){ e.printStackTrace(); - ui.showError("[accent]" + Core.bundle.get("savefail")); + ui.showError("[accent]" + Core.bundle.get("savefail")); } state.set(State.menu); }); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/SaveDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/SaveDialog.java index 9baf019de2..004a1fafe5 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/SaveDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/SaveDialog.java @@ -22,13 +22,13 @@ 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.loadAnd("$saving", () -> { - control.saves.addSave(text); - Core.app.post(() -> Core.app.post(this::setup)); - }); - }) + slots.addImageTextButton("$save.new", "icon-add", 14 * 3, () -> + ui.showTextInput("$save", "$save.newslot", "", text -> { + ui.loadAnd("$saving", () -> { + control.saves.addSave(text); + Core.app.post(() -> Core.app.post(this::setup)); + }); + }) ).fillX().margin(10f).minWidth(300f).height(70f).pad(4f).padRight(-4); } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java index fa55b6534d..403d24d44b 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java @@ -14,6 +14,7 @@ import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.util.Align; import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.net.Net; @@ -49,7 +50,7 @@ public class SettingsMenuDialog extends SettingsDialog{ title.setAlignment(Align.center); titleTable.row(); titleTable.add(new Image("white")) - .growX().height(3f).pad(4f).get().setColor(Pal.accent); + .growX().height(3f).pad(4f).get().setColor(Pal.accent); cont.clearChildren(); cont.remove(); @@ -177,8 +178,12 @@ 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("chatopacity", 100, 0, 100, 5, s -> s + "%"); + if(!mobile){ + graphics.sliderPref("antialias", 0, 0, 5, 1, s -> (s == 0 ? 0 : (1 << s)) + "x"); + graphics.checkPref("vsync", true, b -> Core.graphics.setVSync(b)); graphics.checkPref("fullscreen", false, b -> { if(b){ @@ -192,12 +197,28 @@ public class SettingsMenuDialog extends SettingsDialog{ if(Core.settings.getBool("fullscreen")){ Core.graphics.setFullscreenMode(Core.graphics.getDisplayMode()); } + }else{ + graphics.checkPref("landscape", false, b -> { + if(b){ + Platform.instance.beginForceLandscape(); + }else{ + Platform.instance.endForceLandscape(); + } + }); + + if(Core.settings.getBool("landscape")){ + Platform.instance.beginForceLandscape(); + } } + graphics.checkPref("playerchat", true); + graphics.checkPref("minimap", !mobile); graphics.checkPref("fps", false); graphics.checkPref("indicators", true); - graphics.checkPref("animatedwater", !mobile); + graphics.checkPref("animatedwater", false); + graphics.checkPref("animatedshields", !mobile); graphics.checkPref("lasers", true); + graphics.checkPref("pixelate", false); } private void back(){ diff --git a/core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java index a8ace4a842..ce6d71f580 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java @@ -7,8 +7,10 @@ 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; @@ -46,7 +48,7 @@ public class TechTreeDialog extends FloatingDialog{ hidden(ui.deploy::setup); addCloseButton(); - buttons.addImageTextButton("$database", "icon-database", 14*2, () -> { + buttons.addImageTextButton("$database", "icon-database", 14 * 2, () -> { hide(); ui.database.show(); }).size(210f, 64f); @@ -94,7 +96,7 @@ public class TechTreeDialog extends FloatingDialog{ table.setName("toast"); table.update(() -> { table.toFront(); - table.setPosition(Core.graphics.getWidth()/2f, Core.graphics.getHeight() - 21, Align.top); + table.setPosition(Core.graphics.getWidth() / 2f, Core.graphics.getHeight() - 21, Align.top); }); Core.scene.add(table); } @@ -150,6 +152,21 @@ public class TechTreeDialog extends FloatingDialog{ if(mobile){ hoverNode = button; rebuild(); + float right = infoTable.getRight(); + if(right > Core.graphics.getWidth()){ + float moveBy = right - Core.graphics.getWidth(); + addAction(new RelativeTemporalAction(){ + { + setDuration(0.1f); + setInterpolation(Interpolation.fade); + } + + @Override + protected void updateRelative(float percentDelta){ + panX -= moveBy * percentDelta; + } + }); + } }else if(data.hasItems(node.node.requirements) && locked(node.node)){ unlock(node.node); } @@ -172,15 +189,25 @@ public class TechTreeDialog extends FloatingDialog{ button.setSize(nodeSize); 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" : "content-background-locked"); + 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"); ((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-tree-locked")); button.getImage().setColor(!locked(node.node) ? Color.WHITE : Color.GRAY); }); addChild(button); } + if(mobile){ + tapped(() -> { + Element e = hit(Core.input.mouseX(), Core.input.mouseY(), true); + if(e == this){ + hoverNode = null; + rebuild(); + } + }); + } + dragged((x, y) -> { moved = true; panX += x; @@ -222,7 +249,7 @@ public class TechTreeDialog extends FloatingDialog{ infoTable.margin(0).left().defaults().left(); - infoTable.addImageButton("icon-info", "node", 14*2, () -> ui.content.show(node.block)).growY().width(50f); + infoTable.addImageButton("icon-info", "node", 14 * 2, () -> ui.content.show(node.block)).growY().width(50f); infoTable.add().grow(); @@ -251,17 +278,18 @@ public class TechTreeDialog extends FloatingDialog{ if(mobile && locked(node)){ infoTable.row(); - infoTable.addImageTextButton("$research", "icon-check", "node", 16*2, () -> unlock(node)) + infoTable.addImageTextButton("$research", "icon-check", "node", 16 * 2, () -> unlock(node)) .disabled(b -> !data.hasItems(node.requirements)).growX().height(44f).colspan(3); } addChild(infoTable); infoTable.pack(); + infoTable.act(Core.graphics.getDeltaTime()); } @Override public void draw(){ - float offsetX = panX + width/2f + x, offsetY = panY + height/2f + y; + float offsetX = panX + width / 2f + x, offsetY = panY + height / 2f + y; for(TechTreeNode node : nodes){ if(!node.visible) continue; diff --git a/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java index bb5ef324f5..fc716b74a7 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java @@ -6,10 +6,8 @@ import io.anuke.arc.scene.ui.Button; import io.anuke.arc.scene.ui.TextButton; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.graphics.Pal; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.type.ItemType; -import io.anuke.mindustry.type.Zone; +import io.anuke.mindustry.type.*; +import io.anuke.mindustry.type.Zone.ZoneRequirement; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block.Icon; @@ -41,14 +39,17 @@ public class ZoneInfoDialog extends FloatingDialog{ Runnable rebuildItems = () -> { int i = 0; iteminfo.clear(); - ItemStack[] stacks = zone.unlocked() ? zone.getLaunchCost() : zone.itemRequirements; + + if(!zone.unlocked()) return; + + ItemStack[] stacks = zone.getLaunchCost(); for(ItemStack stack : stacks){ if(stack.amount == 0) continue; if(i++ % 2 == 0){ iteminfo.row(); } - iteminfo.addImage(stack.item.icon(Item.Icon.medium)).size(8*3).padRight(1); + iteminfo.addImage(stack.item.icon(Item.Icon.medium)).size(8 * 3).padRight(1); iteminfo.add(stack.amount + "").color(Color.LIGHT_GRAY).padRight(5); } }; @@ -69,11 +70,11 @@ public class ZoneInfoDialog extends FloatingDialog{ req.table(r -> { r.add("$complete").colspan(2).left(); r.row(); - for(Zone other : zone.zoneRequirements){ + for(ZoneRequirement other : zone.zoneRequirements){ r.addImage("icon-zone").padRight(4); - r.add(other.localizedName()).color(Color.LIGHT_GRAY); - r.addImage(other.isCompleted() ? "icon-check-2" : "icon-cancel-2") - .color(other.isCompleted() ? Color.LIGHT_GRAY : Color.SCARLET).padLeft(3); + 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.row(); } }); @@ -124,10 +125,17 @@ public class ZoneInfoDialog extends FloatingDialog{ rebuildLoadout[0] = () -> { load.clear(); float bsize = 40f; - int step = 100; + int step = 50; load.left(); for(ItemStack stack : zone.getStartingItems()){ + load.addButton("x", () -> { + zone.getStartingItems().remove(stack); + zone.updateLaunchCost(); + rebuildItems.run(); + rebuildLoadout[0].run(); + }).size(bsize).pad(2); + load.addButton("-", () -> { stack.amount = Math.max(stack.amount - step, 0); zone.updateLaunchCost(); @@ -157,7 +165,7 @@ public class ZoneInfoDialog extends FloatingDialog{ }).size(300f, 35f).pad(1).get(); button.clearChildren(); button.left(); - button.addImage(item.icon(Item.Icon.medium)).size(8*3).pad(4); + button.addImage(item.icon(Item.Icon.medium)).size(8 * 3).pad(4); button.add(item.localizedName); dialog.cont.row(); } @@ -183,7 +191,6 @@ public class ZoneInfoDialog extends FloatingDialog{ Button button = cont.addButton(zone.locked() ? "$uncover" : "$launch", () -> { if(!data.isUnlocked(zone)){ - data.removeItems(zone.itemRequirements); data.unlockContent(zone); ui.deploy.setup(); setup(zone); @@ -204,8 +211,8 @@ public class ZoneInfoDialog extends FloatingDialog{ return true; } - for(Zone other : zone.zoneRequirements){ - if(!other.isCompleted()){ + for(ZoneRequirement other : zone.zoneRequirements){ + if(other.zone.bestWave() < other.wave){ return false; } } @@ -216,6 +223,6 @@ public class ZoneInfoDialog extends FloatingDialog{ } } - return data.hasItems(zone.itemRequirements); + return true; } } diff --git a/core/src/io/anuke/mindustry/ui/fragments/BackgroundFragment.java b/core/src/io/anuke/mindustry/ui/fragments/BackgroundFragment.java index de0b8851cb..1914fbf8fa 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/BackgroundFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/BackgroundFragment.java @@ -1,9 +1,7 @@ package io.anuke.mindustry.ui.fragments; import io.anuke.arc.Core; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Fill; -import io.anuke.arc.graphics.g2d.TextureRegion; +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; @@ -23,13 +21,13 @@ public class BackgroundFragment extends Fragment{ Draw.shader(); boolean portrait = Core.graphics.getWidth() < Core.graphics.getHeight(); - float logoscl = (int) Unit.dp.scl(1); + 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); + 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 4dc0efa263..e51801c200 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/BlockConfigFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/BlockConfigFragment.java @@ -14,8 +14,7 @@ import io.anuke.mindustry.input.InputHandler; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; -import static io.anuke.mindustry.Vars.state; -import static io.anuke.mindustry.Vars.tilesize; +import static io.anuke.mindustry.Vars.*; public class BlockConfigFragment extends Fragment{ private Table table = new Table(); @@ -51,7 +50,7 @@ public class BlockConfigFragment extends Fragment{ table.pack(); table.setTransform(true); table.actions(Actions.scaleTo(0f, 1f), Actions.visible(true), - Actions.scaleTo(1f, 1f, 0.07f, Interpolation.pow3Out)); + Actions.scaleTo(1f, 1f, 0.07f, Interpolation.pow3Out)); table.update(() -> { if(state.is(State.menu)){ @@ -59,7 +58,7 @@ public class BlockConfigFragment extends Fragment{ return; } - if(configTile != null && configTile.block().shouldHideConfigure(configTile, input.player)){ + 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 4d65d33136..77e0670121 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java @@ -11,14 +11,9 @@ import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.scene.Group; import io.anuke.arc.scene.actions.Actions; -import io.anuke.arc.scene.event.HandCursorListener; -import io.anuke.arc.scene.event.InputEvent; -import io.anuke.arc.scene.event.InputListener; -import io.anuke.arc.scene.event.Touchable; +import io.anuke.arc.scene.event.*; import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.arc.util.Align; -import io.anuke.arc.util.Strings; -import io.anuke.arc.util.Time; +import io.anuke.arc.util.*; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.gen.Call; @@ -31,7 +26,7 @@ import io.anuke.mindustry.world.Tile; import static io.anuke.mindustry.Vars.*; public class BlockInventoryFragment extends Fragment{ - private final static float holdWithdraw = 40f; + private final static float holdWithdraw = 20f; private Table table; private Tile tile; @@ -87,8 +82,6 @@ public class BlockInventoryFragment extends Fragment{ private void rebuild(boolean actions){ - Player player = input.player; - IntSet container = new IntSet(); table.clearChildren(); @@ -182,18 +175,18 @@ public class BlockInventoryFragment extends Fragment{ if(actions){ table.actions(Actions.scaleTo(0f, 1f), Actions.visible(true), - Actions.scaleTo(1f, 1f, 0.07f, Interpolation.pow3Out)); + Actions.scaleTo(1f, 1f, 0.07f, Interpolation.pow3Out)); } } private String round(float f){ - f = (int) f; + f = (int)f; if(f >= 1000000){ - return Strings.toFixed(f / 1000000f, 1) + "[gray]mil[]"; + return Strings.fixed(f / 1000000f, 1) + "[gray]mil[]"; }else if(f >= 1000){ - return Strings.toFixed(f / 1000, 1) + "k"; + return Strings.fixed(f / 1000, 1) + "k"; }else{ - return (int) f + ""; + return (int)f + ""; } } diff --git a/core/src/io/anuke/mindustry/ui/fragments/ChatFragment.java b/core/src/io/anuke/mindustry/ui/fragments/ChatFragment.java index 40083a7524..df9e17abdf 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/ChatFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/ChatFragment.java @@ -1,16 +1,12 @@ package io.anuke.mindustry.ui.fragments; import io.anuke.arc.Core; +import io.anuke.arc.Input.TextInput; import io.anuke.arc.collection.Array; import io.anuke.arc.graphics.Color; -import io.anuke.arc.graphics.g2d.BitmapFont; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Fill; -import io.anuke.arc.graphics.g2d.GlyphLayout; -import io.anuke.arc.input.KeyCode; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Mathf; import io.anuke.arc.scene.Group; -import io.anuke.arc.scene.ui.Dialog; import io.anuke.arc.scene.ui.Label; import io.anuke.arc.scene.ui.Label.LabelStyle; import io.anuke.arc.scene.ui.TextField; @@ -85,7 +81,7 @@ public class ChatFragment extends Table{ historyPos--; updateChat(); } - scrollPos = (int) Mathf.clamp(scrollPos + input.axis(Binding.chat_scroll), 0, Math.max(0, messages.size - messagesShown)); + scrollPos = (int)Mathf.clamp(scrollPos + input.axis(Binding.chat_scroll), 0, Math.max(0, messages.size - messagesShown)); } }); @@ -109,41 +105,12 @@ public class ChatFragment extends Table{ fieldlabel.setStyle(fieldlabel.getStyle()); chatfield = new TextField("", new TextField.TextFieldStyle(scene.skin.get(TextField.TextFieldStyle.class))); - chatfield.setTextFieldFilter((field, c) -> field.getText().length() < Vars.maxTextLength); + chatfield.setFilter((field, c) -> field.getText().length() < Vars.maxTextLength); chatfield.getStyle().background = null; chatfield.getStyle().font = scene.skin.getFont("default-font-chat"); chatfield.getStyle().fontColor = Color.WHITE; chatfield.setStyle(chatfield.getStyle()); - if(mobile){ - chatfield.tapped(() -> { - Dialog dialog = new Dialog("", "dialog"); - dialog.setFillParent(true); - dialog.cont.top(); - dialog.cont.defaults().height(65f); - TextField to = dialog.cont.addField("", t-> {}).pad(15).width(250f).get(); - to.setMaxLength(maxTextLength); - to.keyDown(KeyCode.ENTER, () -> { - dialog.cont.find("okb").fireClick(); - }); - dialog.cont.addButton("$ok", () -> { - chatfield.clearText(); - chatfield.appendText(to.getText()); - chatfield.change(); - dialog.hide(); - Core.input.setOnscreenKeyboardVisible(false); - toggle(); - }).width(90f).name("okb"); - - dialog.show(); - Time.runTask(1f, () -> { - to.setCursorPosition(to.getText().length()); - Core.scene.setKeyboardFocus(to); - Core.input.setOnscreenKeyboardVisible(true); - }); - }); - } - bottom().left().marginBottom(offsety).marginLeft(offsetx * 2).add(fieldlabel).padBottom(6f); add(chatfield).padBottom(offsety).padLeft(offsetx).growX().padRight(offsetx).height(28); @@ -156,6 +123,7 @@ public class ChatFragment extends Table{ @Override public void draw(){ + float opacity = Core.settings.getInt("chatopacity") / 100f; Draw.color(shadowColor); @@ -171,6 +139,7 @@ public class ChatFragment extends Table{ fieldlabel.visible(chatOpen); Draw.color(shadowColor); + Draw.alpha(shadowColor.a * opacity); float theight = offsety + spacing + getMarginBottom(); for(int i = scrollPos; i < messages.size && i < messagesShown + scrollPos && (i < fadetime || chatOpen); i++){ @@ -183,12 +152,15 @@ public class ChatFragment extends Table{ font.getCache().addText(messages.get(i).formattedMessage, fontoffsetx + offsetx, offsety + theight, textWidth, Align.bottomLeft, true); if(!chatOpen && fadetime - i < 1f && fadetime - i >= 0f){ - font.getCache().setAlphas(fadetime - i); - Draw.color(0, 0, 0, shadowColor.a * (fadetime - i)); + font.getCache().setAlphas((fadetime - i) * opacity); + Draw.color(0, 0, 0, shadowColor.a * (fadetime - i) * opacity); + }else{ + font.getCache().setAlphas(opacity); } Fill.crect(offsetx, theight - layout.height - 2, textWidth + Unit.dp.scl(4f), layout.height + textspacing); Draw.color(shadowColor); + Draw.alpha(opacity * shadowColor.a); font.getCache().draw(); } @@ -207,15 +179,28 @@ public class ChatFragment extends Table{ history.insert(1, message); - Call.sendMessage(players[0], message); + Call.sendChatMessage(message); } public void toggle(){ if(!chatOpen){ scene.setKeyboardFocus(chatfield); - chatfield.fireClick(); chatOpen = !chatOpen; + if(mobile){ + TextInput input = new TextInput(); + input.maxLength = maxTextLength; + input.accepted = text -> { + chatfield.setText(text); + sendMessage(); + hide(); + Core.input.setOnscreenKeyboardVisible(false); + }; + input.canceled = this::hide; + Core.input.getTextInput(input); + }else{ + chatfield.fireClick(); + } }else{ scene.setKeyboardFocus(null); chatOpen = !chatOpen; diff --git a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java index 2727032970..ef847fb53e 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java @@ -11,18 +11,11 @@ import io.anuke.arc.scene.Element; import io.anuke.arc.scene.Group; import io.anuke.arc.scene.actions.Actions; import io.anuke.arc.scene.event.Touchable; -import io.anuke.arc.scene.ui.Image; -import io.anuke.arc.scene.ui.ImageButton; -import io.anuke.arc.scene.ui.TextButton; -import io.anuke.arc.scene.ui.layout.Stack; -import io.anuke.arc.scene.ui.layout.Table; +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.Align; -import io.anuke.arc.util.Scaling; -import io.anuke.arc.util.Time; -import io.anuke.arc.util.Tmp; +import io.anuke.arc.util.*; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.game.EventType.PlayEvent; import io.anuke.mindustry.game.EventType.StateChangeEvent; import io.anuke.mindustry.game.UnlockableContent; import io.anuke.mindustry.gen.Call; @@ -30,10 +23,11 @@ import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.input.Binding; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Packets.AdminAction; -import io.anuke.mindustry.ui.Bar; -import io.anuke.mindustry.ui.IntFormat; +import io.anuke.mindustry.ui.*; import io.anuke.mindustry.ui.dialogs.FloatingDialog; +import java.lang.StringBuilder; + import static io.anuke.mindustry.Vars.*; public class HudFragment extends Fragment{ @@ -49,16 +43,6 @@ public class HudFragment extends Fragment{ private float coreAttackTime; private float lastCoreHP; private float coreAttackOpacity = 0f; - private Table goshDarnHeckingFlippedTableWhyDoesThisHappen; - - { - Events.on(PlayEvent.class, event -> { - if(goshDarnHeckingFlippedTableWhyDoesThisHappen != null){ - goshDarnHeckingFlippedTableWhyDoesThisHappen.invalidateHierarchy(); - goshDarnHeckingFlippedTableWhyDoesThisHappen.pack(); - } - }); - } public void build(Group parent){ @@ -67,8 +51,11 @@ public class HudFragment extends Fragment{ cont.top().left().visible(() -> !state.is(State.menu)); if(mobile){ - cont.table(select -> { - goshDarnHeckingFlippedTableWhyDoesThisHappen = select; + + { + Table select = new Table(); + + select.visible(() -> !state.is(State.menu)); select.left(); select.defaults().size(dsize).left(); @@ -111,7 +98,27 @@ public class HudFragment extends Fragment{ }).get(); select.addImage("blank").color(Pal.accent).width(3f).fillY(); - }).left(); + + float size = Unit.dp.scl(dsize); + Array children = new Array<>(select.getChildren()); + + int index = 0; + for(Element elem : children){ + int fi = index++; + Core.scene.add(elem); + elem.visible(() -> { + if(fi < 4){ + elem.setSize(size); + }else{ + elem.setSize(3f, size); + } + elem.setPosition(fi * size, Core.graphics.getHeight(), Align.topLeft); + return !state.is(State.menu); + }); + } + + cont.add().size(dsize * 4 + 3, dsize).left(); + } cont.row(); cont.addImage("blank").height(3f).color(Pal.accent).fillX(); @@ -138,21 +145,25 @@ public class HudFragment extends Fragment{ stuff.add(stack).width(dsize * 4 + 3f); stuff.row(); stuff.table("button", t -> t.margin(10f).add(new Bar("boss.health", Pal.health, () -> state.boss() == null ? 0f : state.boss().healthf()).blink(Color.WHITE)) - .grow()).fillX().visible(() -> state.rules.waves && state.boss() != null).height(60f).get(); + .grow()).fillX().visible(() -> state.rules.waves && state.boss() != null).height(60f).get(); stuff.row(); }).visible(() -> shown); + + //fps display + cont.table(info -> { + info.top().left().margin(4).visible(() -> Core.settings.getBool("fps")); + info.update(() -> info.setTranslation(state.rules.waves ? 0f : -Unit.dp.scl(dsize * 4 + 3), 0)); + IntFormat fps = new IntFormat("fps"); + IntFormat ping = new IntFormat("ping"); + + info.label(() -> fps.get(Core.graphics.getFramesPerSecond())).left(); + info.row(); + info.label(() -> ping.get(Net.getPing())).visible(Net::client).left(); + }).top().left(); }); - - //fps display - parent.fill(info -> { - info.top().right().margin(4).visible(() -> Core.settings.getBool("fps") && !state.is(State.menu)); - IntFormat fps = new IntFormat("fps"); - IntFormat ping = new IntFormat("ping"); - info.label(() -> fps.get(Core.graphics.getFramesPerSecond())).right(); - info.row(); - info.label(() -> ping.get(Net.getPing())).visible(Net::client).right(); - }); + //minimap + parent.fill(t -> t.top().right().add(new Minimap()).visible(() -> !state.is(State.menu) && Core.settings.getBool("minimap"))); //spawner warning parent.fill(t -> { @@ -169,11 +180,11 @@ public class HudFragment extends Fragment{ t.touchable(Touchable.disabled); t.visible(() -> !state.is(State.menu)); t.table("flat", c -> c.add("") - .update(l ->{ + .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 - players[0].destructTime) / 60f))); + 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(players[0].isOutOfBounds()), 0.1f); + u.color.a = Mathf.lerpDelta(u.color.a, Mathf.num(player.isOutOfBounds()), 0.1f); }).get().color.a = 0f; }); @@ -184,6 +195,7 @@ public class HudFragment extends Fragment{ //'core is under attack' table parent.fill(t -> { + t.touchable(Touchable.disabled); float notifDuration = 240f; Events.on(StateChangeEvent.class, event -> { @@ -194,13 +206,13 @@ public class HudFragment extends Fragment{ }); t.top().visible(() -> { - if(state.is(State.menu) || state.teams.get(players[0].getTeam()).cores.size == 0 || - state.teams.get(players[0].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(players[0].getTeam()).cores.first().entity.health; + float curr = state.teams.get(player.getTeam()).cores.first().entity.health; if(!Float.isNaN(lastCoreHP) && curr < lastCoreHP){ coreAttackTime = notifDuration; } @@ -218,14 +230,13 @@ public class HudFragment extends Fragment{ return coreAttackOpacity > 0; }); t.table("button", top -> top.add("$coreattack").pad(2) - .update(label -> label.getColor().set(Color.ORANGE).lerp(Color.SCARLET, Mathf.absin(Time.time(), 2f, 1f)))); + .update(label -> label.getColor().set(Color.ORANGE).lerp(Color.SCARLET, Mathf.absin(Time.time(), 2f, 1f)))).touchable(Touchable.disabled); }); //launch button parent.fill(t -> { - t.top().visible(() -> !state.is(State.menu)); + t.top().right().visible(() -> !state.is(State.menu)); TextButton[] testb = {null}; - TextButton button = Elements.newButton("$launch", () -> { FloatingDialog dialog = new FloatingDialog("$launch"); dialog.update(() -> { @@ -250,11 +261,12 @@ public class HudFragment extends Fragment{ testb[0] = button; 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){ @@ -263,17 +275,15 @@ public class HudFragment extends Fragment{ } button.setText(state.enemies() > 0 ? Core.bundle.format("launch.unable", state.enemies()) : Core.bundle.get("launch") + "\n" + - Core.bundle.format("launch.next", state.wave + world.getZone().launchPeriod)); + Core.bundle.format("launch.next", state.wave + world.getZone().launchPeriod)); - button.getLabel().setColor(Tmp.c1.set(Color.WHITE).lerp(state.enemies() > 0 ? Color.WHITE : Pal.accent, - Mathf.absin(Time.time(), 7f, 1f))); + button.getLabel().setColor(Tmp.c1.set(Color.WHITE).lerp(state.enemies() > 0 ? Color.WHITE : Color.SCARLET, + Mathf.absin(Time.time(), 2f, 1f))); }); button.setDisabled(() -> state.enemies() > 0); - button.getLabelCell().left().get().setAlignment(Align.left, Align.left); - - t.add(button).size(350f, 80f); + t.add(button).size(250f, 80f); }); //paused table @@ -439,15 +449,18 @@ public class HudFragment extends Fragment{ builder.append(wavef.get(state.wave)); builder.append("\n"); - if(state.enemies() > 0 && !state.rules.waveTimer){ + if(state.enemies() > 0){ if(state.enemies() == 1){ builder.append(enemyf.get(state.enemies())); }else{ builder.append(enemiesf.get(state.enemies())); } - }else if(state.rules.waveTimer){ - builder.append(waitingf.get((int)(state.wavetime/60))); - }else{ + builder.append("\n"); + } + + if(state.rules.waveTimer){ + builder.append(waitingf.get((int)(state.wavetime / 60))); + }else if(state.enemies() == 0){ builder.append(Core.bundle.get("waiting")); } @@ -460,13 +473,13 @@ public class HudFragment extends Fragment{ private void addPlayButton(Table table){ table.right().addImageButton("icon-play", "right", 30f, () -> { - if(Net.client() && players[0].isAdmin){ - Call.onAdminRequest(players[0], AdminAction.wave); + if(Net.client() && player.isAdmin){ + Call.onAdminRequest(player, AdminAction.wave); }else{ state.wavetime = 0f; } }).growY().fillX().right().width(40f) - .visible(() -> state.rules.waves && ((Net.server() || players[0].isAdmin) || !Net.active()) && state.enemies() == 0 - && (!world.spawner.isSpawning() || !state.rules.waveTimer)); + .visible(() -> state.rules.waves && ((Net.server() || player.isAdmin) || !Net.active()) && state.enemies() == 0 + && !world.spawner.isSpawning()); } } diff --git a/core/src/io/anuke/mindustry/ui/fragments/LoadingFragment.java b/core/src/io/anuke/mindustry/ui/fragments/LoadingFragment.java index 2b178a2125..18876d0e08 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/LoadingFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/LoadingFragment.java @@ -1,11 +1,11 @@ package io.anuke.mindustry.ui.fragments; -import io.anuke.mindustry.graphics.Pal; import io.anuke.arc.scene.Group; import io.anuke.arc.scene.event.Touchable; import io.anuke.arc.scene.ui.Label; import io.anuke.arc.scene.ui.TextButton; import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.graphics.Pal; public class LoadingFragment extends Fragment{ private Table table; @@ -25,7 +25,8 @@ public class LoadingFragment extends Fragment{ t.addImage("white").growX().height(3f).pad(4f).growX().get().setColor(Pal.accent); t.row(); - button = t.addButton("$cancel", () -> {}).pad(20).size(250f, 70f).visible(false).get(); + button = t.addButton("$cancel", () -> { + }).pad(20).size(250f, 70f).visible(false).get(); table = t; }); } diff --git a/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java b/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java index 09671c6f7c..f012fe48ac 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java @@ -34,18 +34,18 @@ 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))); + .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))); + .visible(() -> state.is(State.menu))); } //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))); + (Version.build == -1 ? "custom build" : "build " + Version.build), Version.revision == 0 ? "" : "." + Version.revision)) + .visible(() -> state.is(State.menu))); } private void buildMobile(){ @@ -57,13 +57,13 @@ public class MenuFragment extends Fragment{ 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", Platform.instance::openDonations); + 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)); if(Core.graphics.getWidth() > Core.graphics.getHeight()){ container.add(play); diff --git a/core/src/io/anuke/mindustry/ui/fragments/OverlayFragment.java b/core/src/io/anuke/mindustry/ui/fragments/OverlayFragment.java index f69986634d..6493496d76 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/OverlayFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/OverlayFragment.java @@ -1,9 +1,9 @@ package io.anuke.mindustry.ui.fragments; -import io.anuke.mindustry.input.InputHandler; import io.anuke.arc.scene.Group; +import io.anuke.mindustry.input.InputHandler; -/**Fragment for displaying overlays such as block inventories. One is created for each input handler.*/ +/** Fragment for displaying overlays such as block inventories. One is created for each input handler. */ public class OverlayFragment extends Fragment{ public final BlockInventoryFragment inv; public final BlockConfigFragment config; diff --git a/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java b/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java index 2a05fe64f0..74275cf327 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java @@ -9,11 +9,8 @@ import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.scene.Group; import io.anuke.arc.scene.event.Touchable; import io.anuke.arc.scene.style.TextureRegionDrawable; -import io.anuke.arc.scene.ui.ButtonGroup; -import io.anuke.arc.scene.ui.Image; -import io.anuke.arc.scene.ui.ImageButton; +import io.anuke.arc.scene.ui.*; import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.game.EventType.UnlockEvent; @@ -21,9 +18,7 @@ import io.anuke.mindustry.game.EventType.WorldLoadEvent; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.input.Binding; import io.anuke.mindustry.input.InputHandler; -import io.anuke.mindustry.type.Category; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.ItemStack; +import io.anuke.mindustry.type.*; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block.Icon; import io.anuke.mindustry.world.Tile; @@ -45,20 +40,20 @@ public class PlacementFragment extends Fragment{ //TODO make this configurable final KeyCode[] inputGrid = { - KeyCode.NUM_1, KeyCode.NUM_2, KeyCode.NUM_3, KeyCode.NUM_4, - KeyCode.Q, KeyCode.W, KeyCode.E, KeyCode.R, - KeyCode.A, KeyCode.S, KeyCode.D, KeyCode.F, - KeyCode.Z, KeyCode.X, KeyCode.C, KeyCode.V + KeyCode.NUM_1, KeyCode.NUM_2, KeyCode.NUM_3, KeyCode.NUM_4, + KeyCode.Q, KeyCode.W, KeyCode.E, KeyCode.R, + KeyCode.A, KeyCode.S, KeyCode.D, KeyCode.F, + KeyCode.Z, KeyCode.X, KeyCode.C, KeyCode.V }, inputCatGrid = { - KeyCode.NUM_1, KeyCode.NUM_2, - KeyCode.Q, KeyCode.W, - KeyCode.A, KeyCode.S, - KeyCode.Z, KeyCode.X, KeyCode.C, KeyCode.V + KeyCode.NUM_1, KeyCode.NUM_2, + KeyCode.Q, KeyCode.W, + KeyCode.A, KeyCode.S, + KeyCode.Z, KeyCode.X, KeyCode.C, KeyCode.V }; public PlacementFragment(){ Events.on(WorldLoadEvent.class, event -> { - control.input(0).block = null; + control.input().block = null; rebuild(); }); @@ -123,7 +118,7 @@ public class PlacementFragment extends Fragment{ full.bottom().right().visible(() -> !state.is(State.menu) && ui.hudfrag.shown()); full.table(frame -> { - InputHandler input = control.input(0); + InputHandler input = control.input(); //rebuilds the category table with the correct recipes Runnable rebuildCategory = () -> { @@ -154,8 +149,8 @@ public class PlacementFragment extends Fragment{ button.getStyle().imageUp = new TextureRegionDrawable(block.icon(Icon.medium)); button.update(() -> { //color unplacable things gray - TileEntity core = players[0].getClosestCore(); - Color color = core != null && (core.items.has(block.buildRequirements) || state.rules.infiniteResources) ? Color.WHITE : Color.GRAY; + TileEntity core = player.getClosestCore(); + Color color = 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); }); @@ -192,7 +187,7 @@ public class PlacementFragment extends Fragment{ topTable.table(header -> { header.left(); header.add(new Image(lastDisplay.icon(Icon.medium))).size(8 * 4); - header.labelWrap(() -> !unlocked(lastDisplay) ? Core.bundle.get("blocks.unknown") : lastDisplay.localizedName) + header.labelWrap(() -> !unlocked(lastDisplay) ? Core.bundle.get("block.unknown") : lastDisplay.localizedName) .left().width(190f).padLeft(5); header.add().growX(); if(unlocked(lastDisplay)){ @@ -211,13 +206,14 @@ public class PlacementFragment extends Fragment{ line.addImage(stack.item.icon(Item.Icon.small)).size(8 * 2); line.add(stack.item.localizedName()).color(Color.LIGHT_GRAY).padLeft(2).left(); line.labelWrap(() -> { - TileEntity core = players[0].getClosestCore(); + TileEntity core = player.getClosestCore(); if(core == null || state.rules.infiniteResources) return "*/*"; int amount = core.items.get(stack.item); - String color = (amount < stack.amount / 2f ? "[red]" : amount < stack.amount ? "[accent]" : "[white]"); + int stackamount = Math.round(stack.amount * state.rules.buildCostMultiplier); + String color = (amount < stackamount / 2f ? "[red]" : amount < stackamount ? "[accent]" : "[white]"); - return color + ui.formatAmount(amount) + "[white]/" + stack.amount; + return color + ui.formatAmount(amount) + "[white]/" + stackamount; }).padLeft(5); }).left(); req.row(); @@ -231,7 +227,7 @@ public class PlacementFragment extends Fragment{ t.add(new Image(lastDisplay.getDisplayIcon(hoverTile))).size(8 * 4); t.labelWrap(lastDisplay.getDisplayName(hoverTile)).left().width(190f).padLeft(5); }).growX().left(); - if(hoverTile.getTeam() == players[0].getTeam()){ + if(hoverTile.getTeam() == player.getTeam()){ topTable.row(); topTable.table(t -> { t.left().defaults().left(); @@ -291,7 +287,7 @@ public class PlacementFragment extends Fragment{ returnCatArray.sort((c1, c2) -> Boolean.compare(categoryEmpty[c1.ordinal()], categoryEmpty[c2.ordinal()])); return returnCatArray; } - + Array getByCategory(Category cat){ returnArray.clear(); for(Block block : content.blocks()){ @@ -326,8 +322,8 @@ public class PlacementFragment extends Fragment{ } //block currently selected - if(control.input(0).block != null){ - toDisplay = control.input(0).block; + if(control.input().block != null){ + toDisplay = control.input().block; } //block hovered on in build menu @@ -340,6 +336,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.ore() != Blocks.air ? hoverTile.ore() : null; + return hoverTile == null ? null : hoverTile.block().synthetic() ? hoverTile.block() : hoverTile.overlay().itemDrop != null ? hoverTile.overlay() : 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 dbad24b6a6..544fbd5ce7 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java @@ -69,10 +69,10 @@ public class PlayerListFragment extends Fragment{ playerGroup.all().sort((p1, p2) -> p1.getTeam().compareTo(p2.getTeam())); - playerGroup.forEach(player -> { - NetConnection connection = player.con; + playerGroup.forEach(user -> { + NetConnection connection = user.con; - if(connection == null && Net.server() && !player.isLocal) return; + if(connection == null && Net.server() && !user.isLocal) return; Table button = new Table(); button.left(); @@ -90,15 +90,15 @@ public class PlayerListFragment extends Fragment{ } }; table.margin(8); - table.add(new Image(player.mech.iconRegion)).grow(); + table.add(new Image(user.mech.iconRegion)).grow(); button.add(table).size(h); - button.labelWrap("[#" + player.color.toString().toUpperCase() + "]" + player.name).width(170f).pad(10); + button.labelWrap("[#" + user.color.toString().toUpperCase() + "]" + user.name).width(170f).pad(10); button.add().grow(); - button.addImage("icon-admin").size(14 * 2).visible(() -> player.isAdmin && !(!player.isLocal && Net.server())).padRight(5).get().updateVisibility(); + button.addImage("icon-admin").size(14 * 2).visible(() -> user.isAdmin && !(!user.isLocal && Net.server())).padRight(5).get().updateVisibility(); - if((Net.server() || players[0].isAdmin) && !player.isLocal && (!player.isAdmin || Net.server())){ + if((Net.server() || player.isAdmin) && !user.isLocal && (!user.isAdmin || Net.server())){ button.add().growY(); float bs = (h) / 2f; @@ -107,36 +107,36 @@ public class PlayerListFragment extends Fragment{ t.defaults().size(bs); t.addImageButton("icon-ban", "clear-partial", 14 * 2, - () -> ui.showConfirm("$confirm", "$confirmban", () -> Call.onAdminRequest(player, AdminAction.ban))); + () -> ui.showConfirm("$confirm", "$confirmban", () -> Call.onAdminRequest(user, AdminAction.ban))); t.addImageButton("icon-cancel", "clear-partial", 16 * 2, - () -> ui.showConfirm("$confirm", "$confirmkick", () -> Call.onAdminRequest(player, AdminAction.kick))); + () -> ui.showConfirm("$confirm", "$confirmkick", () -> Call.onAdminRequest(user, AdminAction.kick))); t.row(); t.addImageButton("icon-admin", "clear-toggle-partial", 14 * 2, () -> { if(Net.client()) return; - String id = player.uuid; + String id = user.uuid; if(netServer.admins.isAdmin(id, connection.address)){ ui.showConfirm("$confirm", "$confirmunadmin", () -> netServer.admins.unAdminPlayer(id)); }else{ - ui.showConfirm("$confirm", "$confirmadmin", () -> netServer.admins.adminPlayer(id, player.usid)); + ui.showConfirm("$confirm", "$confirmadmin", () -> netServer.admins.adminPlayer(id, user.usid)); } }) - .update(b -> b.setChecked(player.isAdmin)) + .update(b -> b.setChecked(user.isAdmin)) .disabled(b -> Net.client()) .touchable(() -> Net.client() ? Touchable.disabled : Touchable.enabled) - .checked(player.isAdmin); + .checked(user.isAdmin); - t.addImageButton("icon-zoom-small", "clear-partial", 14 * 2, () -> ui.showError("Currently unimplemented.")/*Call.onAdminRequest(player, AdminAction.trace)*/); + t.addImageButton("icon-zoom-small", "clear-partial", 14 * 2, () -> ui.showError("Currently unimplemented.")/*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 ? player.getTeam().color : Pal.accent).growX(); + content.addImage("blank").height(3f).color(state.rules.pvp ? user.getTeam().color : Pal.accent).growX(); content.row(); }); diff --git a/core/src/io/anuke/mindustry/world/Block.java b/core/src/io/anuke/mindustry/world/Block.java index 749ee5cc64..bbcd360ecf 100644 --- a/core/src/io/anuke/mindustry/world/Block.java +++ b/core/src/io/anuke/mindustry/world/Block.java @@ -19,20 +19,14 @@ import io.anuke.mindustry.entities.Damage; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.effect.Puddle; import io.anuke.mindustry.entities.effect.RubbleDecal; -import io.anuke.mindustry.entities.type.Player; -import io.anuke.mindustry.entities.type.TileEntity; -import io.anuke.mindustry.entities.type.Unit; +import io.anuke.mindustry.entities.type.*; import io.anuke.mindustry.game.UnlockableContent; -import io.anuke.mindustry.graphics.CacheLayer; -import io.anuke.mindustry.graphics.Layer; -import io.anuke.mindustry.graphics.Pal; +import io.anuke.mindustry.graphics.*; 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.consumers.Consume; -import io.anuke.mindustry.world.consumers.ConsumeLiquid; -import io.anuke.mindustry.world.consumers.ConsumePower; +import io.anuke.mindustry.world.consumers.*; import io.anuke.mindustry.world.meta.*; import java.util.Arrays; @@ -68,7 +62,7 @@ public class Block extends BlockStorage{ public int timers = 0; /** Cache layer. Only used for 'cached' rendering. */ public CacheLayer cacheLayer = CacheLayer.normal; - /**Special flag; if false, floor will be drawn under this block even if it is cached.*/ + /** Special flag; if false, floor will be drawn under this block even if it is cached. */ public boolean fillsTile = true; /** Layer to draw extra stuff on. */ public Layer layer = null; @@ -86,32 +80,44 @@ public class Block extends BlockStorage{ public boolean configurable; /** Whether this block consumes touchDown events when tapped. */ public boolean consumesTap; - /** The color of this block when displayed on the minimap or map preview. - * Do not set manually! This is overriden when loading for most blocks.*/ + /** + * The color of this block when displayed on the minimap or map preview. + * Do not set manually! This is overriden when loading for most blocks. + */ public Color color = new Color(0, 0, 0, 1); - /**Whether units target this block.*/ + /** Whether units target this block. */ public boolean targetable = true; - /**Whether the overdrive core has any effect on this block.*/ + /** Whether the overdrive core has any effect on this block. */ public boolean canOverdrive = true; - /**Whether the icon region has an outline added.*/ + /** Whether the icon region has an outline added. */ public boolean outlineIcon = false; + /** Whether this block has a shadow under it. */ + public boolean hasShadow = true; - /**Cost of constructing this block.*/ + /** Cost of constructing this block. */ public ItemStack[] buildRequirements = new ItemStack[]{}; - /**Category in place menu.*/ + /** Category in place menu. */ public Category buildCategory = Category.distribution; - /**Cost of building this block; do not modify directly!*/ + /** Cost of building this block; do not modify directly! */ public float buildCost; - /**Whether this block is visible and can currently be built.*/ + /** Whether this block is visible and can currently be built. */ public BooleanProvider buildVisibility = () -> false; public boolean alwaysUnlocked = false; + protected TextureRegion[] cacheRegions = {}; + protected Array cacheRegionStrings = new Array<>(); + protected Array tempTiles = new Array<>(); protected TextureRegion[] icons = new TextureRegion[Icon.values().length]; protected TextureRegion[] generatedIcons; protected TextureRegion[] variantRegions, editorVariantRegions; protected TextureRegion region, editorIcon; + /** Dump timer ID.*/ + protected final int timerDump = timers++; + /** How often to try dumping items in ticks, e.g. 5 = 12 times/sec*/ + protected final int dumpTime = 5; + public Block(String name){ super(name); this.description = Core.bundle.getOrNull("block." + name + ".description"); @@ -136,13 +142,17 @@ public class Block extends BlockStorage{ TileEntity entity = tile.entity(); for(Tile other : getPowerConnections(tile, tempTiles)){ - if(other.entity.power != null && other.entity.power.graph != null){ + if(other.entity.power != null){ other.entity.power.graph.add(entity.power.graph); } } } protected void powerGraphRemoved(Tile tile){ + if(tile.entity == null || tile.entity.power == null){ + return; + } + tile.entity.power.graph.remove(tile); for(int i = 0; i < tile.entity.power.links.size; i++){ Tile other = world.tile(tile.entity.power.links.get(i)); @@ -157,8 +167,8 @@ public class Block extends BlockStorage{ if(tile == null || tile.entity == null || tile.entity.power == null) return out; for(Tile other : tile.entity.proximity()){ - if(other.entity.power != null && !(consumesPower && other.block().consumesPower && !outputsPower && !other.block().outputsPower) - && !tile.entity.power.links.contains(other.pos())){ + if(other != null && other.entity != null && other.entity.power != null && !(consumesPower && other.block().consumesPower && !outputsPower && !other.block().outputsPower) + && !tile.entity.power.links.contains(other.pos())){ out.add(other); } } @@ -201,6 +211,8 @@ public class Block extends BlockStorage{ } protected void drawPlaceText(String text, int x, int y, boolean valid){ + if(renderer.pixelator.enabled()) return; + Color color = valid ? Pal.accent : Pal.remove; BitmapFont font = Core.scene.skin.getFont("default-font"); GlyphLayout layout = Pools.obtain(GlyphLayout.class, GlyphLayout::new); @@ -210,10 +222,10 @@ public class Block extends BlockStorage{ layout.setText(font, text); font.setColor(color); - float dx = x*tilesize + offset(), dy = y*tilesize + offset() + size*tilesize/2f + 2; + float dx = x * tilesize + offset(), dy = y * tilesize + offset() + size * tilesize / 2f + 2; font.draw(text, dx, dy + layout.height + 1, Align.center); Lines.stroke(1f, color); - Lines.line(dx - layout.width/2f - 2f, dy, dx + layout.width/2f + 2f, dy); + Lines.line(dx - layout.width / 2f - 2f, dy, dx + layout.width / 2f + 2f, dy); font.setUseIntegerPositions(ints); font.setColor(Color.WHITE); @@ -226,13 +238,9 @@ public class Block extends BlockStorage{ Draw.rect(region, tile.drawx(), tile.drawy(), rotate ? tile.getRotation() * 90 : 0); } - public void drawShadow(Tile tile){ - draw(tile); - } - public void drawTeam(Tile tile){ Draw.color(tile.getTeam().color); - Draw.rect("block-border", tile.drawx() - size * tilesize/2f + 4, tile.drawy() - size * tilesize/2f + 4); + Draw.rect("block-border", tile.drawx() - size * tilesize / 2f + 4, tile.drawy() - size * tilesize / 2f + 4); Draw.color(); } @@ -251,7 +259,7 @@ public class Block extends BlockStorage{ public void unitOn(Tile tile, Unit unit){ } - /** Called when a unit that spawned at this tile is removed.*/ + /** Called when a unit that spawned at this tile is removed. */ public void unitRemoved(Tile tile, Unit unit){ } @@ -261,9 +269,9 @@ public class Block extends BlockStorage{ return true; } - /**Call when some content is produced. This unlocks the content if it is applicable.*/ + /** Call when some content is produced. This unlocks the content if it is applicable. */ public void useContent(Tile tile, UnlockableContent content){ - if(!headless && tile.getTeam() == players[0].getTeam()){ + if(!headless && tile.getTeam() == player.getTeam()){ logic.handleContent(content); } } @@ -285,7 +293,7 @@ public class Block extends BlockStorage{ @Override public TextureRegion getContentIcon(){ - return icon(Icon.medium); + return icon(Icon.large); } @Override @@ -314,12 +322,28 @@ public class Block extends BlockStorage{ setStats(); setBars(); - consumes.checkRequired(this); + consumes.init(); } @Override public void load(){ region = Core.atlas.find(name); + + cacheRegions = new TextureRegion[cacheRegionStrings.size]; + for(int i = 0; i < cacheRegions.length; i++){ + cacheRegions[i] = Core.atlas.find(cacheRegionStrings.get(i)); + } + } + + /** Adds a region by name to be loaded, with the final name "{name}-suffix". Returns an ID to looks this region up by in {@link #reg(int)}. */ + protected int reg(String suffix){ + cacheRegionStrings.add(name + suffix); + return cacheRegionStrings.size - 1; + } + + /** Returns an internally cached region by ID. */ + protected TextureRegion reg(int id){ + return cacheRegions[id]; } /** Called when the block is tapped. */ @@ -372,7 +396,7 @@ public class Block extends BlockStorage{ stats.add(BlockStat.size, "{0}x{0}", size); stats.add(BlockStat.health, health, StatUnit.none); - consumes.forEach(cons -> cons.display(stats)); + consumes.display(stats); // Note: Power stats are added by the consumers. if(hasLiquids) stats.add(BlockStat.liquidCapacity, liquidCapacity, StatUnit.liquidUnits); @@ -384,25 +408,25 @@ public class Block extends BlockStorage{ if(hasLiquids){ Function current; - if(consumes.has(ConsumeLiquid.class)){ - Liquid liquid = consumes.liquid(); + if(consumes.has(ConsumeType.liquid) && consumes.get(ConsumeType.liquid) instanceof ConsumeLiquid){ + Liquid liquid = consumes.get(ConsumeType.liquid).liquid; current = entity -> liquid; }else{ current = entity -> entity.liquids.current(); } - bars.add("liquid", entity -> new Bar(() -> entity.liquids.get(current.get(entity)) <= 0.001f ? Core.bundle.get("blocks.liquid") : current.get(entity).localizedName(), () -> current.get(entity).color, () -> entity.liquids.get(current.get(entity)) / liquidCapacity)); + bars.add("liquid", entity -> new Bar(() -> entity.liquids.get(current.get(entity)) <= 0.001f ? Core.bundle.get("bar.liquid") : current.get(entity).localizedName(), () -> current.get(entity).color, () -> entity.liquids.get(current.get(entity)) / liquidCapacity)); } - if(hasPower && consumes.has(ConsumePower.class)){ - boolean buffered = consumes.get(ConsumePower.class).isBuffered; - float capacity = consumes.get(ConsumePower.class).powerCapacity; + if(hasPower && consumes.hasPower()){ + boolean buffered = consumes.getPower().isBuffered; + float capacity = consumes.getPower().powerCapacity; - bars.add("power", entity -> new Bar(() -> buffered ? Core.bundle.format("blocks.powerbalance", Float.isNaN(entity.power.satisfaction * capacity) ? "" : (int)(entity.power.satisfaction * capacity)) : - Core.bundle.get("blocks.power"), () -> Pal.powerBar, () -> entity.power.satisfaction)); + bars.add("power", entity -> new Bar(() -> buffered ? Core.bundle.format("bar.poweramount", Float.isNaN(entity.power.satisfaction * capacity) ? "" : (int)(entity.power.satisfaction * capacity)) : + Core.bundle.get("bar.power"), () -> Pal.powerBar, () -> entity.power.satisfaction)); } if(hasItems && configurable){ - bars.add("items", entity -> new Bar(() -> Core.bundle.format("blocks.items", entity.items.total()), () -> Pal.items, () -> (float)entity.items.total() / itemCapacity)); + bars.add("items", entity -> new Bar(() -> Core.bundle.format("bar.items", entity.items.total()), () -> Pal.items, () -> (float)entity.items.total() / itemCapacity)); } } @@ -454,8 +478,8 @@ public class Block extends BlockStorage{ explosiveness += tile.entity.liquids.sum((liquid, amount) -> liquid.flammability * amount / 2f); } - if(consumes.has(ConsumePower.class) && consumes.get(ConsumePower.class).isBuffered){ - power += tile.entity.power.satisfaction * consumes.get(ConsumePower.class).powerCapacity; + if(consumes.hasPower() && consumes.getPower().isBuffered){ + power += tile.entity.power.satisfaction * consumes.getPower().powerCapacity; } if(hasLiquids){ @@ -554,18 +578,18 @@ public class Block extends BlockStorage{ draw.rotation = rotation; } - /**Never use outside of the editor!*/ + /** Never use outside of the editor! */ public TextureRegion editorIcon(){ if(editorIcon == null) editorIcon = Core.atlas.find(name + "-icon-editor"); return editorIcon; } - /**Never use outside of the editor!*/ + /** Never use outside of the editor! */ public TextureRegion[] editorVariantRegions(){ if(editorVariantRegions == null){ variantRegions(); editorVariantRegions = new TextureRegion[variantRegions.length]; - for(int i = 0; i < variantRegions.length; i ++){ + for(int i = 0; i < variantRegions.length; i++){ AtlasRegion region = (AtlasRegion)variantRegions[i]; editorVariantRegions[i] = Core.atlas.find("editor-" + region.name); } @@ -631,7 +655,7 @@ public class Block extends BlockStorage{ requirements(cat, () -> true, stacks); } - /**Sets up requirements. Use only this method to set up requirements.*/ + /** Sets up requirements. Use only this method to set up requirements. */ protected void requirements(Category cat, BooleanProvider visible, ItemStack[] stacks){ this.buildCategory = cat; this.buildRequirements = stacks; @@ -644,7 +668,7 @@ public class Block extends BlockStorage{ 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 */ full(0); public final int size; diff --git a/core/src/io/anuke/mindustry/world/BlockStorage.java b/core/src/io/anuke/mindustry/world/BlockStorage.java index 6232f22e4a..b6c6f2e0c1 100644 --- a/core/src/io/anuke/mindustry/world/BlockStorage.java +++ b/core/src/io/anuke/mindustry/world/BlockStorage.java @@ -12,15 +12,10 @@ import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.game.UnlockableContent; import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.Liquid; -import io.anuke.mindustry.world.consumers.ConsumeItem; -import io.anuke.mindustry.world.consumers.ConsumeItems; -import io.anuke.mindustry.world.consumers.ConsumeLiquid; import io.anuke.mindustry.world.consumers.Consumers; import io.anuke.mindustry.world.meta.BlockBars; import io.anuke.mindustry.world.meta.BlockStats; -import io.anuke.mindustry.world.meta.Producers; public abstract class BlockStorage extends UnlockableContent{ public boolean hasItems; @@ -28,7 +23,6 @@ public abstract class BlockStorage extends UnlockableContent{ public boolean hasPower; public boolean outputsLiquid = false; - public boolean singleLiquid = true; public boolean consumesPower = true; public boolean outputsPower = false; @@ -39,7 +33,6 @@ public abstract class BlockStorage extends UnlockableContent{ public final BlockStats stats = new BlockStats(); public final BlockBars bars = new BlockBars(); public final Consumers consumes = new Consumers(); - public final Producers produces = new Producers(); public BlockStorage(String name){ super(name); @@ -53,7 +46,7 @@ public abstract class BlockStorage extends UnlockableContent{ return 0f; } - /**Returns the amount of items this block can accept.*/ + /** Returns the amount of items this block can accept. */ public int acceptStack(Item item, int amount, Tile tile, Unit source){ if(acceptItem(item, tile, tile) && hasItems && (source == null || source.getTeam() == tile.getTeam())){ return Math.min(getMaximumAccepted(tile, item) - tile.entity.items.get(item), amount); @@ -66,15 +59,16 @@ public abstract class BlockStorage extends UnlockableContent{ return itemCapacity; } - /**Remove a stack from this inventory, and return the amount removed.*/ + /** Remove a stack from this inventory, and return the amount removed. */ public int removeStack(Tile tile, Item item, int amount){ + if(tile.entity == null || tile.entity.items == null) return 0; amount = Math.min(amount, tile.entity.items.get(item)); tile.entity.noSleep(); tile.entity.items.remove(item, amount); return amount; } - /**Handle a stack input.*/ + /** Handle a stack input. */ public void handleStack(Item item, int amount, Tile tile, Unit source){ tile.entity.noSleep(); tile.entity.items.add(item, amount); @@ -84,7 +78,7 @@ public abstract class BlockStorage extends UnlockableContent{ return hasItems; } - /**Returns offset for stack placement.*/ + /** Returns offset for stack placement. */ public void getStackOffset(Item item, Tile tile, Vector2 trns){ } @@ -98,21 +92,11 @@ public abstract class BlockStorage extends UnlockableContent{ } public boolean acceptItem(Item item, Tile tile, Tile source){ - if(tile.entity != null && consumes.has(ConsumeItems.class)){ - for(ItemStack stack : consumes.items()){ - if(stack.item == item){ - return tile.entity.items.get(item) < getMaximumAccepted(tile, item); - } - } - } - return tile.entity != null && consumes.has(ConsumeItem.class) && consumes.item() == item && - tile.entity.items.get(item) < getMaximumAccepted(tile, item); + return consumes.itemFilters[item.id] && tile.entity.items.get(item) < getMaximumAccepted(tile, item); } public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ - return hasLiquids && tile.entity.liquids.get(liquid) + amount < liquidCapacity && - (!singleLiquid || (tile.entity.liquids.current() == liquid || tile.entity.liquids.get(tile.entity.liquids.current()) < 0.2f)) && - (!consumes.has(ConsumeLiquid.class) || consumes.liquid() == liquid); + return hasLiquids && tile.entity.liquids.get(liquid) + amount < liquidCapacity && consumes.liquidfilters[liquid.id]; } public void handleLiquid(Tile tile, Tile source, Liquid liquid, float amount){ @@ -128,7 +112,7 @@ public abstract class BlockStorage extends UnlockableContent{ Tile other = proximity.get((i + dump) % proximity.size); Tile in = Edges.getFacingEdge(tile, other); - if(other.getTeamID() == tile.getTeamID() && other.block().hasLiquids && canDumpLiquid(tile, other, liquid)){ + if(other.getTeam() == tile.getTeam() && other.block().hasLiquids && canDumpLiquid(tile, other, liquid)){ float ofract = other.entity.liquids.get(liquid) / other.block().liquidCapacity; float fract = tile.entity.liquids.get(liquid) / liquidCapacity; @@ -156,7 +140,7 @@ public abstract class BlockStorage extends UnlockableContent{ next = next.target(); - if(next.getTeamID() == tile.getTeamID() && next.block().hasLiquids && tile.entity.liquids.get(liquid) > 0f){ + if(next.getTeam() == tile.getTeam() && next.block().hasLiquids && tile.entity.liquids.get(liquid) > 0f){ if(next.block().acceptLiquid(next, tile, liquid, 0f)){ float ofract = next.entity.liquids.get(liquid) / next.block().liquidCapacity; @@ -171,14 +155,14 @@ public abstract class BlockStorage extends UnlockableContent{ }else if(ofract > 0.1f && fract > 0.1f){ Liquid other = next.entity.liquids.current(); if((other.flammability > 0.3f && liquid.temperature > 0.7f) || - (liquid.flammability > 0.3f && other.temperature > 0.7f)){ + (liquid.flammability > 0.3f && other.temperature > 0.7f)){ tile.entity.damage(1 * Time.delta()); next.entity.damage(1 * Time.delta()); if(Mathf.chance(0.1 * Time.delta())){ Effects.effect(Fx.fire, (tile.worldx() + next.worldx()) / 2f, (tile.worldy() + next.worldy()) / 2f); } }else if((liquid.temperature > 0.7f && other.temperature < 0.55f) || - (other.temperature > 0.7f && liquid.temperature < 0.55f)){ + (other.temperature > 0.7f && liquid.temperature < 0.55f)){ tile.entity.liquids.remove(liquid, Math.min(tile.entity.liquids.get(liquid), 0.7f * Time.delta())); if(Mathf.chance(0.2f * Time.delta())){ Effects.effect(Fx.steam, (tile.worldx() + next.worldx()) / 2f, (tile.worldy() + next.worldy()) / 2f); @@ -206,7 +190,7 @@ public abstract class BlockStorage extends UnlockableContent{ incrementDump(tile, proximity.size); Tile other = proximity.get((i + dump) % proximity.size); Tile in = Edges.getFacingEdge(tile, other); - if(other.getTeamID() == tile.getTeamID() && other.block().acceptItem(item, other, in) && canDump(tile, other, item)){ + if(other.getTeam() == tile.getTeam() && other.block().acceptItem(item, other, in) && canDump(tile, other, item)){ other.block().handleItem(item, other, in); return; } @@ -215,16 +199,13 @@ public abstract class BlockStorage extends UnlockableContent{ handleItem(item, tile, tile); } - /** - * Try dumping any item near the tile. - */ + /** Try dumping any item near the tile. */ public boolean tryDump(Tile tile){ return tryDump(tile, null); } /** * Try dumping a specific item near the tile. - * * @param todump Item to dump. Can be null to dump anything. */ public boolean tryDump(Tile tile, Item todump){ @@ -246,7 +227,7 @@ public abstract class BlockStorage extends UnlockableContent{ for(int ii = 0; ii < Vars.content.items().size; ii++){ Item item = Vars.content.item(ii); - if(other.getTeamID() == tile.getTeamID() && entity.items.has(item) && other.block().acceptItem(item, other, in) && canDump(tile, other, item)){ + if(other.getTeam() == tile.getTeam() && entity.items.has(item) && other.block().acceptItem(item, other, in) && canDump(tile, other, item)){ other.block().handleItem(item, other, in); tile.entity.items.remove(item, 1); incrementDump(tile, proximity.size); @@ -255,7 +236,7 @@ public abstract class BlockStorage extends UnlockableContent{ } }else{ - if(other.getTeamID() == tile.getTeamID() && other.block().acceptItem(todump, other, in) && canDump(tile, other, todump)){ + if(other.getTeam() == tile.getTeam() && other.block().acceptItem(todump, other, in) && canDump(tile, other, todump)){ other.block().handleItem(todump, other, in); tile.entity.items.remove(todump, 1); incrementDump(tile, proximity.size); @@ -270,15 +251,15 @@ public abstract class BlockStorage extends UnlockableContent{ } protected void incrementDump(Tile tile, int prox){ - tile.setDump((byte) ((tile.getDump() + 1) % prox)); + tile.setDump((byte)((tile.getDump() + 1) % prox)); } - /** Used for dumping items.*/ + /** Used for dumping items. */ public boolean canDump(Tile tile, Tile to, Item item){ return true; } - /** Try offloading an item to a nearby container in its facing direction. Returns true if success.*/ + /** Try offloading an item to a nearby container in its facing direction. Returns true if success. */ public boolean offloadDir(Tile tile, Item item){ Tile other = tile.getNearby(tile.getRotation()); if(other != null && other.target().getTeamID() == tile.getTeamID() && other.block().acceptItem(item, other, tile)){ @@ -288,7 +269,7 @@ public abstract class BlockStorage extends UnlockableContent{ return false; } - /** Returns whether this block's inventory has space and is ready for production.*/ + /** Returns whether this block's inventory has space and is ready for production. */ public boolean canProduce(Tile tile){ return true; } diff --git a/core/src/io/anuke/mindustry/world/Build.java b/core/src/io/anuke/mindustry/world/Build.java index 9d77ee82f5..cc9b761488 100644 --- a/core/src/io/anuke/mindustry/world/Build.java +++ b/core/src/io/anuke/mindustry/world/Build.java @@ -1,11 +1,11 @@ package io.anuke.mindustry.world; +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.math.Mathf; -import io.anuke.arc.math.geom.Geometry; -import io.anuke.arc.math.geom.Point2; -import io.anuke.arc.math.geom.Rectangle; +import io.anuke.arc.math.geom.*; import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.game.EventType.BlockBuildBeginEvent; @@ -18,7 +18,8 @@ import static io.anuke.mindustry.Vars.*; public class Build{ private static final Rectangle rect = new Rectangle(); - /**Returns block type that was broken, or null if unsuccesful.*/ + /** Returns block type that was broken, or null if unsuccesful. */ + @Remote(called = Loc.server) public static void beginBreak(Team team, int x, int y){ if(!validBreak(team, x, y)){ return; @@ -56,7 +57,7 @@ public class Build{ if(!(worldx == tile.x && worldy == tile.y)){ Tile toplace = world.tile(worldx, worldy); if(toplace != null){ - toplace.setLinked((byte) (dx + offsetx), (byte) (dy + offsety)); + toplace.setLinked((byte)(dx + offsetx), (byte)(dy + offsety)); toplace.setTeam(team); } } @@ -68,7 +69,8 @@ public class Build{ Core.app.post(() -> Events.fire(new BlockBuildBeginEvent(ftile, team, true))); } - /**Places a BuildBlock at this location.*/ + /** Places a BuildBlock at this location. */ + @Remote(called = Loc.server) public static void beginPlace(Team team, int x, int y, Block result, int rotation){ if(!validPlace(team, x, y, result, rotation)){ return; @@ -98,7 +100,7 @@ public class Build{ if(!(worldx == x && worldy == y)){ Tile toplace = world.tile(worldx, worldy); if(toplace != null){ - toplace.setLinked((byte) (dx + offsetx), (byte) (dy + offsety)); + toplace.setLinked((byte)(dx + offsetx), (byte)(dy + offsety)); toplace.setTeam(team); } } @@ -109,21 +111,21 @@ public class Build{ Core.app.post(() -> Events.fire(new BlockBuildBeginEvent(tile, team, false))); } - /**Returns whether a tile can be placed at this location by this team.*/ + /** Returns whether a tile can be placed at this location by this team. */ public static boolean validPlace(Team team, int x, int y, Block type, int rotation){ if(!type.isVisible() || type.isHidden()){ return false; } if((type.solid || type.solidifes) && - Units.anyEntities(rect.setSize(tilesize * type.size).setCenter(x * tilesize + type.offset(), y * tilesize + type.offset()))){ + Units.anyEntities(rect.setSize(tilesize * type.size).setCenter(x * tilesize + type.offset(), y * tilesize + type.offset()))){ return false; } //check for enemy cores for(Team enemy : state.teams.enemiesOf(team)){ for(Tile core : state.teams.get(enemy).cores){ - if(Mathf.dst(x*tilesize + type.offset(), y*tilesize + type.offset(), core.drawx(), core.drawy()) < state.rules.enemyCoreBuildRadius + type.size*tilesize/2f){ + if(Mathf.dst(x * tilesize + type.offset(), y * tilesize + type.offset(), core.drawx(), core.drawy()) < state.rules.enemyCoreBuildRadius + type.size * tilesize / 2f){ return false; } } @@ -152,8 +154,8 @@ public class Build{ for(int dy = 0; dy < type.size; dy++){ Tile other = world.tile(x + dx + offsetx, y + dy + offsety); if(other == null || (other.block() != Blocks.air && !other.block().alwaysReplace) || - !other.floor().placeableOn || - (other.floor().isLiquid && !type.floating)){ + !other.floor().placeableOn || + (other.floor().isDeep() && !type.floating)){ return false; } } @@ -161,12 +163,12 @@ public class Build{ return true; }else{ return tile.interactable(team) - && contactsGround(tile.x, tile.y, type) - && (!tile.floor().isLiquid || type.floating) - && tile.floor().placeableOn - && ((type.canReplace(tile.block()) - && !(type == tile.block() && rotation == tile.getRotation() && type.rotate)) || tile.block().alwaysReplace || tile.block() == Blocks.air) - && tile.block().isMultiblock() == type.isMultiblock() && type.canPlaceOn(tile); + && contactsGround(tile.x, tile.y, type) + && (!tile.floor().isDeep() || type.floating) + && tile.floor().placeableOn + && ((type.canReplace(tile.block()) + && !(type == tile.block() && rotation == tile.getRotation() && type.rotate)) || tile.block().alwaysReplace || tile.block() == Blocks.air) + && tile.block().isMultiblock() == type.isMultiblock() && type.canPlaceOn(tile); } } @@ -174,24 +176,25 @@ public class Build{ if(block.isMultiblock()){ for(Point2 point : Edges.getInsideEdges(block.size)){ Tile tile = world.tile(x + point.x, y + point.y); - if(tile != null && !tile.floor().isLiquid) return true; + if(tile != null && !tile.floor().isDeep()) return true; } for(Point2 point : Edges.getEdges(block.size)){ Tile tile = world.tile(x + point.x, y + point.y); - if(tile != null && !tile.floor().isLiquid) return true; + if(tile != null && !tile.floor().isDeep()) return true; } }else{ for(Point2 point : Geometry.d4){ Tile tile = world.tile(x + point.x, y + point.y); - if(tile != null && !tile.floor().isLiquid) return true; + if(tile != null && !tile.floor().isDeep()) return true; } - return world.tile(x, y) != null && !world.tile(x, y).floor().isLiquid; + Tile tile = world.tile(x, y); + return tile != null && !tile.floor().isDeep(); } return false; } - /**Returns whether the tile at this position is breakable by this team*/ + /** Returns whether the tile at this position is breakable by this team */ public static boolean validBreak(Team team, int x, int y){ Tile tile = world.tile(x, y); if(tile != null) tile = tile.target(); diff --git a/core/src/io/anuke/mindustry/world/CachedTile.java b/core/src/io/anuke/mindustry/world/CachedTile.java index 6672bb6d2f..75dded63db 100644 --- a/core/src/io/anuke/mindustry/world/CachedTile.java +++ b/core/src/io/anuke/mindustry/world/CachedTile.java @@ -3,13 +3,12 @@ package io.anuke.mindustry.world; import io.anuke.arc.collection.IntMap; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.world.modules.ConsumeModule; -import io.anuke.mindustry.world.modules.ItemModule; -import io.anuke.mindustry.world.modules.LiquidModule; -import io.anuke.mindustry.world.modules.PowerModule; +import io.anuke.mindustry.world.modules.*; -/**A tile which does not trigger change events and whose entity types are cached. - * Prevents garbage when loading previews.*/ +/** + * A tile which does not trigger change events and whose entity types are cached. + * Prevents garbage when loading previews. + */ public class CachedTile extends Tile{ private static IntMap entities = new IntMap<>(); diff --git a/core/src/io/anuke/mindustry/world/Edges.java b/core/src/io/anuke/mindustry/world/Edges.java index e3501f42ed..dc9586aca0 100644 --- a/core/src/io/anuke/mindustry/world/Edges.java +++ b/core/src/io/anuke/mindustry/world/Edges.java @@ -1,9 +1,7 @@ package io.anuke.mindustry.world; import io.anuke.arc.math.Mathf; -import io.anuke.arc.math.geom.Geometry; -import io.anuke.arc.math.geom.Point2; -import io.anuke.arc.math.geom.Vector2; +import io.anuke.arc.math.geom.*; import java.util.Arrays; @@ -22,8 +20,8 @@ public class Edges{ } for(int i = 0; i < maxSize; i++){ - int bot = -(int) (i / 2f) - 1; - int top = (int) (i / 2f + 0.5f) + 1; + int bot = -(int)(i / 2f) - 1; + int top = (int)(i / 2f + 0.5f) + 1; edges[i] = new Point2[(i + 1) * 4]; int idx = 0; @@ -45,8 +43,8 @@ public class Edges{ for(int j = 0; j < edges[i].length; j++){ Point2 point = edges[i][j]; - edgeInside[i][j] = new Point2(Mathf.clamp(point.x, -(int) ((i) / 2f), (int) (i / 2f + 0.5f)), - Mathf.clamp(point.y, -(int) ((i) / 2f), (int) (i / 2f + 0.5f))); + edgeInside[i][j] = new Point2(Mathf.clamp(point.x, -(int)((i) / 2f), (int)(i / 2f + 0.5f)), + Mathf.clamp(point.y, -(int)((i) / 2f), (int)(i / 2f + 0.5f))); } } } @@ -55,13 +53,13 @@ public class Edges{ if(!tile.block().isMultiblock()) return tile; int size = tile.block().size; return world.tile(tile.x + Mathf.clamp(other.x - tile.x, -(size - 1) / 2, (size / 2)), - tile.y + Mathf.clamp(other.y - tile.y, -(size - 1) / 2, (size / 2))); + tile.y + Mathf.clamp(other.y - tile.y, -(size - 1) / 2, (size / 2))); } public static Vector2[] getPixelPolygon(float radius){ if(radius < 1 || radius > maxRadius) throw new RuntimeException("Polygon size must be between 1 and " + maxRadius); - return polygons[(int) (radius * 2) - 1]; + return polygons[(int)(radius * 2) - 1]; } public static Point2[] getEdges(int size){ diff --git a/core/src/io/anuke/mindustry/world/ItemBuffer.java b/core/src/io/anuke/mindustry/world/ItemBuffer.java index d9f3b584ec..fbb16ad3e0 100644 --- a/core/src/io/anuke/mindustry/world/ItemBuffer.java +++ b/core/src/io/anuke/mindustry/world/ItemBuffer.java @@ -1,8 +1,6 @@ package io.anuke.mindustry.world; -import io.anuke.arc.util.NumberUtils; -import io.anuke.arc.util.Pack; -import io.anuke.arc.util.Time; +import io.anuke.arc.util.*; import io.anuke.mindustry.type.Item; import static io.anuke.mindustry.Vars.content; @@ -24,11 +22,11 @@ public class ItemBuffer{ public void accept(Item item, short data){ //if(!accepts()) return; - buffer[index++] = Pack.longInt(NumberUtils.floatToIntBits(Time.time()), Pack.shortInt((short) item.id, data)); + buffer[index++] = Pack.longInt(NumberUtils.floatToIntBits(Time.time()), Pack.shortInt((short)item.id, data)); } public void accept(Item item){ - accept(item, (short) -1); + accept(item, (short)-1); } public Item poll(){ diff --git a/core/src/io/anuke/mindustry/world/LegacyColorMapper.java b/core/src/io/anuke/mindustry/world/LegacyColorMapper.java index 2879f7d894..1c9e3f2ec1 100644 --- a/core/src/io/anuke/mindustry/world/LegacyColorMapper.java +++ b/core/src/io/anuke/mindustry/world/LegacyColorMapper.java @@ -45,7 +45,7 @@ public class LegacyColorMapper implements ContentList{ private void map(String color, Block block, Block wall, Block ore){ blockMap.put(Color.rgba8888(Color.valueOf(color)), new LegacyBlock(block, wall, ore)); } - + private void map(String color, Block block, Block wall){ blockMap.put(Color.rgba8888(Color.valueOf(color)), new LegacyBlock(block, wall)); } @@ -60,13 +60,13 @@ public class LegacyColorMapper implements ContentList{ public final Block ore; public LegacyBlock(Block floor, Block wall){ - this.floor = (Floor) floor; + this.floor = (Floor)floor; this.wall = wall; this.ore = null; } public LegacyBlock(Block floor, Block wall, Block ore){ - this.floor = (Floor) floor; + this.floor = (Floor)floor; this.wall = wall; this.ore = ore; } diff --git a/core/src/io/anuke/mindustry/world/Pos.java b/core/src/io/anuke/mindustry/world/Pos.java index 9a2860ee2a..97a4d560b8 100644 --- a/core/src/io/anuke/mindustry/world/Pos.java +++ b/core/src/io/anuke/mindustry/world/Pos.java @@ -1,21 +1,21 @@ package io.anuke.mindustry.world; -/**Methods for a packed position 'struct', contained in an int.*/ +/** Methods for a packed position 'struct', contained in an int. */ public class Pos{ public static final int invalid = get(-1, -1); - /**Returns packed position from an x/y position. The values must be within short limits.*/ + /** Returns packed position from an x/y position. The values must be within short limits. */ public static int get(int x, int y){ return (((short)x) << 16) | (((short)y) & 0xFFFF); } - /**Returns the x component of a position.*/ + /** Returns the x component of a position. */ public static short x(int pos){ - return (short) (pos >>> 16); + return (short)(pos >>> 16); } - /**Returns the y component of a position.*/ + /** Returns the y component of a position. */ public static short y(int pos){ - return (short) (pos & 0xFFFF); + return (short)(pos & 0xFFFF); } } diff --git a/core/src/io/anuke/mindustry/world/Tile.java b/core/src/io/anuke/mindustry/world/Tile.java index 6bd1f201a3..6a46deac64 100644 --- a/core/src/io/anuke/mindustry/world/Tile.java +++ b/core/src/io/anuke/mindustry/world/Tile.java @@ -3,10 +3,7 @@ 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.math.geom.Geometry; -import io.anuke.arc.math.geom.Point2; -import io.anuke.arc.math.geom.Position; -import io.anuke.arc.math.geom.Vector2; +import io.anuke.arc.math.geom.*; import io.anuke.arc.util.Pack; import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.entities.traits.TargetTrait; @@ -15,63 +12,56 @@ import io.anuke.mindustry.game.Team; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.blocks.BlockPart; import io.anuke.mindustry.world.blocks.Floor; -import io.anuke.mindustry.world.modules.ConsumeModule; -import io.anuke.mindustry.world.modules.ItemModule; -import io.anuke.mindustry.world.modules.LiquidModule; -import io.anuke.mindustry.world.modules.PowerModule; +import io.anuke.mindustry.world.modules.*; import static io.anuke.mindustry.Vars.*; - public class Tile implements Position, TargetTrait{ - /** - * The coordinates of the core tile this is linked to, in the form of two bytes packed into one. - * This is relative to the block it is linked to; negate coords to find the link. - */ - public byte link = 0; /** Tile traversal cost. */ public byte cost = 1; + /** Weight of [ground] units on this tile. */ + public byte weight, airWeight = 0; /** Tile entity, usually null. */ public TileEntity entity; public short x, y; - private Block wall; - private Floor floor; + protected Block block; + protected Floor floor; /** Rotation, 0-3. Also used to store offload location, in which case it can be any number. */ private byte rotation; /** Team ordinal. */ private byte team; - /**Ore that is on top of this (floor) block.*/ - private byte ore = 0; + /** Ore that is on top of this (floor) block. */ + private byte overlay = 0; public Tile(int x, int y){ - this.x = (short) x; - this.y = (short) y; - wall = floor = (Floor)Blocks.air; + this.x = (short)x; + this.y = (short)y; + block = floor = (Floor)Blocks.air; } - public Tile(int x, int y, byte floor, byte wall){ + public Tile(int x, int y, byte floor, byte block){ this(x, y); - this.floor = (Floor) content.block(floor); - this.wall = content.block(wall); + this.floor = (Floor)content.block(floor); + this.block = content.block(block); changed(); } - public Tile(int x, int y, byte floor, byte wall, byte rotation, byte team){ + public Tile(int x, int y, byte floor, byte block, byte rotation, byte team){ this(x, y); - this.floor = (Floor) content.block(floor); - this.wall = content.block(wall); + this.floor = (Floor)content.block(floor); + this.block = content.block(block); this.rotation = rotation; changed(); this.team = team; } - /**Returns this tile's position as a {@link Pos}.*/ + /** Returns this tile's position as a {@link Pos}. */ public int pos(){ return Pos.get(x, y); } public byte getBlockID(){ - return wall.id; + return block.id; } public byte getFloorID(){ @@ -113,7 +103,7 @@ public class Tile implements Position, TargetTrait{ @SuppressWarnings("unchecked") public T entity(){ - return (T) entity; + return (T)entity; } public float worldx(){ @@ -137,7 +127,16 @@ public class Tile implements Position, TargetTrait{ } public Block block(){ - return wall; + return block; + } + + public Floor overlay(){ + return (Floor)content.block(overlay); + } + + @SuppressWarnings("unchecked") + public T cblock(){ + return (T)block; } @Override @@ -146,40 +145,49 @@ public class Tile implements Position, TargetTrait{ } public void setTeam(Team team){ - this.team = (byte) team.ordinal(); + this.team = (byte)team.ordinal(); } public byte getTeamID(){ return team; } + public void setBlock(Block type, Team team, int rotation){ + preChanged(); + this.block = type; + this.team = (byte)team.ordinal(); + this.rotation = 0; + this.rotation = (byte)Mathf.mod(rotation, 4); + changed(); + } + public void setBlock(Block type, int rotation){ preChanged(); - if(rotation < 0) rotation = (-rotation + 2); - this.wall = type; - this.link = 0; - setRotation((byte) (rotation % 4)); + this.block = type; + this.rotation = 0; + this.rotation = (byte)Mathf.mod(rotation, 4); changed(); } public void setBlock(Block type, Team team){ preChanged(); - this.wall = type; + this.block = type; this.team = (byte)team.ordinal(); - this.link = 0; + this.rotation = 0; changed(); } public void setBlock(Block type){ preChanged(); - this.wall = type; - this.link = 0; + this.block = type; + this.rotation = 0; changed(); } + /**This resets the overlay!*/ public void setFloor(Floor type){ this.floor = type; - this.ore = 0; + this.overlay = 0; } public byte getRotation(){ @@ -198,6 +206,22 @@ public class Tile implements Position, TargetTrait{ this.rotation = dump; } + public byte getOverlayID(){ + return overlay; + } + + public void setOverlayID(byte ore){ + this.overlay = ore; + } + + public void setOverlay(Block block){ + setOverlayID(block.id); + } + + public void clearOverlay(){ + this.overlay = 0; + } + public boolean passable(){ Block block = block(); Block floor = floor(); @@ -219,7 +243,7 @@ public class Tile implements Position, TargetTrait{ public boolean breakable(){ Block block = block(); - if(link == 0){ + if(!isLinked()){ return (block.destructible || block.breakable || block.update); }else{ return getLinked() != this && getLinked().getLinked() == null && getLinked().breakable(); @@ -231,21 +255,21 @@ public class Tile implements Position, TargetTrait{ } public boolean isLinked(){ - return link != 0; + return block == Blocks.part; } public byte getLinkByte(){ - return link; + return rotation; } public void setLinkByte(byte b){ - this.link = b; + this.rotation = b; } /** Sets this to a linked tile, which sets the block to a part. dx and dy can only be -8-7. */ public void setLinked(byte dx, byte dy){ setBlock(Blocks.part); - link = Pack.byteByte((byte)(dx + 8), (byte)(dy + 8)); + rotation = Pack.byteByte((byte)(dx + 8), (byte)(dy + 8)); } /** @@ -293,12 +317,10 @@ public class Tile implements Position, TargetTrait{ /** Returns the block the multiblock is linked to, or null if it is not linked to any block. */ public Tile getLinked(){ - if(link == 0){ + if(!isLinked()){ return null; }else{ - byte dx = Pack.leftByte(link); - byte dy = Pack.rightByte(link); - return world.tile(x - (dx - 8), y - (dy - 8)); + return world.tile(x + linkX(rotation), y + linkY(rotation)); } } @@ -325,6 +347,10 @@ public class Tile implements Position, TargetTrait{ return link == null ? this : link; } + public Rectangle getHitbox(Rectangle rect){ + return rect.setSize(block().size * tilesize).setCenter(drawx(), drawy()); + } + public Tile getNearby(Point2 relative){ return world.tile(x + relative.x, y + relative.y); } @@ -345,28 +371,8 @@ public class Tile implements Position, TargetTrait{ return getTeam() == Team.none || team == getTeam(); } - public byte getOreByte(){ - return ore; - } - - public void setOreByte(byte ore){ - this.ore = ore; - } - - public void setOre(Block block){ - setOreByte(block.id); - } - - public void clearOre(){ - this.ore = 0; - } - - public Floor ore(){ - return (Floor)content.block(ore); - } - public Item drop(){ - return ore == 0 ? floor.itemDrop : ((Floor)content.block(ore)).itemDrop; + return overlay == 0 || ((Floor)content.block(overlay)).itemDrop == null ? floor.itemDrop : ((Floor)content.block(overlay)).itemDrop; } public void updateOcclusion(){ @@ -377,6 +383,9 @@ public class Tile implements Position, TargetTrait{ for(int i = 0; i < 8; i++){ Point2 point = Geometry.d8[i]; Tile tile = world.tile(x + point.x, y + point.y); + if(tile != null && tile.floor.isLiquid){ + cost += 3; + } if(tile != null && tile.solid()){ occluded = true; break; @@ -443,7 +452,7 @@ public class Tile implements Position, TargetTrait{ @Override public boolean isDead(){ - return false; //tiles never die + return entity == null; } @Override @@ -476,7 +485,17 @@ public class Tile implements Position, TargetTrait{ Block block = block(); Block floor = floor(); - return floor.name + ":" + block.name + "[" + x + "," + y + "] " + "entity=" + (entity == null ? "null" : (entity.getClass())) + - (link != 0 ? " link=[" + (Pack.leftByte(link) - 8) + ", " + (Pack.rightByte(link) - 8) + "]" : ""); + return floor.name + ":" + block.name + ":" + content.block(overlay) + "[" + x + "," + y + "] " + "entity=" + (entity == null ? "null" : (entity.getClass())) + + (isLinked() ? " link=[" + linkX(rotation) + ", " + linkY(rotation) + "]" : ""); + } + + /**Returns the relative X from a link byte.*/ + public static int linkX(byte value){ + return -((byte)((value >> 4) & (byte)0x0F) - 8); + } + + /**Returns the relative Y from a link byte.*/ + public static int linkY(byte value){ + return -((byte)(value & 0x0F) - 8); } } \ No newline at end of file diff --git a/core/src/io/anuke/mindustry/world/blocks/BlockPart.java b/core/src/io/anuke/mindustry/world/blocks/BlockPart.java index 512b39df20..bc82001109 100644 --- a/core/src/io/anuke/mindustry/world/blocks/BlockPart.java +++ b/core/src/io/anuke/mindustry/world/blocks/BlockPart.java @@ -38,16 +38,11 @@ public class BlockPart extends Block{ //do nothing } - @Override - public void drawShadow(Tile tile){ - //also do nothing - } - @Override public boolean isSolidFor(Tile tile){ return tile.getLinked() == null - || (tile.getLinked().block() instanceof BlockPart || tile.getLinked().solid() - || tile.getLinked().block().isSolidFor(tile.getLinked())); + || (tile.getLinked().block() instanceof BlockPart || tile.getLinked().solid() + || tile.getLinked().block().isSolidFor(tile.getLinked())); } @Override @@ -64,7 +59,7 @@ public class BlockPart extends Block{ public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ Block block = linked(tile); return block.hasLiquids - && block.acceptLiquid(tile.getLinked(), source, liquid, amount); + && block.acceptLiquid(tile.getLinked(), source, liquid, amount); } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java b/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java index f81fb7859e..f1fb7c7929 100644 --- a/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java @@ -13,23 +13,17 @@ import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.effect.RubbleDecal; import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest; -import io.anuke.mindustry.entities.type.Player; -import io.anuke.mindustry.entities.type.TileEntity; -import io.anuke.mindustry.entities.type.Unit; +import io.anuke.mindustry.entities.type.*; import io.anuke.mindustry.game.EventType.BlockBuildEndEvent; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.graphics.Layer; -import io.anuke.mindustry.graphics.Pal; -import io.anuke.mindustry.graphics.Shaders; +import io.anuke.mindustry.graphics.*; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.modules.ItemModule; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.*; @@ -57,8 +51,7 @@ public class BuildBlock extends Block{ public static void onConstructFinish(Tile tile, Block block, int builderID, byte rotation, Team team){ if(tile == null) return; float healthf = tile.entity == null ? 1f : tile.entity.healthf(); - tile.setRotation(rotation); - world.setBlock(tile, block, team); + world.setBlock(tile, block, team, rotation); if(tile.entity != null){ tile.entity.health = block.health * healthf; } @@ -66,7 +59,7 @@ public class BuildBlock extends Block{ Core.app.post(() -> tile.block().placed(tile)); //last builder was this local client player, call placed() - if(!headless && builderID == players[0].id){ + if(!headless && builderID == player.id){ //this is run delayed, since if this is called on the server, all clients need to recieve the onBuildFinish() //event first before they can recieve the placed() event modification results Core.app.post(() -> tile.block().playerPlaced(tile)); @@ -82,19 +75,19 @@ public class BuildBlock extends Block{ @Override public String getDisplayName(Tile tile){ BuildEntity entity = tile.entity(); - return Core.bundle.format("block.constructing", entity.block == null ? entity.previous.localizedName : entity.block.localizedName); + return Core.bundle.format("block.constructing", entity.cblock == null ? entity.previous.localizedName : entity.cblock.localizedName); } @Override public TextureRegion getDisplayIcon(Tile tile){ BuildEntity entity = tile.entity(); - return (entity.block == null ? entity.previous : entity.block).icon(Icon.full); + return (entity.cblock == null ? entity.previous : entity.cblock).icon(Icon.full); } @Override public boolean isSolidFor(Tile tile){ BuildEntity entity = tile.entity(); - return entity == null || (entity.block != null && entity.block.solid) || entity.previous == null || entity.previous.solid; + return entity == null || (entity.cblock != null && entity.cblock.solid) || entity.previous == null || entity.previous.solid; } @Override @@ -107,9 +100,9 @@ public class BuildBlock extends Block{ BuildEntity entity = tile.entity(); //if the target is constructible, begin constructing - if(entity.block != null){ + if(entity.cblock != null){ player.clearBuilding(); - player.addBuildRequest(new BuildRequest(tile.x, tile.y, tile.getRotation(), entity.block)); + player.addBuildRequest(new BuildRequest(tile.x, tile.y, tile.getRotation(), entity.cblock)); } } @@ -127,7 +120,7 @@ public class BuildBlock extends Block{ BuildEntity entity = tile.entity(); //When breaking, don't draw the previous block... since it's the thing you were breaking - if(entity.block != null && entity.previous == entity.block){ + if(entity.cblock != null && entity.previous == entity.cblock){ return; } @@ -145,7 +138,7 @@ public class BuildBlock extends Block{ Shaders.blockbuild.color = Pal.accent; - Block target = entity.block == null ? entity.previous : entity.block; + Block target = entity.cblock == null ? entity.previous : entity.cblock; if(target == null) return; @@ -158,12 +151,6 @@ public class BuildBlock extends Block{ } } - @Override - public void drawShadow(Tile tile){ - //don't - //TODO maybe do - } - @Override public TileEntity newEntity(){ return new BuildEntity(); @@ -174,7 +161,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 block; + public Block cblock; public float progress = 0; public float buildCost; @@ -189,16 +176,17 @@ public class BuildBlock extends Block{ private float[] totalAccumulator; public void construct(Unit builder, TileEntity core, float amount){ - if(block == null){ + if(cblock == null){ kill(); return; } float maxProgress = checkRequired(core.items, amount, false); - for(int i = 0; i < block.buildRequirements.length; i++){ - accumulator[i] += Math.min(block.buildRequirements[i].amount * maxProgress, block.buildRequirements[i].amount - totalAccumulator[i] + 0.00001f); //add min amount progressed to the accumulator - totalAccumulator[i] = Math.min(totalAccumulator[i] + block.buildRequirements[i].amount * maxProgress, block.buildRequirements[i].amount); + for(int i = 0; i < cblock.buildRequirements.length; i++){ + int reqamount = Math.round(state.rules.buildCostMultiplier * cblock.buildRequirements[i].amount); + accumulator[i] += Math.min(reqamount * maxProgress, reqamount - totalAccumulator[i] + 0.00001f); //add min amount progressed to the accumulator + totalAccumulator[i] = Math.min(totalAccumulator[i] + reqamount * maxProgress, reqamount); } maxProgress = checkRequired(core.items, maxProgress, true); @@ -208,23 +196,25 @@ public class BuildBlock extends Block{ if(builder instanceof Player){ builderID = builder.getID(); } - + if(progress >= 1f || state.rules.infiniteResources){ - Call.onConstructFinish(tile, block, builderID, tile.getRotation(), builder.getTeam()); + Call.onConstructFinish(tile, cblock, builderID, tile.getRotation(), builder.getTeam()); } } public void deconstruct(Unit builder, TileEntity core, float amount){ + float deconstructMultiplier = 0.5f; - if(block != null){ - ItemStack[] requirements = block.buildRequirements; + if(cblock != null){ + ItemStack[] requirements = cblock.buildRequirements; if(requirements.length != accumulator.length || totalAccumulator.length != requirements.length){ setDeconstruct(previous); } for(int i = 0; i < requirements.length; i++){ - accumulator[i] += Math.min(requirements[i].amount * amount / 2f, requirements[i].amount / 2f - totalAccumulator[i]); //add scaled amount progressed to the accumulator - totalAccumulator[i] = Math.min(totalAccumulator[i] + requirements[i].amount * amount / 2f, requirements[i].amount); + 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); int accumulated = (int)(accumulator[i]); //get amount @@ -240,23 +230,24 @@ public class BuildBlock extends Block{ progress = Mathf.clamp(progress - amount); if(progress <= 0 || state.rules.infiniteResources){ - Call.onDeconstructFinish(tile, this.block == null ? previous : this.block); + Call.onDeconstructFinish(tile, this.cblock == null ? previous : this.cblock); } } private float checkRequired(ItemModule inventory, float amount, boolean remove){ float maxProgress = amount; - for(int i = 0; i < block.buildRequirements.length; i++){ - int required = (int) (accumulator[i]); //calculate items that are required now + for(int i = 0; i < cblock.buildRequirements.length; i++){ + int sclamount = Math.round(state.rules.buildCostMultiplier * cblock.buildRequirements[i].amount); + int required = (int)(accumulator[i]); //calculate items that are required now - if(inventory.get(block.buildRequirements[i].item) == 0){ + if(inventory.get(cblock.buildRequirements[i].item) == 0 && sclamount != 0){ maxProgress = 0f; }else if(required > 0){ //if this amount is positive... //calculate how many items it can actually use - int maxUse = Math.min(required, inventory.get(block.buildRequirements[i].item)); + int maxUse = Math.min(required, inventory.get(cblock.buildRequirements[i].item)); //get this as a fraction - float fraction = maxUse / (float) required; + float fraction = maxUse / (float)required; //move max progress down if this fraction is less than 1 maxProgress = Math.min(maxProgress, maxProgress * fraction); @@ -265,7 +256,7 @@ public class BuildBlock extends Block{ //remove stuff that is actually used if(remove){ - inventory.remove(block.buildRequirements[i].item, maxUse); + inventory.remove(cblock.buildRequirements[i].item, maxUse); } } //else, no items are required yet, so just keep going @@ -279,21 +270,21 @@ public class BuildBlock extends Block{ } public void setConstruct(Block previous, Block block){ - this.block = block; + this.cblock = block; this.previous = previous; this.accumulator = new float[block.buildRequirements.length]; this.totalAccumulator = new float[block.buildRequirements.length]; - this.buildCost = block.buildCost; + this.buildCost = block.buildCost * state.rules.buildCostMultiplier; } public void setDeconstruct(Block previous){ this.previous = previous; this.progress = 1f; if(previous.buildCost >= 0.01f){ - this.block = previous; + this.cblock = previous; this.accumulator = new float[previous.buildRequirements.length]; this.totalAccumulator = new float[previous.buildRequirements.length]; - this.buildCost = previous.buildCost; + this.buildCost = previous.buildCost * state.rules.buildCostMultiplier; }else{ this.buildCost = 20f; //default no-requirement build cost is 20 } @@ -303,7 +294,7 @@ public class BuildBlock extends Block{ public void write(DataOutput stream) throws IOException{ stream.writeFloat(progress); stream.writeShort(previous == null ? -1 : previous.id); - stream.writeShort(block == null ? -1 : block.id); + stream.writeShort(cblock == null ? -1 : cblock.id); if(accumulator == null){ stream.writeByte(-1); @@ -333,10 +324,10 @@ public class BuildBlock extends Block{ } if(pid != -1) previous = content.block(pid); - if(rid != -1) block = content.block(rid); + if(rid != -1) cblock = content.block(rid); - if(block != null){ - buildCost = block.buildCost; + if(cblock != null){ + buildCost = cblock.buildCost * state.rules.buildCostMultiplier; }else{ buildCost = 20f; } diff --git a/core/src/io/anuke/mindustry/world/blocks/Floor.java b/core/src/io/anuke/mindustry/world/blocks/Floor.java index 023224df81..7cfa2b9103 100644 --- a/core/src/io/anuke/mindustry/world/blocks/Floor.java +++ b/core/src/io/anuke/mindustry/world/blocks/Floor.java @@ -1,19 +1,16 @@ package io.anuke.mindustry.world.blocks; import io.anuke.arc.Core; -import io.anuke.arc.graphics.Color; +import io.anuke.arc.collection.Array; +import io.anuke.arc.collection.IntSet; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Geometry; import io.anuke.arc.math.geom.Point2; -import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.content.StatusEffects; +import io.anuke.mindustry.content.*; import io.anuke.mindustry.entities.Effects.Effect; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.Liquid; -import io.anuke.mindustry.type.StatusEffect; +import io.anuke.mindustry.type.*; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -21,7 +18,7 @@ import static io.anuke.mindustry.Vars.tilesize; public class Floor extends Block{ /** number of different variant regions to use */ - public int variants; + public int variants = 3; /** edge fallback, used mainly for ores */ public String edge = "stone"; /** Multiplies unit velocity by this when walked on. */ @@ -40,8 +37,6 @@ public class Floor extends Block{ public StatusEffect status = StatusEffects.none; /** Intensity of applied status effect. */ public float statusDuration = 60f; - /** Color of this floor's liquid. Used for tinting sprites. */ - public Color liquidColor; /** liquids that drop from this block, used for pumps */ public Liquid liquidDrop = null; /** item that drops from this block, used for drills */ @@ -50,21 +45,22 @@ public class Floor extends Block{ public boolean isLiquid; /** if true, this block cannot be mined by players. useful for annoying things like sand. */ public boolean playerUnmineable = false; - /**Style of the edge stencil. Loaded by looking up "edge-stencil-{name}".*/ + /** Style of the edge stencil. Loaded by looking up "edge-stencil-{name}". */ public String edgeStyle = "smooth"; - /**Group of blocks that this block does not draw edges on.*/ + /** Group of blocks that this block does not draw edges on. */ public Block blendGroup = this; - /**Effect displayed when randomly updated.*/ + /** Effect displayed when randomly updated. */ public Effect updateEffect = Fx.none; - /**Array of affinities to certain things.*/ + /** Array of affinities to certain things. */ public Attributes attributes = new Attributes(); protected TextureRegion[][] edges; protected byte eq = 0; + protected Array blenders = new Array<>(); + protected IntSet blended = new IntSet(); public Floor(String name){ super(name); - variants = 3; } @Override @@ -95,15 +91,6 @@ public class Floor extends Block{ return new TextureRegion[]{Core.atlas.find(Core.atlas.has(name) ? name : name + "1")}; } - @Override - public void init(){ - super.init(); - - if(isLiquid && liquidColor == null){ - throw new RuntimeException("All liquids must define a liquidColor! Problematic block: " + name); - } - } - @Override public void draw(Tile tile){ Mathf.random.setSeed(tile.pos()); @@ -112,12 +99,15 @@ public class Floor extends Block{ drawEdges(tile); - Floor floor = tile.ore(); + Floor floor = tile.overlay(); if(floor != Blocks.air && floor != this){ //ore should never have itself on top, but it's possible, so prevent a crash in that case floor.draw(tile); } } + public boolean isDeep(){ + return drownTime > 0; + } public void drawNonLayer(Tile tile){ Mathf.random.setSeed(tile.pos()); @@ -130,25 +120,34 @@ public class Floor extends Block{ } protected void drawEdges(Tile tile, boolean sameLayer){ + blenders.clear(); + blended.clear(); eq = 0; for(int i = 0; i < 8; i++){ Point2 point = Geometry.d8[i]; Tile other = tile.getNearby(point); if(other != null && doEdge(other.floor(), sameLayer) && other.floor().edges() != null){ + if(blended.add(other.floor().id)){ + blenders.add(other.floor()); + } eq |= (1 << i); } } - for(int i = 0; i < 8; i++){ - if(eq(i)){ + blenders.sort((a, b) -> Integer.compare(a.id, b.id)); + + for(Block block : blenders){ + for(int i = 0; i < 8; i++){ Point2 point = Geometry.d8[i]; Tile other = tile.getNearby(point); - - TextureRegion region = edge(other.floor(), type(i), 2-(point.x + 1), 2-(point.y + 1)); - Draw.rect(region, tile.worldx(), tile.worldy()); + if(other != null && other.floor() == block){ + TextureRegion region = edge((Floor)block, type(i), 2 - (point.x + 1), 2 - (point.y + 1)); + Draw.rect(region, tile.worldx(), tile.worldy()); + } } } + } protected TextureRegion[][] edges(){ @@ -184,7 +183,7 @@ public class Floor extends Block{ } TextureRegion edge(Floor block, int type, int x, int y){ - return block.edges()[x + type*3][2-y]; + return block.edges()[x + type * 3][2 - y]; } } \ No newline at end of file diff --git a/core/src/io/anuke/mindustry/world/blocks/SelectionTrait.java b/core/src/io/anuke/mindustry/world/blocks/ItemSelection.java similarity index 85% rename from core/src/io/anuke/mindustry/world/blocks/SelectionTrait.java rename to core/src/io/anuke/mindustry/world/blocks/ItemSelection.java index ef6d0d5c7c..2515f58ec8 100644 --- a/core/src/io/anuke/mindustry/world/blocks/SelectionTrait.java +++ b/core/src/io/anuke/mindustry/world/blocks/ItemSelection.java @@ -1,20 +1,20 @@ package io.anuke.mindustry.world.blocks; import io.anuke.arc.collection.Array; -import io.anuke.mindustry.type.Item; import io.anuke.arc.function.Consumer; import io.anuke.arc.function.Supplier; import io.anuke.arc.scene.style.TextureRegionDrawable; import io.anuke.arc.scene.ui.ButtonGroup; import io.anuke.arc.scene.ui.ImageButton; import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Item.Icon; import static io.anuke.mindustry.Vars.*; -public interface SelectionTrait{ +public class ItemSelection{ - default void buildItemTable(Table table, Supplier holder, Consumer consumer){ + public static void buildItemTable(Table table, Supplier holder, Consumer consumer){ Array items = content.items(); @@ -28,7 +28,7 @@ public interface SelectionTrait{ for(Item item : items){ if(!data.isUnlocked(item) && world.isZone()) continue; - ImageButton button = cont.addImageButton("white", "clear-toggle", 24, () -> control.input(0).frag.config.hideConfig()).group(group).get(); + ImageButton button = cont.addImageButton("white", "clear-toggle", 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/LiquidBlock.java b/core/src/io/anuke/mindustry/world/blocks/LiquidBlock.java index 9cb743e41e..f20db17790 100644 --- a/core/src/io/anuke/mindustry/world/blocks/LiquidBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/LiquidBlock.java @@ -1,12 +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.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockGroup; import io.anuke.mindustry.world.modules.LiquidModule; -import io.anuke.arc.graphics.g2d.Draw; public class LiquidBlock extends Block{ protected TextureRegion liquidRegion, bottomRegion, topRegion; diff --git a/core/src/io/anuke/mindustry/world/blocks/OreBlock.java b/core/src/io/anuke/mindustry/world/blocks/OreBlock.java index d8ba5b6435..b4ee4078f8 100644 --- a/core/src/io/anuke/mindustry/world/blocks/OreBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/OreBlock.java @@ -1,11 +1,10 @@ package io.anuke.mindustry.world.blocks; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.math.Mathf; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Tile; -public class OreBlock extends Floor{ +/**An overlay ore for a specific item type.*/ +public class OreBlock extends OverlayFloor{ public OreBlock(Item ore){ super("ore-" + ore.name); @@ -24,9 +23,4 @@ public class OreBlock extends Floor{ public String getDisplayName(Tile tile){ return itemDrop.localizedName(); } - - @Override - public void draw(Tile tile){ - 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/OverlayFloor.java b/core/src/io/anuke/mindustry/world/blocks/OverlayFloor.java new file mode 100644 index 0000000000..a2527e6a67 --- /dev/null +++ b/core/src/io/anuke/mindustry/world/blocks/OverlayFloor.java @@ -0,0 +1,18 @@ +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; + +/**A type of floor that is overlaid on top of over floors.*/ +public class OverlayFloor extends Floor{ + + public OverlayFloor(String name){ + super(name); + } + + @Override + public void draw(Tile tile){ + 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/Rock.java b/core/src/io/anuke/mindustry/world/blocks/Rock.java index 7f10510e96..a178ce74f0 100644 --- a/core/src/io/anuke/mindustry/world/blocks/Rock.java +++ b/core/src/io/anuke/mindustry/world/blocks/Rock.java @@ -1,11 +1,11 @@ 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.math.Mathf; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.math.Mathf; public class Rock extends Block{ protected int variants; diff --git a/core/src/io/anuke/mindustry/world/blocks/StaticWall.java b/core/src/io/anuke/mindustry/world/blocks/StaticWall.java index cc2d73ce0b..d1cb3334c7 100644 --- a/core/src/io/anuke/mindustry/world/blocks/StaticWall.java +++ b/core/src/io/anuke/mindustry/world/blocks/StaticWall.java @@ -18,6 +18,7 @@ public class StaticWall extends Rock{ super(name); breakable = alwaysReplace = false; solid = true; + variants = 2; cacheLayer = CacheLayer.walls; } @@ -28,7 +29,7 @@ public class StaticWall extends Rock{ if(Core.atlas.isFound(large) && eq(rx, ry) && Mathf.randomSeed(Pos.get(rx, ry)) < 0.5){ if(rx == tile.x && ry == tile.y){ - Draw.rect(large, tile.worldx() + tilesize/2f, tile.worldy() + tilesize/2f); + Draw.rect(large, tile.worldx() + tilesize / 2f, tile.worldy() + tilesize / 2f); } }else if(variants > 0){ Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy()); @@ -43,19 +44,10 @@ public class StaticWall extends Rock{ large = Core.atlas.find(name + "-large"); } - //two functions for calculating 2x2 tile brightness - int min(int rx, int ry){ - return Math.min(world.tile(rx + 1, ry).getRotation(), Math.min(world.tile(rx, ry).getRotation(), Math.min(world.tile(rx + 1, ry + 1).getRotation(), world.tile(rx, ry + 1).getRotation()))); - } - - int avg(int rx, int ry){ - return (world.tile(rx + 1, ry).getRotation() + world.tile(rx, ry).getRotation() + world.tile(rx + 1, ry + 1).getRotation() + world.tile(rx, ry + 1).getRotation()) / 4; - } - boolean eq(int rx, int ry){ return world.tile(rx + 1, ry).block() == this - && world.tile(rx, ry + 1).block() == this - && world.tile(rx, ry).block() == this - && world.tile(rx + 1, ry + 1).block() == this; + && world.tile(rx, ry + 1).block() == this + && world.tile(rx, ry).block() == this + && world.tile(rx + 1, ry + 1).block() == this; } } diff --git a/core/src/io/anuke/mindustry/world/blocks/TreeBlock.java b/core/src/io/anuke/mindustry/world/blocks/TreeBlock.java index 60534c8be0..11d110fc31 100644 --- a/core/src/io/anuke/mindustry/world/blocks/TreeBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/TreeBlock.java @@ -7,7 +7,6 @@ import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; public class TreeBlock extends Block{ - static final float shadowOffset = 10f; public TreeBlock(String name){ super(name); @@ -19,12 +18,6 @@ public class TreeBlock extends Block{ @Override public void draw(Tile tile){} - @Override - public void drawShadow(Tile tile){ - Draw.rect(region, tile.drawx(), tile.drawy(), Mathf.randomSeed(tile.pos(), 0, 4) * 90); - Draw.rect(region, tile.drawx() - shadowOffset, tile.drawy() - shadowOffset, Mathf.randomSeed(tile.pos(), 0, 4) * 90); - } - @Override public void drawLayer(Tile tile){ Draw.rect(region, tile.drawx(), tile.drawy(), Mathf.randomSeed(tile.pos(), 0, 4) * 90); 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 5d9b9080b9..1d0822d14f 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/DeflectorWall.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/DeflectorWall.java @@ -4,12 +4,10 @@ import io.anuke.arc.graphics.Blending; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.math.Mathf; -import io.anuke.arc.math.geom.Geometry; -import io.anuke.arc.math.geom.Rectangle; -import io.anuke.arc.math.geom.Vector2; +import io.anuke.arc.math.geom.*; import io.anuke.arc.util.Time; -import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.entities.bullet.Bullet; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.world.Tile; @@ -56,7 +54,7 @@ public class DeflectorWall extends Wall{ bullet.hitbox(rect2); Vector2 position = Geometry.raycastRect(bullet.x, bullet.y, bullet.x + bullet.velocity().x, bullet.y + bullet.velocity().y, - rect.setCenter(entity.x, entity.y).setSize(size * tilesize + rect2.width + rect2.height)); + rect.setCenter(entity.x, entity.y).setSize(size * tilesize + rect2.width + rect2.height)); if(position != null){ bullet.set(position.x, position.y); @@ -73,7 +71,7 @@ public class DeflectorWall extends Wall{ bullet.scaleTime(1f); bullet.supress(); - ((DeflectorEntity) entity).hit = 1f; + ((DeflectorEntity)entity).hit = 1f; } @Override 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 d4c6fd75cc..5676592267 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/Door.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/Door.java @@ -3,20 +3,18 @@ package io.anuke.mindustry.world.blocks.defense; import io.anuke.arc.Core; import io.anuke.arc.Graphics.Cursor; import io.anuke.arc.Graphics.Cursor.SystemCursor; -import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.geom.Rectangle; import io.anuke.mindustry.content.Fx; +import io.anuke.mindustry.entities.Effects; +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.Units; import io.anuke.mindustry.world.Tile; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; public class Door extends Wall{ protected final Rectangle rect = new Rectangle(); diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/ForceProjector.java b/core/src/io/anuke/mindustry/world/blocks/defense/ForceProjector.java index 55ecd34d38..93bc7d6648 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/ForceProjector.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/ForceProjector.java @@ -1,41 +1,34 @@ package io.anuke.mindustry.world.blocks.defense; import io.anuke.arc.Core; -import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.EntityGroup; -import io.anuke.mindustry.entities.EntityQuery; -import io.anuke.mindustry.entities.impl.BaseEntity; -import io.anuke.mindustry.entities.traits.DrawTrait; +import io.anuke.arc.function.Consumer; 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.Fill; -import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Fx; +import io.anuke.mindustry.entities.*; +import io.anuke.mindustry.entities.impl.BaseEntity; +import io.anuke.mindustry.entities.traits.*; import io.anuke.mindustry.entities.type.TileEntity; -import io.anuke.mindustry.entities.traits.AbsorbTrait; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.consumers.ConsumeLiquidFilter; -import io.anuke.mindustry.world.consumers.ConsumePower; +import io.anuke.mindustry.world.consumers.*; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.StatUnit; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.*; -public class ForceProjector extends Block { - protected int timerUse = timers ++; +public class ForceProjector extends Block{ + protected int timerUse = timers++; protected float phaseUseTime = 350f; protected float phaseRadiusBoost = 80f; - protected float radius = 100f; + protected float radius = 101.7f; protected float breakage = 550f; protected float cooldownNormal = 1.75f; protected float cooldownLiquid = 1.5f; @@ -45,8 +38,26 @@ public class ForceProjector extends Block { protected final ConsumeForceProjectorPower consumePower; protected TextureRegion topRegion; + private static Tile paramTile; + private static ForceProjector paramBlock; + private static ForceEntity paramEntity; + private static Consumer shieldConsumer = bullet -> { + AbsorbTrait trait = (AbsorbTrait)bullet; + if(trait.canBeAbsorbed() && trait.getTeam() != paramTile.getTeam() && paramBlock.isInsideHexagon(trait.getX(), trait.getY(), paramBlock.realRadius(paramEntity) * 2f, paramTile.drawx(), paramTile.drawy())){ + trait.absorb(); + Effects.effect(Fx.absorb, trait); + float relativeDamagePowerDraw = trait.getShieldDamage() * paramBlock.powerDamage / paramBlock.consumePower.powerCapacity; + paramEntity.hit = 1f; - public ForceProjector(String name) { + paramEntity.power.satisfaction -= Math.min(relativeDamagePowerDraw, paramEntity.power.satisfaction); + if(paramEntity.power.satisfaction <= 0.0001f){ + paramEntity.buildup += trait.getShieldDamage() * paramEntity.warmup * 2f; + } + paramEntity.buildup += trait.getShieldDamage() * paramEntity.warmup; + } + }; + + public ForceProjector(String name){ super(name); update = true; solid = true; @@ -54,7 +65,7 @@ public class ForceProjector extends Block { canOverdrive = false; hasLiquids = true; hasItems = true; - consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, 0.1f)).optional(true).boost(true).update(false); + consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, 0.1f)).boost().update(false); consumePower = new ConsumeForceProjectorPower(60f, 60f); consumes.add(consumePower); } @@ -71,6 +82,18 @@ public class ForceProjector extends Block { stats.add(BlockStat.powerUse, basePowerDraw * 60f, StatUnit.powerSecond); stats.add(BlockStat.powerDamage, powerDamage, StatUnit.powerUnits); + + stats.add(BlockStat.boostEffect, phaseRadiusBoost / tilesize, StatUnit.blocks); + } + + @Override + public void drawPlace(int x, int y, int rotation, boolean valid){ + super.drawPlace(x, y, rotation, valid); + + Draw.color(Pal.accent); + Lines.stroke(1f); + Lines.poly(x * tilesize, y * tilesize, 6, radius); + Draw.color(); } @Override @@ -83,19 +106,21 @@ public class ForceProjector extends Block { entity.shield.add(); } - entity.phaseHeat = Mathf.lerpDelta(entity.phaseHeat, (float)entity.items.get(consumes.item()) / itemCapacity, 0.1f); + boolean phaseValid = consumes.get(ConsumeType.item).valid(tile.entity); - if(entity.cons.valid() && !entity.broken && entity.timer.get(timerUse, phaseUseTime) && entity.items.total() > 0){ - entity.items.remove(consumes.item(), 1); + entity.phaseHeat = Mathf.lerpDelta(entity.phaseHeat, Mathf.num(phaseValid), 0.1f); + + if(phaseValid && !entity.broken && entity.timer.get(timerUse, phaseUseTime)){ + entity.cons.trigger(); } entity.radscl = Mathf.lerpDelta(entity.radscl, entity.broken ? 0f : 1f, 0.05f); if(Mathf.chance(Time.delta() * entity.buildup / breakage * 0.1f)){ - Effects.effect(Fx.reactorsmoke, tile.drawx() + Mathf.range(tilesize/2f), tile.drawy() + Mathf.range(tilesize/2f)); + Effects.effect(Fx.reactorsmoke, tile.drawx() + Mathf.range(tilesize / 2f), tile.drawy() + Mathf.range(tilesize / 2f)); } - // Use Cases: + //use cases: // - There is enough power in the buffer, and there are no shots fired => Draw base power and keep shield up // - There is enough power in the buffer, but not enough power to cope for shots being fired => Draw all power and break shield // - There is enough power in the buffer and enough power to cope for shots being fired => Draw base power + additional power based on shots absorbed @@ -109,23 +134,24 @@ public class ForceProjector extends Block { if(entity.power.satisfaction < relativePowerDraw){ entity.warmup = Mathf.lerpDelta(entity.warmup, 0f, 0.15f); - entity.power.satisfaction = .0f; + entity.power.satisfaction = 0f; if(entity.warmup <= 0.09f){ entity.broken = true; } }else{ entity.warmup = Mathf.lerpDelta(entity.warmup, 1f, 0.1f); - entity.power.satisfaction -= Math.min(entity.power.satisfaction, relativePowerDraw); + entity.power.satisfaction -= Math.min(entity.power.satisfaction, relativePowerDraw * Time.delta()); } if(entity.buildup > 0){ float scale = !entity.broken ? cooldownNormal : cooldownBrokenBase; - if(consumes.get(ConsumeLiquidFilter.class).valid(this, entity)){ - consumes.get(ConsumeLiquidFilter.class).update(this, entity); - scale *= (cooldownLiquid * (1f+(entity.liquids.current().heatCapacity-0.4f)*0.9f)); + ConsumeLiquidFilter cons = consumes.get(ConsumeType.liquid); + if(cons.valid(entity)){ + cons.update(entity); + scale *= (cooldownLiquid * (1f + (entity.liquids.current().heatCapacity - 0.4f) * 0.9f)); } - entity.buildup -= Time.delta()*scale; + entity.buildup -= Time.delta() * scale; } if(entity.broken && entity.buildup <= 0 && entity.warmup >= 0.9f){ @@ -139,39 +165,26 @@ public class ForceProjector extends Block { } if(entity.hit > 0f){ - entity.hit -= 1f/5f * Time.delta(); + entity.hit -= 1f / 5f * Time.delta(); } float realRadius = realRadius(entity); - if(!entity.broken){ - EntityQuery.getNearby(bulletGroup, tile.drawx(), tile.drawy(), realRadius*2f, bullet -> { - AbsorbTrait trait = (AbsorbTrait)bullet; - if(trait.canBeAbsorbed() && trait.getTeam() != tile.getTeam() && isInsideHexagon(trait.getX(), trait.getY(), realRadius * 2f, tile.drawx(), tile.drawy())){ - trait.absorb(); - Effects.effect(Fx.absorb, trait); - float relativeDamagePowerDraw = trait.getShieldDamage() * powerDamage / consumePower.powerCapacity; - entity.hit = 1f; - - entity.power.satisfaction -= Math.min(relativeDamagePowerDraw, entity.power.satisfaction); - if(entity.power.satisfaction <= 0.0001f){ - entity.buildup += trait.getShieldDamage() * entity.warmup * 2f; - } - entity.buildup += trait.getShieldDamage() * entity.warmup; - } - }); - } + paramTile = tile; + paramEntity = entity; + paramBlock = this; + EntityQuery.getNearby(bulletGroup, tile.drawx(), tile.drawy(), realRadius * 2f, shieldConsumer); } float realRadius(ForceEntity entity){ - return (radius+entity.phaseHeat*phaseRadiusBoost) * entity.radscl; + return (radius + entity.phaseHeat * phaseRadiusBoost) * entity.radscl; } - boolean isInsideHexagon(float x0, float y0, float d, float x, float y) { - float dx = Math.abs(x - x0)/d; - float dy = Math.abs(y - y0)/d; + boolean isInsideHexagon(float x0, float y0, float d, float x, float y){ + float dx = Math.abs(x - x0) / d; + float dy = Math.abs(y - y0) / d; float a = 0.25f * Mathf.sqrt3; - return (dy <= a) && (a*dx + 0.25*dy <= 0.5*a); + return (dy <= a) && (a * dx + 0.25 * dy <= 0.5 * a); } @Override @@ -238,7 +251,7 @@ public class ForceProjector extends Block { @Override public float drawSize(){ - return realRadius(entity)*2f+2f; + return realRadius(entity) * 2f + 2f; } @Override @@ -257,6 +270,21 @@ public class ForceProjector extends Block { Draw.color(); } + public void drawSimple(){ + if(realRadius(entity) < 0.5f) return; + ; + + float rad = realRadius(entity); + + Draw.color(Pal.accent); + Lines.stroke(1.5f); + Draw.alpha(0.09f + 0.08f * entity.hit); + Fill.poly(x, y, 6, rad); + Draw.alpha(1f); + Lines.poly(x, y, 6, rad); + Draw.reset(); + } + @Override public EntityGroup targetGroup(){ return shieldGroup; @@ -267,9 +295,10 @@ public class ForceProjector extends Block { public ConsumeForceProjectorPower(float powerCapacity, float ticksToFill){ super(powerCapacity / ticksToFill, powerCapacity, true); } + @Override - public boolean valid(Block block, TileEntity entity){ - return entity.power.satisfaction >= basePowerDraw / powerCapacity && super.valid(block, entity); + public boolean valid(TileEntity entity){ + return entity.power.satisfaction >= basePowerDraw / powerCapacity && super.valid(entity); } } } 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 1419f6fd30..df97089bda 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/MendProjector.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/MendProjector.java @@ -2,23 +2,22 @@ package io.anuke.mindustry.world.blocks.defense; import io.anuke.arc.Core; import io.anuke.arc.collection.IntSet; -import io.anuke.mindustry.entities.Effects; 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.Lines; -import io.anuke.arc.graphics.g2d.TextureRegion; +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.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 java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.tilesize; import static io.anuke.mindustry.Vars.world; @@ -28,12 +27,12 @@ public class MendProjector extends Block{ private static Color phase = Color.valueOf("ffd59e"); private static IntSet healed = new IntSet(); - protected int timerUse = timers ++; + protected int timerUse = timers++; protected TextureRegion topRegion; protected float reload = 250f; - protected float range = 50f; - protected float healPercent = 6f; + protected float range = 60f; + protected float healPercent = 12f; protected float phaseBoost = 12f; protected float phaseRangeBoost = 50f; protected float useTime = 400f; @@ -52,16 +51,27 @@ public class MendProjector extends Block{ topRegion = Core.atlas.find(name + "-top"); } + @Override + public void setStats(){ + super.setStats(); + + stats.add(BlockStat.repairTime, (int)(100f / healPercent * reload / 60f), StatUnit.seconds); + stats.add(BlockStat.range, range / tilesize, StatUnit.blocks); + + stats.add(BlockStat.boostEffect, phaseRangeBoost / tilesize, StatUnit.blocks); + stats.add(BlockStat.boostEffect, (phaseBoost + healPercent) / healPercent, StatUnit.timesSpeed); + } + @Override public void update(Tile tile){ MendEntity entity = tile.entity(); entity.heat = Mathf.lerpDelta(entity.heat, entity.cons.valid() || tile.isEnemyCheat() ? 1f : 0f, 0.08f); entity.charge += entity.heat * entity.delta(); - entity.phaseHeat = Mathf.lerpDelta(entity.phaseHeat, (float)entity.items.get(consumes.item()) / itemCapacity, 0.1f); + entity.phaseHeat = Mathf.lerpDelta(entity.phaseHeat, Mathf.num(entity.cons.optionalValid()), 0.1f); - if(entity.cons.valid() && entity.timer.get(timerUse, useTime) && entity.items.total() > 0){ - entity.items.remove(consumes.item(), 1); + if(entity.cons.optionalValid() && entity.timer.get(timerUse, useTime)){ + entity.cons.trigger(); } if(entity.charge >= reload){ @@ -73,7 +83,7 @@ public class MendProjector extends Block{ for(int x = -tileRange + tile.x; x <= tileRange + tile.x; x++){ for(int y = -tileRange + tile.y; y <= tileRange + tile.y; y++){ - if(Mathf.dst(x, y, tile.x, tile.y) > realRange) continue; + if(Mathf.dst(x, y, tile.x, tile.y) > tileRange) continue; Tile other = world.tile(x, y); @@ -81,7 +91,7 @@ public class MendProjector extends Block{ other = other.target(); if(other.getTeamID() == tile.getTeamID() && !healed.contains(other.pos()) && other.entity != null && other.entity.health < other.entity.maxHealth()){ - other.entity.healBy(other.entity.maxHealth() * (healPercent + entity.phaseHeat*phaseBoost)/100f * entity.power.satisfaction); + other.entity.healBy(other.entity.maxHealth() * (healPercent + entity.phaseHeat * phaseBoost) / 100f * entity.power.satisfaction); Effects.effect(Fx.healBlockFull, Tmp.c1.set(color).lerp(phase, entity.phaseHeat), other.drawx(), other.drawy(), other.block().size); healed.add(other.pos()); } @@ -90,6 +100,13 @@ public class MendProjector extends Block{ } } + @Override + public void drawPlace(int x, int y, int rotation, boolean valid){ + Draw.color(Pal.accent); + Lines.dashCircle(x * tilesize, y * tilesize, range); + Draw.color(); + } + @Override public void drawSelect(Tile tile){ MendEntity entity = tile.entity(); @@ -114,8 +131,8 @@ public class MendProjector extends Block{ Draw.blend(); Draw.alpha(1f); - Lines.stroke((2f * f + 0.2f)* entity.heat); - Lines.circle(tile.drawx(), tile.drawy(), (1f-f) * 9f); + Lines.stroke((2f * f + 0.2f) * entity.heat); + Lines.circle(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 e8ce6425a9..1e284f2717 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/OverdriveProjector.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/OverdriveProjector.java @@ -4,18 +4,17 @@ 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.Draw; -import io.anuke.arc.graphics.g2d.Lines; -import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.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 java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.tilesize; import static io.anuke.mindustry.Vars.world; @@ -25,7 +24,7 @@ public class OverdriveProjector extends Block{ private static Color phase = Color.valueOf("ffd59e"); private static IntSet healed = new IntSet(); - protected int timerUse = timers ++; + protected int timerUse = timers++; protected TextureRegion topRegion; protected float reload = 60f; @@ -50,21 +49,39 @@ public class OverdriveProjector extends Block{ topRegion = Core.atlas.find(name + "-top"); } + @Override + public void drawPlace(int x, int y, int rotation, boolean valid){ + Draw.color(Pal.accent); + Lines.dashCircle(x * tilesize, y * tilesize, range); + Draw.color(); + } + + @Override + public void setStats(){ + super.setStats(); + + stats.add(BlockStat.speedIncrease, (int)(100f * speedBoost), StatUnit.percent); + stats.add(BlockStat.range, range / tilesize, StatUnit.blocks); + + stats.add(BlockStat.boostEffect, phaseRangeBoost / tilesize, StatUnit.blocks); + stats.add(BlockStat.boostEffect, (int)((speedBoost + speedBoostPhase) * 100f), StatUnit.percent); + } + @Override public void update(Tile tile){ OverdriveEntity entity = tile.entity(); entity.heat = Mathf.lerpDelta(entity.heat, entity.cons.valid() ? 1f : 0f, 0.08f); entity.charge += entity.heat * Time.delta(); - entity.phaseHeat = Mathf.lerpDelta(entity.phaseHeat, (float)entity.items.get(consumes.item()) / itemCapacity, 0.1f); + entity.phaseHeat = Mathf.lerpDelta(entity.phaseHeat, Mathf.num(entity.cons.optionalValid()), 0.1f); - if(entity.timer.get(timerUse, useTime) && entity.items.total() > 0){ - entity.items.remove(consumes.item(), 1); + if(entity.timer.get(timerUse, useTime)){ + entity.cons.trigger(); } if(entity.charge >= reload){ float realRange = range + entity.phaseHeat * phaseRangeBoost; - float realBoost = (speedBoost + entity.phaseHeat*speedBoostPhase) * entity.power.satisfaction; + float realBoost = (speedBoost + entity.phaseHeat * speedBoostPhase) * entity.power.satisfaction; entity.charge = 0f; @@ -83,7 +100,7 @@ public class OverdriveProjector extends Block{ 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); - healed.add(other.pos()); + healed.add(other.pos()); } } } @@ -113,8 +130,8 @@ public class OverdriveProjector extends Block{ Draw.rect(topRegion, tile.drawx(), tile.drawy()); Draw.blend(); Draw.alpha(1f); - Lines.stroke((2f * f + 0.2f)* entity.heat); - Lines.circle(tile.drawx(), tile.drawy(), (1f-f) * 9f); + Lines.stroke((2f * f + 0.2f) * entity.heat); + Lines.circle(tile.drawx(), tile.drawy(), (1f - f) * 9f); Draw.reset(); } diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/ShockMine.java b/core/src/io/anuke/mindustry/world/blocks/defense/ShockMine.java index 94e8a0590c..e834812f5a 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/ShockMine.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/ShockMine.java @@ -3,15 +3,15 @@ package io.anuke.mindustry.world.blocks.defense; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Fill; import io.anuke.arc.math.Mathf; -import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.entities.effect.Lightning; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.graphics.Layer; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; public class ShockMine extends Block{ - protected int timerDamage = timers ++; + protected int timerDamage = timers++; protected float cooldown = 80f; protected float tileDamage = 5f; diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/SurgeWall.java b/core/src/io/anuke/mindustry/world/blocks/defense/SurgeWall.java index e9a26e505a..d7cd84b321 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/SurgeWall.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/SurgeWall.java @@ -1,10 +1,10 @@ package io.anuke.mindustry.world.blocks.defense; -import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.arc.math.Mathf; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.effect.Lightning; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.graphics.Pal; -import io.anuke.arc.math.Mathf; public class SurgeWall extends Wall{ protected float lightningChance = 0.05f; diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/BurstTurret.java b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/BurstTurret.java index dac9df8e98..d746227559 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/BurstTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/BurstTurret.java @@ -23,7 +23,7 @@ public class BurstTurret extends ItemTurret{ for(int i = 0; i < shots; i++){ Time.run(burstSpacing * i, () -> { if(!(tile.entity instanceof TurretEntity) || - !hasAmmo(tile)) return; + !hasAmmo(tile)) return; entity.recoil = recoil; diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/ChargeTurret.java b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/ChargeTurret.java index 47faa0bd91..aa7151df98 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/ChargeTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/ChargeTurret.java @@ -1,12 +1,12 @@ package io.anuke.mindustry.world.blocks.defense.turrets; -import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.mindustry.entities.bullet.BulletType; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.world.Tile; import static io.anuke.mindustry.Vars.tilesize; diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/CooledTurret.java b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/CooledTurret.java index d81805a721..b425dd689d 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/CooledTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/CooledTurret.java @@ -1,21 +1,21 @@ package io.anuke.mindustry.world.blocks.defense.turrets; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.type.Liquid; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.consumers.ConsumeLiquidFilter; import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.Effects.Effect; -import io.anuke.arc.util.Time; -import io.anuke.arc.math.Mathf; +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; public class CooledTurret extends Turret{ - /**How much reload is lowered by for each unit of liquid of heat capacity 1.*/ - protected float coolantMultiplier = 1f; - /**Max coolant used per tick.*/ - protected float maxCoolantUsed = 1f; + /** How much reload is lowered by for each unit of liquid of heat capacity. */ + protected float coolantMultiplier = 5f; protected Effect coolEffect = Fx.fuelburn; public CooledTurret(String name){ @@ -23,17 +23,28 @@ public class CooledTurret extends Turret{ hasLiquids = true; liquidCapacity = 20f; - consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, 0.01f)).update(false).optional(true); + consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, 0.2f)).update(false).boost(); + } + + @Override + public void setStats(){ + super.setStats(); + + float maxUsed = consumes.get(ConsumeType.liquid).amount; + + stats.add(BlockStat.boostEffect, 1f + maxUsed * coolantMultiplier, StatUnit.timesSpeed); } @Override protected void updateShooting(Tile tile){ super.updateShooting(tile); + float maxUsed = consumes.get(ConsumeType.liquid).amount; + TurretEntity entity = tile.entity(); Liquid liquid = entity.liquids.current(); - float used = Math.min(Math.min(entity.liquids.get(liquid), maxCoolantUsed * Time.delta()), Math.max(0, ((reload - entity.reload) / coolantMultiplier) / liquid.heatCapacity)); + float used = Math.min(Math.min(entity.liquids.get(liquid), maxUsed * Time.delta()), Math.max(0, ((reload - entity.reload) / coolantMultiplier) / liquid.heatCapacity)); entity.reload += (used * liquid.heatCapacity) / liquid.heatCapacity; entity.liquids.remove(liquid, used); @@ -41,9 +52,4 @@ public class CooledTurret extends Turret{ Effects.effect(coolEffect, tile.drawx() + Mathf.range(size * tilesize / 2f), tile.drawy() + Mathf.range(size * tilesize / 2f)); } } - - @Override - public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ - return super.acceptLiquid(tile, source, liquid, amount) && liquid.temperature <= 0.5f; - } } diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/DoubleTurret.java b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/DoubleTurret.java index f8830aaefe..2067bd285a 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/DoubleTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/DoubleTurret.java @@ -3,6 +3,8 @@ package io.anuke.mindustry.world.blocks.defense.turrets; import io.anuke.arc.math.Mathf; 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; import static io.anuke.mindustry.Vars.tilesize; @@ -14,6 +16,14 @@ public class DoubleTurret extends ItemTurret{ shots = 2; } + @Override + public void setStats(){ + super.setStats(); + + stats.remove(BlockStat.reload); + stats.add(BlockStat.reload, 60f / reload, StatUnit.none); + } + @Override protected void shoot(Tile tile, BulletType ammo){ TurretEntity entity = tile.entity(); diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/ItemTurret.java b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/ItemTurret.java index 616ffb0d53..6caa16390e 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/ItemTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/ItemTurret.java @@ -1,6 +1,7 @@ package io.anuke.mindustry.world.blocks.defense.turrets; import io.anuke.arc.collection.ObjectMap; +import io.anuke.arc.collection.OrderedMap; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.bullet.BulletType; @@ -11,11 +12,9 @@ import io.anuke.mindustry.type.Item; import io.anuke.mindustry.ui.Bar; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.mindustry.world.meta.values.ItemFilterValue; +import io.anuke.mindustry.world.meta.values.AmmoListValue; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; public class ItemTurret extends CooledTurret{ protected int maxAmmo = 30; @@ -26,9 +25,9 @@ public class ItemTurret extends CooledTurret{ hasItems = true; } - /**Initializes accepted ammo map. Format: [item1, bullet1, item2, bullet2...]*/ + /** Initializes accepted ammo map. Format: [item1, bullet1, item2, bullet2...] */ protected void ammo(Object... objects){ - ammo = ObjectMap.of(objects); + ammo = OrderedMap.of(objects); } @Override @@ -36,7 +35,7 @@ public class ItemTurret extends CooledTurret{ super.setStats(); stats.remove(BlockStat.itemCapacity); - stats.add(BlockStat.inputItems, new ItemFilterValue(item -> ammo.containsKey(item))); + stats.add(BlockStat.ammo, new AmmoListValue<>(ammo)); } @@ -58,7 +57,7 @@ public class ItemTurret extends CooledTurret{ if(type == null) return 0; - return Math.min((int) ((maxAmmo - entity.totalAmmo) / ammo.get(item).ammoMultiplier), amount); + return Math.min((int)((maxAmmo - entity.totalAmmo) / ammo.get(item).ammoMultiplier), amount); } @Override @@ -95,7 +94,7 @@ public class ItemTurret extends CooledTurret{ } //must not be found - entity.ammo.add(new ItemEntry(item, (int) type.ammoMultiplier)); + entity.ammo.add(new ItemEntry(item, (int)type.ammoMultiplier)); } @Override 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 3796103fe3..fabfa0349d 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 @@ -1,15 +1,16 @@ package io.anuke.mindustry.world.blocks.defense.turrets; -import io.anuke.mindustry.entities.Effects; import io.anuke.arc.math.Angles; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; -import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.bullet.BulletType; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.consumers.ConsumeLiquidFilter; +import io.anuke.mindustry.world.consumers.*; +import io.anuke.mindustry.world.meta.BlockStat; import static io.anuke.mindustry.Vars.tilesize; @@ -21,12 +22,18 @@ public class LaserTurret extends PowerTurret{ super(name); canOverdrive = false; - consumes.remove(ConsumeLiquidFilter.class); consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, 0.01f)).update(false); } @Override - public void update(Tile tile) { + public void setStats(){ + super.setStats(); + + stats.remove(BlockStat.boostEffect); + } + + @Override + public void update(Tile tile){ super.update(tile); LaserTurretEntity entity = tile.entity(); @@ -61,9 +68,10 @@ public class LaserTurret extends PowerTurret{ entity.reload = 0f; }else{ Liquid liquid = entity.liquids.current(); + float maxUsed = consumes.get(ConsumeType.liquid).amount; - float used = Math.min(Math.min(entity.liquids.get(liquid), maxCoolantUsed * Time.delta()), Math.max(0, ((reload - entity.reload) / coolantMultiplier) / liquid.heatCapacity)); - entity.reload += (used * liquid.heatCapacity) / liquid.heatCapacity; + float used = Math.min(entity.liquids.get(liquid), maxUsed * Time.delta()); + entity.reload += used; entity.liquids.remove(liquid, used); if(Mathf.chance(0.06 * used)){ diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/LiquidTurret.java b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/LiquidTurret.java index ee321ac2ed..48e3f52c77 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/LiquidTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/LiquidTurret.java @@ -1,6 +1,7 @@ package io.anuke.mindustry.world.blocks.defense.turrets; import io.anuke.arc.collection.ObjectMap; +import io.anuke.arc.collection.OrderedMap; import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.bullet.BulletType; import io.anuke.mindustry.entities.effect.Fire; @@ -8,7 +9,7 @@ import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.mindustry.world.meta.values.LiquidFilterValue; +import io.anuke.mindustry.world.meta.values.AmmoListValue; import static io.anuke.mindustry.Vars.tilesize; import static io.anuke.mindustry.Vars.world; @@ -21,34 +22,34 @@ public abstract class LiquidTurret extends Turret{ hasLiquids = true; } - /**Initializes accepted ammo map. Format: [liquid1, bullet1, liquid2, bullet2...]*/ + /** Initializes accepted ammo map. Format: [liquid1, bullet1, liquid2, bullet2...] */ protected void ammo(Object... objects){ - ammo = ObjectMap.of(objects); + ammo = OrderedMap.of(objects); } @Override public void setStats(){ super.setStats(); - stats.add(BlockStat.inputLiquid, new LiquidFilterValue(item -> ammo.containsKey(item))); + stats.add(BlockStat.ammo, new AmmoListValue<>(ammo)); } @Override - protected boolean validateTarget(Tile tile) { + protected boolean validateTarget(Tile tile){ TurretEntity entity = tile.entity(); if(entity.liquids.current().canExtinguish() && entity.target instanceof Tile){ - return Fire.has(((Tile) entity.target).x, ((Tile) entity.target).y); + return Fire.has(((Tile)entity.target).x, ((Tile)entity.target).y); } return super.validateTarget(tile); } @Override - protected void findTarget(Tile tile) { + protected void findTarget(Tile tile){ TurretEntity entity = tile.entity(); if(entity.liquids.current().canExtinguish()){ int tr = (int)(range / tilesize); - for (int x = -tr; x <= tr; x++) { - for (int y = -tr; y <= tr; y++) { + for(int x = -tr; x <= tr; x++){ + for(int y = -tr; y <= tr; y++){ if(Fire.has(x + tile.x, y + tile.y)){ entity.target = world.tile(x + tile.x, y + tile.y); return; @@ -103,8 +104,8 @@ public abstract class LiquidTurret extends Turret{ @Override public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ - return super.acceptLiquid(tile, source, liquid, amount) && ammo.get(liquid) != null - && (tile.entity.liquids.current() == liquid || (ammo.containsKey(tile.entity.liquids.current()) && tile.entity.liquids.get(tile.entity.liquids.current()) <= ammo.get(tile.entity.liquids.current()).ammoMultiplier + 0.001f)); + return ammo.get(liquid) != null + && (tile.entity.liquids.current() == liquid || (ammo.containsKey(tile.entity.liquids.current()) && tile.entity.liquids.get(tile.entity.liquids.current()) <= ammo.get(tile.entity.liquids.current()).ammoMultiplier + 0.001f)); } } 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 8f3d143a23..111a7024ec 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,7 +2,6 @@ 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.consumers.ConsumePower; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.StatUnit; @@ -20,7 +19,7 @@ public abstract class PowerTurret extends CooledTurret{ public void setStats(){ super.setStats(); - stats.add(BlockStat.powerShot, powerUsed * consumes.get(ConsumePower.class).powerCapacity, StatUnit.powerUnits); + stats.add(BlockStat.powerShot, powerUsed * consumes.getPower().powerCapacity, StatUnit.powerUnits); } @Override 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 fb79202269..3755868fb9 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 @@ -3,33 +3,26 @@ package io.anuke.mindustry.world.blocks.defense.turrets; import io.anuke.arc.Core; import io.anuke.arc.collection.Array; import io.anuke.arc.collection.EnumSet; -import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.arc.function.BiConsumer; 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.Lines; -import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Angles; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.Predict; -import io.anuke.mindustry.entities.type.TileEntity; -import io.anuke.mindustry.entities.Units; +import io.anuke.mindustry.entities.*; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.bullet.BulletType; import io.anuke.mindustry.entities.traits.TargetTrait; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.graphics.Layer; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.meta.BlockFlag; -import io.anuke.mindustry.world.meta.BlockGroup; -import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.mindustry.world.meta.StatUnit; +import io.anuke.mindustry.world.meta.*; import static io.anuke.mindustry.Vars.tilesize; @@ -66,7 +59,7 @@ public abstract class Turret extends Block{ protected TextureRegion baseRegion, heatRegion; protected BiConsumer drawer = (tile, entity) -> - Draw.rect(region, tile.drawx() + tr2.x, tile.drawy() + tr2.y, entity.rotation - 90); + Draw.rect(region, tile.drawx() + tr2.x, tile.drawy() + tr2.y, entity.rotation - 90); protected BiConsumer heatDrawer = (tile, entity) -> { if(entity.heat <= 0.00001f) return; Draw.color(heatColor, entity.heat); @@ -105,8 +98,8 @@ public abstract class Turret extends Block{ super.setStats(); stats.add(BlockStat.shootRange, range, StatUnit.blocks); - stats.add(BlockStat.inaccuracy, (int) inaccuracy, StatUnit.degrees); - stats.add(BlockStat.reload, 60f / reload, StatUnit.none); + stats.add(BlockStat.inaccuracy, (int)inaccuracy, StatUnit.degrees); + stats.add(BlockStat.reload, 60f / reload * shots, StatUnit.none); stats.add(BlockStat.shots, shots, StatUnit.none); stats.add(BlockStat.targetsAir, targetAir); stats.add(BlockStat.targetsGround, targetGround); @@ -203,7 +196,7 @@ public abstract class Turret extends Block{ TurretEntity entity = tile.entity(); entity.target = Units.getClosestTarget(tile.getTeam(), - tile.drawx(), tile.drawy(), range, e -> !e.isDead() && (!e.isFlying() || targetAir) && (e.isFlying() || targetGround)); + tile.drawx(), tile.drawy(), range, e -> !e.isDead() && (!e.isFlying() || targetAir) && (e.isFlying() || targetGround)); } protected void turnToTarget(Tile tile, float targetRot){ @@ -216,7 +209,7 @@ public abstract class Turret extends Block{ return true; } - /**Consume ammo and return a type.*/ + /** Consume ammo and return a type. */ public BulletType useAmmo(Tile tile){ if(tile.isEnemyCheat()) return peekAmmo(tile); @@ -268,7 +261,7 @@ public abstract class Turret extends Block{ tr.trns(entity.rotation, size * tilesize / 2f, Mathf.range(xRand)); for(int i = 0; i < shots; i++){ - bullet(tile, type, entity.rotation + Mathf.range(inaccuracy + type.inaccuracy) + (i-shots/2) * spread); + bullet(tile, type, entity.rotation + Mathf.range(inaccuracy + type.inaccuracy) + (i - shots / 2) * spread); } effects(tile); @@ -300,7 +293,7 @@ public abstract class Turret extends Block{ TurretEntity entity = tile.entity(); Effects.effect(ammoUseEffect, tile.drawx() - Angles.trnsx(entity.rotation, ammoEjectBack), - tile.drawy() - Angles.trnsy(entity.rotation, ammoEjectBack), entity.rotation); + tile.drawy() - Angles.trnsy(entity.rotation, ammoEjectBack), entity.rotation); } protected boolean isTurret(Tile tile){ diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/BufferedItemBridge.java b/core/src/io/anuke/mindustry/world/blocks/distribution/BufferedItemBridge.java index 6e833659c5..709c84300e 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/BufferedItemBridge.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/BufferedItemBridge.java @@ -1,10 +1,10 @@ package io.anuke.mindustry.world.blocks.distribution; +import io.anuke.arc.math.Mathf; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.ItemBuffer; import io.anuke.mindustry.world.Tile; -import io.anuke.arc.math.Mathf; public class BufferedItemBridge extends ExtendingItemBridge{ protected int timerAccept = timers++; 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 22d9c2e873..44c54540ce 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Conduit.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Conduit.java @@ -1,18 +1,16 @@ package io.anuke.mindustry.world.blocks.distribution; import io.anuke.arc.Core; +import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.math.Mathf; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.LiquidBlock; import io.anuke.mindustry.world.modules.LiquidModule; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.math.Mathf; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; public class Conduit extends LiquidBlock{ protected final int timerFlow = timers++; @@ -108,7 +106,7 @@ public class Conduit extends LiquidBlock{ @Override public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ tile.entity.noSleep(); - return super.acceptLiquid(tile, source, liquid, amount) && ((2 + source.relativeTo(tile.x, tile.y)) % 4 != tile.getRotation()); + return tile.entity.liquids.get(liquid) + amount < liquidCapacity && (tile.entity.liquids.current() == liquid || tile.entity.liquids.get(tile.entity.liquids.current()) < 0.2f) && ((2 + source.relativeTo(tile.x, tile.y)) % 4 != tile.getRotation()); } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/Conveyor.java b/core/src/io/anuke/mindustry/world/blocks/distribution/Conveyor.java index 92fd7c65f1..1e602a1ff5 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Conveyor.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Conveyor.java @@ -5,12 +5,8 @@ import io.anuke.arc.collection.LongArray; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; -import io.anuke.arc.math.geom.Geometry; -import io.anuke.arc.math.geom.Point2; -import io.anuke.arc.math.geom.Vector2; -import io.anuke.arc.util.Log; -import io.anuke.arc.util.Pack; -import io.anuke.arc.util.Time; +import io.anuke.arc.math.geom.*; +import io.anuke.arc.util.*; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.graphics.Layer; @@ -18,18 +14,14 @@ import io.anuke.mindustry.input.InputHandler.PlaceDraw; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.meta.BlockGroup; -import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.mindustry.world.meta.StatUnit; +import io.anuke.mindustry.world.meta.*; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.*; public class Conveyor extends Block{ - private static final float itemSpace = 0.135f * 3f; + private static final float itemSpace = 0.4f; private static final float minmove = 1f / (Short.MAX_VALUE - 2); private static ItemPos drawpos = new ItemPos(); private static ItemPos pos1 = new ItemPos(); @@ -60,7 +52,7 @@ public class Conveyor extends Block{ @Override public void setStats(){ super.setStats(); - stats.add(BlockStat.itemsMoved, speed * 60, StatUnit.itemsSecond); + stats.add(BlockStat.itemsMoved, speed * 60 * (1f / itemSpace), StatUnit.itemsSecond); } @Override @@ -79,9 +71,9 @@ public class Conveyor extends Block{ ConveyorEntity entity = tile.entity(); byte rotation = tile.getRotation(); - int frame = entity.clogHeat <= 0.5f ? (int) (((Time.time() * speed * 8f * entity.timeScale)) % 4) : 0; + int frame = entity.clogHeat <= 0.5f ? (int)(((Time.time() * speed * 8f * entity.timeScale)) % 4) : 0; Draw.rect(regions[Mathf.clamp(entity.blendbits, 0, regions.length - 1)][Mathf.clamp(frame, 0, regions[0].length - 1)], tile.drawx(), tile.drawy(), - tilesize * entity.blendsclx, tilesize * entity.blendscly, rotation*90); + tilesize * entity.blendsclx, tilesize * entity.blendscly, rotation * 90); } @Override @@ -162,8 +154,8 @@ public class Conveyor extends Block{ tr2.trns(rotation * 90, -tilesize / 2f, pos.x * tilesize / 2f); Draw.rect(pos.item.icon(Item.Icon.medium), - (tile.x * tilesize + tr1.x * pos.y + tr2.x), - (tile.y * tilesize + tr1.y * pos.y + tr2.y), itemSize, itemSize); + (tile.x * tilesize + tr1.x * pos.y + tr2.x), + (tile.y * tilesize + tr1.y * pos.y + tr2.y), itemSize, itemSize); } }catch(IndexOutOfBoundsException e){ @@ -175,6 +167,10 @@ public class Conveyor extends Block{ public void unitOn(Tile tile, Unit unit){ ConveyorEntity entity = tile.entity(); + if(entity.clogHeat > 0.5f){ + return; + } + entity.noSleep(); float speed = this.speed * tilesize / 2.4f; @@ -199,7 +195,6 @@ public class Conveyor extends Block{ @Override public void update(Tile tile){ - ConveyorEntity entity = tile.entity(); entity.minitem = 1f; Tile next = tile.getNearby(tile.getRotation()); @@ -231,7 +226,7 @@ public class Conveyor extends Block{ pos.y = Mathf.clamp(pos.y, 0, nextMax); if(pos.y >= 0.9999f && offloadDir(tile, pos.item)){ - if(next.block() instanceof Conveyor){ + if(next != null && next.block() instanceof Conveyor){ ConveyorEntity othere = next.entity(); ItemPos ni = pos2.set(othere.convey.get(othere.lastInserted), ItemPos.updateShorts); @@ -322,7 +317,7 @@ public class Conveyor extends Block{ int direction = source == null ? 0 : Math.abs(source.relativeTo(tile.x, tile.y) - tile.getRotation()); float minitem = tile.entity().minitem; return (((direction == 0) && minitem > itemSpace) || - ((direction % 2 == 1) && minitem > 0.52f)) && (source == null || !(source.block().rotate && (source.getRotation() + 2) % 4 == tile.getRotation())); + ((direction % 2 == 1) && minitem > 0.52f)) && (source == null || !(source.block().rotate && (source.getRotation() + 2) % 4 == tile.getRotation())); } @Override @@ -351,7 +346,7 @@ public class Conveyor extends Block{ //this item must be greater than anything there... entity.convey.add(result); - entity.lastInserted = (byte)(entity.convey.size-1); + entity.lastInserted = (byte)(entity.convey.size - 1); } @Override @@ -408,9 +403,9 @@ public class Conveyor extends Block{ static long packItem(Item item, float x, float y){ short[] shorts = packShorts; - shorts[0] = (short) item.id; - shorts[1] = (short) (x * Short.MAX_VALUE); - shorts[2] = (short) ((y - 1f) * Short.MAX_VALUE); + shorts[0] = (short)item.id; + shorts[1] = (short)(x * Short.MAX_VALUE); + shorts[2] = (short)((y - 1f) * Short.MAX_VALUE); return Pack.longShorts(shorts); } @@ -418,13 +413,13 @@ public class Conveyor extends Block{ short[] values = Pack.shorts(value, writeShort); short itemid = values[0]; - float x = values[1] / (float) Short.MAX_VALUE; - float y = ((float) values[2]) / Short.MAX_VALUE + 1f; + float x = values[1] / (float)Short.MAX_VALUE; + float y = ((float)values[2]) / Short.MAX_VALUE + 1f; byte[] bytes = writeByte; - bytes[0] = (byte) itemid; - bytes[1] = (byte) (x * 127); - bytes[2] = (byte) (y * 255 - 128); + bytes[0] = (byte)itemid; + bytes[1] = (byte)(x * 127); + bytes[2] = (byte)(y * 255 - 128); return Pack.intBytes(bytes); } @@ -434,12 +429,12 @@ public class Conveyor extends Block{ byte itemid = values[0]; float x = values[1] / 127f; - float y = ((int) values[2] + 128) / 255f; + float y = ((int)values[2] + 128) / 255f; short[] shorts = writeShort; - shorts[0] = (short) itemid; - shorts[1] = (short) (x * Short.MAX_VALUE); - shorts[2] = (short) ((y - 1f) * Short.MAX_VALUE); + shorts[0] = (short)itemid; + shorts[1] = (short)(x * Short.MAX_VALUE); + shorts[2] = (short)((y - 1f) * Short.MAX_VALUE); return Pack.longShorts(shorts); } @@ -451,8 +446,8 @@ public class Conveyor extends Block{ else item = content.items().get(values[0]); - x = values[1] / (float) Short.MAX_VALUE; - y = ((float) values[2]) / Short.MAX_VALUE + 1f; + x = values[1] / (float)Short.MAX_VALUE; + y = ((float)values[2]) / Short.MAX_VALUE + 1f; return this; } diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/ExtendingItemBridge.java b/core/src/io/anuke/mindustry/world/blocks/distribution/ExtendingItemBridge.java index 1df134830f..4f145022c7 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/ExtendingItemBridge.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/ExtendingItemBridge.java @@ -1,8 +1,6 @@ package io.anuke.mindustry.world.blocks.distribution; -import io.anuke.arc.graphics.g2d.CapStyle; -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.Mathf; import io.anuke.arc.math.geom.Geometry; import io.anuke.mindustry.world.Tile; @@ -27,22 +25,22 @@ public class ExtendingItemBridge extends ItemBridge{ int i = tile.absoluteRelativeTo(other.x, other.y); float ex = other.worldx() - tile.worldx() - Geometry.d4[i].x * tilesize / 2f, - ey = other.worldy() - tile.worldy() - Geometry.d4[i].y * tilesize / 2f; + ey = other.worldy() - tile.worldy() - Geometry.d4[i].y * tilesize / 2f; ex *= entity.uptime; ey *= entity.uptime; Lines.stroke(8f); Lines.line(bridgeRegion, - tile.worldx() + Geometry.d4[i].x * tilesize / 2f, - tile.worldy() + Geometry.d4[i].y * tilesize / 2f, - tile.worldx() + ex, - tile.worldy() + ey, CapStyle.none, 0f); + tile.worldx() + Geometry.d4[i].x * tilesize / 2f, + tile.worldy() + Geometry.d4[i].y * tilesize / 2f, + tile.worldx() + ex, + tile.worldy() + ey, CapStyle.none, 0f); Draw.rect(endRegion, tile.drawx(), tile.drawy(), i * 90 + 90); Draw.rect(endRegion, - tile.worldx() + ex + Geometry.d4[i].x * tilesize / 2f, - tile.worldy() + ey + Geometry.d4[i].y * tilesize / 2f, i * 90 + 270); + tile.worldx() + ex + Geometry.d4[i].x * tilesize / 2f, + tile.worldy() + ey + Geometry.d4[i].y * tilesize / 2f, i * 90 + 270); int dist = Math.max(Math.abs(other.x - tile.x), Math.abs(other.y - tile.y)); @@ -51,10 +49,10 @@ public class ExtendingItemBridge extends ItemBridge{ Draw.color(); for(int a = 0; a < arrows; a++){ - Draw.alpha(Mathf.absin(a / (float) arrows - entity.time / 100f, 0.1f, 1f) * entity.uptime); + Draw.alpha(Mathf.absin(a / (float)arrows - entity.time / 100f, 0.1f, 1f) * entity.uptime); Draw.rect(arrowRegion, - tile.worldx() + Geometry.d4[i].x * (tilesize / 2f + a * 6f + 2) * entity.uptime, - tile.worldy() + Geometry.d4[i].y * (tilesize / 2f + a * 6f + 2) * entity.uptime, i * 90f); + tile.worldx() + Geometry.d4[i].x * (tilesize / 2f + a * 6f + 2) * entity.uptime, + tile.worldy() + Geometry.d4[i].y * (tilesize / 2f + a * 6f + 2) * entity.uptime, i * 90f); } Draw.reset(); } 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 20be93efda..2218991af5 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/ItemBridge.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/ItemBridge.java @@ -10,7 +10,6 @@ import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.*; 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.Time; import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.entities.type.TileEntity; @@ -18,15 +17,10 @@ import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Layer; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Edges; -import io.anuke.mindustry.world.Pos; -import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.meta.BlockGroup; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.tilesize; import static io.anuke.mindustry.Vars.world; @@ -94,18 +88,6 @@ public class ItemBridge extends Block{ if(world.tile(x, y) != null && linkValid(world.tile(x, y), world.tile(lastPlaced)) && lastPlaced != Pos.get(x, y)){ return world.tile(lastPlaced); } - - for(int j = 0; j < 4; j ++){ - Point2 p = Geometry.d4(j + 1); - for(int i = 1; i <= range; i++){ - Tile tile = world.tile(x + p.x * i, y + p.y * i); - - if(tile == null) break; - if(tile.block() == this && !(tile.x == x && tile.y == y) && tile.entity != null && tile.entity().link == Pos.invalid){ - return tile; - } - } - } return null; } @@ -113,14 +95,25 @@ public class ItemBridge extends Block{ public void drawPlace(int x, int y, int rotation, boolean valid){ Tile link = findLink(x, y); - Draw.tint(Pal.placing); + Lines.stroke(2f, Pal.placing); + for(int i = 0; i < 4; i++){ + Lines.dashLine( + x * tilesize + Geometry.d4[i].x * (tilesize / 2f + 2), + y * tilesize + Geometry.d4[i].y * (tilesize / 2f + 2), + x * tilesize + Geometry.d4[i].x * (range + 0.5f) * tilesize, + y * tilesize + Geometry.d4[i].y * (range + 0.5f) * tilesize, + range); + } + + Draw.reset(); + Draw.color(Pal.placing); Lines.stroke(1f); if(link != null){ int rot = link.absoluteRelativeTo(x, y); 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); + 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.reset(); } @@ -132,7 +125,7 @@ public class ItemBridge extends Block{ Draw.color(Pal.accent); Lines.stroke(1f); Lines.square(tile.drawx(), tile.drawy(), - tile.block().size * tilesize / 2f + 1f); + tile.block().size * tilesize / 2f + 1f); for(int i = 1; i <= range; i++){ for(int j = 0; j < 4; j++){ @@ -142,7 +135,7 @@ public class ItemBridge extends Block{ Draw.color(linked ? Pal.place : Pal.breakInvalid); Lines.square(other.drawx(), other.drawy(), - other.block().size * tilesize / 2f + 1f + (linked ? 0f : Mathf.absin(Time.time(), 4f, 1f))); + other.block().size * tilesize / 2f + 1f + (linked ? 0f : Mathf.absin(Time.time(), 4f, 1f))); } } } @@ -236,10 +229,10 @@ public class ItemBridge extends Block{ Lines.stroke(8f); Lines.line(bridgeRegion, - tile.worldx(), - tile.worldy(), - other.worldx(), - other.worldy(), CapStyle.none, -tilesize / 2f); + tile.worldx(), + tile.worldy(), + other.worldx(), + other.worldy(), CapStyle.none, -tilesize / 2f); int dist = Math.max(Math.abs(other.x - tile.x), Math.abs(other.y - tile.y)); @@ -249,17 +242,17 @@ public class ItemBridge extends Block{ Draw.color(); for(int a = 0; a < arrows; a++){ - Draw.alpha(Mathf.absin(a / (float) arrows - entity.time / 100f, 0.1f, 1f) * entity.uptime); + Draw.alpha(Mathf.absin(a / (float)arrows - entity.time / 100f, 0.1f, 1f) * entity.uptime); Draw.rect(arrowRegion, - tile.worldx() + Geometry.d4[i].x * (tilesize / 2f + a * 4f + time % 4f), - tile.worldy() + Geometry.d4[i].y * (tilesize / 2f + a * 4f + time % 4f), i * 90f); + tile.worldx() + Geometry.d4[i].x * (tilesize / 2f + a * 4f + time % 4f), + tile.worldy() + Geometry.d4[i].y * (tilesize / 2f + a * 4f + time % 4f), i * 90f); } Draw.reset(); } @Override public boolean acceptItem(Item item, Tile tile, Tile source){ - if(tile.getTeamID() != source.target().getTeamID()) return false; + if(tile.getTeam() != source.target().getTeam()) return false; ItemBridgeEntity entity = tile.entity(); Tile other = world.tile(entity.link); diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/Junction.java b/core/src/io/anuke/mindustry/world/blocks/distribution/Junction.java index 84a6f32c6b..2e145a59e5 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Junction.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Junction.java @@ -1,8 +1,6 @@ package io.anuke.mindustry.world.blocks.distribution; -import io.anuke.arc.util.NumberUtils; -import io.anuke.arc.util.Pack; -import io.anuke.arc.util.Time; +import io.anuke.arc.util.*; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Block; diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidBridge.java b/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidBridge.java index ba8350c5d4..1999136d89 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidBridge.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidBridge.java @@ -1,11 +1,12 @@ package io.anuke.mindustry.world.blocks.distribution; +import io.anuke.arc.collection.IntSet.IntSetIterator; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.util.Time; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Liquid; -import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.meta.BlockGroup; -import io.anuke.arc.util.Time; -import io.anuke.arc.math.Mathf; import static io.anuke.mindustry.Vars.world; @@ -27,7 +28,7 @@ public class LiquidBridge extends ItemBridge{ entity.time2 += (entity.cycleSpeed - 1f) * Time.delta(); Tile other = world.tile(entity.link); - if(!linkValid(tile, other) ){ + if(!linkValid(tile, other)){ tryDumpLiquid(tile, entity.liquids.current()); }else{ if(entity.cons.valid()){ @@ -56,13 +57,43 @@ public class LiquidBridge extends ItemBridge{ return false; } + @Override + public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ + if(tile.getTeam() != source.target().getTeam()) return false; + + ItemBridgeEntity entity = tile.entity(); + Tile other = world.tile(entity.link); + + if(linkValid(tile, other)){ + int rel = tile.absoluteRelativeTo(other.x, other.y); + int rel2 = tile.relativeTo(source.x, source.y); + + if(rel == rel2) return false; + }else if(!(source.block() instanceof ItemBridge && source.entity().link == tile.pos())){ + return false; + } + + return tile.entity.liquids.get(liquid) + amount < liquidCapacity && (tile.entity.liquids.current() == liquid || tile.entity.liquids.get(tile.entity.liquids.current()) < 0.2f); + } + @Override public boolean canDumpLiquid(Tile tile, Tile to, Liquid liquid){ ItemBridgeEntity entity = tile.entity(); Tile other = world.tile(entity.link); if(!linkValid(tile, other)){ - return !(to.block() instanceof LiquidBridge); + Tile edge = Edges.getFacingEdge(to, tile); + int i = tile.absoluteRelativeTo(edge.x, edge.y); + + IntSetIterator it = entity.incoming.iterator(); + + while(it.hasNext){ + int v = it.next(); + if(tile.absoluteRelativeTo(Pos.x(v), Pos.y(v)) == i){ + return false; + } + } + return true; } int rel = tile.absoluteRelativeTo(other.x, other.y); diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidExtendingBridge.java b/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidExtendingBridge.java index cdbb697e77..9d75b6f849 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidExtendingBridge.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidExtendingBridge.java @@ -54,6 +54,11 @@ public class LiquidExtendingBridge extends ExtendingItemBridge{ return false; } + @Override + public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ + return tile.entity.liquids.get(liquid) + amount < liquidCapacity && (tile.entity.liquids.current() == liquid || tile.entity.liquids.get(tile.entity.liquids.current()) < 0.2f); + } + @Override public boolean canDumpLiquid(Tile tile, Tile to, Liquid liquid){ ItemBridgeEntity entity = tile.entity(); diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidJunction.java b/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidJunction.java index 7dfd439bc6..8e57c24777 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidJunction.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidJunction.java @@ -1,12 +1,12 @@ package io.anuke.mindustry.world.blocks.distribution; import io.anuke.arc.Core; +import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.LiquidBlock; import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.arc.graphics.g2d.Draw; public class LiquidJunction extends LiquidBlock{ diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidRouter.java b/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidRouter.java index 4ca44a549c..52dbe920fd 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidRouter.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidRouter.java @@ -1,5 +1,6 @@ package io.anuke.mindustry.world.blocks.distribution; +import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.LiquidBlock; @@ -17,4 +18,8 @@ public class LiquidRouter extends LiquidBlock{ } } + @Override + public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ + return tile.entity.liquids.get(liquid) + amount < liquidCapacity && (tile.entity.liquids.current() == liquid || tile.entity.liquids.get(tile.entity.liquids.current()) < 0.2f); + } } 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 37c059464a..8cb1ea19d7 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/MassDriver.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/MassDriver.java @@ -4,12 +4,8 @@ import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.Core; import io.anuke.arc.collection.ObjectSet; -import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.arc.graphics.Color; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Lines; -import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Angles; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; @@ -17,22 +13,21 @@ import io.anuke.arc.util.pooling.Pool.Poolable; import io.anuke.arc.util.pooling.Pools; import io.anuke.mindustry.content.Bullets; import io.anuke.mindustry.content.Fx; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; +import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.entities.type.TileEntity; -import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Layer; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.consumers.ConsumePower; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.StatUnit; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.*; @@ -73,7 +68,7 @@ public class MassDriver extends Block{ //just in case the client has invalid data if(!(tile.entity instanceof MassDriverEntity) || !(target.entity instanceof MassDriverEntity)) return; - MassDriver driver = (MassDriver) tile.block(); + MassDriver driver = (MassDriver)tile.block(); MassDriverEntity entity = tile.entity(); MassDriverEntity other = target.entity(); @@ -87,7 +82,7 @@ public class MassDriver extends Block{ data.to = other; int totalUsed = 0; for(int i = 0; i < content.items().size; i++){ - int maxTransfer = Math.min(entity.items.get(content.item(i)), ((MassDriver) tile.block()).itemCapacity - totalUsed); + int maxTransfer = Math.min(entity.items.get(content.item(i)), ((MassDriver)tile.block()).itemCapacity - totalUsed); data.items[i] = maxTransfer; totalUsed += maxTransfer; } @@ -97,14 +92,14 @@ public class MassDriver extends Block{ other.isRecieving = true; Bullet.create(Bullets.driverBolt, entity, entity.getTeam(), - tile.drawx() + Angles.trnsx(angle, driver.translation), tile.drawy() + Angles.trnsy(angle, driver.translation), - angle, 1f, 1f, data); + tile.drawx() + Angles.trnsx(angle, driver.translation), tile.drawy() + Angles.trnsy(angle, driver.translation), + angle, 1f, 1f, data); Effects.effect(driver.shootEffect, tile.drawx() + Angles.trnsx(angle, driver.translation), - tile.drawy() + Angles.trnsy(angle, driver.translation), angle); + tile.drawy() + Angles.trnsy(angle, driver.translation), angle); Effects.effect(driver.smokeEffect, tile.drawx() + Angles.trnsx(angle, driver.translation), - tile.drawy() + Angles.trnsy(angle, driver.translation), angle); + tile.drawy() + Angles.trnsy(angle, driver.translation), angle); Effects.shake(driver.shake, driver.shake, entity); } @@ -125,7 +120,7 @@ public class MassDriver extends Block{ public void setStats(){ super.setStats(); - stats.add(BlockStat.powerShot, consumes.get(ConsumePower.class).powerCapacity * powerPercentageUsed, StatUnit.powerUnits); + stats.add(BlockStat.powerShot, consumes.getPower().powerCapacity * powerPercentageUsed, StatUnit.powerUnits); } @Override @@ -157,9 +152,9 @@ public class MassDriver extends Block{ entity.rotation = Mathf.slerpDelta(entity.rotation, tile.angleTo(waiter), rotateSpeed); }else if(tile.entity.items.total() >= minDistribute && - linkValid(tile) && //only fire when at 100% power capacity - tile.entity.power.satisfaction >= powerPercentageUsed && - link.block().itemCapacity - link.entity.items.total() >= minDistribute && entity.reload <= 0.0001f){ + linkValid(tile) && //only fire when at 100% power capacity + tile.entity.power.satisfaction >= powerPercentageUsed && + link.block().itemCapacity - link.entity.items.total() >= minDistribute && entity.reload <= 0.0001f){ MassDriverEntity other = link.entity(); other.waiting.add(tile); @@ -188,8 +183,8 @@ public class MassDriver extends Block{ MassDriverEntity entity = tile.entity(); Draw.rect(region, - tile.drawx() + Angles.trnsx(entity.rotation + 180f, entity.reload * knockback), - tile.drawy() + Angles.trnsy(entity.rotation + 180f, entity.reload * knockback), entity.rotation - 90); + tile.drawx() + Angles.trnsx(entity.rotation + 180f, entity.reload * knockback), + tile.drawy() + Angles.trnsy(entity.rotation + 180f, entity.reload * knockback), entity.rotation - 90); } @Override @@ -198,7 +193,7 @@ public class MassDriver extends Block{ Draw.color(Pal.accent); Lines.stroke(1f); - Lines.poly(tile.drawx(), tile.drawy(), 20, (tile.block().size/2f+1) * tilesize + sin); + Lines.poly(tile.drawx(), tile.drawy(), 20, (tile.block().size / 2f + 1) * tilesize + sin); MassDriverEntity entity = tile.entity(); @@ -206,7 +201,7 @@ public class MassDriver extends Block{ Tile target = world.tile(entity.link); Draw.color(Pal.place); - Lines.poly(target.drawx(), target.drawy(), 20, (target.block().size/2f+1) * tilesize + sin); + Lines.poly(target.drawx(), target.drawy(), 20, (target.block().size / 2f + 1) * tilesize + sin); Draw.reset(); } @@ -278,12 +273,12 @@ public class MassDriver extends Block{ //add all the items possible for(int i = 0; i < data.items.length; i++){ - int maxAdd = Math.min(data.items[i], itemCapacity*2 - totalItems); + int maxAdd = Math.min(data.items[i], itemCapacity * 2 - totalItems); items.add(content.item(i), maxAdd); data.items[i] -= maxAdd; totalItems += maxAdd; - if(totalItems >= itemCapacity*2){ + if(totalItems >= itemCapacity * 2){ break; } } diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/OverflowGate.java b/core/src/io/anuke/mindustry/world/blocks/distribution/OverflowGate.java index 3b22972f08..6ba2d1496b 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/OverflowGate.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/OverflowGate.java @@ -1,10 +1,10 @@ package io.anuke.mindustry.world.blocks.distribution; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.util.Time; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Edges; import io.anuke.mindustry.world.Tile; -import io.anuke.arc.util.Time; -import io.anuke.arc.math.Mathf; public class OverflowGate extends Router{ @@ -23,7 +23,7 @@ public class OverflowGate extends Router{ } if(entity.lastItem != null){ - entity.time += 1f/speed * Time.delta(); + entity.time += 1f / speed * Time.delta(); Tile target = getTileTarget(tile, entity.lastItem, entity.lastInput, false); if(target != null && (entity.time >= 1f)){ @@ -60,10 +60,10 @@ public class OverflowGate extends Router{ }else{ if(tile.getDump() == 0){ to = a; - if(flip) tile.setDump((byte) 1); + if(flip) tile.setDump((byte)1); }else{ to = b; - if(flip) tile.setDump((byte) 0); + if(flip) tile.setDump((byte)0); } } } diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/Router.java b/core/src/io/anuke/mindustry/world/blocks/distribution/Router.java index fd1e3cc499..a272f1011e 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Router.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Router.java @@ -1,13 +1,11 @@ package io.anuke.mindustry.world.blocks.distribution; import io.anuke.arc.collection.Array; +import io.anuke.arc.util.Time; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Edges; -import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.meta.BlockGroup; -import io.anuke.arc.util.Time; public class Router extends Block{ protected float speed = 8f; @@ -30,7 +28,7 @@ public class Router extends Block{ } if(entity.lastItem != null){ - entity.time += 1f/speed * Time.delta(); + entity.time += 1f / speed * Time.delta(); Tile target = getTileTarget(tile, entity.lastItem, entity.lastInput, false); if(target != null && (entity.time >= 1f || !(target.block() instanceof Router))){ @@ -46,7 +44,7 @@ public class Router extends Block{ public boolean acceptItem(Item item, Tile tile, Tile source){ SplitterEntity entity = tile.entity(); - return tile.getTeamID() == source.getTeamID() && entity.lastItem == null && entity.items.total() == 0; + return tile.getTeam() == source.getTeam() && entity.lastItem == null && entity.items.total() == 0; } @Override @@ -64,7 +62,7 @@ public class Router extends Block{ for(int i = 0; i < proximity.size; i++){ Tile other = proximity.get((i + counter) % proximity.size); if(tile == from) continue; - if(set) tile.setDump((byte) ((tile.getDump() + 1) % proximity.size)); + if(set) tile.setDump((byte)((tile.getDump() + 1) % proximity.size)); if(other.block().acceptItem(item, other, Edges.getFacingEdge(tile, other))){ return other; } 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 fada43be00..e62e0da1a8 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Sorter.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Sorter.java @@ -3,25 +3,23 @@ package io.anuke.mindustry.world.blocks.distribution; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.Core; +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.math.Mathf; +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.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.blocks.SelectionTrait; +import io.anuke.mindustry.world.blocks.ItemSelection; import io.anuke.mindustry.world.meta.BlockGroup; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.arc.math.Mathf; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.content; -public class Sorter extends Block implements SelectionTrait{ +public class Sorter extends Block{ private static Item lastItem; public Sorter(String name){ @@ -90,9 +88,9 @@ public class Sorter extends Block implements SelectionTrait{ Tile a = dest.getNearby(Mathf.mod(dir - 1, 4)); Tile b = dest.getNearby(Mathf.mod(dir + 1, 4)); boolean ac = a != null && !(a.block().instantTransfer && source.block().instantTransfer) && - a.block().acceptItem(item, a, dest); + a.block().acceptItem(item, a, dest); boolean bc = b != null && !(b.block().instantTransfer && source.block().instantTransfer) && - b.block().acceptItem(item, b, dest); + b.block().acceptItem(item, b, dest); if(ac && !bc){ to = a; @@ -104,11 +102,11 @@ public class Sorter extends Block implements SelectionTrait{ if(dest.getDump() == 0){ to = a; if(flip) - dest.setDump((byte) 1); + dest.setDump((byte)1); }else{ to = b; if(flip) - dest.setDump((byte) 0); + dest.setDump((byte)0); } } } @@ -119,7 +117,7 @@ public class Sorter extends Block implements SelectionTrait{ @Override public void buildTable(Tile tile, Table table){ SorterEntity entity = tile.entity(); - buildItemTable(table, () -> entity.sortItem, item -> { + ItemSelection.buildItemTable(table, () -> entity.sortItem, item -> { lastItem = item; Call.setSorterItem(null, tile, item); }); diff --git a/core/src/io/anuke/mindustry/world/blocks/power/DifferentialGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/DifferentialGenerator.java deleted file mode 100644 index 38f20f53db..0000000000 --- a/core/src/io/anuke/mindustry/world/blocks/power/DifferentialGenerator.java +++ /dev/null @@ -1,28 +0,0 @@ -package io.anuke.mindustry.world.blocks.power; - -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.Liquid; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.consumers.ConsumeItem; -import io.anuke.mindustry.world.consumers.ConsumeLiquid; - -public class DifferentialGenerator extends TurbineGenerator{ - - public DifferentialGenerator(String name){ - super(name); - - hasLiquids = true; - consumes.require(ConsumeItem.class); - consumes.require(ConsumeLiquid.class); - } - - @Override - public boolean acceptItem(Item item, Tile tile, Tile source){ - return hasItems && consumes.item() == item && tile.entity.items.total() < itemCapacity; - } - - @Override - public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ - return hasLiquids && consumes.liquid() == liquid && tile.entity.liquids.get(liquid) < liquidCapacity; - } -} 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 9a18a8fe4f..6a4823069a 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/ImpactReactor.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/ImpactReactor.java @@ -6,9 +6,7 @@ import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; -import io.anuke.arc.util.Strings; -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.Damage; import io.anuke.mindustry.entities.Effects; @@ -16,11 +14,10 @@ import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.ui.Bar; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.consumers.ConsumePower; +import io.anuke.mindustry.world.meta.BlockStat; +import io.anuke.mindustry.world.meta.StatUnit; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.tilesize; @@ -29,21 +26,30 @@ public class ImpactReactor extends PowerGenerator{ protected int plasmas = 4; protected float warmupSpeed = 0.001f; - protected float useTime = 60f; - protected int explosionRadius = 30; - protected int explosionDamage = 180; + protected float itemDuration = 60f; + protected int explosionRadius = 50; + 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[] plasmaRegions; public ImpactReactor(String name){ super(name); hasPower = true; hasLiquids = true; - powerProduction = 2.0f; liquidCapacity = 30f; hasItems = true; 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); + } } @Override @@ -51,10 +57,19 @@ public class ImpactReactor extends PowerGenerator{ super.setBars(); bars.add("poweroutput", entity -> new Bar(() -> - Core.bundle.format("blocks.poweroutput", - Strings.toFixed(Math.max(entity.tile.block().getPowerProduction(entity.tile) - consumes.get(ConsumePower.class).powerPerTick, 0)*60 * entity.delta(), 1)), - () -> Pal.powerBar, - () -> ((GeneratorEntity)entity).productionEfficiency)); + Core.bundle.format("bar.poweroutput", + Strings.fixed(Math.max(entity.block.getPowerProduction(entity.tile) - consumes.getPower().powerPerTick, 0) * 60 * entity.timeScale, 1)), + () -> Pal.powerBar, + () -> ((GeneratorEntity)entity).productionEfficiency)); + } + + @Override + public void setStats(){ + super.setStats(); + + if(hasItems){ + stats.add(BlockStat.productionTime, itemDuration / 60f, StatUnit.seconds); + } } @Override @@ -63,32 +78,33 @@ public class ImpactReactor extends PowerGenerator{ if(entity.cons.valid()){ entity.warmup = Mathf.lerpDelta(entity.warmup, 1f, warmupSpeed); + if(Mathf.isEqual(entity.warmup, 1f, 0.001f)){ + entity.warmup = 1f; + } - if(entity.timer.get(timerUse, useTime)){ - entity.items.remove(consumes.item(), consumes.itemAmount()); + if(entity.timer.get(timerUse, itemDuration)){ + entity.cons.trigger(); } }else{ entity.warmup = Mathf.lerpDelta(entity.warmup, 0f, 0.01f); } entity.productionEfficiency = Mathf.pow(entity.warmup, 5f); - - super.update(tile); } @Override public void draw(Tile tile){ FusionReactorEntity entity = tile.entity(); - Draw.rect(name + "-bottom", tile.drawx(), tile.drawy()); + Draw.rect(reg(bottomRegion), tile.drawx(), tile.drawy()); for(int i = 0; i < plasmas; i++){ float r = 29f + Mathf.absin(Time.time(), 2f + i * 1f, 5f - i * 0.5f); - Draw.color(plasma1, plasma2, (float) i / plasmas); + Draw.color(plasma1, plasma2, (float)i / plasmas); Draw.alpha((0.3f + Mathf.absin(Time.time(), 2f + i * 2f, 0.3f + i * 0.05f)) * entity.warmup); Draw.blend(Blending.additive); - Draw.rect(name + "-plasma-" + i, tile.drawx(), tile.drawy(), r, r, Time.time() * (12 + i * 6f) * entity.warmup); + Draw.rect(reg(plasmaRegions[i]), tile.drawx(), tile.drawy(), r, r, Time.time() * (12 + i * 6f) * entity.warmup); Draw.blend(); } @@ -96,10 +112,10 @@ public class ImpactReactor extends PowerGenerator{ Draw.rect(region, tile.drawx(), tile.drawy()); - Draw.rect(name + "-top", 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(name + "-light", tile.drawx(), tile.drawy()); + Draw.rect(reg(lightRegion), tile.drawx(), tile.drawy()); Draw.color(); } 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 6a45c18a4d..6af6b8f13f 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/ItemLiquidGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/ItemLiquidGenerator.java @@ -1,19 +1,21 @@ package io.anuke.mindustry.world.blocks.power; import io.anuke.arc.Core; -import io.anuke.mindustry.entities.Effects; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Fx; +import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.consumers.ConsumeItemFilter; import io.anuke.mindustry.world.consumers.ConsumeLiquidFilter; +import io.anuke.mindustry.world.meta.BlockStat; +import io.anuke.mindustry.world.meta.StatUnit; import static io.anuke.mindustry.Vars.content; import static io.anuke.mindustry.Vars.tilesize; @@ -44,11 +46,11 @@ public class ItemLiquidGenerator extends PowerGenerator{ this.hasLiquids = hasLiquids; if(hasItems){ - consumes.add(new ConsumeItemFilter(item -> getItemEfficiency(item) >= minItemEfficiency)).update(false).optional(true); + consumes.add(new ConsumeItemFilter(item -> getItemEfficiency(item) >= minItemEfficiency)).update(false).optional(true, false); } if(hasLiquids){ - consumes.add(new ConsumeLiquidFilter(liquid -> getLiquidEfficiency(liquid) >= minLiquidEfficiency, 0.001f, true)).update(false).optional(true); + consumes.add(new ConsumeLiquidFilter(liquid -> getLiquidEfficiency(liquid) >= minLiquidEfficiency, maxLiquidGenerate)).update(false).optional(true, false); } } @@ -60,6 +62,15 @@ public class ItemLiquidGenerator extends PowerGenerator{ } } + @Override + public void setStats(){ + super.setStats(); + + if(hasItems){ + stats.add(BlockStat.productionTime, itemDuration / 60f, StatUnit.seconds); + } + } + @Override public void update(Tile tile){ ItemLiquidGeneratorEntity entity = tile.entity(); @@ -117,18 +128,6 @@ public class ItemLiquidGenerator extends PowerGenerator{ entity.productionEfficiency = 0.0f; } } - - super.update(tile); - } - - @Override - public boolean acceptItem(Item item, Tile tile, Tile source){ - return hasItems && getItemEfficiency(item) >= minItemEfficiency && tile.entity.items.total() < itemCapacity; - } - - @Override - public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ - return hasLiquids && getLiquidEfficiency(liquid) >= minLiquidEfficiency && tile.entity.liquids.get(liquid) < liquidCapacity; } @Override 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 3300a6cf2e..6468094447 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/NuclearReactor.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/NuclearReactor.java @@ -12,13 +12,15 @@ import io.anuke.mindustry.entities.Damage; import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.graphics.Pal; +import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.ui.Bar; 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 java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.tilesize; @@ -29,11 +31,11 @@ public class NuclearReactor extends PowerGenerator{ protected Color coolColor = new Color(1, 1, 1, 0f); protected Color hotColor = Color.valueOf("ff9575a3"); - protected int fuelUseTime = 120; //time to consume 1 fuel + protected int itemDuration = 120; //time to consume 1 fuel protected float heating = 0.01f; //heating per frame * fullness protected float smokeThreshold = 0.3f; //threshold at which block starts smoking - protected int explosionRadius = 19; - protected int explosionDamage = 135; + protected int explosionRadius = 40; + protected int explosionDamage = 1350; protected float flashThreshold = 0.46f; //heat threshold at which the lights start flashing protected float coolantPower = 0.5f; @@ -47,6 +49,15 @@ public class NuclearReactor extends PowerGenerator{ hasLiquids = true; } + @Override + public void setStats(){ + super.setStats(); + + if(hasItems){ + stats.add(BlockStat.productionTime, itemDuration / 60f, StatUnit.seconds); + } + } + @Override public void load(){ super.load(); @@ -58,27 +69,30 @@ public class NuclearReactor extends PowerGenerator{ @Override public void setBars(){ super.setBars(); - bars.add("heat", entity -> new Bar("blocks.heat", Pal.lightOrange, () -> ((NuclearReactorEntity)entity).heat)); + bars.add("heat", entity -> new Bar("bar.heat", Pal.lightOrange, () -> ((NuclearReactorEntity)entity).heat)); } @Override public void update(Tile tile){ NuclearReactorEntity entity = tile.entity(); - int fuel = entity.items.get(consumes.item()); - float fullness = (float) fuel / itemCapacity; + ConsumeLiquid cliquid = consumes.get(ConsumeType.liquid); + Item item = consumes.get(ConsumeType.item).items[0].item; + + int fuel = entity.items.get(item); + float fullness = (float)fuel / itemCapacity; entity.productionEfficiency = fullness; if(fuel > 0){ entity.heat += fullness * heating * Math.min(entity.delta(), 4f); - if(entity.timer.get(timerFuel, fuelUseTime)){ + if(entity.timer.get(timerFuel, itemDuration)){ entity.cons.trigger(); } } - Liquid liquid = consumes.liquid(); - float liquidAmount = consumes.liquidAmount(); + Liquid liquid = cliquid.liquid; + float liquidAmount = cliquid.amount; if(entity.heat > 0){ float maxUsed = Math.min(Math.min(entity.liquids.get(liquid), entity.heat / coolantPower), liquidAmount * entity.delta()); @@ -90,7 +104,7 @@ public class NuclearReactor extends PowerGenerator{ float smoke = 1.0f + (entity.heat - smokeThreshold) / (1f - smokeThreshold); //ranges from 1.0 to 2.0 if(Mathf.chance(smoke / 20.0 * entity.delta())){ Effects.effect(Fx.reactorsmoke, tile.worldx() + Mathf.range(size * tilesize / 2f), - tile.worldy() + Mathf.random(size * tilesize / 2f)); + tile.worldy() + Mathf.random(size * tilesize / 2f)); } } @@ -98,8 +112,6 @@ public class NuclearReactor extends PowerGenerator{ if(entity.heat >= 0.999f){ entity.kill(); - }else{ - super.update(tile); } } @@ -109,7 +121,7 @@ public class NuclearReactor extends PowerGenerator{ NuclearReactorEntity entity = tile.entity(); - int fuel = entity.items.get(consumes.item()); + int fuel = entity.items.get(consumes.get(ConsumeType.item).items[0].item); if(fuel < 5 && entity.heat < 0.5f) return; @@ -121,7 +133,6 @@ public class NuclearReactor extends PowerGenerator{ Damage.damage(tile.worldx(), tile.worldy(), explosionRadius * tilesize, explosionDamage * 4); - for(int i = 0; i < 20; i++){ Time.run(Mathf.random(50), () -> { tr.rnd(Mathf.random(40f)); diff --git a/core/src/io/anuke/mindustry/world/blocks/power/PowerDistributor.java b/core/src/io/anuke/mindustry/world/blocks/power/PowerDistributor.java index 5a4bbfcdce..38ef286d78 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/PowerDistributor.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/PowerDistributor.java @@ -1,6 +1,5 @@ package io.anuke.mindustry.world.blocks.power; -import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.PowerBlock; public class PowerDistributor extends PowerBlock{ @@ -10,11 +9,4 @@ public class PowerDistributor extends PowerBlock{ consumesPower = false; outputsPower = true; } - - @Override - public void update(Tile tile){ - if(tile.entity != null && tile.entity.power != null && tile.entity.power.graph != null){ - tile.entity.power.graph.update(); - } - } } diff --git a/core/src/io/anuke/mindustry/world/blocks/power/PowerGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/PowerGenerator.java index 88d7608636..fa0043dbbc 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/PowerGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/PowerGenerator.java @@ -7,14 +7,9 @@ import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.ui.Bar; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.consumers.ConsumePower; -import io.anuke.mindustry.world.meta.BlockFlag; -import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.mindustry.world.meta.StatUnit; +import io.anuke.mindustry.world.meta.*; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; public class PowerGenerator extends PowerDistributor{ /** The amount of power produced per tick in case of an efficiency of 1.0, which represents 100%. */ @@ -37,10 +32,10 @@ public class PowerGenerator extends PowerDistributor{ public void setBars(){ super.setBars(); - if(hasPower && outputsPower && !consumes.has(ConsumePower.class)){ + if(hasPower && outputsPower && !consumes.hasPower()){ bars.add("power", entity -> new Bar(() -> - Core.bundle.format("blocks.poweroutput", - Strings.toFixed(entity.tile.block().getPowerProduction(entity.tile)*60 * entity.timeScale, 1)), + Core.bundle.format("bar.poweroutput", + Strings.fixed(entity.block.getPowerProduction(entity.tile) * 60 * entity.timeScale, 1)), () -> Pal.powerBar, () -> ((GeneratorEntity)entity).productionEfficiency)); } 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 6de3fbbff2..c4bcdb4fdc 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/PowerGraph.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/PowerGraph.java @@ -1,17 +1,12 @@ package io.anuke.mindustry.world.blocks.power; import io.anuke.arc.Core; -import io.anuke.arc.collection.Array; -import io.anuke.arc.collection.IntSet; -import io.anuke.arc.collection.ObjectSet; -import io.anuke.arc.collection.Queue; +import io.anuke.arc.collection.*; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.WindowedMean; import io.anuke.arc.util.Time; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.consumers.Consume; -import io.anuke.mindustry.world.consumers.ConsumePower; -import io.anuke.mindustry.world.consumers.Consumers; +import io.anuke.mindustry.world.consumers.*; public class PowerGraph{ private final static Queue queue = new Queue<>(); @@ -54,8 +49,8 @@ public class PowerGraph{ float powerNeeded = 0f; for(Tile consumer : consumers){ Consumers consumes = consumer.block().consumes; - if(consumes.has(ConsumePower.class)){ - ConsumePower consumePower = consumes.get(ConsumePower.class); + if(consumes.hasPower()){ + ConsumePower consumePower = consumes.getPower(); if(otherConsumersAreValid(consumer, consumePower)){ powerNeeded += consumePower.requestedPower(consumer.block(), consumer.entity) * consumer.entity.delta(); } @@ -68,8 +63,8 @@ public class PowerGraph{ float totalAccumulator = 0f; for(Tile battery : batteries){ Consumers consumes = battery.block().consumes; - if(consumes.has(ConsumePower.class)){ - totalAccumulator += battery.entity.power.satisfaction * consumes.get(ConsumePower.class).powerCapacity; + if(consumes.hasPower()){ + totalAccumulator += battery.entity.power.satisfaction * consumes.getPower().powerCapacity; } } return totalAccumulator; @@ -79,8 +74,8 @@ public class PowerGraph{ float totalCapacity = 0f; for(Tile battery : batteries){ Consumers consumes = battery.block().consumes; - if(consumes.has(ConsumePower.class)){ - totalCapacity += consumes.get(ConsumePower.class).requestedPower(battery.block(), battery.entity) * battery.entity.delta(); + if(consumes.hasPower()){ + totalCapacity += consumes.getPower().requestedPower(battery.block(), battery.entity) * battery.entity.delta(); } } return totalCapacity; @@ -94,8 +89,8 @@ public class PowerGraph{ float consumedPowerPercentage = Math.min(1.0f, needed / stored); for(Tile battery : batteries){ Consumers consumes = battery.block().consumes; - if(consumes.has(ConsumePower.class)){ - ConsumePower consumePower = consumes.get(ConsumePower.class); + if(consumes.hasPower()){ + ConsumePower consumePower = consumes.getPower(); if(consumePower.powerCapacity > 0f){ battery.entity.power.satisfaction = Math.max(0.0f, battery.entity.power.satisfaction - consumedPowerPercentage); } @@ -110,8 +105,8 @@ public class PowerGraph{ for(Tile battery : batteries){ Consumers consumes = battery.block().consumes; - if(consumes.has(ConsumePower.class)){ - ConsumePower consumePower = consumes.get(ConsumePower.class); + if(consumes.hasPower()){ + ConsumePower consumePower = consumes.getPower(); if(consumePower.powerCapacity > 0f){ float additionalPowerPercentage = Math.min(1.0f, excess / consumePower.powerCapacity); battery.entity.power.satisfaction = Math.min(1.0f, battery.entity.power.satisfaction + additionalPowerPercentage); @@ -123,11 +118,11 @@ public class PowerGraph{ public void distributePower(float needed, float produced){ //distribute even if not needed. this is because some might be requiring power but not requesting it; it updates consumers - float coverage = Mathf.isZero(needed) ? 1f : Math.min(1, produced / needed); + float coverage = Mathf.isZero(needed) && Mathf.isZero(produced) ? 0f : Mathf.isZero(needed) ? 1f : Math.min(1, produced / needed); for(Tile consumer : consumers){ Consumers consumes = consumer.block().consumes; - if(consumes.has(ConsumePower.class)){ - ConsumePower consumePower = consumes.get(ConsumePower.class); + if(consumes.hasPower()){ + ConsumePower consumePower = consumes.getPower(); //currently satisfies power even if it's not required yet if(consumePower.isBuffered){ if(!Mathf.isZero(consumePower.powerCapacity)){ @@ -176,10 +171,15 @@ public class PowerGraph{ } public void add(Tile tile){ + if(tile.block().consumes.hasPower() && !tile.block().consumes.getPower().isBuffered){ + //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); - if(tile.block().outputsPower && tile.block().consumesPower && !tile.block().consumes.get(ConsumePower.class).isBuffered){ + if(tile.block().outputsPower && tile.block().consumesPower && !tile.block().consumes.getPower().isBuffered){ producers.add(tile); consumers.add(tile); }else if(tile.block().outputsPower && tile.block().consumesPower){ @@ -191,32 +191,15 @@ public class PowerGraph{ } } - public void clear(){ - for(Tile other : all){ - if(other.entity != null && other.entity.power != null){ - if(other.block().consumes.has(ConsumePower.class) && !other.block().consumes.get(ConsumePower.class).isBuffered){ - // Reset satisfaction to zero in case of direct consumer. There is no reason to clear power from buffered consumers. - other.entity.power.satisfaction = 0.0f; - } - other.entity.power.graph = null; - } - } - all.clear(); - producers.clear(); - consumers.clear(); - batteries.clear(); - } - public void reflow(Tile tile){ queue.clear(); queue.addLast(tile); closedSet.clear(); while(queue.size > 0){ Tile child = queue.removeFirst(); - child.entity.power.graph = this; add(child); for(Tile next : child.block().getPowerConnections(child, outArray2)){ - if(next.entity.power != null && next.entity.power.graph == null && !closedSet.contains(next.pos())){ + if(!closedSet.contains(next.pos())){ queue.addLast(next); closedSet.add(next.pos()); } @@ -224,34 +207,54 @@ public class PowerGraph{ } } + private void removeSingle(Tile tile){ + all.remove(tile); + producers.remove(tile); + consumers.remove(tile); + batteries.remove(tile); + } + public void remove(Tile tile){ - clear(); + removeSingle(tile); + //begin by clearing the closed set closedSet.clear(); + //go through all the connections of this tile for(Tile other : tile.block().getPowerConnections(tile, outArray1)){ - if(other.entity.power == null || other.entity.power.graph != null){ continue; } + //a graph has already been assigned to this tile from a previous call, skip it + if(other.entity.power.graph != this) continue; + + //create graph for this branch PowerGraph graph = new PowerGraph(); + graph.add(other); + //add to queue for BFS queue.clear(); queue.addLast(other); while(queue.size > 0){ + //get child from queue Tile child = queue.removeFirst(); - child.entity.power.graph = graph; + //remove it from this graph + removeSingle(child); + //add it to the new branch graph graph.add(child); + //go through connections for(Tile next : child.block().getPowerConnections(child, outArray2)){ - if(next != tile && next.entity.power != null && next.entity.power.graph == null && !closedSet.contains(next.pos())){ + //make sure it hasn't looped back, and that the new graph being assigned hasn't already been assigned + //also skip closed tiles + if(next != tile && next.entity.power.graph != graph && !closedSet.contains(next.pos())){ queue.addLast(next); closedSet.add(next.pos()); } } } - // Update the graph once so direct consumers without any connected producer lose their power + //update the graph once so direct consumers without any connected producer lose their power graph.update(); } } private boolean otherConsumersAreValid(Tile tile, Consume consumePower){ for(Consume cons : tile.block().consumes.all()){ - if(cons != consumePower && !cons.isOptional() && !cons.valid(tile.block(), tile.entity())){ + if(cons != consumePower && !cons.isOptional() && !cons.valid(tile.entity())){ return false; } } @@ -261,12 +264,12 @@ public class PowerGraph{ @Override public String toString(){ return "PowerGraph{" + - "producers=" + producers + - ", consumers=" + consumers + - ", batteries=" + batteries + - ", all=" + all + - ", lastFrameUpdated=" + lastFrameUpdated + - ", graphID=" + graphID + - '}'; + "producers=" + producers + + ", consumers=" + consumers + + ", batteries=" + batteries + + ", all=" + all + + ", lastFrameUpdated=" + lastFrameUpdated + + ", graphID=" + graphID + + '}'; } } 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 338b433d9f..6c32d91b99 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/PowerNode.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/PowerNode.java @@ -8,15 +8,13 @@ import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Lines; import io.anuke.arc.math.Angles; import io.anuke.arc.math.Mathf; +import io.anuke.arc.math.geom.Intersector; import io.anuke.arc.math.geom.Vector2; -import io.anuke.arc.util.Strings; -import io.anuke.arc.util.Time; +import io.anuke.arc.util.*; import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.graphics.Layer; -import io.anuke.mindustry.graphics.Pal; -import io.anuke.mindustry.graphics.Shapes; +import io.anuke.mindustry.graphics.*; import io.anuke.mindustry.ui.Bar; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.PowerBlock; @@ -48,7 +46,7 @@ public class PowerNode extends PowerBlock{ @Remote(targets = Loc.both, called = Loc.server, forward = true) public static void linkPowerNodes(Player player, Tile tile, Tile other){ if(tile.entity.power == null || !((PowerNode)tile.block()).linkValid(tile, other) - || tile.entity.power.links.size >= ((PowerNode)tile.block()).maxNodes) return; + || tile.entity.power.links.size >= ((PowerNode)tile.block()).maxNodes) return; TileEntity entity = tile.entity(); @@ -72,17 +70,15 @@ public class PowerNode extends PowerBlock{ TileEntity entity = tile.entity(); - //clear all graph data first - PowerGraph tg = entity.power.graph; - tg.clear(); - entity.power.links.removeValue(other.pos()); other.entity.power.links.removeValue(tile.pos()); - //reflow from this point, covering all tiles on this side - tg.reflow(tile); + PowerGraph newgraph = new PowerGraph(); - if(other.entity.power.graph != tg){ + //reflow from this point, covering all tiles on this side + newgraph.reflow(tile); + + if(other.entity.power.graph != newgraph){ //create new graph for other end PowerGraph og = new PowerGraph(); //reflow from other end @@ -94,10 +90,10 @@ public class PowerNode extends PowerBlock{ public void setBars(){ super.setBars(); bars.add("power", entity -> new Bar(() -> - Core.bundle.format("blocks.powerbalance", - entity.power.graph == null ? "+0" : ((entity.power.graph.getPowerBalance() >= 0 ? "+" : "") + Strings.toFixed(entity.power.graph.getPowerBalance()*60, 1))), - () -> Pal.powerBar, - () -> entity.power.graph == null ? 0 : Mathf.clamp(entity.power.graph.getPowerProduced() / entity.power.graph.getPowerNeeded()))); + Core.bundle.format("bar.powerbalance", + ((entity.power.graph.getPowerBalance() >= 0 ? "+" : "") + Strings.fixed(entity.power.graph.getPowerBalance() * 60, 1))), + () -> Pal.powerBar, + () -> Mathf.clamp(entity.power.graph.getPowerProduced() / entity.power.graph.getPowerNeeded()))); } @Override @@ -153,7 +149,7 @@ public class PowerNode extends PowerBlock{ Lines.stroke(1f); Draw.color(Pal.accent); - Lines.poly(tile.drawx(), tile.drawy(), 50, laserRange*tilesize); + Lines.poly(tile.drawx(), tile.drawy(), 50, laserRange * tilesize); Draw.reset(); } @@ -165,12 +161,12 @@ public class PowerNode extends PowerBlock{ Lines.stroke(1.5f); Lines.circle(tile.drawx(), tile.drawy(), - tile.block().size * tilesize / 2f + 1f + Mathf.absin(Time.time(), 4f, 1f)); + tile.block().size * tilesize / 2f + 1f + Mathf.absin(Time.time(), 4f, 1f)); - Lines.poly(tile.drawx(), tile.drawy(), 50, laserRange*tilesize); + Lines.poly(tile.drawx(), tile.drawy(), 50, laserRange * tilesize); - for(int x = (int) (tile.x - laserRange); x <= tile.x + laserRange; x++){ - for(int y = (int) (tile.y - laserRange); y <= tile.y + laserRange; y++){ + for(int x = (int)(tile.x - laserRange - 1); x <= tile.x + laserRange + 1; x++){ + for(int y = (int)(tile.y - laserRange - 1); y <= tile.y + laserRange + 1; y++){ Tile link = world.tile(x, y); if(link != null) link = link.target(); @@ -179,9 +175,9 @@ public class PowerNode extends PowerBlock{ Draw.color(linked ? Pal.place : Pal.breakInvalid); Lines.circle(link.drawx(), link.drawy(), - link.block().size * tilesize / 2f + 1f + (linked ? 0f : Mathf.absin(Time.time(), 4f, 1f))); + link.block().size * tilesize / 2f + 1f + (linked ? 0f : Mathf.absin(Time.time(), 4f, 1f))); - if((entity.power.links.size >= maxNodes || (link.block() instanceof PowerNode && link.entity.power.links.size >= ((PowerNode) link.block()).maxNodes)) && !linked){ + if((entity.power.links.size >= maxNodes || (link.block() instanceof PowerNode && link.entity.power.links.size >= ((PowerNode)link.block()).maxNodes)) && !linked){ Draw.color(Pal.breakInvalid); Lines.lineAngleCenter(link.drawx(), link.drawy(), 45, link.block().size * Mathf.sqrt2 * tilesize * 0.9f); Draw.color(); @@ -197,7 +193,7 @@ public class PowerNode extends PowerBlock{ public void drawPlace(int x, int y, int rotation, boolean valid){ Lines.stroke(1f); Draw.color(Pal.placing); - Lines.poly(x * tilesize + offset(), y * tilesize + offset(), 50, laserRange*tilesize); + Lines.poly(x * tilesize + offset(), y * tilesize + offset(), 50, laserRange * tilesize); Draw.reset(); } @@ -226,25 +222,25 @@ public class PowerNode extends PowerBlock{ } protected boolean linkValid(Tile tile, Tile link, boolean checkMaxNodes){ - if(!(tile != link && link != null && link.block().hasPower) || tile.getTeamID() != link.getTeamID()) return false; + if(tile == link || link == null || !link.block().hasPower || tile.getTeam() != link.getTeam()) return false; - if(link.block() instanceof PowerNode){ - TileEntity oe = link.entity(); - - return Mathf.dst(tile.drawx(), tile.drawy(), link.drawx(), link.drawy()) <= Math.max(laserRange * tilesize, - ((PowerNode) link.block()).laserRange * tilesize) - + (link.block().size - 1) * tilesize / 2f + (tile.block().size - 1) * tilesize / 2f && - (!checkMaxNodes || (oe.power.links.size < ((PowerNode) link.block()).maxNodes || oe.power.links.contains(tile.pos()))); - }else{ - return Mathf.dst(tile.drawx(), tile.drawy(), link.drawx(), link.drawy()) - <= laserRange * tilesize + (link.block().size - 1) * tilesize; + if(overlaps(tile, link, laserRange * tilesize) || (link.block() instanceof PowerNode && overlaps(link, tile, link.cblock().laserRange * tilesize))){ + if(checkMaxNodes && link.block() instanceof PowerNode){ + return link.entity.power.links.size < link.cblock().maxNodes || link.entity.power.links.contains(tile.pos()); + } + return true; } + return false; + } + + protected boolean overlaps(Tile src, Tile other, float range){ + return Intersector.overlaps(Tmp.cr1.set(src.drawx(), src.drawy(), range), other.getHitbox(Tmp.r1)); } protected void drawLaser(Tile tile, Tile target){ float x1 = tile.drawx(), y1 = tile.drawy(), - x2 = target.drawx(), y2 = target.drawy(); + x2 = target.drawx(), y2 = target.drawy(); float angle1 = Angles.angle(x1, y1, x2, y2); float angle2 = angle1 + 180f; diff --git a/core/src/io/anuke/mindustry/world/blocks/power/SingleTypeGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/SingleTypeGenerator.java new file mode 100644 index 0000000000..9caf39dc5c --- /dev/null +++ b/core/src/io/anuke/mindustry/world/blocks/power/SingleTypeGenerator.java @@ -0,0 +1,20 @@ +package io.anuke.mindustry.world.blocks.power; + +import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.Liquid; + +public class SingleTypeGenerator extends ItemLiquidGenerator{ + public SingleTypeGenerator(boolean hasItems, boolean hasLiquids, String name){ + super(hasItems, hasLiquids, name); + } + + @Override + protected float getItemEfficiency(Item item){ + return 1f; + } + + @Override + protected float getLiquidEfficiency(Liquid liquid){ + return 0f; + } +} diff --git a/core/src/io/anuke/mindustry/world/blocks/power/SolarGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/SolarGenerator.java index 96f3109fc9..fd8f9cf642 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/SolarGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/SolarGenerator.java @@ -1,8 +1,8 @@ package io.anuke.mindustry.world.blocks.power; +import io.anuke.arc.collection.EnumSet; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.world.meta.StatUnit; -import io.anuke.arc.collection.EnumSet; public class SolarGenerator extends PowerGenerator{ diff --git a/core/src/io/anuke/mindustry/world/blocks/power/ThermalGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/ThermalGenerator.java index f79007b348..be88b2ff01 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/ThermalGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/ThermalGenerator.java @@ -22,13 +22,11 @@ public class ThermalGenerator extends PowerGenerator{ if(entity.productionEfficiency > 0.1f && Mathf.chance(0.05 * entity.delta())){ Effects.effect(generateEffect, tile.drawx() + Mathf.range(3f), tile.drawy() + Mathf.range(3f)); } - - super.update(tile); } @Override public void drawPlace(int x, int y, int rotation, boolean valid){ - drawPlaceText(Core.bundle.formatDouble("blocks.efficiency", sumAttribute(Attribute.heat, x, y)*100, 1), x, y, valid); + drawPlaceText(Core.bundle.formatFloat("bar.efficiency", sumAttribute(Attribute.heat, x, y) * 100, 1), x, y, valid); } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/power/TurbineGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/TurbineGenerator.java deleted file mode 100644 index ed485d9492..0000000000 --- a/core/src/io/anuke/mindustry/world/blocks/power/TurbineGenerator.java +++ /dev/null @@ -1,20 +0,0 @@ -package io.anuke.mindustry.world.blocks.power; - -import io.anuke.mindustry.type.Liquid; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.consumers.ConsumeLiquid; - -public class TurbineGenerator extends BurnerGenerator{ - - public TurbineGenerator(String name){ - super(name); - singleLiquid = false; - - consumes.require(ConsumeLiquid.class); - } - - @Override - public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ - return (liquid == consumes.liquid() && tile.entity.liquids.get(consumes.liquid()) < liquidCapacity); - } -} diff --git a/core/src/io/anuke/mindustry/world/blocks/production/Compressor.java b/core/src/io/anuke/mindustry/world/blocks/production/Compressor.java deleted file mode 100644 index 0144971bfe..0000000000 --- a/core/src/io/anuke/mindustry/world/blocks/production/Compressor.java +++ /dev/null @@ -1,49 +0,0 @@ -package io.anuke.mindustry.world.blocks.production; - -import io.anuke.arc.Core; -import io.anuke.arc.graphics.Color; -import io.anuke.arc.graphics.g2d.TextureRegion; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.production.GenericCrafter.GenericCrafterEntity; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.math.Mathf; - -public class Compressor extends PowerCrafter{ - protected TextureRegion liquidRegion, topRegion; - protected TextureRegion[] frameRegions; - - public Compressor(String name){ - super(name); - hasLiquids = true; - } - - @Override - public void load(){ - super.load(); - - frameRegions = new TextureRegion[3]; - for(int i = 0; i < 3; i++){ - frameRegions[i] = Core.atlas.find(name + "-frame" + i); - } - - liquidRegion = Core.atlas.find(name + "-liquid"); - topRegion = Core.atlas.find(name + "-top"); - } - - @Override - public void draw(Tile tile){ - GenericCrafterEntity entity = tile.entity(); - - Draw.rect(region, tile.drawx(), tile.drawy()); - Draw.rect(frameRegions[(int) Mathf.absin(entity.totalProgress, 5f, 2.999f)], tile.drawx(), tile.drawy()); - Draw.color(Color.CLEAR, tile.entity.liquids.current().color, tile.entity.liquids.total() / liquidCapacity); - Draw.rect(liquidRegion, tile.drawx(), tile.drawy()); - Draw.color(); - Draw.rect(topRegion, tile.drawx(), tile.drawy()); - } - - @Override - public TextureRegion[] generateIcons(){ - return new TextureRegion[]{Core.atlas.find(name), Core.atlas.find(name + "-top")}; - } -} diff --git a/core/src/io/anuke/mindustry/world/blocks/production/Cultivator.java b/core/src/io/anuke/mindustry/world/blocks/production/Cultivator.java index 8251519d57..955c786520 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Cultivator.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Cultivator.java @@ -2,9 +2,7 @@ package io.anuke.mindustry.world.blocks.production; 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.TextureRegion; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.RandomXS128; import io.anuke.arc.util.Time; @@ -15,9 +13,7 @@ import io.anuke.mindustry.ui.Bar; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.Attribute; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; public class Cultivator extends GenericCrafter{ protected static final Color plantColor = Color.valueOf("5541b1"); @@ -53,15 +49,15 @@ public class Cultivator extends GenericCrafter{ public void setBars(){ super.setBars(); bars.add("multiplier", entity -> new Bar(() -> - Core.bundle.formatDouble("blocks.efficiency", - ((((CultivatorEntity)entity).boost + 1f) * ((CultivatorEntity)entity).warmup)*100f,1), + Core.bundle.formatFloat("bar.efficiency", + ((((CultivatorEntity)entity).boost + 1f) * ((CultivatorEntity)entity).warmup) * 100f, 1), () -> Pal.ammo, () -> ((CultivatorEntity)entity).warmup)); } @Override public void drawPlace(int x, int y, int rotation, boolean valid){ - drawPlaceText(Core.bundle.formatDouble("blocks.efficiency", (1+sumAttribute(Attribute.spores, x, y))*100, 1), x, y, valid); + drawPlaceText(Core.bundle.formatFloat("bar.efficiency", (1 + sumAttribute(Attribute.spores, x, y)) * 100, 1), x, y, valid); } @Override 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 7b4713aeb7..d9e814c8ca 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Drill.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Drill.java @@ -3,17 +3,16 @@ package io.anuke.mindustry.world.blocks.production; import io.anuke.arc.Core; import io.anuke.arc.collection.Array; import io.anuke.arc.collection.ObjectIntMap; -import io.anuke.arc.util.Strings; -import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.Effects.Effect; 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.math.Mathf; +import io.anuke.arc.util.Strings; import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.content.Liquids; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.graphics.Layer; import io.anuke.mindustry.graphics.Pal; @@ -22,41 +21,34 @@ import io.anuke.mindustry.type.ItemType; import io.anuke.mindustry.ui.Bar; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.consumers.ConsumeLiquid; -import io.anuke.mindustry.world.meta.BlockGroup; -import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.mindustry.world.meta.StatUnit; +import io.anuke.mindustry.world.meta.*; import static io.anuke.mindustry.Vars.content; public class Drill extends Block{ protected final static float hardnessDrillMultiplier = 50f; - protected final int timerDump = timers++; - protected final Array drawTiles = new Array<>(); protected final ObjectIntMap oreCount = new ObjectIntMap<>(); protected final Array itemArray = new Array<>(); - /**Maximum tier of blocks this drill can mine.*/ + /** Maximum tier of blocks this drill can mine. */ protected int tier; - /**Base time to drill one ore, in frames.*/ + /** Base time to drill one ore, in frames. */ protected float drillTime = 300; - /**Whether the liquid is required to drill. If false, then it will be used as a speed booster.*/ - protected boolean liquidRequired = false; - /**How many times faster the drill will progress when boosted by liquid.*/ + /** How many times faster the drill will progress when boosted by liquid. */ protected float liquidBoostIntensity = 1.6f; - /**Speed at which the drill speeds up.*/ + /** Speed at which the drill speeds up. */ protected float warmupSpeed = 0.02f; - /**Whether to draw the item this drill is mining.*/ + /** Whether to draw the item this drill is mining. */ protected boolean drawMineItem = false; - /**Effect played when an item is produced. This is colored.*/ + /** Effect played when an item is produced. This is colored. */ protected Effect drillEffect = Fx.mine; - /**Speed the drill bit rotates at.*/ + /** Speed the drill bit rotates at. */ protected float rotateSpeed = 2f; - /**Effect randomly played while drilling.*/ + /** Effect randomly played while drilling. */ protected Effect updateEffect = Fx.pulverizeSmall; - /**Chance the update effect will appear.*/ + /** Chance the update effect will appear. */ protected float updateEffectChance = 0.02f; protected boolean drawRim = false; @@ -75,8 +67,6 @@ public class Drill extends Block{ hasLiquids = true; liquidCapacity = 5f; hasItems = true; - - consumes.liquid(Liquids.water, 0.05f).optional(true); } @Override @@ -86,7 +76,7 @@ public class Drill extends Block{ bars.add("drillspeed", e -> { DrillEntity entity = (DrillEntity)e; - return new Bar(() -> Core.bundle.format("blocks.outputspeed", Strings.toFixed(entity.lastDrillSpeed * 60 * entity.timeScale, 2)), () -> Pal.ammo, () -> entity.warmup); + return new Bar(() -> Core.bundle.format("bar.drillspeed", Strings.fixed(entity.lastDrillSpeed * 60 * entity.timeScale, 2)), () -> Pal.ammo, () -> entity.warmup); }); } @@ -162,6 +152,7 @@ public class Drill extends Block{ }); stats.add(BlockStat.drillSpeed, 60f / drillTime * size * size, StatUnit.itemsSecond); + stats.add(BlockStat.boostEffect, liquidBoostIntensity, StatUnit.timesSpeed); } @Override @@ -182,8 +173,13 @@ public class Drill extends Block{ itemArray.add(item); } - itemArray.sort((item1, item2) -> Integer.compare(oreCount.get(item1, 0), oreCount.get(item2, 0))); - itemArray.sort((item1, item2) -> Boolean.compare(item1.type == ItemType.material, item2.type == ItemType.material)); + itemArray.sort((item1, item2) -> { + int type = Boolean.compare(item1.type == ItemType.material, item2.type == ItemType.material); + if(type != 0) return type; + int count = Integer.compare(oreCount.get(item1, 0), oreCount.get(item2, 0)); + if(count != 0) return count; + return Integer.compare(item1.id, item2.id); + }); if(itemArray.size == 0){ return; @@ -195,8 +191,8 @@ public class Drill extends Block{ float totalHardness = entity.dominantItems * entity.dominantItem.hardness; - if(entity.timer.get(timerDump, 15)){ - tryDump(tile); + if(entity.timer.get(timerDump, dumpTime)){ + tryDump(tile, entity.dominantItem); } entity.drillTime += entity.warmup * entity.delta(); @@ -205,9 +201,10 @@ public class Drill extends Block{ float speed = 1f; - if(entity.consumed(ConsumeLiquid.class) && !liquidRequired){ + if(entity.cons.optionalValid()){ speed = liquidBoostIntensity; } + if(hasPower){ speed *= entity.power.satisfaction; // Drill slower when not at full power } @@ -226,7 +223,7 @@ public class Drill extends Block{ } if(entity.dominantItems > 0 && entity.progress >= drillTime + hardnessDrillMultiplier * Math.max(totalHardness, 1f) / entity.dominantItems - && tile.entity.items.total() < itemCapacity){ + && tile.entity.items.total() < itemCapacity){ offloadNear(tile, entity.dominantItem); @@ -236,7 +233,7 @@ public class Drill extends Block{ entity.progress = 0f; Effects.effect(drillEffect, entity.dominantItem.color, - entity.x + Mathf.range(size), entity.y + Mathf.range(size)); + entity.x + Mathf.range(size), entity.y + Mathf.range(size)); } } @@ -270,14 +267,14 @@ public class Drill extends Block{ } public static class DrillEntity extends TileEntity{ - public float progress; - public int index; - public float warmup; - public float drillTime; - public float lastDrillSpeed; + float progress; + int index; + float warmup; + float drillTime; + float lastDrillSpeed; - public int dominantItems; - public Item dominantItem; + int dominantItems; + Item dominantItem; } } 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 2f6e2609a0..177e870768 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Fracker.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Fracker.java @@ -1,12 +1,12 @@ package io.anuke.mindustry.world.blocks.production; import io.anuke.arc.Core; +import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.mindustry.entities.type.TileEntity; -import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.consumers.ConsumeItem; -import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.mindustry.world.meta.BlockStat; +import io.anuke.mindustry.world.meta.StatUnit; public class Fracker extends SolidPump{ protected final float itemUseTime = 100f; @@ -18,9 +18,13 @@ public class Fracker extends SolidPump{ public Fracker(String name){ super(name); hasItems = true; - singleLiquid = false; + } - consumes.require(ConsumeItem.class); + @Override + public void setStats(){ + super.setStats(); + + stats.add(BlockStat.productionTime, itemUseTime / 60f, StatUnit.seconds); } @Override @@ -55,14 +59,13 @@ public class Fracker extends SolidPump{ @Override public void update(Tile tile){ FrackerEntity entity = tile.entity(); - Item item = consumes.item(); - while(entity.accumulator >= itemUseTime && entity.items.has(item, 1)){ - entity.items.remove(item, 1); - entity.accumulator -= itemUseTime; - } + if(entity.cons.valid()){ + if(entity.accumulator >= itemUseTime){ + entity.cons.trigger(); + entity.accumulator -= itemUseTime; + } - if(entity.cons.valid() && entity.accumulator < itemUseTime){ super.update(tile); entity.accumulator += entity.delta() * entity.power.satisfaction; }else{ diff --git a/core/src/io/anuke/mindustry/world/blocks/production/GenericCrafter.java b/core/src/io/anuke/mindustry/world/blocks/production/GenericCrafter.java index 68b40ea6cc..7376b0738b 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/GenericCrafter.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/GenericCrafter.java @@ -1,77 +1,90 @@ package io.anuke.mindustry.world.blocks.production; -import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.function.Consumer; +import io.anuke.arc.function.Supplier; +import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.mindustry.entities.type.TileEntity; -import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.*; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.consumers.ConsumeLiquidBase; +import io.anuke.mindustry.world.consumers.ConsumeType; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.StatUnit; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; public class GenericCrafter extends Block{ - protected final int timerDump = timers++; - - protected Item output; + protected ItemStack outputItem; + protected LiquidStack outputLiquid; protected float craftTime = 80; - protected Effect craftEffect = Fx.purify; + protected Effect craftEffect = Fx.none; protected Effect updateEffect = Fx.none; protected float updateEffectChance = 0.04f; + protected Consumer drawer = null; + protected Supplier drawIcons = null; + public GenericCrafter(String name){ super(name); update = true; solid = true; + hasItems = true; health = 60; } - @Override - public void init(){ - super.init(); - - produces.set(output); - } - @Override public void setStats(){ + if(consumes.has(ConsumeType.liquid)){ + ConsumeLiquidBase cons = consumes.get(ConsumeType.liquid); + cons.timePeriod = craftTime; + } + super.setStats(); - stats.add(BlockStat.craftSpeed, 60f / craftTime, StatUnit.itemsSecond); - stats.add(BlockStat.outputItem, output); + stats.add(BlockStat.productionTime, craftTime / 60f, StatUnit.seconds); + + if(outputItem != null){ + stats.add(BlockStat.output, outputItem); + } + + if(outputLiquid != null){ + stats.add(BlockStat.output, outputLiquid.liquid, outputLiquid.amount, false); + } } @Override public void draw(Tile tile){ - Draw.rect(name, tile.drawx(), tile.drawy()); + if(drawer == null){ + super.draw(tile); + }else{ + drawer.accept(tile); + } + } - if(!hasLiquids) return; - - Draw.color(tile.entity.liquids.current().color); - Draw.alpha(tile.entity.liquids.total() / liquidCapacity); - Draw.rect("blank", tile.drawx(), tile.drawy(), 2, 2); - Draw.color(); + @Override + public TextureRegion[] generateIcons(){ + return drawIcons == null ? super.generateIcons() : drawIcons.get(); } @Override public void update(Tile tile){ GenericCrafterEntity entity = tile.entity(); - if(entity.cons.valid() && tile.entity.items.get(output) < itemCapacity){ + if(entity.cons.valid()){ entity.progress += getProgressIncrease(entity, craftTime); entity.totalProgress += entity.delta(); entity.warmup = Mathf.lerpDelta(entity.warmup, 1f, 0.02f); - if(Mathf.chance(Time.delta() * updateEffectChance)) + if(Mathf.chance(Time.delta() * updateEffectChance)){ Effects.effect(updateEffect, entity.x + Mathf.range(size * 4f), entity.y + Mathf.range(size * 4)); + } }else{ entity.warmup = Mathf.lerp(entity.warmup, 0f, 0.02f); } @@ -79,20 +92,37 @@ public class GenericCrafter extends Block{ if(entity.progress >= 1f){ entity.cons.trigger(); - useContent(tile, output); - offloadNear(tile, output); + if(outputItem != null){ + useContent(tile, outputItem.item); + for(int i = 0; i < outputItem.amount; i++){ + offloadNear(tile, outputItem.item); + } + } + + if(outputLiquid != null){ + useContent(tile, outputLiquid.liquid); + handleLiquid(tile, tile, outputLiquid.liquid, outputLiquid.amount); + } + Effects.effect(craftEffect, tile.drawx(), tile.drawy()); entity.progress = 0f; } - if(tile.entity.timer.get(timerDump, 5)){ - tryDump(tile, output); + if(outputItem != null && tile.entity.timer.get(timerDump, dumpTime)){ + tryDump(tile, outputItem.item); + } + + if(outputLiquid != null){ + tryDumpLiquid(tile, outputLiquid.liquid); } } @Override public boolean canProduce(Tile tile){ - return super.canProduce(tile); + if(outputItem != null && tile.entity.items.get(outputItem.item) >= itemCapacity){ + return false; + } + return outputLiquid == null || !(tile.entity.liquids.get(outputLiquid.liquid) >= liquidCapacity); } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/production/GenericSmelter.java b/core/src/io/anuke/mindustry/world/blocks/production/GenericSmelter.java new file mode 100644 index 0000000000..576236cd53 --- /dev/null +++ b/core/src/io/anuke/mindustry/world/blocks/production/GenericSmelter.java @@ -0,0 +1,48 @@ +package io.anuke.mindustry.world.blocks.production; + +import io.anuke.arc.Core; +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.world.Tile; + +/** A GenericCrafter with a new glowing region drawn on top. */ +public class GenericSmelter extends GenericCrafter{ + protected Color flameColor = Color.valueOf("ffc999"); + protected TextureRegion topRegion; + + public GenericSmelter(String name){ + super(name); + } + + @Override + public void load(){ + super.load(); + topRegion = Core.atlas.find(name + "-top"); + } + + @Override + public void draw(Tile tile){ + super.draw(tile); + + GenericCrafterEntity entity = tile.entity(); + + //draw glowing center + if(entity.warmup > 0f && flameColor.a > 0.001f){ + float g = 0.3f; + float r = 0.06f; + float cr = Mathf.random(0.1f); + + Draw.alpha(((1f - g) + Mathf.absin(Time.time(), 8f, g) + Mathf.random(r) - r) * entity.warmup); + + Draw.tint(flameColor); + Fill.circle(tile.drawx(), tile.drawy(), 3f + Mathf.absin(Time.time(), 5f, 2f) + cr); + Draw.color(1f, 1f, 1f, entity.warmup); + Draw.rect(topRegion, tile.drawx(), tile.drawy()); + Fill.circle(tile.drawx(), tile.drawy(), 1.9f + Mathf.absin(Time.time(), 5f, 1f) + cr); + + Draw.color(); + } + } +} diff --git a/core/src/io/anuke/mindustry/world/blocks/production/Incinerator.java b/core/src/io/anuke/mindustry/world/blocks/production/Incinerator.java index 23825bf5a8..7e28b8bc67 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Incinerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Incinerator.java @@ -1,13 +1,13 @@ package io.anuke.mindustry.world.blocks.production; -import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Fill; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Fx; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Liquid; diff --git a/core/src/io/anuke/mindustry/world/blocks/production/LiquidConverter.java b/core/src/io/anuke/mindustry/world/blocks/production/LiquidConverter.java new file mode 100644 index 0000000000..0cbe849905 --- /dev/null +++ b/core/src/io/anuke/mindustry/world/blocks/production/LiquidConverter.java @@ -0,0 +1,50 @@ +package io.anuke.mindustry.world.blocks.production; + +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.consumers.ConsumeLiquidBase; +import io.anuke.mindustry.world.consumers.ConsumeType; +import io.anuke.mindustry.world.meta.BlockStat; + +public class LiquidConverter extends GenericCrafter{ + + public LiquidConverter(String name){ + super(name); + hasLiquids = true; + } + + @Override + public void init(){ + ConsumeLiquidBase cl = consumes.get(ConsumeType.liquid); + cl.update(true); + outputLiquid.amount = cl.amount; + super.init(); + } + + @Override + public void setStats(){ + super.setStats(); + stats.remove(BlockStat.output); + stats.add(BlockStat.output, outputLiquid.liquid, outputLiquid.amount * craftTime, false); + } + + @Override + public void update(Tile tile){ + GenericCrafterEntity entity = tile.entity(); + ConsumeLiquidBase cl = consumes.get(ConsumeType.liquid); + + if(tile.entity.cons.valid()){ + float use = Math.min(cl.amount * entity.delta(), liquidCapacity - entity.liquids.get(outputLiquid.liquid)); + if(hasPower){ + use *= entity.power.satisfaction; // Produce less liquid if power is not maxed + } + entity.progress += use / cl.amount / craftTime; + entity.liquids.add(outputLiquid.liquid, use); + if(entity.progress >= 1f){ + entity.cons.trigger(); + entity.progress = 0f; + } + } + + tryDumpLiquid(tile, outputLiquid.liquid); + } +} diff --git a/core/src/io/anuke/mindustry/world/blocks/production/LiquidMixer.java b/core/src/io/anuke/mindustry/world/blocks/production/LiquidMixer.java deleted file mode 100644 index 9f0cb76b22..0000000000 --- a/core/src/io/anuke/mindustry/world/blocks/production/LiquidMixer.java +++ /dev/null @@ -1,93 +0,0 @@ -package io.anuke.mindustry.world.blocks.production; - -import io.anuke.mindustry.entities.type.TileEntity; -import io.anuke.mindustry.type.Liquid; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.LiquidBlock; -import io.anuke.mindustry.world.consumers.ConsumeLiquid; -import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.mindustry.world.meta.StatUnit; -import io.anuke.mindustry.world.modules.LiquidModule; -import io.anuke.arc.graphics.g2d.Draw; - -public class LiquidMixer extends LiquidBlock{ - protected Liquid outputLiquid; - protected float liquidPerItem = 50f; - - public LiquidMixer(String name){ - super(name); - hasItems = true; - rotate = false; - solid = true; - singleLiquid = false; - outputsLiquid = true; - } - - @Override - public void init(){ - super.init(); - - produces.set(outputLiquid); - } - - @Override - public void setStats(){ - super.setStats(); - - stats.add(BlockStat.liquidOutput, outputLiquid); - stats.add(BlockStat.liquidOutputSpeed, 60f * consumes.get(ConsumeLiquid.class).used(), StatUnit.liquidSecond); - } - - @Override - public boolean shouldConsume(Tile tile){ - return tile.entity.liquids.get(outputLiquid) < liquidCapacity; - } - - @Override - public void update(Tile tile){ - LiquidMixerEntity entity = tile.entity(); - - if(tile.entity.cons.valid()){ - float use = Math.min(consumes.get(ConsumeLiquid.class).used() * entity.delta(), liquidCapacity - entity.liquids.get(outputLiquid)); - if(hasPower){ - use *= entity.power.satisfaction; // Produce less liquid if power is not maxed - } - entity.accumulator += use; - entity.liquids.add(outputLiquid, use); - for(int i = 0; i < (int) (entity.accumulator / liquidPerItem); i++){ - if(!entity.items.has(consumes.item())) break; - entity.items.remove(consumes.item(), 1); - entity.accumulator -= liquidPerItem; - } - } - - tryDumpLiquid(tile, outputLiquid); - } - - @Override - public void draw(Tile tile){ - LiquidModule mod = tile.entity.liquids; - - int rotation = rotate ? tile.getRotation() * 90 : 0; - - Draw.rect(bottomRegion, tile.drawx(), tile.drawy(), rotation); - - if(mod.total() > 0.001f){ - Draw.color(outputLiquid.color); - Draw.alpha(mod.get(outputLiquid) / liquidCapacity); - Draw.rect(liquidRegion, tile.drawx(), tile.drawy(), rotation); - Draw.color(); - } - - Draw.rect(topRegion, tile.drawx(), tile.drawy(), rotation); - } - - @Override - public TileEntity newEntity(){ - return new LiquidMixerEntity(); - } - - static class LiquidMixerEntity extends TileEntity{ - float accumulator; - } -} diff --git a/core/src/io/anuke/mindustry/world/blocks/production/PhaseWeaver.java b/core/src/io/anuke/mindustry/world/blocks/production/PhaseWeaver.java deleted file mode 100644 index ae7b2e3530..0000000000 --- a/core/src/io/anuke/mindustry/world/blocks/production/PhaseWeaver.java +++ /dev/null @@ -1,66 +0,0 @@ -package io.anuke.mindustry.world.blocks.production; - -import io.anuke.arc.Core; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Lines; -import io.anuke.arc.graphics.g2d.TextureRegion; -import io.anuke.arc.math.Mathf; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.graphics.Pal; -import io.anuke.mindustry.graphics.Shaders; -import io.anuke.mindustry.world.Tile; - -public class PhaseWeaver extends PowerSmelter{ - protected TextureRegion bottomRegion; - protected TextureRegion weaveRegion; - - public PhaseWeaver(String name){ - super(name); - } - - @Override - public void load(){ - super.load(); - - bottomRegion = Core.atlas.find(name + "-bottom"); - weaveRegion = Core.atlas.find(name + "-weave"); - } - - @Override - public TextureRegion[] generateIcons(){ - return new TextureRegion[]{Core.atlas.find(name + "-bottom"), Core.atlas.find(name)}; - } - - @Override - public void draw(Tile tile){ - PowerSmelterEntity entity = tile.entity(); - - Draw.rect(bottomRegion, tile.drawx(), tile.drawy()); - - float progress = 0.5f; - - Shaders.build.region = weaveRegion; - Shaders.build.progress = progress; - Shaders.build.color.set(Pal.accent); - Shaders.build.color.a = entity.heat; - Shaders.build.time = -entity.time / 10f; - - Draw.shader(Shaders.build, false); - Shaders.build.apply(); - Draw.rect(weaveRegion, tile.drawx(), tile.drawy(), entity.time); - Draw.shader(); - - Draw.color(Pal.accent); - Draw.alpha(entity.heat); - - Lines.lineAngleCenter( - tile.drawx() + Mathf.sin(entity.time, 6f, Vars.tilesize / 3f * size), - tile.drawy(), - 90, - size * Vars.tilesize / 2f); - - Draw.reset(); - - Draw.rect(region, tile.drawx(), tile.drawy()); - } -} diff --git a/core/src/io/anuke/mindustry/world/blocks/production/PlastaniumCompressor.java b/core/src/io/anuke/mindustry/world/blocks/production/PlastaniumCompressor.java deleted file mode 100644 index 1c76b5b821..0000000000 --- a/core/src/io/anuke/mindustry/world/blocks/production/PlastaniumCompressor.java +++ /dev/null @@ -1,33 +0,0 @@ -package io.anuke.mindustry.world.blocks.production; - -import io.anuke.arc.Core; -import io.anuke.arc.graphics.g2d.TextureRegion; -import io.anuke.mindustry.world.Tile; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.math.Mathf; - -public class PlastaniumCompressor extends GenericCrafter{ - protected TextureRegion topRegion; - - public PlastaniumCompressor(String name){ - super(name); - } - - @Override - public void load(){ - super.load(); - - topRegion = Core.atlas.find(name + "-top"); - } - - @Override - public void draw(Tile tile){ - super.draw(tile); - - GenericCrafterEntity entity = tile.entity(); - - Draw.alpha(Mathf.absin(entity.totalProgress, 3f, 0.9f) * entity.warmup); - Draw.rect(topRegion, tile.drawx(), tile.drawy()); - Draw.reset(); - } -} diff --git a/core/src/io/anuke/mindustry/world/blocks/production/PowerCrafter.java b/core/src/io/anuke/mindustry/world/blocks/production/PowerCrafter.java deleted file mode 100644 index c57831f628..0000000000 --- a/core/src/io/anuke/mindustry/world/blocks/production/PowerCrafter.java +++ /dev/null @@ -1,114 +0,0 @@ -package io.anuke.mindustry.world.blocks.production; - -import io.anuke.mindustry.entities.type.TileEntity; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.Liquid; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.production.GenericCrafter.GenericCrafterEntity; -import io.anuke.mindustry.world.meta.BlockStat; - -/**Similar to GenericCrafter, but also optionally outputs liquids. - * TODO consolidate into one class*/ -public class PowerCrafter extends Block{ - protected final int timerDump = timers++; - protected final int timerContentCheck = timers++; - - /**Optional.*/ - protected Item outputItem; - /**Optional. Set hasLiquids to true when using.*/ - protected Liquid outputLiquid; - protected float outputLiquidAmount; - protected float craftTime; - - public PowerCrafter(String name){ - super(name); - solid = true; - update = true; - hasPower = true; - hasItems = true; - } - - @Override - public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ - return false; - } - - @Override - public void init(){ - super.init(); - - if(outputLiquid != null){ - outputsLiquid = true; - } - - if(outputLiquid != null){ - produces.set(outputLiquid); - }else if(outputItem != null){ - produces.set(outputItem); - } - } - - @Override - public void setStats(){ - super.setStats(); - - if(outputItem != null){ - stats.add(BlockStat.outputItem, outputItem); - } - - if(outputLiquid != null){ - stats.add(BlockStat.liquidOutput, outputLiquid); - } - } - - @Override - public boolean canProduce(Tile tile){ - if(outputItem != null && tile.entity.items.get(outputItem) >= itemCapacity){ - return false; - } - if(outputLiquid != null && tile.entity.liquids.get(outputLiquid) >= liquidCapacity - 0.01f){ - return false; - } - return true; - } - - @Override - public void update(Tile tile){ - GenericCrafterEntity entity = tile.entity(); - - if(entity.cons.valid()){ - entity.progress += getProgressIncrease(entity, craftTime); - entity.totalProgress += entity.delta(); - } - - if(entity.progress >= 1f){ - entity.items.remove(consumes.item(), consumes.itemAmount()); - if(outputItem != null){ - offloadNear(tile, outputItem); - useContent(tile, outputItem); - } - - if(outputLiquid != null){ - handleLiquid(tile, tile, outputLiquid, outputLiquidAmount); - if(tile.entity.liquids.currentAmount() > 0f && tile.entity.timer.get(timerContentCheck, 10)){ - useContent(tile, outputLiquid); - } - } - entity.progress = 0f; - } - - if(outputItem != null && entity.timer.get(timerDump, 5)){ - tryDump(tile, outputItem); - } - - if(outputLiquid != null){ - tryDumpLiquid(tile, entity.liquids.current()); - } - } - - @Override - public TileEntity newEntity(){ - return new GenericCrafterEntity(); - } -} diff --git a/core/src/io/anuke/mindustry/world/blocks/production/PowerSmelter.java b/core/src/io/anuke/mindustry/world/blocks/production/PowerSmelter.java deleted file mode 100644 index b6d39ad5f9..0000000000 --- a/core/src/io/anuke/mindustry/world/blocks/production/PowerSmelter.java +++ /dev/null @@ -1,175 +0,0 @@ -package io.anuke.mindustry.world.blocks.production; - -import io.anuke.arc.Core; -import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.Effects.Effect; -import io.anuke.arc.graphics.Color; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Fill; -import io.anuke.arc.graphics.g2d.TextureRegion; -import io.anuke.arc.math.Mathf; -import io.anuke.arc.util.Time; -import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.type.TileEntity; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.PowerBlock; -import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.mindustry.world.meta.StatUnit; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -public class PowerSmelter extends PowerBlock{ - protected final int timerDump = timers++; - - protected Item output; - - protected float heatUpTime = 80f; - protected float minHeat = 0.5f; - - protected float craftTime = 20f; //time to craft one item, so max 3 items per second by default - protected float burnEffectChance = 0.01f; - protected Effect craftEffect = Fx.smelt, - burnEffect = Fx.fuelburn; - protected Color flameColor = Color.valueOf("ffc999"); - - protected TextureRegion topRegion; - - public PowerSmelter(String name){ - super(name); - hasItems = true; - update = true; - solid = true; - } - - @Override - public void init(){ - super.init(); - - produces.set(output); - } - - @Override - public void load(){ - super.load(); - topRegion = Core.atlas.find(name + "-top"); - } - - @Override - public void setStats(){ - super.setStats(); - - stats.add(BlockStat.outputItem, output); - stats.add(BlockStat.craftSpeed, 60f / craftTime, StatUnit.itemsSecond); - stats.add(BlockStat.inputItemCapacity, itemCapacity, StatUnit.items); - stats.add(BlockStat.outputItemCapacity, itemCapacity, StatUnit.items); - } - - @Override - public void update(Tile tile){ - - PowerSmelterEntity entity = tile.entity(); - - if(entity.timer.get(timerDump, 5) && entity.items.has(output)){ - tryDump(tile, output); - } - - //heat it up if there's enough power - if(entity.cons.valid()){ - entity.heat += 1f / heatUpTime * entity.delta(); - if(Mathf.chance(entity.delta() * burnEffectChance)) - Effects.effect(burnEffect, entity.x + Mathf.range(size * 4f), entity.y + Mathf.range(size * 4)); - }else{ - entity.heat -= 1f / heatUpTime * Time.delta(); - } - - entity.heat = Mathf.clamp(entity.heat); - entity.time += entity.heat * entity.delta(); - - if(!entity.cons.valid()){ - return; - } - - entity.craftTime += entity.delta() * entity.power.satisfaction; - - if(entity.items.get(output) >= itemCapacity //output full - || entity.heat <= minHeat //not burning - || entity.craftTime < craftTime){ //not yet time - return; - } - - entity.craftTime = 0f; - - for(ItemStack item : consumes.items()){ - entity.items.remove(item.item, item.amount); - } - - offloadNear(tile, output); - Effects.effect(craftEffect, flameColor, tile.drawx(), tile.drawy()); - } - - @Override - public boolean acceptItem(Item item, Tile tile, Tile source){ - - for(ItemStack stack : consumes.items()){ - if(stack.item == item){ - return tile.entity.items.get(item) < itemCapacity; - } - } - - return false; - } - - @Override - public int getMaximumAccepted(Tile tile, Item item){ - return itemCapacity; - } - - @Override - public void draw(Tile tile){ - super.draw(tile); - - PowerSmelterEntity entity = tile.entity(); - - //draw glowing center - if(entity.heat > 0f && flameColor.a > 0.001f){ - float g = 0.3f; - float r = 0.06f; - float cr = Mathf.random(0.1f); - - Draw.alpha(((1f - g) + Mathf.absin(Time.time(), 8f, g) + Mathf.random(r) - r) * entity.heat); - - Draw.tint(flameColor); - Fill.circle(tile.drawx(), tile.drawy(), 3f + Mathf.absin(Time.time(), 5f, 2f) + cr); - Draw.color(1f, 1f, 1f, entity.heat); - Draw.rect(topRegion, tile.drawx(), tile.drawy()); - Fill.circle(tile.drawx(), tile.drawy(), 1.9f + Mathf.absin(Time.time(), 5f, 1f) + cr); - - Draw.color(); - } - } - - @Override - public TileEntity newEntity(){ - return new PowerSmelterEntity(); - } - - class PowerSmelterEntity extends TileEntity{ - public float heat; - public float time; - public float craftTime; - - @Override - public void write(DataOutput stream) throws IOException{ - stream.writeFloat(heat); - } - - @Override - public void read(DataInput stream) throws IOException{ - heat = stream.readFloat(); - } - } -} diff --git a/core/src/io/anuke/mindustry/world/blocks/production/Pulverizer.java b/core/src/io/anuke/mindustry/world/blocks/production/Pulverizer.java deleted file mode 100644 index d15d024647..0000000000 --- a/core/src/io/anuke/mindustry/world/blocks/production/Pulverizer.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.anuke.mindustry.world.blocks.production; - -import io.anuke.arc.Core; -import io.anuke.arc.graphics.g2d.TextureRegion; -import io.anuke.mindustry.world.Tile; -import io.anuke.arc.graphics.g2d.Draw; - -public class Pulverizer extends GenericCrafter{ - protected TextureRegion rotatorRegion; - - public Pulverizer(String name){ - super(name); - hasItems = true; - } - - @Override - public void load(){ - super.load(); - - rotatorRegion = Core.atlas.find(name + "-rotator"); - } - - @Override - public void draw(Tile tile){ - GenericCrafterEntity entity = tile.entity(); - - Draw.rect(region, tile.drawx(), tile.drawy()); - Draw.rect(rotatorRegion, tile.drawx(), tile.drawy(), entity.totalProgress * 2f); - } - - @Override - public TextureRegion[] generateIcons(){ - return new TextureRegion[]{Core.atlas.find(name), Core.atlas.find(name + "-rotator")}; - } -} diff --git a/core/src/io/anuke/mindustry/world/blocks/production/Pump.java b/core/src/io/anuke/mindustry/world/blocks/production/Pump.java index e788e380fb..4dddcd36b0 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Pump.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Pump.java @@ -1,17 +1,14 @@ package io.anuke.mindustry.world.blocks.production; import io.anuke.arc.Core; -import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.collection.Array; +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.mindustry.graphics.Layer; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.LiquidBlock; -import io.anuke.mindustry.world.consumers.ConsumeLiquid; -import io.anuke.mindustry.world.meta.BlockGroup; -import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.mindustry.world.meta.StatUnit; -import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.mindustry.world.meta.*; public class Pump extends LiquidBlock{ protected final Array drawTiles = new Array<>(); @@ -19,7 +16,7 @@ public class Pump extends LiquidBlock{ protected final int timerContentCheck = timers++; - /**Pump amount, total.*/ + /** Pump amount, total. */ protected float pumpAmount = 1f; public Pump(String name){ @@ -40,7 +37,7 @@ public class Pump extends LiquidBlock{ @Override public void setStats(){ super.setStats(); - stats.add(BlockStat.liquidOutputSpeed, 60f * pumpAmount, StatUnit.liquidSecond); + stats.add(BlockStat.output, 60f * pumpAmount, StatUnit.liquidSecond); } @Override @@ -107,11 +104,6 @@ public class Pump extends LiquidBlock{ tryDumpLiquid(tile, tile.entity.liquids.current()); } - @Override - public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ - return consumes.has(ConsumeLiquid.class) && consumes.liquid() == liquid && super.acceptLiquid(tile, source, liquid, amount); - } - protected boolean isValid(Tile tile){ return tile != null && tile.floor().liquidDrop != null; } 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 160a5cb240..e29f2fe218 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Separator.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Separator.java @@ -1,10 +1,8 @@ package io.anuke.mindustry.world.blocks.production; -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.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; @@ -12,25 +10,25 @@ import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.production.GenericCrafter.GenericCrafterEntity; -import io.anuke.mindustry.world.consumers.ConsumeItem; +import io.anuke.mindustry.world.consumers.ConsumeLiquidBase; +import io.anuke.mindustry.world.consumers.ConsumeType; import io.anuke.mindustry.world.meta.BlockStat; +import io.anuke.mindustry.world.meta.StatUnit; import io.anuke.mindustry.world.meta.values.ItemFilterValue; /** * Extracts a random list of items from an input item and an input liquid. */ public class Separator extends Block{ - protected final int timerDump = timers++; - protected ItemStack[] results; - protected float filterTime; + protected float craftTime; protected float spinnerRadius = 2.5f; protected float spinnerLength = 1f; protected float spinnerThickness = 1f; protected float spinnerSpeed = 2f; protected Color color = Color.valueOf("858585"); - protected TextureRegion liquidRegion; + protected int liquidRegion; public Separator(String name){ super(name); @@ -38,25 +36,28 @@ public class Separator extends Block{ solid = true; hasItems = true; hasLiquids = true; - } - @Override - public void load(){ - super.load(); - - liquidRegion = Core.atlas.find(name + "-liquid"); + liquidRegion = reg("-liquid"); } @Override public void setStats(){ + if(consumes.has(ConsumeType.liquid)){ + ConsumeLiquidBase cons = consumes.get(ConsumeType.liquid); + cons.timePeriod = craftTime; + } + super.setStats(); - stats.add(BlockStat.outputItem, new ItemFilterValue(item -> { + stats.add(BlockStat.output, new ItemFilterValue(item -> { for(ItemStack i : results){ if(item == i.item) return true; } return false; })); + + stats.add(BlockStat.productionTime, craftTime / 60f, StatUnit.seconds); + } @Override @@ -67,7 +68,7 @@ public class Separator extends Block{ Draw.color(tile.entity.liquids.current().color); Draw.alpha(tile.entity.liquids.total() / liquidCapacity); - Draw.rect(liquidRegion, tile.drawx(), tile.drawy()); + Draw.rect(reg(liquidRegion), tile.drawx(), tile.drawy()); Draw.color(color); Lines.stroke(spinnerThickness); @@ -82,7 +83,7 @@ public class Separator extends Block{ entity.totalProgress += entity.warmup * entity.delta(); if(entity.cons.valid()){ - entity.progress += getProgressIncrease(entity, filterTime); + entity.progress += getProgressIncrease(entity, craftTime); entity.warmup = Mathf.lerpDelta(entity.warmup, 1f, 0.02f); }else{ entity.warmup = Mathf.lerpDelta(entity.warmup, 0f, 0.02f); @@ -106,16 +107,14 @@ public class Separator extends Block{ count += stack.amount; } - if(consumes.has(ConsumeItem.class)){ - entity.items.remove(consumes.item(), consumes.itemAmount()); - } + entity.cons.trigger(); if(item != null && entity.items.get(item) < itemCapacity){ offloadNear(tile, item); } } - if(entity.timer.get(timerDump, 5)){ + if(entity.timer.get(timerDump, dumpTime)){ tryDump(tile); } } diff --git a/core/src/io/anuke/mindustry/world/blocks/production/Smelter.java b/core/src/io/anuke/mindustry/world/blocks/production/Smelter.java deleted file mode 100644 index c73732cace..0000000000 --- a/core/src/io/anuke/mindustry/world/blocks/production/Smelter.java +++ /dev/null @@ -1,148 +0,0 @@ -package io.anuke.mindustry.world.blocks.production; - -import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.Effects.Effect; -import io.anuke.arc.graphics.Color; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Fill; -import io.anuke.arc.math.Mathf; -import io.anuke.arc.util.Time; -import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.type.TileEntity; -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.consumers.ConsumeItem; -import io.anuke.mindustry.world.consumers.ConsumeItems; -import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.mindustry.world.meta.StatUnit; - -public class Smelter extends Block{ - protected final int timerDump = timers++; - - protected Item result; - - protected float craftTime = 20f; - protected float burnDuration = 50f; - protected Effect craftEffect = Fx.smelt, burnEffect = Fx.fuelburn; - protected Color flameColor = Color.valueOf("ffb879"); - - public Smelter(String name){ - super(name); - update = true; - hasItems = true; - solid = true; - - consumes.require(ConsumeItems.class); - consumes.require(ConsumeItem.class); - } - - @Override - public void setStats(){ - super.setStats(); - - stats.add(BlockStat.fuelBurnTime, burnDuration / 60f, StatUnit.seconds); - stats.add(BlockStat.outputItem, result); - stats.add(BlockStat.craftSpeed, 60f / craftTime, StatUnit.itemsSecond); - stats.add(BlockStat.inputItemCapacity, itemCapacity, StatUnit.items); - stats.add(BlockStat.outputItemCapacity, itemCapacity, StatUnit.items); - } - - @Override - public void init(){ - super.init(); - produces.set(result); - } - - @Override - public void update(Tile tile){ - SmelterEntity entity = tile.entity(); - - if(entity.timer.get(timerDump, 5) && entity.items.has(result)){ - tryDump(tile, result); - } - - //add fuel - if(entity.consumed(ConsumeItem.class) && entity.burnTime <= 0f){ - entity.items.remove(consumes.item(), 1); - entity.burnTime += burnDuration; - Effects.effect(burnEffect, entity.x + Mathf.range(2f), entity.y + Mathf.range(2f)); - } - - //decrement burntime - if(entity.burnTime > 0){ - entity.burnTime -= entity.delta(); - entity.heat = Mathf.lerpDelta(entity.heat, 1f, 0.02f); - }else{ - entity.heat = Mathf.lerpDelta(entity.heat, 0f, 0.02f); - } - - //make sure it has all the items - if(!entity.cons.valid()){ - return; - } - - entity.craftTime += entity.delta(); - - if(entity.items.get(result) >= itemCapacity //output full - || entity.burnTime <= 0 //not burning - || entity.craftTime < craftTime){ //not yet time - return; - } - - entity.craftTime = 0f; - for(ItemStack item : consumes.items()){ - entity.items.remove(item.item, item.amount); - } - - offloadNear(tile, result); - Effects.effect(craftEffect, flameColor, tile.drawx(), tile.drawy()); - } - - @Override - public boolean acceptItem(Item item, Tile tile, Tile source){ - boolean isInput = false; - - for(ItemStack req : consumes.items()){ - if(req.item == item){ - isInput = true; - break; - } - } - - return (isInput && tile.entity.items.get(item) < itemCapacity) || (item == consumes.item() && tile.entity.items.get(consumes.item()) < itemCapacity); - } - - @Override - public void draw(Tile tile){ - super.draw(tile); - - SmelterEntity entity = tile.entity(); - - //draw glowing center - if(entity.heat > 0f){ - float g = 0.1f; - - Draw.alpha(((1f - g) + Mathf.absin(Time.time(), 8f, g)) * entity.heat); - - Draw.tint(flameColor); - Fill.circle(tile.drawx(), tile.drawy(), 2f + Mathf.absin(Time.time(), 5f, 0.8f)); - Draw.color(1f, 1f, 1f, entity.heat); - Fill.circle(tile.drawx(), tile.drawy(), 1f + Mathf.absin(Time.time(), 5f, 0.7f)); - - Draw.color(); - } - } - - @Override - public TileEntity newEntity(){ - return new SmelterEntity(); - } - - public class SmelterEntity extends TileEntity{ - public float burnTime; - public float heat; - public float craftTime; - } -} diff --git a/core/src/io/anuke/mindustry/world/blocks/production/SolidPump.java b/core/src/io/anuke/mindustry/world/blocks/production/SolidPump.java index 6bdecaf130..9f5c2bcc96 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/SolidPump.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/SolidPump.java @@ -24,7 +24,7 @@ public class SolidPump extends Pump{ protected Effect updateEffect = Fx.none; protected float updateEffectChance = 0.02f; protected float rotateSpeed = 1f; - /**Attribute that is checked when calculating output.*/ + /** Attribute that is checked when calculating output. */ protected Attribute attribute; public SolidPump(String name){ @@ -42,7 +42,7 @@ public class SolidPump extends Pump{ @Override public void drawPlace(int x, int y, int rotation, boolean valid){ if(attribute != null){ - drawPlaceText(Core.bundle.formatDouble("blocks.efficiency", (sumAttribute(attribute, x, y) + 1f)*100, 1), x, y, valid); + drawPlaceText(Core.bundle.formatFloat("bar.efficiency", (sumAttribute(attribute, x, y) + 1f) * 100, 1), x, y, valid); } } @@ -50,7 +50,7 @@ public class SolidPump extends Pump{ public void setBars(){ super.setBars(); bars.add("efficiency", entity -> new Bar(() -> - Core.bundle.formatDouble("blocks.efficiency", + Core.bundle.formatFloat("bar.efficiency", ((((SolidPumpEntity)entity).boost + 1f) * ((SolidPumpEntity)entity).warmup) * 100, 1), () -> Pal.ammo, () -> ((SolidPumpEntity)entity).warmup)); @@ -60,7 +60,8 @@ public class SolidPump extends Pump{ public void setStats(){ super.setStats(); - stats.add(BlockStat.liquidOutput, result); + stats.remove(BlockStat.output); + stats.add(BlockStat.output, result, 60f * pumpAmount, true); } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/sandbox/ItemVoid.java b/core/src/io/anuke/mindustry/world/blocks/sandbox/ItemVoid.java index aa4d55371b..2a59aeab8b 100644 --- a/core/src/io/anuke/mindustry/world/blocks/sandbox/ItemVoid.java +++ b/core/src/io/anuke/mindustry/world/blocks/sandbox/ItemVoid.java @@ -12,7 +12,8 @@ public class ItemVoid extends Block{ } @Override - public void handleItem(Item item, Tile tile, Tile source){} + public void handleItem(Item item, Tile tile, Tile source){ + } @Override public boolean acceptItem(Item item, Tile tile, Tile source){ 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 86d189c639..7640d99945 100644 --- a/core/src/io/anuke/mindustry/world/blocks/sandbox/LiquidSource.java +++ b/core/src/io/anuke/mindustry/world/blocks/sandbox/LiquidSource.java @@ -2,6 +2,7 @@ package io.anuke.mindustry.world.blocks.sandbox; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; +import io.anuke.arc.Core; import io.anuke.arc.collection.Array; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.scene.style.TextureRegionDrawable; @@ -16,14 +17,13 @@ import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.content; import static io.anuke.mindustry.Vars.control; public class LiquidSource extends Block{ + private static Liquid lastLiquid; public LiquidSource(String name){ super(name); @@ -35,6 +35,11 @@ public class LiquidSource extends Block{ outputsLiquid = true; } + @Override + public void playerPlaced(Tile tile){ + if(lastLiquid != null) Core.app.post(() -> Call.setLiquidSourceLiquid(null, tile, lastLiquid)); + } + @Override public void setBars(){ super.setBars(); @@ -74,7 +79,8 @@ public class LiquidSource extends Block{ final int f = i; ImageButton button = cont.addImageButton("clear", "clear-toggle", 24, () -> { Call.setLiquidSourceLiquid(null, tile, items.get(f)); - control.input(0).frag.config.hideConfig(); + control.input().frag.config.hideConfig(); + lastLiquid = items.get(f); }).size(38).group(group).get(); button.getStyle().imageUp = new TextureRegionDrawable(items.get(i).iconRegion); button.setChecked(entity.source.id == f); diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java b/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java index 7bb4946473..844d7cc058 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java @@ -4,17 +4,13 @@ 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.Draw; -import io.anuke.arc.graphics.g2d.Lines; -import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Mathf; import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.traits.SpawnerTrait; -import io.anuke.mindustry.entities.type.Player; -import io.anuke.mindustry.entities.type.TileEntity; -import io.anuke.mindustry.entities.type.Unit; +import io.anuke.mindustry.entities.type.*; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.graphics.Shaders; @@ -63,7 +59,7 @@ public class CoreBlock extends StorageBlock{ } @Override - public void onProximityUpdate(Tile tile) { + public void onProximityUpdate(Tile tile){ for(Tile other : state.teams.get(tile.getTeam()).cores){ if(other != tile){ tile.entity.items = other.entity.items; @@ -128,10 +124,10 @@ public class CoreBlock extends StorageBlock{ Draw.color(Pal.accent); Lines.lineAngleCenter( - tile.drawx() + Mathf.sin(entity.time, 6f, Vars.tilesize / 3f * size), - tile.drawy(), - 90, - size * Vars.tilesize / 2f); + tile.drawx() + Mathf.sin(entity.time, 6f, Vars.tilesize / 3f * size), + tile.drawy(), + 90, + size * Vars.tilesize / 2f); Draw.reset(); } @@ -176,11 +172,12 @@ public class CoreBlock extends StorageBlock{ float heat; @Override - public void updateSpawning(Player unit){ + public void updateSpawning(Player player){ if(!netServer.isWaitingForPlayers() && currentUnit == null){ - currentUnit = unit; + currentUnit = player; progress = 0f; - unit.set(tile.drawx(), tile.drawy()); + player.mech = player.getStarterMech(); + player.set(tile.drawx(), tile.drawy()); } } } diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/LaunchPad.java b/core/src/io/anuke/mindustry/world/blocks/storage/LaunchPad.java index 206c63f1ac..71c16f5393 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/LaunchPad.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/LaunchPad.java @@ -1,19 +1,26 @@ package io.anuke.mindustry.world.blocks.storage; -import io.anuke.mindustry.entities.Effects; +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.g2d.Lines; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.util.Time; import io.anuke.mindustry.Vars; 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.type.Item; import io.anuke.mindustry.type.ItemType; import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.meta.BlockStat; +import io.anuke.mindustry.world.meta.StatUnit; import static io.anuke.mindustry.Vars.data; import static io.anuke.mindustry.Vars.world; public class LaunchPad extends StorageBlock{ protected final int timerLaunch = timers++; - /**Time inbetween launches.*/ + /** Time inbetween launches. */ protected float launchTime; public LaunchPad(String name){ @@ -23,23 +30,52 @@ public class LaunchPad extends StorageBlock{ solid = true; } + @Override + public void setStats(){ + super.setStats(); + + stats.add(BlockStat.launchTime, launchTime / 60f, StatUnit.seconds); + } + @Override public boolean acceptItem(Item item, Tile tile, Tile source){ - return item.type == ItemType.material && super.acceptItem(item, tile, source); + return item.type == ItemType.material && tile.entity.items.total() < itemCapacity; + } + + @Override + public void draw(Tile tile){ + super.draw(tile); + + float progress = Mathf.clamp((tile.entity.items.total() / (float)itemCapacity) * ((tile.entity.timer.getTime(timerLaunch) / (launchTime / tile.entity.timeScale)))); + float scale = size / 3f; + + Lines.stroke(2f); + Draw.color(Pal.accentBack); + Lines.poly(tile.drawx(), tile.drawy(), 4, scale * 10f * (1f - progress), 45 + 360f * progress); + + Draw.color(Pal.accent); + + if(tile.entity.cons.valid()){ + for(int i = 0; i < 3; i++){ + float f = (Time.time() / 100f + i * 0.5f) % 1f; + + Lines.stroke(((2f * (2f - Math.abs(0.5f - f) * 2f)) - 2f + 0.2f)); + Lines.poly(tile.drawx(), tile.drawy(), 4, (1f - f) * 10f * scale); + } + } + + Draw.reset(); } @Override public void update(Tile tile){ TileEntity entity = tile.entity; - if(entity.cons.valid() && world.isZone()){ + if(entity.cons.valid() && world.isZone() && entity.items.total() >= itemCapacity && entity.timer.get(timerLaunch, launchTime / entity.timeScale)){ for(Item item : Vars.content.items()){ - if(entity.items.get(item) >= itemCapacity && entity.timer.get(timerLaunch, launchTime / entity.timeScale)){ - //TODO play animation of some sort - Effects.effect(Fx.dooropenlarge, tile); - data.addItem(item, entity.items.get(item)); - entity.items.set(item, 0); - } + Effects.effect(Fx.padlaunch, tile); + data.addItem(item, entity.items.get(item)); + entity.items.set(item, 0); } } } 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 b60fed4eba..f755175992 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/Unloader.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/Unloader.java @@ -12,15 +12,13 @@ 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.blocks.SelectionTrait; +import io.anuke.mindustry.world.blocks.ItemSelection; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.content; -public class Unloader extends Block implements SelectionTrait{ +public class Unloader extends Block{ protected float speed = 1f; protected final int timerUnload = timers++; @@ -66,8 +64,8 @@ public class Unloader extends Block implements SelectionTrait{ if(tile.entity.timer.get(timerUnload, speed / entity.timeScale) && tile.entity.items.total() == 0){ for(Tile other : tile.entity.proximity()){ if(other.interactable(tile.getTeam()) && other.block() instanceof StorageBlock && entity.items.total() == 0 && - ((entity.sortItem == null && other.entity.items.total() > 0) || ((StorageBlock) other.block()).hasItem(other, entity.sortItem))){ - offloadNear(tile, ((StorageBlock) other.block()).removeItem(other, entity.sortItem)); + ((entity.sortItem == null && other.entity.items.total() > 0) || ((StorageBlock)other.block()).hasItem(other, entity.sortItem))){ + offloadNear(tile, ((StorageBlock)other.block()).removeItem(other, entity.sortItem)); } } } @@ -91,7 +89,7 @@ public class Unloader extends Block implements SelectionTrait{ @Override public void buildTable(Tile tile, Table table){ SortedUnloaderEntity entity = tile.entity(); - buildItemTable(table, () -> entity.sortItem, item -> { + ItemSelection.buildItemTable(table, () -> entity.sortItem, item -> { lastItem = item; Call.setSortedUnloaderItem(null, tile, item); }); diff --git a/core/src/io/anuke/mindustry/world/blocks/units/MechPad.java b/core/src/io/anuke/mindustry/world/blocks/units/MechPad.java index 92a8e9212c..d4564e5eae 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/MechPad.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/MechPad.java @@ -3,9 +3,7 @@ package io.anuke.mindustry.world.blocks.units; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.Core; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Lines; -import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Geometry; import io.anuke.arc.util.Time; @@ -13,7 +11,6 @@ import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.content.Mechs; import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.traits.SpawnerTrait; import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.entities.type.TileEntity; @@ -23,10 +20,10 @@ import io.anuke.mindustry.graphics.Shaders; import io.anuke.mindustry.type.Mech; 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 java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.mobile; import static io.anuke.mindustry.Vars.tilesize; @@ -41,10 +38,17 @@ public class MechPad extends Block{ public MechPad(String name){ super(name); update = true; - solidifes = true; + solid = false; hasPower = true; } + @Override + public void setStats(){ + super.setStats(); + + stats.add(BlockStat.productionTime, buildTime / 60f, StatUnit.seconds); + } + @Override public void init(){ super.init(); @@ -57,7 +61,7 @@ public class MechPad extends Block{ @Remote(targets = Loc.both, called = Loc.server) public static void onMechFactoryTap(Player player, Tile tile){ - if(player == null || !(tile.block() instanceof MechPad) || !checkValidTap(tile, player)) return; + if(player == null || !(tile.block() instanceof MechPad) || !checkValidTap(tile, player)) return; MechFactoryEntity entity = tile.entity(); MechPad pad = (MechPad)tile.block(); @@ -78,7 +82,7 @@ public class MechPad extends Block{ if(entity.player == null) return; - Mech result = ((MechPad) tile.block()).mech; + Mech result = ((MechPad)tile.block()).mech; if(entity.player.mech == result){ Mech target = (entity.player.isMobile ? Mechs.starterMobile : Mechs.starterDesktop); @@ -94,7 +98,6 @@ public class MechPad extends Block{ entity.progress = 0; entity.player.heal(); entity.player.endRespawning(); - entity.open = true; entity.player.setDead(false); entity.player.clearItem(); entity.player = null; @@ -102,32 +105,27 @@ public class MechPad extends Block{ protected static boolean checkValidTap(Tile tile, Player player){ MechFactoryEntity entity = tile.entity(); - return Math.abs(player.x - tile.drawx()) <= tile.block().size * tilesize / 2f && - Math.abs(player.y - tile.drawy()) <= tile.block().size * tilesize / 2f && entity.cons.valid() && entity.player == null; + return Math.abs(player.x - tile.drawx()) <= tile.block().size * tilesize / 2f && + Math.abs(player.y - tile.drawy()) <= tile.block().size * tilesize / 2f && entity.cons.valid() && entity.player == null; } @Override public void drawSelect(Tile tile){ Draw.color(Pal.accent); - for(int i = 0; i < 4; i ++){ - float length = tilesize * size/2f + 3 + Mathf.absin(Time.time(), 5f, 2f); - Draw.rect("transfer-arrow", tile.drawx() + Geometry.d4[i].x * length, tile.drawy() + Geometry.d4[i].y * length, (i+2) * 90); + for(int i = 0; i < 4; i++){ + float length = tilesize * size / 2f + 3 + Mathf.absin(Time.time(), 5f, 2f); + Draw.rect("transfer-arrow", tile.drawx() + Geometry.d4[i].x * length, tile.drawy() + Geometry.d4[i].y * length, (i + 2) * 90); } Draw.color(); } - @Override - public boolean isSolidFor(Tile tile){ - MechFactoryEntity entity = tile.entity(); - return !entity.open; - } - @Override public void tapped(Tile tile, Player player){ + MechFactoryEntity entity = tile.entity(); if(checkValidTap(tile, player)){ Call.onMechFactoryTap(player, tile); - }else if(player.isLocal && mobile && !player.isDead()){ + }else if(player.isLocal && mobile && !player.isDead() && entity.cons.valid() && entity.player == null){ player.moveTarget = tile.entity; } } @@ -142,7 +140,7 @@ public class MechPad extends Block{ public void draw(Tile tile){ MechFactoryEntity entity = tile.entity(); - Draw.rect(Core.atlas.find(name), tile.drawx(), tile.drawy(), entity.open ? 180f : 0f); + Draw.rect(Core.atlas.find(name), tile.drawx(), tile.drawy()); if(entity.player != null){ TextureRegion region = mech.iconRegion; @@ -163,10 +161,10 @@ public class MechPad extends Block{ Draw.color(Pal.accent); Lines.lineAngleCenter( - tile.drawx() + Mathf.sin(entity.time, 6f, Vars.tilesize / 3f * size), - tile.drawy(), - 90, - size * Vars.tilesize / 2f + 1f); + tile.drawx() + Mathf.sin(entity.time, 6f, Vars.tilesize / 3f * size), + tile.drawy(), + 90, + size * Vars.tilesize / 2f + 1f); Draw.reset(); } @@ -176,14 +174,6 @@ public class MechPad extends Block{ public void update(Tile tile){ MechFactoryEntity entity = tile.entity(); - if(entity.open){ - if(!Units.anyEntities(tile)){ - entity.open = false; - }else{ - entity.heat = Mathf.lerpDelta(entity.heat, 0f, 0.1f); - } - } - if(entity.player != null){ entity.heat = Mathf.lerpDelta(entity.heat, 1f, 0.1f); entity.progress += 1f / buildTime * entity.delta(); @@ -194,10 +184,6 @@ public class MechPad extends Block{ Call.onMechFactoryDone(tile); } }else{ - if(entity.cons.valid() && Units.anyEntities(tile, 4f, unit -> unit.getTeam() == entity.getTeam() && unit instanceof Player)){ - entity.open = true; - } - entity.heat = Mathf.lerpDelta(entity.heat, 0f, 0.1f); } } @@ -212,7 +198,6 @@ public class MechPad extends Block{ float progress; float time; float heat; - boolean open; @Override public void updateSpawning(Player unit){ 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 7b3beb34c6..c0b949d055 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/RepairPoint.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/RepairPoint.java @@ -3,25 +3,19 @@ package io.anuke.mindustry.world.blocks.units; import io.anuke.arc.Core; import io.anuke.arc.collection.EnumSet; import io.anuke.arc.graphics.Color; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Lines; -import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Angles; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.util.Time; +import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.entities.type.Unit; -import io.anuke.mindustry.entities.Units; -import io.anuke.mindustry.graphics.Layer; -import io.anuke.mindustry.graphics.Pal; -import io.anuke.mindustry.graphics.Shapes; +import io.anuke.mindustry.graphics.*; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.consumers.ConsumePower; -import io.anuke.mindustry.world.meta.BlockFlag; -import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.mindustry.world.meta.StatUnit; +import io.anuke.mindustry.world.meta.*; public class RepairPoint extends Block{ private static Rectangle rect = new Rectangle(); @@ -84,14 +78,14 @@ public class RepairPoint extends Block{ RepairPointEntity entity = tile.entity(); if(entity.target != null && - Angles.angleDist(entity.angleTo(entity.target), entity.rotation) < 30f){ + Angles.angleDist(entity.angleTo(entity.target), entity.rotation) < 30f){ float ang = entity.angleTo(entity.target); 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); + tile.drawx() + Angles.trnsx(ang, len), tile.drawy() + Angles.trnsy(ang, len), + entity.target.x, entity.target.y, entity.strength); Draw.color(); } } @@ -107,7 +101,7 @@ public class RepairPoint extends Block{ boolean targetIsBeingRepaired = false; if(entity.target != null && (entity.target.isDead() || entity.target.dst(tile) > repairRadius || - entity.target.health >= entity.target.maxHealth())){ + entity.target.health >= entity.target.maxHealth())){ entity.target = null; }else if(entity.target != null){ float relativeConsumption = powerPerEvent / consumePower.powerCapacity; @@ -129,7 +123,7 @@ public class RepairPoint extends Block{ if(entity.timer.get(timerTarget, 20)){ rect.setSize(repairRadius * 2).setCenter(tile.drawx(), tile.drawy()); entity.target = Units.getClosest(tile.getTeam(), tile.drawx(), tile.drawy(), repairRadius, - unit -> unit.health < unit.maxHealth()); + unit -> unit.health < unit.maxHealth()); } } 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 2d75666b01..afe5e8daaf 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java @@ -4,35 +4,25 @@ 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.Draw; -import io.anuke.arc.graphics.g2d.Lines; -import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Mathf; import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.type.BaseUnit; -import io.anuke.mindustry.entities.type.TileEntity; -import io.anuke.mindustry.entities.type.Unit; +import io.anuke.mindustry.entities.type.*; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.graphics.Shaders; import io.anuke.mindustry.net.Net; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.type.UnitType; +import io.anuke.mindustry.type.*; import io.anuke.mindustry.ui.Bar; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.consumers.ConsumeItems; -import io.anuke.mindustry.world.meta.BlockFlag; -import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.mindustry.world.meta.StatUnit; -import io.anuke.mindustry.world.modules.ItemModule; +import io.anuke.mindustry.world.consumers.ConsumeType; +import io.anuke.mindustry.world.meta.*; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; public class UnitFactory extends Block{ //for attack mode @@ -44,7 +34,8 @@ public class UnitFactory extends Block{ protected float produceTime = 1000f; protected float launchVelocity = 0f; protected TextureRegion topRegion; - protected int maxSpawn = 2; + protected int maxSpawn = 4; + protected int[] capacities; public UnitFactory(String name){ super(name); @@ -53,8 +44,6 @@ public class UnitFactory extends Block{ hasItems = true; solid = false; flags = EnumSet.of(BlockFlag.producer); - - consumes.require(ConsumeItems.class); } @Remote(called = Loc.server) @@ -62,7 +51,7 @@ public class UnitFactory extends Block{ if(!(tile.entity instanceof UnitFactoryEntity) || !(tile.block() instanceof UnitFactory)) return; UnitFactoryEntity entity = tile.entity(); - UnitFactory factory = (UnitFactory) tile.block(); + UnitFactory factory = (UnitFactory)tile.block(); entity.buildTime = 0f; entity.spawned = spawns; @@ -79,6 +68,19 @@ public class UnitFactory extends Block{ } } + @Override + public void init(){ + super.init(); + + capacities = new int[Vars.content.items().size]; + if(consumes.has(ConsumeType.item)){ + ConsumeItems cons = consumes.get(ConsumeType.item); + for(ItemStack stack : cons.items){ + capacities[stack.item.id] = stack.amount * 2; + } + } + } + @Override public void load(){ super.load(); @@ -89,8 +91,8 @@ public class UnitFactory extends Block{ @Override public void setBars(){ super.setBars(); - bars.add("progress", entity -> new Bar("blocks.progress", Pal.ammo, () -> ((UnitFactoryEntity)entity).buildTime / produceTime)); - bars.add("spawned", entity -> new Bar(() -> Core.bundle.format("blocks.spawned", ((UnitFactoryEntity)entity).spawned, maxSpawn), () -> Pal.command, () -> (float)((UnitFactoryEntity)entity).spawned / maxSpawn)); + bars.add("progress", entity -> new Bar("bar.progress", Pal.ammo, () -> ((UnitFactoryEntity)entity).buildTime / produceTime)); + bars.add("spawned", entity -> new Bar(() -> Core.bundle.format("bar.spawned", ((UnitFactoryEntity)entity).spawned, maxSpawn), () -> Pal.command, () -> (float)((UnitFactoryEntity)entity).spawned / maxSpawn)); } @Override @@ -102,14 +104,16 @@ public class UnitFactory extends Block{ public void setStats(){ super.setStats(); - stats.add(BlockStat.craftSpeed, produceTime / 60f, StatUnit.seconds); + stats.remove(BlockStat.itemCapacity); + stats.add(BlockStat.productionTime, produceTime / 60f, StatUnit.seconds); stats.add(BlockStat.maxUnits, maxSpawn, StatUnit.none); } @Override public void unitRemoved(Tile tile, Unit unit){ UnitFactoryEntity entity = tile.entity(); - entity.spawned --; + entity.spawned--; + entity.spawned = Math.max(entity.spawned, 0); } @Override @@ -138,10 +142,10 @@ public class UnitFactory extends Block{ Draw.alpha(entity.speedScl); Lines.lineAngleCenter( - tile.drawx() + Mathf.sin(entity.time, 6f, Vars.tilesize / 2f * size - 2f), - tile.drawy(), - 90, - size * Vars.tilesize - 4f); + tile.drawx() + Mathf.sin(entity.time, 6f, Vars.tilesize / 2f * size - 2f), + tile.drawy(), + 90, + size * Vars.tilesize - 4f); Draw.reset(); @@ -162,15 +166,15 @@ public class UnitFactory extends Block{ if(!tile.isEnemyCheat()){ //player-made spawners have default behavior - if(hasRequirements(entity.items, entity.buildTime / produceTime) && entity.cons.valid()){ - entity.time += entity.delta() * entity.speedScl; - entity.buildTime += entity.delta() * entity.power.satisfaction; + if(entity.cons.valid()){ + entity.time += entity.delta() * entity.speedScl * Vars.state.rules.unitBuildSpeedMultiplier; + entity.buildTime += entity.delta() * entity.power.satisfaction * Vars.state.rules.unitBuildSpeedMultiplier; entity.speedScl = Mathf.lerpDelta(entity.speedScl, 1f, 0.05f); }else{ entity.speedScl = Mathf.lerpDelta(entity.speedScl, 0f, 0.05f); } //check if grace period had passed - }else if(entity.warmup > produceTime*gracePeriodMultiplier){ + }else if(entity.warmup > produceTime * gracePeriodMultiplier){ float speedMultiplier = Math.min(0.1f + (entity.warmup - produceTime * gracePeriodMultiplier) / speedupTime, maxSpeedup); entity.time += entity.delta() * entity.speedScl; //otherwise, it's an enemy, cheat by not requiring resources @@ -186,30 +190,13 @@ public class UnitFactory extends Block{ Call.onUnitFactorySpawn(tile, entity.spawned + 1); useContent(tile, type); - for(ItemStack stack : consumes.items()){ - entity.items.remove(stack.item, stack.amount); - } + entity.cons.trigger(); } } - @Override - public boolean acceptItem(Item item, Tile tile, Tile source){ - for(ItemStack stack : consumes.items()){ - if(item == stack.item && tile.entity.items.get(item) < stack.amount * 2){ - return true; - } - } - return false; - } - @Override public int getMaximumAccepted(Tile tile, Item item){ - for(ItemStack stack : consumes.items()){ - if(item == stack.item){ - return stack.amount * 2; - } - } - return 0; + return capacities[item.id]; } @Override @@ -223,21 +210,12 @@ public class UnitFactory extends Block{ return entity.spawned < maxSpawn; } - protected boolean hasRequirements(ItemModule inv, float fraction){ - for(ItemStack stack : consumes.items()){ - if(!inv.has(stack.item, (int) (fraction * stack.amount))){ - return false; - } - } - return true; - } - public static class UnitFactoryEntity extends TileEntity{ - public float buildTime; - public float time; - public float speedScl; - public float warmup; //only for enemy spawners - public int spawned; + float buildTime; + float time; + float speedScl; + float warmup; //only for enemy spawners + int spawned; @Override public void write(DataOutput stream) throws IOException{ diff --git a/core/src/io/anuke/mindustry/world/consumers/Consume.java b/core/src/io/anuke/mindustry/world/consumers/Consume.java index 1baea5fd3a..98ead521d7 100644 --- a/core/src/io/anuke/mindustry/world/consumers/Consume.java +++ b/core/src/io/anuke/mindustry/world/consumers/Consume.java @@ -2,30 +2,48 @@ package io.anuke.mindustry.world.consumers; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.entities.type.TileEntity; -import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockStats; -/**An abstract class that defines a type of resource that a block can consume.*/ +/** An abstract class that defines a type of resource that a block can consume. */ public abstract class Consume{ + /** If true, this consumer will not influence consumer validity. */ protected boolean optional; - protected boolean update = true, boost = false; + /** If true, this consumer will be displayed as a boost input. */ + protected boolean booster; + protected boolean update = true; - public Consume optional(boolean optional){ + /** + * Apply a filter to items accepted. + * This should set all item IDs that are present in the filter to true. + */ + public void applyItemFilter(boolean[] filter){ + + } + + /** + * Apply a filter to liquids accepted. + * This should set all liquid IDs that are present in the filter to true. + */ + public void applyLiquidFilter(boolean[] filter){ + + } + + public Consume optional(boolean optional, boolean boost){ this.optional = optional; + this.booster = boost; return this; } + public Consume boost(){ + return optional(true, true); + } + public Consume update(boolean update){ this.update = update; return this; } - public Consume boost(boolean boost){ - this.boost = boost; - return this; - } - public boolean isOptional(){ return optional; } @@ -34,31 +52,20 @@ public abstract class Consume{ return update; } - public abstract void build(Tile tile, Table table);/*{ + public abstract ConsumeType type(); - Table t = new Table("flat"); - t.margin(4); - buildTooltip(t); + public abstract void build(Tile tile, Table table); - int scale = mobile ? 4 : 3; - - table.table(out -> { - out.addImage(getIcon()).size(10 * scale).color(Color.DARK_GRAY).padRight(-10 * scale).padBottom(-scale * 2); - out.addImage(getIcon()).size(10 * scale).color(Pal.accent); - out.addImage("icon-missing").size(10 * scale).color(Pal.remove).padLeft(-10 * scale); - }).size(10 * scale).get().addListener(new Tooltip<>(t)); - }*/ - - /**Called when a consumption is triggered manually.*/ - public void trigger(Block block, TileEntity entity){ + /** Called when a consumption is triggered manually. */ + public void trigger(TileEntity entity){ } public abstract String getIcon(); - public abstract void update(Block block, TileEntity entity); + public abstract void update(TileEntity entity); - public abstract boolean valid(Block block, TileEntity entity); + public abstract boolean valid(TileEntity entity); public abstract void display(BlockStats stats); } diff --git a/core/src/io/anuke/mindustry/world/consumers/ConsumeItem.java b/core/src/io/anuke/mindustry/world/consumers/ConsumeItem.java deleted file mode 100644 index d6806db4c5..0000000000 --- a/core/src/io/anuke/mindustry/world/consumers/ConsumeItem.java +++ /dev/null @@ -1,66 +0,0 @@ -package io.anuke.mindustry.world.consumers; - -import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.mindustry.entities.type.TileEntity; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.Item.Icon; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.ui.ItemImage; -import io.anuke.mindustry.ui.ReqImage; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.mindustry.world.meta.BlockStats; - -public class ConsumeItem extends Consume{ - private final Item item; - private final int amount; - - public ConsumeItem(Item item){ - this.item = item; - this.amount = 1; - } - - public ConsumeItem(Item item, int amount){ - this.item = item; - this.amount = amount; - } - - public int getAmount(){ - return amount; - } - - public Item get(){ - return item; - } - - @Override - public void trigger(Block block, TileEntity entity){ - entity.items.remove(item, amount); - } - - @Override - public void build(Tile tile, Table table){ - table.add(new ReqImage(new ItemImage(item.icon(Icon.large), amount), () -> valid(tile.block(), tile.entity))).size(8*4); - } - - @Override - public String getIcon(){ - return "icon-item"; - } - - @Override - public void update(Block block, TileEntity entity){ - //doesn't update because consuming items is very specific - } - - @Override - public boolean valid(Block block, TileEntity entity){ - return entity != null && entity.items != null && entity.items.has(item, amount); - } - - @Override - public void display(BlockStats stats){ - stats.add(boost ? BlockStat.boostItem : BlockStat.inputItem, new ItemStack(item, amount)); - } -} diff --git a/core/src/io/anuke/mindustry/world/consumers/ConsumeItemFilter.java b/core/src/io/anuke/mindustry/world/consumers/ConsumeItemFilter.java index 597a4a7b77..f2c9edac07 100644 --- a/core/src/io/anuke/mindustry/world/consumers/ConsumeItemFilter.java +++ b/core/src/io/anuke/mindustry/world/consumers/ConsumeItemFilter.java @@ -6,10 +6,7 @@ import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Item.Icon; -import io.anuke.mindustry.ui.ItemImage; -import io.anuke.mindustry.ui.MultiReqImage; -import io.anuke.mindustry.ui.ReqImage; -import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.ui.*; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.BlockStats; @@ -18,19 +15,29 @@ import io.anuke.mindustry.world.meta.values.ItemFilterValue; import static io.anuke.mindustry.Vars.content; public class ConsumeItemFilter extends Consume{ - private final Predicate filter; + public final Predicate filter; public ConsumeItemFilter(Predicate item){ this.filter = item; } + @Override + public void applyItemFilter(boolean[] arr){ + content.items().each(filter, item -> arr[item.id] = true); + } + + @Override + public ConsumeType type(){ + return ConsumeType.item; + } + @Override public void build(Tile tile, Table table){ Array list = content.items().select(filter); MultiReqImage image = new MultiReqImage(); list.each(item -> image.add(new ReqImage(new ItemImage(item.icon(Icon.large), 1), () -> tile.entity != null && tile.entity.items != null && tile.entity.items.has(item)))); - table.add(image).size(8*4); + table.add(image).size(8 * 4); } @Override @@ -39,12 +46,12 @@ public class ConsumeItemFilter extends Consume{ } @Override - public void update(Block block, TileEntity entity){ + public void update(TileEntity entity){ } @Override - public void trigger(Block block, TileEntity entity){ + public void trigger(TileEntity entity){ for(int i = 0; i < content.items().size; i++){ Item item = content.item(i); if(entity.items != null && entity.items.has(item) && this.filter.test(item)){ @@ -55,7 +62,7 @@ public class ConsumeItemFilter extends Consume{ } @Override - public boolean valid(Block block, TileEntity entity){ + public boolean valid(TileEntity entity){ for(int i = 0; i < content.items().size; i++){ Item item = content.item(i); if(entity.items != null && entity.items.has(item) && this.filter.test(item)){ @@ -67,6 +74,6 @@ public class ConsumeItemFilter extends Consume{ @Override public void display(BlockStats stats){ - stats.add(boost ? BlockStat.boostItem : BlockStat.inputItem, new ItemFilterValue(filter)); + stats.add(booster ? BlockStat.booster : BlockStat.input, new ItemFilterValue(filter)); } } diff --git a/core/src/io/anuke/mindustry/world/consumers/ConsumeItems.java b/core/src/io/anuke/mindustry/world/consumers/ConsumeItems.java index 517e29956d..96f38e4aa3 100644 --- a/core/src/io/anuke/mindustry/world/consumers/ConsumeItems.java +++ b/core/src/io/anuke/mindustry/world/consumers/ConsumeItems.java @@ -6,27 +6,34 @@ import io.anuke.mindustry.type.Item.Icon; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.ui.ItemImage; import io.anuke.mindustry.ui.ReqImage; -import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.BlockStats; import io.anuke.mindustry.world.meta.values.ItemListValue; public class ConsumeItems extends Consume{ - private ItemStack[] items; + public final ItemStack[] items; public ConsumeItems(ItemStack[] items){ this.items = items; } - public ItemStack[] getItems(){ - return items; + @Override + public void applyItemFilter(boolean[] filter){ + for(ItemStack stack : items){ + filter[stack.item.id] = true; + } + } + + @Override + public ConsumeType type(){ + return ConsumeType.item; } @Override public void build(Tile tile, Table table){ for(ItemStack stack : items){ - table.add(new ReqImage(new ItemImage(stack.item.icon(Icon.large), stack.amount), () -> tile.entity != null && tile.entity.items != null && tile.entity.items.has(stack.item, stack.amount))).size(8*4).padRight(5); + table.add(new ReqImage(new ItemImage(stack.item.icon(Icon.large), stack.amount), () -> tile.entity != null && tile.entity.items != null && tile.entity.items.has(stack.item, stack.amount))).size(8 * 4).padRight(5); } } @@ -36,24 +43,24 @@ public class ConsumeItems extends Consume{ } @Override - public void update(Block block, TileEntity entity){ + public void update(TileEntity entity){ } @Override - public void trigger(Block block, TileEntity entity){ + public void trigger(TileEntity entity){ for(ItemStack stack : items){ entity.items.remove(stack); } } @Override - public boolean valid(Block block, TileEntity entity){ + public boolean valid(TileEntity entity){ return entity.items != null && entity.items.has(items); } @Override public void display(BlockStats stats){ - stats.add(boost ? BlockStat.boostItem : BlockStat.inputItems, new ItemListValue(items)); + stats.add(booster ? BlockStat.booster : BlockStat.input, new ItemListValue(items)); } } diff --git a/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquid.java b/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquid.java index 3ebeae1509..9cc8eba1fb 100644 --- a/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquid.java +++ b/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquid.java @@ -4,32 +4,26 @@ import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.ui.ReqImage; -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.BlockStats; -import io.anuke.mindustry.world.meta.StatUnit; -public class ConsumeLiquid extends Consume{ - protected final float use; - protected final Liquid liquid; +public class ConsumeLiquid extends ConsumeLiquidBase{ + public final Liquid liquid; - public ConsumeLiquid(Liquid liquid, float use){ + public ConsumeLiquid(Liquid liquid, float amount){ + super(amount); this.liquid = liquid; - this.use = use; } - public float used(){ - return use; - } - - public Liquid get(){ - return liquid; + @Override + public void applyLiquidFilter(boolean[] filter){ + filter[liquid.id] = true; } @Override public void build(Tile tile, Table table){ - table.add(new ReqImage(liquid.getContentIcon(), () -> valid(tile.block(), tile.entity))).size(8*4); + table.add(new ReqImage(liquid.getContentIcon(), () -> valid(tile.entity))).size(8 * 4); } @Override @@ -38,26 +32,17 @@ public class ConsumeLiquid extends Consume{ } @Override - public void update(Block block, TileEntity entity){ - entity.liquids.remove(liquid, Math.min(use(block, entity), entity.liquids.get(liquid))); + public void update(TileEntity entity){ + entity.liquids.remove(liquid, Math.min(use(entity), entity.liquids.get(liquid))); } @Override - public boolean valid(Block block, TileEntity entity){ - return entity != null && entity.liquids != null && entity.liquids.get(liquid) >= use(block, entity); + public boolean valid(TileEntity entity){ + return entity != null && entity.liquids != null && entity.liquids.get(liquid) >= use(entity); } @Override public void display(BlockStats stats){ - if(!boost){ - stats.add(BlockStat.liquidUse, use * 60f, StatUnit.liquidSecond); - stats.add(BlockStat.inputLiquid, liquid); - }else{ - stats.add(BlockStat.boostLiquid, liquid); - } - } - - float use(Block block, TileEntity entity){ - return Math.min(use * entity.delta(), block.liquidCapacity); + stats.add(booster ? BlockStat.booster : BlockStat.input, liquid, amount * timePeriod, timePeriod == 60); } } diff --git a/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquidBase.java b/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquidBase.java new file mode 100644 index 0000000000..34190338f2 --- /dev/null +++ b/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquidBase.java @@ -0,0 +1,28 @@ +package io.anuke.mindustry.world.consumers; + +import io.anuke.mindustry.entities.type.TileEntity; + +public abstract class ConsumeLiquidBase extends Consume{ + /** amount used per frame */ + public final float amount; + /** + * How much time is taken to use this liquid, in ticks. Used only for visual purposes. + * Example: a normal ConsumeLiquid with 10/s and a 10 second timePeriod would display as "100 seconds". + * Without a time override, it would display as "10 liquid/second". + * This is used for generic crafters. + */ + public float timePeriod = 60; + + public ConsumeLiquidBase(float amount){ + this.amount = amount; + } + + @Override + public ConsumeType type(){ + return ConsumeType.liquid; + } + + protected float use(TileEntity entity){ + return Math.min(amount * entity.delta(), entity.block.liquidCapacity); + } +} diff --git a/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquidFilter.java b/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquidFilter.java index bb3accfefe..6da77814e8 100644 --- a/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquidFilter.java +++ b/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquidFilter.java @@ -7,37 +7,33 @@ import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.ui.MultiReqImage; import io.anuke.mindustry.ui.ReqImage; -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.BlockStats; -import io.anuke.mindustry.world.meta.StatUnit; import io.anuke.mindustry.world.meta.values.LiquidFilterValue; import static io.anuke.mindustry.Vars.content; -public class ConsumeLiquidFilter extends Consume{ - private final Predicate filter; - private final float use; - private final boolean isFuel; - - public ConsumeLiquidFilter(Predicate liquid, float amount, boolean isFuel){ - this.filter = liquid; - this.use = amount; - this.isFuel = isFuel; - } +public class ConsumeLiquidFilter extends ConsumeLiquidBase{ + public final Predicate filter; public ConsumeLiquidFilter(Predicate liquid, float amount){ - this(liquid, amount, false); + super(amount); + this.filter = liquid; + } + + @Override + public void applyLiquidFilter(boolean[] arr){ + content.liquids().each(filter, item -> arr[item.id] = true); } @Override public void build(Tile tile, Table table){ Array list = content.liquids().select(l -> !l.isHidden() && filter.test(l)); MultiReqImage image = new MultiReqImage(); - list.each(liquid -> image.add(new ReqImage(liquid.getContentIcon(), () -> tile.entity != null && tile.entity.liquids != null && tile.entity.liquids.get(liquid) >= use(tile.block(), tile.entity)))); + list.each(liquid -> image.add(new ReqImage(liquid.getContentIcon(), () -> tile.entity != null && tile.entity.liquids != null && tile.entity.liquids.get(liquid) >= use(tile.entity)))); - table.add(image).size(8*4); + table.add(image).size(8 * 4); } @Override @@ -46,29 +42,17 @@ public class ConsumeLiquidFilter extends Consume{ } @Override - public void update(Block block, TileEntity entity){ - entity.liquids.remove(entity.liquids.current(), use(block, entity)); + public void update(TileEntity entity){ + entity.liquids.remove(entity.liquids.current(), use(entity)); } @Override - public boolean valid(Block block, TileEntity entity){ - return entity != null && entity.liquids != null && filter.test(entity.liquids.current()) && entity.liquids.currentAmount() >= use(block, entity); + public boolean valid(TileEntity entity){ + return entity != null && entity.liquids != null && filter.test(entity.liquids.current()) && entity.liquids.currentAmount() >= use(entity); } @Override public void display(BlockStats stats){ - if(boost){ - stats.add(BlockStat.boostLiquid, new LiquidFilterValue(filter)); - }else if(isFuel){ - stats.add(BlockStat.inputLiquidFuel, new LiquidFilterValue(filter)); - stats.add(BlockStat.liquidFuelUse, 60f * use, StatUnit.liquidSecond); - }else { - stats.add(BlockStat.inputLiquid, new LiquidFilterValue(filter)); - stats.add(BlockStat.liquidUse, 60f * use, StatUnit.liquidSecond); - } - } - - float use(Block block, TileEntity entity){ - return Math.min(use * entity.delta(), block.liquidCapacity); + stats.add(booster ? BlockStat.booster : BlockStat.input, new LiquidFilterValue(filter, amount * timePeriod, timePeriod == 60f)); } } diff --git a/core/src/io/anuke/mindustry/world/consumers/ConsumePower.java b/core/src/io/anuke/mindustry/world/consumers/ConsumePower.java index a88b09a929..6aaf0da2a9 100644 --- a/core/src/io/anuke/mindustry/world/consumers/ConsumePower.java +++ b/core/src/io/anuke/mindustry/world/consumers/ConsumePower.java @@ -5,9 +5,7 @@ import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.entities.type.TileEntity; 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.BlockStats; -import io.anuke.mindustry.world.meta.StatUnit; +import io.anuke.mindustry.world.meta.*; /** Consumer class for blocks which consume power while being connected to a power graph. */ public class ConsumePower extends Consume{ @@ -24,6 +22,11 @@ public class ConsumePower extends Consume{ this.isBuffered = isBuffered; } + @Override + public ConsumeType type(){ + return ConsumeType.power; + } + @Override public void build(Tile tile, Table table){ //No tooltip for power, for now @@ -35,12 +38,12 @@ public class ConsumePower extends Consume{ } @Override - public void update(Block block, TileEntity entity){ + public void update(TileEntity entity){ // Nothing to do since PowerGraph directly updates entity.power.satisfaction } @Override - public boolean valid(Block block, TileEntity entity){ + public boolean valid(TileEntity entity){ if(isBuffered){ return true; }else{ diff --git a/core/src/io/anuke/mindustry/world/consumers/ConsumeType.java b/core/src/io/anuke/mindustry/world/consumers/ConsumeType.java new file mode 100644 index 0000000000..572332f9df --- /dev/null +++ b/core/src/io/anuke/mindustry/world/consumers/ConsumeType.java @@ -0,0 +1,7 @@ +package io.anuke.mindustry.world.consumers; + +public enum ConsumeType{ + item, + power, + liquid +} diff --git a/core/src/io/anuke/mindustry/world/consumers/Consumers.java b/core/src/io/anuke/mindustry/world/consumers/Consumers.java index 0616e8ea80..d544e6481e 100644 --- a/core/src/io/anuke/mindustry/world/consumers/Consumers.java +++ b/core/src/io/anuke/mindustry/world/consumers/Consumers.java @@ -1,39 +1,37 @@ package io.anuke.mindustry.world.consumers; -import io.anuke.arc.collection.Array; -import io.anuke.arc.collection.ObjectMap; -import io.anuke.arc.collection.ObjectSet; -import io.anuke.arc.function.Consumer; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.type.Liquid; -import io.anuke.mindustry.world.Block; +import io.anuke.arc.util.Structs; +import io.anuke.mindustry.Vars; +import io.anuke.mindustry.type.*; +import io.anuke.mindustry.world.meta.BlockStats; public class Consumers{ - private ObjectMap, Consume> map = new ObjectMap<>(); - private ObjectSet> required = new ObjectSet<>(); - private Array results = new Array<>(); + private Consume[] map = new Consume[ConsumeType.values().length]; + private Consume[] results, optionalResults; - public void require(Class type){ - required.add(type); + public final boolean[] itemFilters = new boolean[Vars.content.items().size]; + public final boolean[] liquidfilters = new boolean[Vars.content.liquids().size]; + + public void init(){ + results = Structs.filter(Consume.class, map, m -> m != null); + optionalResults = Structs.filter(Consume.class, map, m -> m != null && m.isOptional()); + + for(Consume cons : results){ + cons.applyItemFilter(itemFilters); + cons.applyLiquidFilter(liquidfilters); + } } - public void checkRequired(Block block){ - for(Class c : required){ - if(!map.containsKey(c)){ - throw new RuntimeException("Missing required consumer of type \"" + c + "\" in block \"" + block.name + "\"!"); - } - } + public ConsumePower getPower(){ + return get(ConsumeType.power); + } - for(Consume cons : map.values()){ - results.add(cons); - } + public boolean hasPower(){ + return has(ConsumeType.power); } public ConsumeLiquid liquid(Liquid liquid, float amount){ - ConsumeLiquid c = new ConsumeLiquid(liquid, amount); - add(c); - return c; + return add(new ConsumeLiquid(liquid, amount)); } /** @@ -42,9 +40,7 @@ public class Consumers{ * @return the created consumer object. */ public ConsumePower power(float powerPerTick){ - ConsumePower c = new ConsumePower(powerPerTick, 0.0f, false); - add(c); - return c; + return add(new ConsumePower(powerPerTick, 0.0f, false)); } /** @@ -59,86 +55,58 @@ public class Consumers{ /** * Creates a consumer which stores power and uses it only in case of certain events (e.g. a turret firing). * @param powerCapacity The maximum capacity in power units. - * @param ticksToFill The number of ticks it shall take to fill the buffer. + * @param ticksToFill The number of ticks it shall take to fill the buffer. */ public ConsumePower powerBuffered(float powerCapacity, float ticksToFill){ - ConsumePower c = new ConsumePower(powerCapacity / ticksToFill, powerCapacity, true); - add(c); - return c; + return add(new ConsumePower(powerCapacity / ticksToFill, powerCapacity, true)); } - public ConsumeItem item(Item item){ + public ConsumeItems item(Item item){ return item(item, 1); } - public ConsumeItem item(Item item, int amount){ - ConsumeItem i = new ConsumeItem(item, amount); - add(i); - return i; + public ConsumeItems item(Item item, int amount){ + return add(new ConsumeItems(new ItemStack[]{new ItemStack(item, amount)})); } public ConsumeItems items(ItemStack... items){ - ConsumeItems i = new ConsumeItems(items); - add(i); - return i; + return add(new ConsumeItems(items)); } - public Item item(){ - return get(ConsumeItem.class).get(); - } - - public ItemStack[] items(){ - return get(ConsumeItems.class).getItems(); - } - - public int itemAmount(){ - return get(ConsumeItem.class).getAmount(); - } - - public Liquid liquid(){ - return get(ConsumeLiquid.class).get(); - } - - public float liquidAmount(){ - return get(ConsumeLiquid.class).use; - } - - public Consume add(Consume consume){ - map.put((consume instanceof ConsumePower ? ConsumePower.class : consume.getClass()), consume); + public T add(T consume){ + map[consume.type().ordinal()] = consume; return consume; } - public void remove(Class type){ - map.remove(type); + public void remove(ConsumeType type){ + map[type.ordinal()] = null; } - public boolean has(Class type){ - return map.containsKey(type); + public boolean has(ConsumeType type){ + return map[type.ordinal()] != null; } @SuppressWarnings("unchecked") - public T get(Class type){ - if(!map.containsKey(type)){ + public T get(ConsumeType type){ + if(map[type.ordinal()] == null){ throw new IllegalArgumentException("Block does not contain consumer of type '" + type + "'!"); } - return (T) map.get(type); + return (T)map[type.ordinal()]; } - public Iterable all(){ - return map.values(); - } - - public Array array(){ + public Consume[] all(){ return results; } - public boolean hasAny(){ - return map.size > 0; + public Consume[] optionals(){ + return optionalResults; } - public void forEach(Consumer cons){ - for(Consume c : all()){ - cons.accept(c); + public void display(BlockStats stats){ + for(Consume c : map){ + if(c != null){ + c.display(stats); + } } } } diff --git a/core/src/io/anuke/mindustry/world/meta/Attribute.java b/core/src/io/anuke/mindustry/world/meta/Attribute.java index 5f761f5359..0604adeba2 100644 --- a/core/src/io/anuke/mindustry/world/meta/Attribute.java +++ b/core/src/io/anuke/mindustry/world/meta/Attribute.java @@ -1,12 +1,12 @@ package io.anuke.mindustry.world.meta; public enum Attribute{ - /** Heat of this block. Used for calculating output of thermal generators.*/ + /** Heat of this block. Used for calculating output of thermal generators. */ heat, - /** Spore content of this block. Used for increasing cultivator yield.*/ + /** Spore content of this block. Used for increasing cultivator yield. */ spores, - /** Water content of this block. Used for increasing water extractor yield.*/ + /** Water content of this block. Used for increasing water extractor yield. */ water, - /** Oil content of this block. Used for increasing oil extractor yield.*/ + /** Oil content of this block. Used for increasing oil extractor yield. */ oil } diff --git a/core/src/io/anuke/mindustry/world/meta/BlockBars.java b/core/src/io/anuke/mindustry/world/meta/BlockBars.java index c47211181f..1e42281ba9 100644 --- a/core/src/io/anuke/mindustry/world/meta/BlockBars.java +++ b/core/src/io/anuke/mindustry/world/meta/BlockBars.java @@ -8,12 +8,13 @@ import io.anuke.mindustry.ui.Bar; public class BlockBars{ private OrderedMap> bars = new OrderedMap<>(); - public void add(String name,Function sup){ + public void add(String name, Function sup){ bars.put(name, sup); } public void remove(String name){ - if(!bars.containsKey(name)) throw new RuntimeException("No bar with name '" + name + "' found; current bars: " + bars.keys().toArray()); + if(!bars.containsKey(name)) + throw new RuntimeException("No bar with name '" + name + "' found; current bars: " + bars.keys().toArray()); bars.remove(name); } diff --git a/core/src/io/anuke/mindustry/world/meta/BlockFlag.java b/core/src/io/anuke/mindustry/world/meta/BlockFlag.java index b5c8339854..716c51d11f 100644 --- a/core/src/io/anuke/mindustry/world/meta/BlockFlag.java +++ b/core/src/io/anuke/mindustry/world/meta/BlockFlag.java @@ -1,13 +1,13 @@ package io.anuke.mindustry.world.meta; public enum BlockFlag{ - /**General important target for all types of units.*/ + /** General important target for all types of units. */ target(0), - /**Producer of important goods.*/ + /** Producer of important goods. */ producer(Float.MAX_VALUE), - /**A turret.*/ + /** A turret. */ turret(Float.MAX_VALUE), - /**Repair point.*/ + /** Repair point. */ repair(Float.MAX_VALUE); public final static BlockFlag[] all = values(); diff --git a/core/src/io/anuke/mindustry/world/meta/BlockStat.java b/core/src/io/anuke/mindustry/world/meta/BlockStat.java index 578339d3ce..705c19ac3c 100644 --- a/core/src/io/anuke/mindustry/world/meta/BlockStat.java +++ b/core/src/io/anuke/mindustry/world/meta/BlockStat.java @@ -4,43 +4,33 @@ import io.anuke.arc.Core; import java.util.Locale; -/**Describes one type of stat for a block.*/ +/** Describes one type of stat for a block. */ public enum BlockStat{ health(StatCategory.general), size(StatCategory.general), itemCapacity(StatCategory.items), - inputItemCapacity(StatCategory.items), - outputItemCapacity(StatCategory.items), itemsMoved(StatCategory.items), + launchTime(StatCategory.items), liquidCapacity(StatCategory.liquids), - liquidOutput(StatCategory.liquids), - liquidOutputSpeed(StatCategory.liquids), - coolant(StatCategory.liquids), - coolantUse(StatCategory.liquids), powerCapacity(StatCategory.power), powerUse(StatCategory.power), powerDamage(StatCategory.power), powerRange(StatCategory.power), - powerTransferSpeed(StatCategory.power), basePowerGeneration(StatCategory.power), - inputLiquidFuel(StatCategory.power), - liquidFuelUse(StatCategory.power), - inputLiquid(StatCategory.crafting), - liquidUse(StatCategory.crafting), - inputItem(StatCategory.crafting), - inputItems(StatCategory.crafting), - inputFuel(StatCategory.crafting), - fuelBurnTime(StatCategory.crafting), - craftSpeed(StatCategory.crafting), - outputItem(StatCategory.crafting), + input(StatCategory.crafting), + output(StatCategory.crafting), + productionTime(StatCategory.crafting), drillTier(StatCategory.crafting), drillSpeed(StatCategory.crafting), maxUnits(StatCategory.crafting), + speedIncrease(StatCategory.shooting), + repairTime(StatCategory.shooting), + range(StatCategory.shooting), shootRange(StatCategory.shooting), inaccuracy(StatCategory.shooting), shots(StatCategory.shooting), @@ -48,9 +38,10 @@ public enum BlockStat{ powerShot(StatCategory.shooting), targetsAir(StatCategory.shooting), targetsGround(StatCategory.shooting), + ammo(StatCategory.shooting), - boostItem(StatCategory.optional), - boostLiquid(StatCategory.optional),; + booster(StatCategory.optional), + boostEffect(StatCategory.optional); public final StatCategory category; diff --git a/core/src/io/anuke/mindustry/world/meta/BlockStats.java b/core/src/io/anuke/mindustry/world/meta/BlockStats.java index d094b16672..dbf3ea0afc 100644 --- a/core/src/io/anuke/mindustry/world/meta/BlockStats.java +++ b/core/src/io/anuke/mindustry/world/meta/BlockStats.java @@ -1,63 +1,58 @@ package io.anuke.mindustry.world.meta; +import io.anuke.arc.collection.Array; import io.anuke.arc.collection.ObjectMap.Entry; import io.anuke.arc.collection.OrderedMap; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.type.Liquid; +import io.anuke.mindustry.type.*; import io.anuke.mindustry.world.meta.values.*; -/**Hold and organizes a list of block stats.*/ +/** Hold and organizes a list of block stats. */ public class BlockStats{ - private final OrderedMap> map = new OrderedMap<>(); + private final OrderedMap>> map = new OrderedMap<>(); private boolean dirty; - /**Adds a single float value with this stat, formatted to 2 decimal places.*/ + /** Adds a single float value with this stat, formatted to 2 decimal places. */ public void add(BlockStat stat, float value, StatUnit unit){ add(stat, new NumberValue(value, unit)); } - /**Adds a single y/n boolean value.*/ + /** Adds a single y/n boolean value. */ public void add(BlockStat stat, boolean value){ add(stat, new BooleanValue(value)); } - /**Adds an item value.*/ + /** Adds an item value. */ public void add(BlockStat stat, Item item){ - add(stat, new ItemValue(new ItemStack(item, 1))); + add(stat, new ItemListValue(new ItemStack(item, 1))); } - /**Adds a liquid value.*/ - public void add(BlockStat stat, Liquid liquid){ - add(stat, new LiquidValue(liquid)); - } - - /**Adds an item value.*/ + /** Adds an item value. */ public void add(BlockStat stat, ItemStack item){ - add(stat, new ItemValue(item)); + add(stat, new ItemListValue(item)); } - /**Adds a single string value with this stat.*/ + /** Adds an item value. */ + public void add(BlockStat stat, Liquid liquid, float amount, boolean perSecond){ + add(stat, new LiquidValue(liquid, amount, perSecond)); + } + + /** Adds a single string value with this stat. */ public void add(BlockStat stat, String format, Object... args){ add(stat, new StringValue(format, args)); } - /**Adds a stat value.*/ + /** Adds a stat value. */ public void add(BlockStat stat, StatValue value){ - if(map.containsKey(stat.category) && map.get(stat.category).containsKey(stat)){ - throw new RuntimeException("Duplicate stat entry: \"" + stat + "\" in block."); - } - if(!map.containsKey(stat.category)){ map.put(stat.category, new OrderedMap<>()); } - map.get(stat.category).put(stat, value); + map.get(stat.category).getOr(stat, Array::new).add(value); dirty = true; } - /**Removes a stat, if it exists.*/ + /** Removes a stat, if it exists. */ public void remove(BlockStat stat){ if(!map.containsKey(stat.category) || !map.get(stat.category).containsKey(stat)){ throw new RuntimeException("No stat entry found: \"" + stat + "\" in block."); @@ -68,11 +63,11 @@ public class BlockStats{ dirty = true; } - public OrderedMap> toMap(){ + public OrderedMap>> toMap(){ //sort stats by index if they've been modified if(dirty){ map.orderedKeys().sort(); - for(Entry> entry : map.entries()){ + for(Entry>> entry : map.entries()){ entry.value.orderedKeys().sort(); } diff --git a/core/src/io/anuke/mindustry/world/meta/ContentStatValue.java b/core/src/io/anuke/mindustry/world/meta/ContentStatValue.java deleted file mode 100644 index 6a8375522e..0000000000 --- a/core/src/io/anuke/mindustry/world/meta/ContentStatValue.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.anuke.mindustry.world.meta; - -import io.anuke.mindustry.game.UnlockableContent; - -public interface ContentStatValue extends StatValue{ - UnlockableContent[] getValueContent(); -} diff --git a/core/src/io/anuke/mindustry/world/meta/StatCategory.java b/core/src/io/anuke/mindustry/world/meta/StatCategory.java index 0080d5daf5..5a498f0a45 100644 --- a/core/src/io/anuke/mindustry/world/meta/StatCategory.java +++ b/core/src/io/anuke/mindustry/world/meta/StatCategory.java @@ -1,6 +1,6 @@ package io.anuke.mindustry.world.meta; -/**A specific category for a stat.*/ +/** A specific category for a stat. */ public enum StatCategory{ general, power, diff --git a/core/src/io/anuke/mindustry/world/meta/StatUnit.java b/core/src/io/anuke/mindustry/world/meta/StatUnit.java index 5dc4e2d2f2..3b22ad68a5 100644 --- a/core/src/io/anuke/mindustry/world/meta/StatUnit.java +++ b/core/src/io/anuke/mindustry/world/meta/StatUnit.java @@ -16,9 +16,22 @@ public enum StatUnit{ powerUnits, degrees, seconds, + perSecond, + timesSpeed(false), + percent(false), none, items; + public final boolean space; + + StatUnit(boolean space){ + this.space = space; + } + + StatUnit(){ + this(true); + } + public String localized(){ if(this == none) return ""; return Core.bundle.get("unit." + name().toLowerCase(Locale.ROOT)); diff --git a/core/src/io/anuke/mindustry/world/meta/values/AmmoListValue.java b/core/src/io/anuke/mindustry/world/meta/values/AmmoListValue.java new file mode 100644 index 0000000000..5b05b47881 --- /dev/null +++ b/core/src/io/anuke/mindustry/world/meta/values/AmmoListValue.java @@ -0,0 +1,92 @@ +package io.anuke.mindustry.world.meta.values; + +import io.anuke.arc.Core; +import io.anuke.arc.collection.ObjectMap; +import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.arc.util.Strings; +import io.anuke.mindustry.content.StatusEffects; +import io.anuke.mindustry.entities.bullet.BulletType; +import io.anuke.mindustry.game.UnlockableContent; +import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.Item.Icon; +import io.anuke.mindustry.world.meta.StatValue; + +import static io.anuke.mindustry.Vars.tilesize; + +public class AmmoListValue implements StatValue{ + private final ObjectMap map; + + public AmmoListValue(ObjectMap map){ + this.map = map; + } + + @Override + public void display(Table table){ + + table.row(); + for(T t : map.keys()){ + BulletType type = map.get(t); + table.addImage(icon(t)).size(3 * 8).padRight(4).right().top(); + table.add(t.localizedName()).padRight(10).left().top(); + table.table("underline", bt -> { + bt.left().defaults().padRight(3).left(); + + if(type.damage > 0){ + bt.add(Core.bundle.format("bullet.damage", type.damage)); + } + + if(type.splashDamage > 0){ + sep(bt, Core.bundle.format("bullet.splashdamage", (int)type.splashDamage, Strings.fixed(type.splashDamageRadius / tilesize, 1))); + } + + if(!Mathf.isEqual(type.ammoMultiplier, 1f)) + sep(bt, Core.bundle.format("bullet.multiplier", (int)type.ammoMultiplier)); + if(!Mathf.isEqual(type.reloadMultiplier, 1f)) + sep(bt, Core.bundle.format("bullet.reload", Strings.fixed(type.reloadMultiplier, 1))); + + if(type.knockback > 0){ + sep(bt, Core.bundle.format("bullet.knockback", Strings.fixed(type.knockback, 1))); + } + + if((type.status == StatusEffects.burning || type.status == StatusEffects.melting) || type.incendAmount > 0){ + sep(bt, "$bullet.incendiary"); + } + + if(type.status == StatusEffects.freezing){ + sep(bt, "$bullet.freezing"); + } + + if(type.status == StatusEffects.tarred){ + sep(bt, "$bullet.tarred"); + } + + if(type.homingPower > 0.01f){ + sep(bt, "$bullet.homing"); + } + + if(type.lightining > 0){ + sep(bt, "$bullet.shock"); + } + + if(type.fragBullet != null){ + sep(bt, "$bullet.frag"); + } + }).left().padTop(-9); + table.row(); + } + } + + void sep(Table table, String text){ + table.row(); + table.add(text); + } + + TextureRegion icon(T t){ + if(t instanceof Item){ + return ((Item)t).icon(Icon.medium); + } + return t.getContentIcon(); + } +} diff --git a/core/src/io/anuke/mindustry/world/meta/values/BooleanValue.java b/core/src/io/anuke/mindustry/world/meta/values/BooleanValue.java index 4d8e144590..49e2967e7e 100644 --- a/core/src/io/anuke/mindustry/world/meta/values/BooleanValue.java +++ b/core/src/io/anuke/mindustry/world/meta/values/BooleanValue.java @@ -1,7 +1,7 @@ package io.anuke.mindustry.world.meta.values; -import io.anuke.mindustry.world.meta.StatValue; import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.world.meta.StatValue; public class BooleanValue implements StatValue{ private final boolean value; diff --git a/core/src/io/anuke/mindustry/world/meta/values/ItemListValue.java b/core/src/io/anuke/mindustry/world/meta/values/ItemListValue.java index a316eb26a7..494be7285c 100644 --- a/core/src/io/anuke/mindustry/world/meta/values/ItemListValue.java +++ b/core/src/io/anuke/mindustry/world/meta/values/ItemListValue.java @@ -1,49 +1,21 @@ package io.anuke.mindustry.world.meta.values; -import io.anuke.mindustry.game.UnlockableContent; -import io.anuke.mindustry.type.Item; +import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.ui.ItemDisplay; -import io.anuke.mindustry.world.meta.ContentStatValue; -import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.world.meta.StatValue; -public class ItemListValue implements ContentStatValue{ - private final Item[] items; +public class ItemListValue implements StatValue{ private final ItemStack[] stacks; - public ItemListValue(Item[] items){ - this.items = items; - this.stacks = null; - } - - public ItemListValue(ItemStack[] stacks){ + public ItemListValue(ItemStack... stacks){ this.stacks = stacks; - this.items = null; - } - - @Override - public UnlockableContent[] getValueContent(){ - if(items != null){ - return items; - }else{ - Item[] res = new Item[stacks.length]; - for(int i = 0; i < res.length; i++){ - res[i] = stacks[i].item; - } - return res; - } } @Override public void display(Table table){ - if(items != null){ - for(Item item : items){ - table.add(new ItemDisplay(item)).padRight(5); - } - }else{ - for(ItemStack stack : stacks){ - table.add(new ItemDisplay(stack.item, stack.amount)).padRight(5); - } + for(ItemStack stack : stacks){ + table.add(new ItemDisplay(stack.item, stack.amount)).padRight(5); } } } diff --git a/core/src/io/anuke/mindustry/world/meta/values/ItemValue.java b/core/src/io/anuke/mindustry/world/meta/values/ItemValue.java deleted file mode 100644 index 97d10985da..0000000000 --- a/core/src/io/anuke/mindustry/world/meta/values/ItemValue.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.anuke.mindustry.world.meta.values; - -import io.anuke.mindustry.game.UnlockableContent; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.ui.ItemDisplay; -import io.anuke.mindustry.world.meta.ContentStatValue; -import io.anuke.arc.scene.ui.layout.Table; - -public class ItemValue implements ContentStatValue{ - private final ItemStack item; - - public ItemValue(ItemStack item){ - this.item = item; - } - - @Override - public UnlockableContent[] getValueContent(){ - return new Item[]{item.item}; - } - - @Override - public void display(Table table){ - table.add(new ItemDisplay(item.item, item.amount)); - } -} diff --git a/core/src/io/anuke/mindustry/world/meta/values/LiquidFilterValue.java b/core/src/io/anuke/mindustry/world/meta/values/LiquidFilterValue.java index 7d34d5049d..e30c2b0ba5 100644 --- a/core/src/io/anuke/mindustry/world/meta/values/LiquidFilterValue.java +++ b/core/src/io/anuke/mindustry/world/meta/values/LiquidFilterValue.java @@ -1,19 +1,23 @@ package io.anuke.mindustry.world.meta.values; import io.anuke.arc.collection.Array; +import io.anuke.arc.function.Predicate; +import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.ui.LiquidDisplay; import io.anuke.mindustry.world.meta.StatValue; -import io.anuke.arc.function.Predicate; -import io.anuke.arc.scene.ui.layout.Table; import static io.anuke.mindustry.Vars.content; public class LiquidFilterValue implements StatValue{ private final Predicate filter; + private final float amount; + private final boolean perSecond; - public LiquidFilterValue(Predicate filter){ + public LiquidFilterValue(Predicate filter, float amount, boolean perSecond){ this.filter = filter; + this.amount = amount; + this.perSecond = perSecond; } @Override @@ -25,7 +29,7 @@ public class LiquidFilterValue implements StatValue{ } for(int i = 0; i < list.size; i++){ - table.add(new LiquidDisplay(list.get(i))).padRight(5); + table.add(new LiquidDisplay(list.get(i), amount, perSecond)).padRight(5); if(i != list.size - 1){ table.add("/"); diff --git a/core/src/io/anuke/mindustry/world/meta/values/LiquidValue.java b/core/src/io/anuke/mindustry/world/meta/values/LiquidValue.java index cd2bd85b6e..be6eabc3f1 100644 --- a/core/src/io/anuke/mindustry/world/meta/values/LiquidValue.java +++ b/core/src/io/anuke/mindustry/world/meta/values/LiquidValue.java @@ -1,25 +1,23 @@ package io.anuke.mindustry.world.meta.values; -import io.anuke.mindustry.game.UnlockableContent; +import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.ui.LiquidDisplay; -import io.anuke.mindustry.world.meta.ContentStatValue; -import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.world.meta.StatValue; -public class LiquidValue implements ContentStatValue{ +public class LiquidValue implements StatValue{ private final Liquid liquid; + private final float amount; + private final boolean perSecond; - public LiquidValue(Liquid liquid){ + public LiquidValue(Liquid liquid, float amount, boolean perSecond){ this.liquid = liquid; - } - - @Override - public UnlockableContent[] getValueContent(){ - return new UnlockableContent[]{liquid}; + this.amount = amount; + this.perSecond = perSecond; } @Override public void display(Table table){ - table.add(new LiquidDisplay(liquid)); + table.add(new LiquidDisplay(liquid, amount, perSecond)); } } diff --git a/core/src/io/anuke/mindustry/world/meta/values/NumberValue.java b/core/src/io/anuke/mindustry/world/meta/values/NumberValue.java index 620bfc1186..11080bc7b3 100644 --- a/core/src/io/anuke/mindustry/world/meta/values/NumberValue.java +++ b/core/src/io/anuke/mindustry/world/meta/values/NumberValue.java @@ -1,9 +1,9 @@ package io.anuke.mindustry.world.meta.values; -import io.anuke.mindustry.world.meta.StatUnit; -import io.anuke.mindustry.world.meta.StatValue; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.util.Strings; +import io.anuke.mindustry.world.meta.StatUnit; +import io.anuke.mindustry.world.meta.StatValue; /** * A stat that is a number with a unit attacked. @@ -20,10 +20,9 @@ public class NumberValue implements StatValue{ @Override public void display(Table table){ - float diff = Math.abs((int) value - value); - int precision = diff <= 0.01f ? 0 : diff <= 0.1f ? 1 : 2; + int precision = Math.abs((int)value - value) <= 0.001f ? 0 : Math.abs((int)(value * 10) - value * 10) <= 0.001f ? 1 : 2; - table.add(Strings.toFixed(value, precision)); - table.add(" " + unit.localized()); + table.add(Strings.fixed(value, precision)); + table.add((unit.space ? " " : "") + unit.localized()); } } diff --git a/core/src/io/anuke/mindustry/world/meta/values/StringValue.java b/core/src/io/anuke/mindustry/world/meta/values/StringValue.java index 830d897ab6..1b90d6b2ca 100644 --- a/core/src/io/anuke/mindustry/world/meta/values/StringValue.java +++ b/core/src/io/anuke/mindustry/world/meta/values/StringValue.java @@ -1,8 +1,8 @@ package io.anuke.mindustry.world.meta.values; -import io.anuke.mindustry.world.meta.StatValue; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.util.Strings; +import io.anuke.mindustry.world.meta.StatValue; public class StringValue implements StatValue{ private final String value; diff --git a/core/src/io/anuke/mindustry/world/modules/BlockModule.java b/core/src/io/anuke/mindustry/world/modules/BlockModule.java index 3d3e003b4e..377ba9c099 100644 --- a/core/src/io/anuke/mindustry/world/modules/BlockModule.java +++ b/core/src/io/anuke/mindustry/world/modules/BlockModule.java @@ -1,11 +1,10 @@ package io.anuke.mindustry.world.modules; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; -/**A class that represents compartmentalized tile entity state.*/ +/** A class that represents compartmentalized tile entity state. */ public abstract class BlockModule{ public abstract void write(DataOutput stream) throws IOException; + public abstract void read(DataInput stream) throws IOException; } diff --git a/core/src/io/anuke/mindustry/world/modules/ConsumeModule.java b/core/src/io/anuke/mindustry/world/modules/ConsumeModule.java index f2daa58255..c7a3c09b17 100644 --- a/core/src/io/anuke/mindustry/world/modules/ConsumeModule.java +++ b/core/src/io/anuke/mindustry/world/modules/ConsumeModule.java @@ -3,12 +3,10 @@ package io.anuke.mindustry.world.modules; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.world.consumers.Consume; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; public class ConsumeModule extends BlockModule{ - private boolean valid; + private boolean valid, optionalValid; private final TileEntity entity; public ConsumeModule(TileEntity entity){ @@ -18,27 +16,40 @@ public class ConsumeModule extends BlockModule{ public void update(){ boolean prevValid = valid(); valid = true; - boolean docons = entity.tile.block().shouldConsume(entity.tile); + optionalValid = true; + boolean docons = entity.block.shouldConsume(entity.tile); - for(Consume cons : entity.tile.block().consumes.all()){ - if(docons && cons.isUpdate() && prevValid && cons.valid(entity.getTile().block(), entity)){ - cons.update(entity.getTile().block(), entity); + for(Consume cons : entity.block.consumes.all()){ + if(cons.isOptional()) continue; + + if(docons && cons.isUpdate() && prevValid && cons.valid(entity)){ + cons.update(entity); } - if(!cons.isOptional()){ - valid &= cons.valid(entity.getTile().block(), entity); + valid &= cons.valid(entity); + } + + for(Consume cons : entity.block.consumes.optionals()){ + if(docons && cons.isUpdate() && prevValid && cons.valid(entity)){ + cons.update(entity); } + + optionalValid &= cons.valid(entity); } } public void trigger(){ - for(Consume cons : entity.tile.block().consumes.all()){ - cons.trigger(entity.tile.block(), entity); + for(Consume cons : entity.block.consumes.all()){ + cons.trigger(entity); } } public boolean valid(){ - return valid && entity.tile.block().canProduce(entity.tile); + return valid && entity.block.canProduce(entity.tile); + } + + public boolean optionalValid(){ + return valid() && optionalValid; } @Override diff --git a/core/src/io/anuke/mindustry/world/modules/ItemModule.java b/core/src/io/anuke/mindustry/world/modules/ItemModule.java index ece14fbe82..7e146d8ab0 100644 --- a/core/src/io/anuke/mindustry/world/modules/ItemModule.java +++ b/core/src/io/anuke/mindustry/world/modules/ItemModule.java @@ -3,19 +3,14 @@ package io.anuke.mindustry.world.modules; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemStack; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; import java.util.Arrays; import static io.anuke.mindustry.Vars.content; public class ItemModule extends BlockModule{ - private static int lastID; - private int[] items = new int[content.items().size]; private int total; - private int id = lastID ++; public void forEach(ItemConsumer cons){ for(int i = 0; i < items.length; i++){ @@ -50,6 +45,13 @@ public class ItemModule extends BlockModule{ return true; } + public boolean has(ItemStack[] stacks, float multiplier){ + for(ItemStack stack : stacks){ + if(!has(stack.item, Math.round(stack.amount * multiplier))) return false; + } + return true; + } + /** * Returns true if this entity has at least one of each item in each stack. */ @@ -91,8 +93,8 @@ public class ItemModule extends BlockModule{ public void addAll(ItemModule items){ for(int i = 0; i < items.items.length; i++){ - this.items[i] += items.items[i]; - total += items.items[i]; + this.items[i] += items.items[i]; + total += items.items[i]; } } @@ -114,8 +116,6 @@ public class ItemModule extends BlockModule{ @Override public void write(DataOutput stream) throws IOException{ - stream.writeInt(id); //unique ID - byte amount = 0; for(int item : items){ if(item > 0) amount++; @@ -133,7 +133,8 @@ public class ItemModule extends BlockModule{ @Override public void read(DataInput stream) throws IOException{ - id = stream.readInt(); + //just in case, reset items + Arrays.fill(items, 0); byte count = stream.readByte(); total = 0; @@ -145,14 +146,6 @@ public class ItemModule extends BlockModule{ } } - public int getID(){ - return id; - } - - public void setID(int id){ - this.id = id; - } - public interface ItemConsumer{ void accept(Item item, float amount); } diff --git a/core/src/io/anuke/mindustry/world/modules/LiquidModule.java b/core/src/io/anuke/mindustry/world/modules/LiquidModule.java index d963b9328f..33b02b85a7 100644 --- a/core/src/io/anuke/mindustry/world/modules/LiquidModule.java +++ b/core/src/io/anuke/mindustry/world/modules/LiquidModule.java @@ -2,9 +2,8 @@ package io.anuke.mindustry.world.modules; import io.anuke.mindustry.type.Liquid; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; + import static io.anuke.mindustry.Vars.content; public class LiquidModule extends BlockModule{ @@ -12,12 +11,12 @@ public class LiquidModule extends BlockModule{ private float total; private Liquid current = content.liquid(0); - /**Returns total amount of liquids.*/ + /** Returns total amount of liquids. */ public float total(){ return total; } - /**Last recieved or loaded liquid. Only valid for liquid modules with 1 type of liquid.*/ + /** Last recieved or loaded liquid. Only valid for liquid modules with 1 type of liquid. */ public Liquid current(){ return current; } diff --git a/core/src/io/anuke/mindustry/world/modules/PowerModule.java b/core/src/io/anuke/mindustry/world/modules/PowerModule.java index 265724c974..a51e469064 100644 --- a/core/src/io/anuke/mindustry/world/modules/PowerModule.java +++ b/core/src/io/anuke/mindustry/world/modules/PowerModule.java @@ -1,21 +1,22 @@ package io.anuke.mindustry.world.modules; +import io.anuke.annotations.Annotations.NonNull; import io.anuke.arc.collection.IntArray; import io.anuke.mindustry.world.blocks.power.PowerGraph; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; +import java.io.*; public class PowerModule extends BlockModule{ - /** In case of unbuffered consumers, this is the percentage (1.0f = 100%) of the demanded power which can be supplied. - * Blocks will work at a reduced efficiency if this is not equal to 1.0f. - * In case of buffered consumers, this is the percentage of power stored in relation to the maximum capacity. + /** + * In case of unbuffered consumers, this is the percentage (1.0f = 100%) of the demanded power which can be supplied. + * Blocks will work at a reduced efficiency if this is not equal to 1.0f. + * In case of buffered consumers, this is the percentage of power stored in relation to the maximum capacity. */ public float satisfaction = 0.0f; /** Specifies power which is required additionally, e.g. while a force projector is being shot at. */ public float extraUse = 0f; - public PowerGraph graph = new PowerGraph(); + public @NonNull + PowerGraph graph = new PowerGraph(); public IntArray links = new IntArray(); @Override diff --git a/desktop/build.gradle b/desktop/build.gradle index 48aa4e3236..641a72cb01 100644 --- a/desktop/build.gradle +++ b/desktop/build.gradle @@ -6,8 +6,9 @@ sourceSets.main.java.srcDirs = ["src/"] project.ext.mainClassName = "io.anuke.mindustry.desktop.DesktopLauncher" project.ext.assetsDir = new File("../core/assets") -import com.badlogicgames.packr.PackrConfig + 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") @@ -83,6 +84,8 @@ task packrCmd(){ outDir = file("packr-out/") mainClass = project.ext.mainClassName classpath = ["desktop/build/libs/desktop-release.jar"] + removePlatformLibs = ["desktop/build/libs/desktop-release.jar"] + vmArgs = ["Djava.net.preferIPv4Stack=true"] minimizeJre = "desktop/packr_minimize.json" jdk = JDK_DIR + "jdk-${getPlatform().toString().toLowerCase()}.zip" @@ -96,6 +99,20 @@ task packrCmd(){ } } +task copyTemplate(){ + doLast{ + copy{ + into "packr-out/" + from "${JDK_DIR}/templates/${getPlatform().toString().toLowerCase()}" + } + + copy{ + into "packr-out/" + from "build/libs/desktop-release.jar" + } + } +} + task packrZip(){ task clearOut(type: Delete){ doLast{ @@ -130,18 +147,23 @@ task packrZip(){ } } } - - dependsOn "packrCmd" + finalizedBy "clearOut" if(project.hasProperty("platform")){ + def plat = getPlatform() + if(plat == PackrConfig.Platform.Windows32 || plat == PackrConfig.Platform.Windows64){ + dependsOn "copyTemplate" + }else{ + dependsOn "packrCmd" - if(getPlatform() == "mac"){ - dependsOn "fixMac" - } + if(getPlatform() == PackrConfig.Platform.MacOS){ + dependsOn "fixMac" + } - if(getPlatform() == "windows32"){ - dependsOn "fixWindows32" + if(getPlatform() == PackrConfig.Platform.Windows32){ + dependsOn "fixWindows32" + } } task rzip(type: Zip){ diff --git a/desktop/packr_minimize.json b/desktop/packr_minimize.json index 0887fdf720..8be61942cc 100644 --- a/desktop/packr_minimize.json +++ b/desktop/packr_minimize.json @@ -3,35 +3,40 @@ { "archive": "jre/lib/rt.jar", "paths": [ - - "javax/transaction", - "javax/tools", - "javax/swing", - "javax/sql", - "javax/smartcardio", - "javax/rmi", - "javax/print", - "javax/naming", - "javax/management", - "javax/lang", - "javax/jws", - "javax/swing", - "javax/imageio", - "javax/annotation", - "javax/activity", - "javax/activation", - "javax/accessibility", + "javax/transaction", + "javax/tools", + "javax/swing", + "javax/sql", + "javax/smartcardio", + "javax/rmi", + "javax/print", + "javax/naming", + "javax/management", + "javax/lang", + "javax/jws", + "javax/swing", + "javax/imageio", + "javax/annotation", + "javax/activity", + "javax/activation", + "javax/accessibility", "com/sun/corba", "com/sun/jmx", + "com/sun/org", + "com/sun/imageio", "com/sun/jndi", "com/sun/xml", "com/sun/script", + "sum/awt", + "sun/java2d", + "sun/font", + "sun/rmi", + "sun/swing", + "java/util/stream", "com/sun/media", "com/sun/naming", "java/awt", - - "com/sun/org/apache/xpath", - + "com/sun/org/apache/xpath", "com/sun/rowset", "com/sun/script", "sun/applet", @@ -67,7 +72,35 @@ "paths": [ "jre/lib/amd64/libawt.so", "jre/lib/amd64/libawt_xawt.so", - "jre/lib/amd64/libjawt.so" + "jre/lib/amd64/libjawt.so", + "jre/lib/amd64/libhprof.so", + "jre/lib/amd64/libdt_socket.so", + "jre/lib/amd64/libsplashscreen.so", + "jre/lib/amd64/libunpack.so", + "jre/lib/amd64/liblcms.so", + "jre/lib/amd64/libnpt.so", + "jre/lib/amd64/libmlib_image.so", + "jre/lib/amd64/libjsig.so", + "jre/lib/amd64/libinstrument.so", + "jre/lib/amd64/libjaas_unix.so", + "jre/lib/amd64/libj2pcsc.so", + "jre/lib/amd64/libsaproc.so", + "jre/lib/amd64/libsunec.so", + "jre/lib/amd64/libj2pkcs11.so", + "jre/lib/amd64/libjsdt.so", + "jre/lib/amd64/libjdwp.so", + "jre/lib/amd64/libjava_crw_demo.so", + "jre/lib/amd64/libfreetype.so", + "jre/lib/amd64/libmanagement.so", + "jre/lib/amd64/libsctp.so", + "jre/lib/amd64/libj2gss.so", + "jre/lib/amd64/libjpeg.so", + "jre/lib/amd64/libfreetype.so.6", + "jre/lib/amd64/libjsoundalsa.so", + "jre/lib/amd64/libjsound.so", + "jre/lib/amd64/libattach.so", + "jre/lib/amd64/libawt_headless.so", + "jre/lib/amd64/libfontmanager.so" ] }, { diff --git a/desktop/src/io/anuke/mindustry/desktop/CrashHandler.java b/desktop/src/io/anuke/mindustry/desktop/CrashHandler.java index 1de445dfc3..24a0fa4529 100644 --- a/desktop/src/io/anuke/mindustry/desktop/CrashHandler.java +++ b/desktop/src/io/anuke/mindustry/desktop/CrashHandler.java @@ -1,8 +1,9 @@ package io.anuke.mindustry.desktop; import io.anuke.arc.Core; -import io.anuke.arc.util.Log; -import io.anuke.arc.util.OS; +import io.anuke.arc.collection.ObjectMap; +import io.anuke.arc.util.*; +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; @@ -11,11 +12,8 @@ import io.anuke.mindustry.game.Version; import io.anuke.mindustry.net.Net; import org.lwjgl.util.tinyfd.TinyFileDialogs; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; +import java.io.*; +import java.nio.file.*; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @@ -23,6 +21,25 @@ public class CrashHandler{ public static void handle(Throwable e){ e.printStackTrace(); + if(Version.number == 0){ + try{ + ObjectMap map = new ObjectMap<>(); + PropertiesUtils.load(map, new InputStreamReader(CrashHandler.class.getResourceAsStream("/version.properties"))); + + Version.type = map.get("type"); + Version.number = Integer.parseInt(map.get("number")); + Version.modifier = map.get("modifier"); + if(map.get("build").contains(".")){ + String[] split = map.get("build").split("\\."); + Version.build = Integer.parseInt(split[0]); + Version.revision = Integer.parseInt(split[1]); + }else{ + Version.build = Strings.canParseInt(map.get("build")) ? Integer.parseInt(map.get("build")) : -1; + } + }catch(Throwable ignored){ + + } + } try{ //check crash report setting @@ -37,9 +54,11 @@ public class CrashHandler{ if(e.getMessage() != null && (e.getMessage().contains("Couldn't create window") || e.getMessage().contains("OpenGL 2.0 or higher"))){ - dialog(() -> TinyFileDialogs.tinyfd_messageBox("oh no", "Your graphics card does not support OpenGL 2.0!\n" + - "Try to update your graphics drivers.\n\n" + - "(If that doesn't work, your computer just doesn't support Mindustry.)", "ok", "error", true)); + dialog(() -> 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." : + "Your graphics card does not support OpenGL 2.0!\n" + + "Try to update your graphics drivers.\n\n" + + "(If that doesn't work, your computer just doesn't support Mindustry.)", "ok", "error", true)); badGPU = true; } @@ -74,12 +93,12 @@ public class CrashHandler{ try{ Path path = Paths.get(OS.getAppDataDirectoryString(Vars.appName), "crashes", - "crash-report-" + DateTimeFormatter.ofPattern("MM_dd_yyyy_HH_mm_ss").format(LocalDateTime.now()) + ".txt"); + "crash-report-" + DateTimeFormatter.ofPattern("MM_dd_yyyy_HH_mm_ss").format(LocalDateTime.now()) + ".txt"); Files.createDirectories(Paths.get(OS.getAppDataDirectoryString(Vars.appName), "crashes")); Files.write(path, parseException(e).getBytes()); if(!badGPU){ - dialog(() -> TinyFileDialogs.tinyfd_messageBox("oh no", "A crash has occured. It has been saved in:\n" + path.toAbsolutePath().toString(), "ok", "error", true)); + dialog(() -> TinyFileDialogs.tinyfd_messageBox("oh no", "A crash has occured. It has been saved in:\n" + path.toAbsolutePath().toString(), "ok", "error", true)); } }catch(Throwable t){ Log.err("Failed to save local crash report."); @@ -97,7 +116,10 @@ public class CrashHandler{ }); //sleep for 10 seconds or until crash report is sent - try{ Thread.sleep(10000); }catch(InterruptedException ignored){} + try{ + Thread.sleep(10000); + }catch(InterruptedException ignored){ + } } private static void dialog(Runnable r){ diff --git a/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java b/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java index 028218e723..3ebae9529f 100644 --- a/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java +++ b/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java @@ -1,9 +1,13 @@ package io.anuke.mindustry.desktop; import io.anuke.arc.ApplicationListener; +import io.anuke.arc.Settings; import io.anuke.arc.backends.lwjgl3.Lwjgl3Application; import io.anuke.arc.backends.lwjgl3.Lwjgl3ApplicationConfiguration; +import io.anuke.arc.files.FileHandle; +import io.anuke.arc.util.OS; import io.anuke.mindustry.Mindustry; +import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.net.Net; import io.anuke.net.KryoClient; @@ -24,6 +28,21 @@ public class DesktopLauncher extends Lwjgl3Application{ config.setWindowedMode(960, 540); config.setWindowIcon("sprites/icon.png"); + try{ + Settings settings = new Settings(){ + @Override + public FileHandle getDataDirectory(){ + return dataDirectory == null ? new FileHandle(OS.getAppDataDirectoryString(appName)) : dataDirectory; + } + }; + settings.setAppName(Vars.appName); + settings.loadValues(); + int level = settings.getInt("antialias", 0); + config.setBackBufferConfig(8, 8, 8, 8, 0, 0, level == 0 ? 0 : 1 << level); + }catch(Throwable t){ + t.printStackTrace(); + } + Platform.instance = new DesktopPlatform(arg); Net.setClientProvider(new KryoClient()); diff --git a/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java b/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java index b1b855d048..8c4559ea60 100644 --- a/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java +++ b/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java @@ -1,8 +1,6 @@ package io.anuke.mindustry.desktop; -import club.minnced.discord.rpc.DiscordEventHandlers; -import club.minnced.discord.rpc.DiscordRPC; -import club.minnced.discord.rpc.DiscordRichPresence; +import club.minnced.discord.rpc.*; import io.anuke.arc.collection.Array; import io.anuke.arc.files.FileHandle; import io.anuke.arc.function.Consumer; @@ -60,11 +58,11 @@ public class DesktopPlatform extends Platform{ presence.largeImageText = "Wave " + state.wave; } - presence.state = unitGroups[players[0].getTeam().ordinal()].size() == 1 ? "1 Unit Active" : - (unitGroups[players[0].getTeam().ordinal()].size() + " Units Active"); + presence.state = unitGroups[player.getTeam().ordinal()].size() == 1 ? "1 Unit Active" : + (unitGroups[player.getTeam().ordinal()].size() + " Units Active"); if(Net.active()){ - presence.partyMax = 16; + presence.partyMax = 100; presence.partySize = playerGroup.size(); } }else{ @@ -85,7 +83,7 @@ public class DesktopPlatform extends Platform{ try{ Enumeration e = NetworkInterface.getNetworkInterfaces(); NetworkInterface out; - for(out = e.nextElement(); (out.getHardwareAddress() == null || !validAddress(out.getHardwareAddress())) && e.hasMoreElements(); out = e.nextElement()) ; + for(out = e.nextElement(); (out.getHardwareAddress() == null || !validAddress(out.getHardwareAddress())) && e.hasMoreElements(); out = e.nextElement()); byte[] bytes = out.getHardwareAddress(); byte[] result = new byte[8]; diff --git a/gradle.properties b/gradle.properties index e08bde78fc..28fb6f7a7c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,3 @@ org.gradle.daemon=true -org.gradle.jvmargs=-Xms512m -Xmx1536m -android.injected.build.model.only.versioned=3 +org.gradle.jvmargs=-Xms256m -Xmx1024m android.enableD8=true \ No newline at end of file diff --git a/ios/build.gradle b/ios/build.gradle index d0bfc1752f..4859a5c758 100644 --- a/ios/build.gradle +++ b/ios/build.gradle @@ -1,10 +1,10 @@ -sourceSets.main.java.srcDirs = [ "src/" ] +sourceSets.main.java.srcDirs = ["src/"] sourceCompatibility = '1.8' [compileJava, compileTestJava]*.options*.encoding = 'UTF-8' -ext { - mainClassName = "io.anuke.mindustry.IOSLauncher" +ext{ + mainClassName = "io.anuke.mindustry.IOSLauncher" } launchIPhoneSimulator.dependsOn build @@ -12,6 +12,6 @@ launchIPadSimulator.dependsOn build launchIOSDevice.dependsOn build createIPA.dependsOn build -robovm { - archs = "thumbv7:arm64" +robovm{ + archs = "thumbv7:arm64" } \ No newline at end of file diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/data/Assets.xcassets/AppIcon.appiconset/Contents.json index fdea475930..2210d686de 100644 --- a/ios/data/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/ios/data/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,116 +1,116 @@ { - "images" : [ + "images": [ { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "icon-40.png", - "scale" : "2x" + "size": "20x20", + "idiom": "iphone", + "filename": "icon-40.png", + "scale": "2x" }, { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "icon-60.png", - "scale" : "3x" + "size": "20x20", + "idiom": "iphone", + "filename": "icon-60.png", + "scale": "3x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "icon.png", - "scale" : "2x" + "size": "29x29", + "idiom": "iphone", + "filename": "icon-58.png", + "scale": "2x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "icon-87.png", - "scale" : "3x" + "size": "29x29", + "idiom": "iphone", + "filename": "icon-87.png", + "scale": "3x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "icon-80.png", - "scale" : "2x" + "size": "40x40", + "idiom": "iphone", + "filename": "icon-80.png", + "scale": "2x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "icon-121.png", - "scale" : "3x" + "size": "40x40", + "idiom": "iphone", + "filename": "icon-120.png", + "scale": "3x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon-120.png", - "scale" : "2x" + "size": "60x60", + "idiom": "iphone", + "filename": "icon-120.png", + "scale": "2x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon-180.png", - "scale" : "3x" + "size": "60x60", + "idiom": "iphone", + "filename": "icon-180.png", + "scale": "3x" }, { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "icon-20.png", - "scale" : "1x" + "size": "20x20", + "idiom": "ipad", + "filename": "icon-20.png", + "scale": "1x" }, { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "icon-42.png", - "scale" : "2x" + "size": "20x20", + "idiom": "ipad", + "filename": "icon-40.png", + "scale": "2x" }, { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "icon-29.png", - "scale" : "1x" + "size": "29x29", + "idiom": "ipad", + "filename": "icon-29.png", + "scale": "1x" }, { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "icon-58.png", - "scale" : "2x" + "size": "29x29", + "idiom": "ipad", + "filename": "icon-58.png", + "scale": "2x" }, { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "icon-41.png", - "scale" : "1x" + "size": "40x40", + "idiom": "ipad", + "filename": "icon-40.png", + "scale": "1x" }, { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "icon-81.png", - "scale" : "2x" + "size": "40x40", + "idiom": "ipad", + "filename": "icon-80.png", + "scale": "2x" }, { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon-77.png", - "scale" : "1x" + "size": "76x76", + "idiom": "ipad", + "filename": "icon-76.png", + "scale": "1x" }, { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon-152.png", - "scale" : "2x" + "size": "76x76", + "idiom": "ipad", + "filename": "icon-152.png", + "scale": "2x" }, { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "icon-167.png", - "scale" : "2x" + "size": "83.5x83.5", + "idiom": "ipad", + "filename": "icon-167.png", + "scale": "2x" }, { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "icon-main.png", - "scale" : "1x" + "size": "1024x1024", + "idiom": "ios-marketing", + "filename": "icon-main.png", + "scale": "1x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } \ No newline at end of file diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-100.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-100.png new file mode 100644 index 0000000000..778158f1a2 Binary files /dev/null and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-100.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-114.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-114.png new file mode 100644 index 0000000000..29db05c2f7 Binary files /dev/null and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-114.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-120.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-120.png index 702df2c000..28ce08fa07 100644 Binary files a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-120.png and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-120.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-121.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-121.png deleted file mode 100644 index 702df2c000..0000000000 Binary files a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-121.png and /dev/null differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-128.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-128.png new file mode 100644 index 0000000000..cbf7402fc9 Binary files /dev/null and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-128.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-144.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-144.png new file mode 100644 index 0000000000..92b596b098 Binary files /dev/null and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-144.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-152.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-152.png index 5e52f828bd..2c65bbbe6c 100644 Binary files a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-152.png and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-152.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-16.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-16.png new file mode 100644 index 0000000000..cf8c679245 Binary files /dev/null and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-16.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-167.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-167.png index 852382d2d4..babd1dc34b 100644 Binary files a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-167.png and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-167.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-172.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-172.png new file mode 100644 index 0000000000..3c54d648b0 Binary files /dev/null and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-172.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-180.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-180.png index f41b36ab77..047a0fb8f1 100644 Binary files a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-180.png and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-180.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-196.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-196.png new file mode 100644 index 0000000000..ebc6adf844 Binary files /dev/null and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-196.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-20.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-20.png index 6e423fdafc..f9ba0b1279 100644 Binary files a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-20.png and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-20.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-256.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-256.png new file mode 100644 index 0000000000..f93e754b74 Binary files /dev/null and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-256.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-29.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-29.png index facb207f41..3f6e0441f7 100644 Binary files a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-29.png and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-29.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-32.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-32.png new file mode 100644 index 0000000000..e3a7001b36 Binary files /dev/null and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-32.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-40.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-40.png index 76b552b940..6720dea79f 100644 Binary files a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-40.png and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-40.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-41.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-41.png deleted file mode 100644 index 76b552b940..0000000000 Binary files a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-41.png and /dev/null differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-42.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-42.png deleted file mode 100644 index 76b552b940..0000000000 Binary files a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-42.png and /dev/null differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-48.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-48.png new file mode 100644 index 0000000000..fa5a086244 Binary files /dev/null and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-48.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-50.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-50.png new file mode 100644 index 0000000000..fbed9e0e77 Binary files /dev/null and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-50.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-512.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-512.png new file mode 100644 index 0000000000..63ec39615b Binary files /dev/null and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-512.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-55.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-55.png new file mode 100644 index 0000000000..a8c01fd243 Binary files /dev/null and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-55.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-57.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-57.png new file mode 100644 index 0000000000..76d4f73f48 Binary files /dev/null and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-57.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-58.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-58.png index f04f8d821b..726f314250 100644 Binary files a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-58.png and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-58.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-60.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-60.png index 8a7b62af39..1034d116e6 100644 Binary files a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-60.png and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-60.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-64.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-64.png new file mode 100644 index 0000000000..12833da797 Binary files /dev/null and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-64.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-72.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-72.png new file mode 100644 index 0000000000..8c4244d967 Binary files /dev/null and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-72.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-76.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-76.png new file mode 100644 index 0000000000..816dadd6c6 Binary files /dev/null and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-76.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-77.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-77.png deleted file mode 100644 index 3358dcd96f..0000000000 Binary files a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-77.png and /dev/null differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-80.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-80.png index bc437d7843..77609f4795 100644 Binary files a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-80.png and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-80.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-81.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-81.png deleted file mode 100644 index bc437d7843..0000000000 Binary files a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-81.png and /dev/null differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-87.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-87.png index 52bf674a50..2164c2a24f 100644 Binary files a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-87.png and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-87.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-88.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-88.png new file mode 100644 index 0000000000..8d3a995317 Binary files /dev/null and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-88.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-main.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-main.png index df2362cbd7..2604a0c85d 100644 Binary files a/ios/data/Assets.xcassets/AppIcon.appiconset/icon-main.png and b/ios/data/Assets.xcassets/AppIcon.appiconset/icon-main.png differ diff --git a/ios/data/Assets.xcassets/AppIcon.appiconset/icon.png b/ios/data/Assets.xcassets/AppIcon.appiconset/icon.png deleted file mode 100644 index f04f8d821b..0000000000 Binary files a/ios/data/Assets.xcassets/AppIcon.appiconset/icon.png and /dev/null differ diff --git a/ios/data/Assets.xcassets/Contents.json b/ios/data/Assets.xcassets/Contents.json index da4a164c91..121dee67a6 100644 --- a/ios/data/Assets.xcassets/Contents.json +++ b/ios/data/Assets.xcassets/Contents.json @@ -1,6 +1,6 @@ { - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } \ No newline at end of file diff --git a/ios/data/icon-120.png b/ios/data/icon-120.png deleted file mode 100644 index 195b90abfc..0000000000 Binary files a/ios/data/icon-120.png and /dev/null differ diff --git a/ios/data/icon-152.png b/ios/data/icon-152.png deleted file mode 100644 index 5f61bd8cf0..0000000000 Binary files a/ios/data/icon-152.png and /dev/null differ diff --git a/ios/data/icon-167.png b/ios/data/icon-167.png deleted file mode 100644 index d1c17eaba6..0000000000 Binary files a/ios/data/icon-167.png and /dev/null differ diff --git a/ios/data/icon-180.png b/ios/data/icon-180.png deleted file mode 100644 index d16f5b0898..0000000000 Binary files a/ios/data/icon-180.png and /dev/null differ diff --git a/ios/data/icon-20.png b/ios/data/icon-20.png deleted file mode 100644 index 8431e6351e..0000000000 Binary files a/ios/data/icon-20.png and /dev/null differ diff --git a/ios/data/icon-29.png b/ios/data/icon-29.png deleted file mode 100644 index ec7545e7e1..0000000000 Binary files a/ios/data/icon-29.png and /dev/null differ diff --git a/ios/data/icon-40.png b/ios/data/icon-40.png deleted file mode 100644 index 3397585443..0000000000 Binary files a/ios/data/icon-40.png and /dev/null differ diff --git a/ios/data/icon-58.png b/ios/data/icon-58.png deleted file mode 100644 index 7484fcaea3..0000000000 Binary files a/ios/data/icon-58.png and /dev/null differ diff --git a/ios/data/icon-60.png b/ios/data/icon-60.png deleted file mode 100644 index aa3d538703..0000000000 Binary files a/ios/data/icon-60.png and /dev/null differ diff --git a/ios/data/icon-72.png b/ios/data/icon-72.png deleted file mode 100644 index b5ac036c98..0000000000 Binary files a/ios/data/icon-72.png and /dev/null differ diff --git a/ios/data/icon-72@2x.png b/ios/data/icon-72@2x.png deleted file mode 100644 index b58b93d117..0000000000 Binary files a/ios/data/icon-72@2x.png and /dev/null differ diff --git a/ios/data/icon-76.png b/ios/data/icon-76.png deleted file mode 100644 index 85c137bab8..0000000000 Binary files a/ios/data/icon-76.png and /dev/null differ diff --git a/ios/data/icon-80.png b/ios/data/icon-80.png deleted file mode 100644 index 28f08c7589..0000000000 Binary files a/ios/data/icon-80.png and /dev/null differ diff --git a/ios/data/icon-87.png b/ios/data/icon-87.png deleted file mode 100644 index 28e085e8af..0000000000 Binary files a/ios/data/icon-87.png and /dev/null differ diff --git a/ios/data/icon-main.png b/ios/data/icon-main.png deleted file mode 100644 index df2362cbd7..0000000000 Binary files a/ios/data/icon-main.png and /dev/null differ diff --git a/ios/data/icon.png b/ios/data/icon.png deleted file mode 100644 index 330c7be74c..0000000000 Binary files a/ios/data/icon.png and /dev/null differ diff --git a/ios/data/icon@2x.png b/ios/data/icon@2x.png deleted file mode 100644 index 1b76170cd0..0000000000 Binary files a/ios/data/icon@2x.png and /dev/null differ diff --git a/ios/robovm.xml b/ios/robovm.xml index a7a06eeb22..146861dd40 100644 --- a/ios/robovm.xml +++ b/ios/robovm.xml @@ -1,49 +1,49 @@ - ${app.executable} - ${app.mainclass} - ios - thumbv7 - ios - Info.plist.xml - - - ../core/assets - - ** - - true - - - data - - - - net.jpountz.lz4.** - io.anuke.arc.scene.** - io.anuke.mindustry.gen.Call - io.anuke.mindustry.net.** - com.android.okhttp.HttpHandler - com.android.okhttp.HttpsHandler - com.android.org.conscrypt.** - com.android.org.bouncycastle.jce.provider.BouncyCastleProvider - com.android.org.bouncycastle.jcajce.provider.keystore.BC$Mappings - com.android.org.bouncycastle.jcajce.provider.keystore.bc.BcKeyStoreSpi - com.android.org.bouncycastle.jcajce.provider.keystore.bc.BcKeyStoreSpi$Std - com.android.org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi - com.android.org.bouncycastle.crypto.digests.AndroidDigestFactoryOpenSSL - org.apache.harmony.security.provider.cert.DRLCertFactory - org.apache.harmony.security.provider.crypto.CryptoProvider - - - z - - - UIKit - OpenGLES - QuartzCore - CoreGraphics - OpenAL - AudioToolbox - AVFoundation - + ${app.executable} + ${app.mainclass} + ios + thumbv7 + ios + Info.plist.xml + + + ../core/assets + + ** + + true + + + data + + + + net.jpountz.lz4.** + io.anuke.arc.scene.** + io.anuke.mindustry.gen.Call + io.anuke.mindustry.net.** + com.android.okhttp.HttpHandler + com.android.okhttp.HttpsHandler + com.android.org.conscrypt.** + com.android.org.bouncycastle.jce.provider.BouncyCastleProvider + com.android.org.bouncycastle.jcajce.provider.keystore.BC$Mappings + com.android.org.bouncycastle.jcajce.provider.keystore.bc.BcKeyStoreSpi + com.android.org.bouncycastle.jcajce.provider.keystore.bc.BcKeyStoreSpi$Std + com.android.org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi + com.android.org.bouncycastle.crypto.digests.AndroidDigestFactoryOpenSSL + org.apache.harmony.security.provider.cert.DRLCertFactory + org.apache.harmony.security.provider.crypto.CryptoProvider + + + z + + + UIKit + OpenGLES + QuartzCore + CoreGraphics + OpenAL + AudioToolbox + AVFoundation + diff --git a/ios/src/io/anuke/mindustry/IOSLauncher.java b/ios/src/io/anuke/mindustry/IOSLauncher.java index a4ce1935dd..3f795ee768 100644 --- a/ios/src/io/anuke/mindustry/IOSLauncher.java +++ b/ios/src/io/anuke/mindustry/IOSLauncher.java @@ -6,12 +6,12 @@ import io.anuke.arc.Core; import io.anuke.arc.files.FileHandle; import io.anuke.arc.scene.ui.layout.Unit; import io.anuke.arc.util.Strings; -import io.anuke.net.KryoClient; -import io.anuke.net.KryoServer; import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.game.Saves.SaveSlot; import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.net.Net; +import io.anuke.net.KryoClient; +import io.anuke.net.KryoServer; import org.robovm.apple.foundation.NSAutoreleasePool; import org.robovm.apple.foundation.NSURL; import org.robovm.apple.uikit.*; @@ -22,19 +22,21 @@ import java.util.Collections; import static io.anuke.mindustry.Vars.*; import static org.robovm.apple.foundation.NSPathUtilities.getDocumentsDirectory; -public class IOSLauncher extends IOSApplication.Delegate { +public class IOSLauncher extends IOSApplication.Delegate{ private boolean forced; @Override - protected IOSApplication createApplication() { + protected IOSApplication createApplication(){ Net.setClientProvider(new KryoClient()); Net.setServerProvider(new KryoServer()); if(UIDevice.getCurrentDevice().getUserInterfaceIdiom() == UIUserInterfaceIdiom.Pad){ Unit.dp.addition = 0.5f; + }else{ + Unit.dp.addition = -0.5f; } - Platform.instance = new Platform() { + Platform.instance = new Platform(){ @Override public void shareFile(FileHandle file){ @@ -70,14 +72,14 @@ public class IOSLauncher extends IOSApplication.Delegate { } @Override - public boolean openURL(UIApplication app, NSURL url, UIApplicationOpenURLOptions options) { + public boolean openURL(UIApplication app, NSURL url, UIApplicationOpenURLOptions options){ System.out.println("Opened URL: " + url.getPath()); openURL(url); return false; } @Override - public boolean didFinishLaunching(UIApplication application, UIApplicationLaunchOptions options) { + public boolean didFinishLaunching(UIApplication application, UIApplicationLaunchOptions options){ boolean b = super.didFinishLaunching(application, options); if(options != null && options.has(UIApplicationLaunchOptions.Keys.URL())){ @@ -100,7 +102,7 @@ public class IOSLauncher extends IOSApplication.Delegate { try{ SaveSlot slot = control.saves.importSave(file); ui.load.runLoadSave(slot); - }catch (IOException e){ + }catch(IOException e){ ui.showError(Core.bundle.format("save.import.fail", Strings.parseException(e, false))); } }else{ @@ -109,7 +111,7 @@ public class IOSLauncher extends IOSApplication.Delegate { }else if(file.extension().equalsIgnoreCase(mapExtension)){ //open map Core.app.post(() -> { - if (!ui.editor.isShown()) { + if(!ui.editor.isShown()){ ui.editor.show(); } @@ -119,7 +121,7 @@ public class IOSLauncher extends IOSApplication.Delegate { }); } - public static void main(String[] argv) { + public static void main(String[] argv){ NSAutoreleasePool pool = new NSAutoreleasePool(); UIApplication.main(argv, null, IOSLauncher.class); pool.close(); diff --git a/net/src/io/anuke/net/ByteSerializer.java b/net/src/io/anuke/net/ByteSerializer.java index a841d71994..4d01745afe 100644 --- a/net/src/io/anuke/net/ByteSerializer.java +++ b/net/src/io/anuke/net/ByteSerializer.java @@ -15,8 +15,8 @@ public class ByteSerializer implements Serialization{ @Override public void write(ByteBuffer byteBuffer, Object o){ if(o instanceof FrameworkMessage){ - byteBuffer.put((byte) -2); //code for framework message - FrameworkSerializer.write(byteBuffer, (FrameworkMessage) o); + byteBuffer.put((byte)-2); //code for framework message + FrameworkSerializer.write(byteBuffer, (FrameworkMessage)o); }else{ if(!(o instanceof Packet)) throw new RuntimeException("All sent objects must implement be Packets! Class: " + o.getClass()); @@ -24,7 +24,7 @@ public class ByteSerializer implements Serialization{ if(id == -1) throw new RuntimeException("Unregistered class: " + o.getClass()); byteBuffer.put(id); - ((Packet) o).write(byteBuffer); + ((Packet)o).write(byteBuffer); } } @@ -34,7 +34,7 @@ public class ByteSerializer implements Serialization{ if(id == -2){ return FrameworkSerializer.read(byteBuffer); }else{ - Packet packet = Pools.obtain((Class) Registrator.getByID(id).type, (Supplier) Registrator.getByID(id).constructor); + Packet packet = Pools.obtain((Class)Registrator.getByID(id).type, (Supplier)Registrator.getByID(id).constructor); packet.read(byteBuffer); return packet; } @@ -47,7 +47,7 @@ public class ByteSerializer implements Serialization{ @Override public void writeLength(ByteBuffer byteBuffer, int i){ - byteBuffer.putShort((short) i); + byteBuffer.putShort((short)i); } @Override diff --git a/net/src/io/anuke/net/FrameworkSerializer.java b/net/src/io/anuke/net/FrameworkSerializer.java index 6cc45e005e..9e7b472e37 100644 --- a/net/src/io/anuke/net/FrameworkSerializer.java +++ b/net/src/io/anuke/net/FrameworkSerializer.java @@ -9,28 +9,28 @@ public class FrameworkSerializer{ public static void write(ByteBuffer buffer, FrameworkMessage message){ if(message instanceof Ping){ - Ping p = (Ping) message; + Ping p = (Ping)message; - buffer.put((byte) 0); + buffer.put((byte)0); buffer.putInt(p.id); - buffer.put(p.isReply ? 1 : (byte) 0); + buffer.put(p.isReply ? 1 : (byte)0); }else if(message instanceof DiscoverHost){ - DiscoverHost p = (DiscoverHost) message; + DiscoverHost p = (DiscoverHost)message; - buffer.put((byte) 1); + buffer.put((byte)1); }else if(message instanceof KeepAlive){ - KeepAlive p = (KeepAlive) message; + KeepAlive p = (KeepAlive)message; - buffer.put((byte) 2); + buffer.put((byte)2); }else if(message instanceof RegisterUDP){ - RegisterUDP p = (RegisterUDP) message; + RegisterUDP p = (RegisterUDP)message; - buffer.put((byte) 3); + buffer.put((byte)3); buffer.putInt(p.connectionID); }else if(message instanceof RegisterTCP){ - RegisterTCP p = (RegisterTCP) message; + RegisterTCP p = (RegisterTCP)message; - buffer.put((byte) 4); + buffer.put((byte)4); buffer.putInt(p.connectionID); } } diff --git a/net/src/io/anuke/net/KryoClient.java b/net/src/io/anuke/net/KryoClient.java index 844ab361f8..2c24b2e687 100644 --- a/net/src/io/anuke/net/KryoClient.java +++ b/net/src/io/anuke/net/KryoClient.java @@ -5,24 +5,17 @@ import io.anuke.arc.Core; import io.anuke.arc.collection.Array; import io.anuke.arc.function.Consumer; import io.anuke.arc.util.pooling.Pools; -import io.anuke.mindustry.net.Host; -import io.anuke.mindustry.net.Net; +import io.anuke.mindustry.net.*; import io.anuke.mindustry.net.Net.ClientProvider; import io.anuke.mindustry.net.Net.SendMode; -import io.anuke.mindustry.net.NetworkIO; 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 java.io.IOException; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.nio.BufferOverflowException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; +import java.net.*; +import java.nio.*; import java.nio.channels.ClosedSelectorException; import static io.anuke.mindustry.Vars.netClient; diff --git a/net/src/io/anuke/net/KryoCore.java b/net/src/io/anuke/net/KryoCore.java index 59792bf67f..3e4be3ab3f 100644 --- a/net/src/io/anuke/net/KryoCore.java +++ b/net/src/io/anuke/net/KryoCore.java @@ -61,6 +61,6 @@ public class KryoCore{ } private static int calculateLag(){ - return fakeLagMin + (int) (Math.random() * (fakeLagMax - fakeLagMin)); + return fakeLagMin + (int)(Math.random() * (fakeLagMax - fakeLagMin)); } } diff --git a/net/src/io/anuke/net/KryoServer.java b/net/src/io/anuke/net/KryoServer.java index 47b495958a..5304913a6d 100644 --- a/net/src/io/anuke/net/KryoServer.java +++ b/net/src/io/anuke/net/KryoServer.java @@ -1,11 +1,8 @@ package io.anuke.net; import com.dosse.upnp.UPnP; -import com.esotericsoftware.kryonet.Connection; -import com.esotericsoftware.kryonet.FrameworkMessage; -import com.esotericsoftware.kryonet.Listener; +import com.esotericsoftware.kryonet.*; import com.esotericsoftware.kryonet.Listener.LagListener; -import com.esotericsoftware.kryonet.Server; import com.esotericsoftware.kryonet.util.InputStreamSender; import io.anuke.arc.Core; import io.anuke.arc.collection.Array; @@ -15,10 +12,7 @@ import io.anuke.mindustry.Vars; import io.anuke.mindustry.net.*; import io.anuke.mindustry.net.Net.SendMode; import io.anuke.mindustry.net.Net.ServerProvider; -import io.anuke.mindustry.net.Packets.Connect; -import io.anuke.mindustry.net.Packets.Disconnect; -import io.anuke.mindustry.net.Packets.StreamBegin; -import io.anuke.mindustry.net.Packets.StreamChunk; +import io.anuke.mindustry.net.Packets.*; import net.jpountz.lz4.LZ4Compressor; import net.jpountz.lz4.LZ4Factory; diff --git a/server/build.gradle b/server/build.gradle index 51240b5170..2148cae4ca 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -1,23 +1,27 @@ apply plugin: "java" sourceCompatibility = 1.8 -sourceSets.main.java.srcDirs = [ "src/" ] +sourceSets.main.java.srcDirs = ["src/"] project.ext.mainClassName = "io.anuke.mindustry.server.ServerLauncher" project.ext.assetsDir = new File("../core/assets") -task run(dependsOn: classes, type: JavaExec) { +ext.getServerFolder = { + return "../deploy/${appName}-server-${getVersionString()}" +} + +task run(dependsOn: classes, type: JavaExec){ main = project.mainClassName classpath = sourceSets.main.runtimeClasspath standardInput = System.in workingDir = project.assetsDir ignoreExitValue = true - if (project.hasProperty("appArgs")) { + if(project.hasProperty("appArgs")){ args Eval.me(appArgs) } } -task debug(dependsOn: classes, type: JavaExec) { +task debug(dependsOn: classes, type: JavaExec){ main = project.mainClassName classpath = sourceSets.main.runtimeClasspath standardInput = System.in @@ -26,10 +30,10 @@ task debug(dependsOn: classes, type: JavaExec) { debug = true } -task dist(type: Jar) { +task dist(type: Jar){ from files(sourceSets.main.output.classesDirs) from files(sourceSets.main.output.resourcesDir) - from {configurations.compile.collect {zipTree(it)}} + from{ configurations.compile.collect{ zipTree(it) } } from files(project.assetsDir) exclude("sprites/**") exclude("fonts/**") @@ -37,18 +41,45 @@ task dist(type: Jar) { exclude("bundles/**") writeVersion() - - manifest { + + manifest{ attributes 'Main-Class': project.mainClassName } } -task deploy(type: Copy){ +task dzip(type: Zip){ + from getServerFolder() + archiveName "$appName-server-${getVersionString()}.zip" + destinationDir(file("../deploy/")) + + finalizedBy 'cleanup' +} + +task cleanup{ + doLast{ + delete{ + delete getServerFolder() + } + } +} + +task deploy{ dependsOn "dist" - - from "build/libs/server-release.jar" - into "../deploy/" - rename ("server-release.jar", appName + "-server-" + getVersionString() + ".jar") + + finalizedBy 'dzip' + + doLast{ + copy{ + from "build/libs/server-release.jar" + into getServerFolder() + rename("server-release.jar", "server.jar") + } + + copy{ + from "server_template" + into getServerFolder() + } + } } dist.dependsOn classes diff --git a/server/server_template/run_server.bat b/server/server_template/run_server.bat new file mode 100644 index 0000000000..64cc23a20c --- /dev/null +++ b/server/server_template/run_server.bat @@ -0,0 +1,5 @@ +@Echo Off +Set "JV=" +For /F "Tokens=3" %%A In ('java -version 2^>^&1') Do If Not Defined JV Set "JV=%%~A" +If /I "%JV%"=="not" (Echo Java is not installed, this server requires Java to run.) Else (start java -jar server.jar) +Pause diff --git a/server/server_template/run_server.sh b/server/server_template/run_server.sh new file mode 100755 index 0000000000..26d919a77b --- /dev/null +++ b/server/server_template/run_server.sh @@ -0,0 +1 @@ +java -jar server.jar \ No newline at end of file diff --git a/server/src/io/anuke/mindustry/server/CrashHandler.java b/server/src/io/anuke/mindustry/server/CrashHandler.java index 9537a1d6bb..3e65ffb84c 100644 --- a/server/src/io/anuke/mindustry/server/CrashHandler.java +++ b/server/src/io/anuke/mindustry/server/CrashHandler.java @@ -12,9 +12,7 @@ import io.anuke.mindustry.net.Net; import java.io.PrintWriter; import java.io.StringWriter; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; +import java.nio.file.*; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @@ -55,7 +53,7 @@ public class CrashHandler{ try{ Path path = Paths.get(OS.getAppDataDirectoryString(Vars.appName), "crashes", - "crash-report-" + DateTimeFormatter.ofPattern("MM-dd-yyyy-HH:mm:ss").format(LocalDateTime.now()) + ".txt"); + "crash-report-" + DateTimeFormatter.ofPattern("MM-dd-yyyy-HH:mm:ss").format(LocalDateTime.now()) + ".txt"); Files.createDirectories(Paths.get(OS.getAppDataDirectoryString(Vars.appName), "crashes")); Files.write(path, parseException(e).getBytes()); @@ -70,7 +68,10 @@ public class CrashHandler{ Net.http(Vars.crashReportURL, "POST", value.toJson(OutputType.json), r -> System.exit(1), t -> System.exit(1)); //sleep forever - try{ Thread.sleep(Long.MAX_VALUE); }catch(InterruptedException ignored){} + try{ + Thread.sleep(Long.MAX_VALUE); + }catch(InterruptedException ignored){ + } } private static String parseException(Throwable e){ diff --git a/server/src/io/anuke/mindustry/server/MindustryServer.java b/server/src/io/anuke/mindustry/server/MindustryServer.java index 94a3a01587..0f61363859 100644 --- a/server/src/io/anuke/mindustry/server/MindustryServer.java +++ b/server/src/io/anuke/mindustry/server/MindustryServer.java @@ -3,9 +3,7 @@ package io.anuke.mindustry.server; import io.anuke.arc.ApplicationListener; import io.anuke.arc.Core; import io.anuke.mindustry.Vars; -import io.anuke.mindustry.core.Logic; -import io.anuke.mindustry.core.NetServer; -import io.anuke.mindustry.core.World; +import io.anuke.mindustry.core.*; import io.anuke.mindustry.game.Content; import io.anuke.mindustry.io.BundleLoader; diff --git a/server/src/io/anuke/mindustry/server/ServerControl.java b/server/src/io/anuke/mindustry/server/ServerControl.java index 4fd507e487..323a6bde73 100644 --- a/server/src/io/anuke/mindustry/server/ServerControl.java +++ b/server/src/io/anuke/mindustry/server/ServerControl.java @@ -1,18 +1,15 @@ package io.anuke.mindustry.server; -import io.anuke.arc.ApplicationListener; -import io.anuke.arc.Core; -import io.anuke.arc.Events; +import io.anuke.arc.*; import io.anuke.arc.collection.Array; +import io.anuke.arc.collection.Array.ArrayIterable; import io.anuke.arc.collection.ObjectSet; -import io.anuke.mindustry.entities.Effects; import io.anuke.arc.files.FileHandle; import io.anuke.arc.util.*; -import io.anuke.arc.util.CommandHandler.Command; -import io.anuke.arc.util.CommandHandler.Response; -import io.anuke.arc.util.CommandHandler.ResponseType; +import io.anuke.arc.util.CommandHandler.*; import io.anuke.arc.util.Timer.Task; import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.game.*; import io.anuke.mindustry.game.EventType.GameOverEvent; @@ -49,13 +46,13 @@ public class ServerControl implements ApplicationListener{ public ServerControl(String[] args){ Core.settings.defaults( - "shufflemode", "normal", - "bans", "", - "admins", "", - "shuffle", true, - "crashreport", false, - "port", port, - "logging", true + "shufflemode", "normal", + "bans", "", + "admins", "", + "shuffle", true, + "crashreport", false, + "port", port, + "logging", true ); Log.setLogger(new LogHandler(){ @@ -93,8 +90,10 @@ public class ServerControl implements ApplicationListener{ }); Time.setDeltaProvider(() -> Core.graphics.getDeltaTime() * 60f); - Effects.setScreenShakeProvider((a, b) -> {}); - Effects.setEffectProvider((a, b, c, d, e, f) -> {}); + Effects.setScreenShakeProvider((a, b) -> { + }); + Effects.setEffectProvider((a, b, c, d, e, f) -> { + }); registerCommands(); @@ -143,8 +142,8 @@ public class ServerControl implements ApplicationListener{ Call.onInfoMessage((state.rules.pvp ? "[YELLOW]The " + event.winner.name() + " team is victorious![]" : "[SCARLET]Game over![]") - + "\nNext selected map:[accent] "+map.name()+"[]" - + (map.author() != null ? " by[accent] " + map.author() + "[]" : "") + "."+ + + "\nNext selected map:[accent] " + map.name() + "[]" + + (map.tags.containsKey("author") && !map.tags.get("author").trim().isEmpty() ? " by[accent] " + map.author() + "[]" : "") + "." + "\nNew game begins in " + roundExtraTime + " seconds."); info("Selected next map to be {0}.", map.name()); @@ -198,7 +197,7 @@ public class ServerControl implements ApplicationListener{ if(lastTask != null) lastTask.cancel(); - Map result = world.maps.all().find(map -> map.name().equalsIgnoreCase(arg[0])); + Map result = world.maps.all().find(map -> map.name().equalsIgnoreCase(arg[0].replace('_', ' ')) || map.name().equalsIgnoreCase(arg[0])); if(result == null){ err("No map with name &y'{0}'&lr found.", arg[0]); @@ -259,6 +258,16 @@ public class ServerControl implements ApplicationListener{ info("&lyMap directory: &lb&fi{0}", customMapDirectory.file().getAbsoluteFile().toString()); }); + handler.register("reloadmaps", "Reload all maps from disk.", arg -> { + int beforeMaps = world.maps.all().size; + world.maps.reload(); + if(world.maps.all().size > beforeMaps){ + info("&lc{0}&ly new map(s) found and reloaded.", world.maps.all().size - beforeMaps); + }else{ + info("&lyMaps reloaded."); + } + }); + handler.register("status", "Display server status.", arg -> { if(state.is(State.menu)){ info("Status: &rserver closed"); @@ -269,10 +278,10 @@ public class ServerControl implements ApplicationListener{ if(state.rules.waves){ info("&ly {0} enemies.", unitGroups[Team.red.ordinal()].size()); }else{ - info("&ly {0} seconds until next wave.", (int) (state.wavetime / 60)); + info("&ly {0} seconds until next wave.", (int)(state.wavetime / 60)); } - info(" &ly{0} FPS, {1} MB used.", (int)(60f/Time.delta()), Core.app.getJavaHeap() / 1024 / 1024); + info(" &ly{0} FPS, {1} MB used.", (int)(60f / Time.delta()), Core.app.getJavaHeap() / 1024 / 1024); if(playerGroup.size() > 0){ info(" &lyPlayers: {0}", playerGroup.size()); @@ -298,7 +307,7 @@ public class ServerControl implements ApplicationListener{ handler.register("difficulty", "", "Set game difficulty.", arg -> { try{ - state.rules.waveSpacing = Difficulty.valueOf(arg[0]).waveTime; + state.rules.waveSpacing = Difficulty.valueOf(arg[0]).waveTime * 60 * 60 * 2; info("Difficulty set to '{0}'.", arg[0]); }catch(IllegalArgumentException e){ err("No difficulty with name '{0}' found.", arg[0]); @@ -310,7 +319,7 @@ public class ServerControl implements ApplicationListener{ err("Not playing. Host first."); return; } - + try{ Team team = arg.length == 0 ? Team.blue : Team.valueOf(arg[0]); @@ -318,13 +327,13 @@ public class ServerControl implements ApplicationListener{ err("That team has no cores."); return; } - + for(Item item : content.items()){ if(item.type == ItemType.material){ state.teams.get(team).cores.first().entity.items.set(item, state.teams.get(team).cores.first().block().itemCapacity); } } - + info("Core filled."); }catch(IllegalArgumentException ignored){ err("No such team exists."); @@ -346,9 +355,9 @@ public class ServerControl implements ApplicationListener{ }); handler.register("strict", "", "Disables or enables strict mode", arg -> { - boolean value = arg[0].equalsIgnoreCase("on"); - netServer.admins.setStrict(value); - info("Strict mode is now {0}.", netServer.admins.getStrict() ? "on" : "off"); + boolean value = arg[0].equalsIgnoreCase("on"); + netServer.admins.setStrict(value); + info("Strict mode is now {0}.", netServer.admins.getStrict() ? "on" : "off"); }); handler.register("allow-custom-clients", "[on/off]", "Allow or disallow custom clients.", arg -> { @@ -536,12 +545,16 @@ public class ServerControl implements ApplicationListener{ int slot = Strings.parseInt(arg[0]); if(!SaveIO.isSaveValid(slot)){ - err("No save data found for slot."); + err("No (valid) save data found for slot."); return; } Core.app.post(() -> { - SaveIO.loadFromSlot(slot); + try{ + SaveIO.loadFromSlot(slot); + }catch(Throwable t){ + err("Failed to load save. Outdated or corrupt file."); + } info("Save loaded."); host(); state.set(State.playing); @@ -584,7 +597,7 @@ public class ServerControl implements ApplicationListener{ int i = 0; for(PlayerInfo info : infos){ - info("&lc[{0}] Trace info for player '{1}' / UUID {2}", i ++, info.lastName, info.id); + info("&lc[{0}] Trace info for player '{1}' / UUID {2}", i++, info.lastName, info.id); info(" &lyall names used: {0}", info.names); info(" &lyIP: {0}", info.lastIP); info(" &lyall IPs used: {0}", info.ips); @@ -652,6 +665,9 @@ public class ServerControl implements ApplicationListener{ logic.play(); for(Player p : players){ p.reset(); + if(state.rules.pvp){ + p.setTeam(netServer.assignTeam(new ArrayIterable<>(players))); + } netServer.sendWorldData(p, p.con.id); } inExtraRound = false; @@ -682,6 +698,7 @@ public class ServerControl implements ApplicationListener{ info("&lcOpened a server on port {0}.", Core.settings.getInt("port")); }catch(BindException e){ Log.err("Unable to host: Port already in use! Make sure no other servers are running on the same port in your network."); + state.set(State.menu); }catch(IOException e){ err(e); state.set(State.menu); @@ -691,14 +708,14 @@ public class ServerControl implements ApplicationListener{ private void logToFile(String text){ if(currentLogFile != null && currentLogFile.length() > maxLogLength){ String date = DateTimeFormatter.ofPattern("MM-dd-yyyy | HH:mm:ss").format(LocalDateTime.now()); - currentLogFile.writeString("[End of log file. Date: "+ date + "]\n", true); + currentLogFile.writeString("[End of log file. Date: " + date + "]\n", true); currentLogFile = null; } if(currentLogFile == null){ int i = 0; while(logFolder.child("log-" + i + ".txt").length() >= maxLogLength){ - i ++; + i++; } currentLogFile = logFolder.child("log-" + i + ".txt"); diff --git a/settings.gradle b/settings.gradle index 2f0aa64e78..dd3c19e139 100644 --- a/settings.gradle +++ b/settings.gradle @@ -19,20 +19,21 @@ if(new File(settingsDir, 'local.properties').exists()){ println("No local.properties found. Not loading Android module.") } -if(System.properties["release"] == null || System.properties["release"] == "false"){ - if (new File(settingsDir, '../Arc').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:postprocessing', '../Arc/extensions/postprocessing') 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') } - if (new File(settingsDir, '../debug').exists()) { + if(new File(settingsDir, '../debug').exists()){ use(':debug', '../debug') } }else{ diff --git a/tests/src/test/java/ApplicationTests.java b/tests/src/test/java/ApplicationTests.java index 91958bf7ab..ef40719bf4 100644 --- a/tests/src/test/java/ApplicationTests.java +++ b/tests/src/test/java/ApplicationTests.java @@ -6,40 +6,33 @@ import io.anuke.arc.math.geom.Point2; import io.anuke.arc.util.Log; import io.anuke.arc.util.Time; import io.anuke.mindustry.Vars; -import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.content.Items; -import io.anuke.mindustry.content.UnitTypes; +import io.anuke.mindustry.content.*; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.core.Logic; -import io.anuke.mindustry.core.NetServer; -import io.anuke.mindustry.core.World; +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.Content; -import io.anuke.mindustry.game.SpawnGroup; -import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.game.*; import io.anuke.mindustry.io.BundleLoader; import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.maps.Map; -import io.anuke.mindustry.type.ContentType; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.Zone; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Edges; -import io.anuke.mindustry.world.Tile; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; +import io.anuke.mindustry.type.*; +import io.anuke.mindustry.world.*; +import org.junit.jupiter.api.*; import static io.anuke.mindustry.Vars.*; import static org.junit.jupiter.api.Assertions.*; public class ApplicationTests{ static Map testMap; + static boolean initialized; @BeforeAll static void launchApplication(){ + //only gets called once + if(initialized) return; + initialized = true; + try{ boolean[] begins = {false}; Throwable[] exceptionThrown = {null}; @@ -94,7 +87,7 @@ public class ApplicationTests{ @BeforeEach void resetWorld(){ - Time.setDeltaProvider(() -> 1f); + Time.setDeltaProvider(() -> 1f); logic.reset(); state.set(State.menu); } @@ -114,6 +107,7 @@ public class ApplicationTests{ @Test void spawnWaves(){ world.loadMap(testMap); + assertTrue(world.spawner.countSpawns() > 0, "No spawns present."); logic.runWave(); //force trigger delayed spawns Time.setDeltaProvider(() -> 1000f); @@ -121,7 +115,7 @@ public class ApplicationTests{ Time.update(); Time.setDeltaProvider(() -> 1f); unitGroups[waveTeam.ordinal()].updateEvents(); - assertFalse(unitGroups[waveTeam.ordinal()].isEmpty()); + assertFalse(unitGroups[waveTeam.ordinal()].isEmpty(), "No enemies spawned."); } @Test @@ -144,8 +138,8 @@ public class ApplicationTests{ int by = 4; world.setBlock(world.tile(bx, by), Blocks.coreShard, Team.blue); assertEquals(world.tile(bx, by).getTeam(), Team.blue); - for(int x = bx-1; x <= bx + 1; x++){ - for(int y = by-1; y <= by + 1; y++){ + for(int x = bx - 1; x <= bx + 1; x++){ + for(int y = by - 1; y <= by + 1; y++){ if(x == bx && by == y){ assertEquals(world.tile(x, y).block(), Blocks.coreShard); }else{ @@ -178,6 +172,37 @@ public class ApplicationTests{ assertTrue(ran[0]); } + @Test + void manyTimers(){ + int runs = 100000; + int[] total = {0}; + for(int i = 0; i < runs; i++){ + Time.run(0.999f, () -> total[0]++); + } + assertEquals(0, total[0]); + Time.update(); + assertEquals(runs, total[0]); + } + + @Test + void longTimers(){ + Time.setDeltaProvider(() -> Float.MAX_VALUE); + Time.update(); + int steps = 100; + float delay = 100000f; + Time.setDeltaProvider(() -> delay / steps + 0.01f); + int runs = 100000; + int[] total = {0}; + for(int i = 0; i < runs; i++){ + Time.run(delay, () -> total[0]++); + } + assertEquals(0, total[0]); + for(int i = 0; i < steps; i++){ + Time.update(); + } + assertEquals(runs, total[0]); + } + @Test void save(){ world.loadMap(testMap); @@ -222,8 +247,8 @@ public class ApplicationTests{ void buildingOverlap(){ initBuilding(); - Spirit d1 = (Spirit) UnitTypes.spirit.create(Team.blue); - Spirit d2 = (Spirit) UnitTypes.spirit.create(Team.blue); + Spirit d1 = (Spirit)UnitTypes.spirit.create(Team.blue); + Spirit d2 = (Spirit)UnitTypes.spirit.create(Team.blue); d1.set(10f, 20f); d2.set(10f, 20f); @@ -277,8 +302,8 @@ public class ApplicationTests{ void buildingDestruction(){ initBuilding(); - Spirit d1 = (Spirit) UnitTypes.spirit.create(Team.blue); - Spirit d2 = (Spirit) UnitTypes.spirit.create(Team.blue); + Spirit d1 = (Spirit)UnitTypes.spirit.create(Team.blue); + Spirit d2 = (Spirit)UnitTypes.spirit.create(Team.blue); d1.set(10f, 20f); d2.set(10f, 20f); @@ -303,6 +328,43 @@ public class ApplicationTests{ assertEquals(Blocks.air, world.tile(1, 1).block()); } + @Test + void allBlockTest(){ + Tile[][] tiles = world.createTiles(256 + 20, 10); + + world.beginMapLoad(); + for(int x = 0; x < tiles.length; x++){ + for(int y = 0; y < tiles[0].length; y++){ + tiles[x][y] = new Tile(x, y, Blocks.stone.id, (byte)0); + } + } + int i = 0; + + for(int x = 5; x < tiles.length && i < content.blocks().size; ){ + Block block = content.block(i++); + if(block.buildVisibility.get()){ + tiles[x][5].setBlock(block); + x += block.size; + } + } + world.endMapLoad(); + + for(int x = 0; x < tiles.length; x++){ + for(int y = 0; y < tiles[0].length; y++){ + Tile tile = world.tile(x, y); + if(tile.entity != null){ + try{ + tile.entity.update(); + }catch(Throwable t){ + fail("Failed to update block '" + tile.block() + "'.", t); + } + assertEquals(tile.block(), tile.entity.block); + assertEquals(tile.block().health, tile.entity.health); + } + } + } + } + void initBuilding(){ createMap(); diff --git a/tests/src/test/java/MapTests.java b/tests/src/test/java/MapTests.java deleted file mode 100644 index 689c7f5d22..0000000000 --- a/tests/src/test/java/MapTests.java +++ /dev/null @@ -1,11 +0,0 @@ -import org.junit.jupiter.api.BeforeAll; - -public class MapTests{ - - @BeforeAll - static void launchApplication(){ - ApplicationTests.launchApplication(); - } - - //TODO -} diff --git a/tests/src/test/java/WorldTests.java b/tests/src/test/java/WorldTests.java index 91c8fdce81..2b4f480bfa 100644 --- a/tests/src/test/java/WorldTests.java +++ b/tests/src/test/java/WorldTests.java @@ -1,90 +1,85 @@ -import static io.anuke.mindustry.Vars.logic; -import static io.anuke.mindustry.Vars.state; -import static io.anuke.mindustry.Vars.world; -import static org.junit.jupiter.api.Assertions.assertEquals; - -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.world.Tile; +import org.junit.jupiter.api.*; -public class WorldTests { +import static io.anuke.mindustry.Vars.*; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class WorldTests{ static Tile[][] tiles; @BeforeAll static void launchApplication(){ - ApplicationTests.launchApplication(); - world.createTiles(10,10); + ApplicationTests.launchApplication(); + world.createTiles(10, 10); tiles = world.getTiles(); } @BeforeEach void resetWorld(){ - Time.setDeltaProvider(() -> 1f); + Time.setDeltaProvider(() -> 1f); logic.reset(); state.set(State.menu); } @Test - void addDarkness_allSolid_maxDarkness(){ + void addDarknessAllSolidMaxDarkness(){ fillWith(Blocks.rocks.id); world.addDarkness(tiles); - for(int x = 0; x < tiles.length; x++) { - for (int y = 0; y < tiles[0].length; y++) { + for(int x = 0; x < tiles.length; x++){ + for(int y = 0; y < tiles[0].length; y++){ assertEquals(4, tiles[x][y].getRotation()); } } } @Test - void addDarkness_allSyntethic_noDarkness(){ + void addDarknessAllSyntethicNoDarkness(){ fillWith(Blocks.copperWall.id); world.addDarkness(tiles); - for(int x = 0; x < tiles.length; x++) { - for (int y = 0; y < tiles[0].length; y++) { + for(int x = 0; x < tiles.length; x++){ + for(int y = 0; y < tiles[0].length; y++){ assertEquals(0, tiles[x][y].getRotation()); } } } @Test - void addDarkness_allNotSolid_noDarkness(){ + void addDarknessAllNotSolidNoDarkness(){ fillWith(Blocks.air.id); world.addDarkness(tiles); - for(int x = 0; x < tiles.length; x++) { - for (int y = 0; y < tiles[0].length; y++) { + for(int x = 0; x < tiles.length; x++){ + for(int y = 0; y < tiles[0].length; y++){ assertEquals(0, tiles[x][y].getRotation()); } } } @Test - void addDarkness_allNotFilled_noDarkness(){ + void addDarknessAllNotFilledNoDarkness(){ fillWith(Blocks.cliffs.id); world.addDarkness(tiles); - for(int x = 0; x < tiles.length; x++) { - for (int y = 0; y < tiles[0].length; y++) { + for(int x = 0; x < tiles.length; x++){ + for(int y = 0; y < tiles[0].length; y++){ assertEquals(0, tiles[x][y].getRotation()); } } } @Test - void addDarkness_oneNotSolidMiddle_noDarkness(){ + void addDarknessOneNotSolidMiddleNoDarkness(){ fillWith(Blocks.rocks.id); tiles[5][5] = new Tile(5, 5, (byte)0, Blocks.copperWall.id, (byte)0, (byte)0); world.addDarkness(tiles); - for(int x = 0; x < tiles.length; x++) { - for (int y = 0; y < tiles[0].length; y++) { + for(int x = 0; x < tiles.length; x++){ + for(int y = 0; y < tiles[0].length; y++){ byte darkness = tiles[x][y].getRotation(); int distance = Math.abs(x - 5) + Math.abs(y - 5); assertEquals(Math.min(Math.max(distance - 1, 0), 4), darkness); @@ -93,13 +88,13 @@ public class WorldTests { } @Test - void addDarkness_oneNotSolidCorner_noDarkness(){ + void addDarknessOneNotSolidCornerNoDarkness(){ fillWith(Blocks.rocks.id); tiles[7][7] = new Tile(5, 5, (byte)0, Blocks.copperWall.id, (byte)0, (byte)0); world.addDarkness(tiles); - for(int x = 0; x < tiles.length; x++) { - for (int y = 0; y < tiles[0].length; y++) { + for(int x = 0; x < tiles.length; x++){ + for(int y = 0; y < tiles[0].length; y++){ byte darkness = tiles[x][y].getRotation(); int distance = Math.abs(x - 7) + Math.abs(y - 7); assertEquals(Math.min(Math.max(distance - 1, 0), 4), darkness); @@ -108,8 +103,8 @@ public class WorldTests { } private static void fillWith(byte tileID){ - for(int x = 0; x < tiles.length; x++) { - for (int y = 0; y < tiles[0].length; y++) { + for(int x = 0; x < tiles.length; x++){ + for(int y = 0; y < tiles[0].length; y++){ tiles[x][y] = new Tile(x, y, (byte)0, tileID, (byte)0, (byte)0); } } diff --git a/tests/src/test/java/ZoneTests.java b/tests/src/test/java/ZoneTests.java new file mode 100644 index 0000000000..39e9d640e2 --- /dev/null +++ b/tests/src/test/java/ZoneTests.java @@ -0,0 +1,68 @@ +import io.anuke.arc.collection.Array; +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.type.Item; +import io.anuke.mindustry.type.Zone; +import io.anuke.mindustry.world.Tile; +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.assertTrue; +import static org.junit.jupiter.api.DynamicTest.dynamicTest; + +public class ZoneTests{ + + @BeforeAll + static void launchApplication(){ + ApplicationTests.launchApplication(); + } + + @BeforeEach + void resetWorld(){ + Time.setDeltaProvider(() -> 1f); + logic.reset(); + state.set(State.menu); + } + + @TestFactory + DynamicTest[] testZoneResources(){ + Array out = new Array<>(); + + for(Zone zone : content.zones()){ + out.add(dynamicTest(zone.name, () -> { + logic.reset(); + world.loadGenerator(zone.generator); + ObjectSet resources = new ObjectSet<>(); + boolean hasSpawnPoint = false; + + for(int x = 0; x < world.width(); x++){ + for(int y = 0; y < world.height(); y++){ + Tile tile = world.tile(x, y); + if(tile.drop() != null){ + resources.add(tile.drop()); + } + if(tile.block() instanceof CoreBlock){ + hasSpawnPoint = true; + } + } + } + + 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()); + + 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 + "\""); + } + })); + } + + return out.toArray(DynamicTest.class); + } +} diff --git a/tests/src/test/java/power/FakeGraphics.java b/tests/src/test/java/power/FakeGraphics.java index 3006810379..bce7d8fbff 100644 --- a/tests/src/test/java/power/FakeGraphics.java +++ b/tests/src/test/java/power/FakeGraphics.java @@ -2,9 +2,7 @@ package power; import io.anuke.arc.Graphics; import io.anuke.arc.Graphics.Cursor.SystemCursor; -import io.anuke.arc.graphics.GL20; -import io.anuke.arc.graphics.GL30; -import io.anuke.arc.graphics.Pixmap; +import io.anuke.arc.graphics.*; import io.anuke.arc.graphics.glutils.GLVersion; public class FakeGraphics extends Graphics{ diff --git a/tests/src/test/java/power/ItemLiquidGeneratorTests.java b/tests/src/test/java/power/ItemLiquidGeneratorTests.java index 153b9ead50..19342611fc 100644 --- a/tests/src/test/java/power/ItemLiquidGeneratorTests.java +++ b/tests/src/test/java/power/ItemLiquidGeneratorTests.java @@ -7,9 +7,7 @@ import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.power.ItemLiquidGenerator; -import org.junit.jupiter.api.DynamicTest; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestFactory; +import org.junit.jupiter.api.*; import java.util.ArrayList; @@ -36,7 +34,6 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{ generator = new ItemLiquidGenerator(inputType != InputType.liquids, inputType != InputType.items, "fakegen"){ { powerProduction = 0.1f; - itemDuration = 60f; itemDuration = fakeItemDuration; maxLiquidGenerate = maximumLiquidUsage; } @@ -62,8 +59,8 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{ // Execute all tests for the case where only liquids are accepted and for the case where liquids and items are accepted (but supply only liquids) InputType[] inputTypesToBeTested = new InputType[]{ - InputType.liquids, - InputType.any + InputType.liquids, + InputType.any }; ArrayList tests = new ArrayList<>(); @@ -90,7 +87,6 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{ entity.liquids.add(liquid, availableLiquidAmount); entity.cons.update(); - assertTrue(entity.cons.valid()); // Perform an update on the generator once - This should use up any resource up to the maximum liquid usage generator.update(tile); @@ -105,8 +101,8 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{ // Execute all tests for the case where only items are accepted and for the case where liquids and items are accepted (but supply only items) InputType[] inputTypesToBeTested = new InputType[]{ - InputType.items, - InputType.any + InputType.items, + InputType.any }; ArrayList tests = new ArrayList<>(); @@ -135,7 +131,6 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{ entity.items.add(item, amount); } entity.cons.update(); - assertTrue(entity.cons.valid()); // Perform an update on the generator once - This should use up one or zero items - dependent on if the item is accepted and available or not. generator.update(tile); @@ -169,12 +164,12 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{ float currentDuration = 0.0f; while((currentDuration += Time.delta()) <= fakeItemDuration){ generator.update(tile); - assertEquals(expectedEfficiency, entity.productionEfficiency, "Duration: " + String.valueOf(currentDuration)); + assertEquals(expectedEfficiency, entity.productionEfficiency, "Duration: " + currentDuration); } generator.update(tile); - assertEquals(0.0f, entity.productionEfficiency, "Duration: " + String.valueOf(currentDuration)); + assertEquals(0.0f, entity.productionEfficiency, "Duration: " + currentDuration); } - + enum InputType{ items, liquids, diff --git a/tests/src/test/java/power/PowerTestFixture.java b/tests/src/test/java/power/PowerTestFixture.java index e94a52ac55..fd3bff5eca 100644 --- a/tests/src/test/java/power/PowerTestFixture.java +++ b/tests/src/test/java/power/PowerTestFixture.java @@ -2,6 +2,7 @@ package power; import io.anuke.arc.Core; import io.anuke.arc.math.Mathf; +import io.anuke.arc.util.Log; import io.anuke.arc.util.Time; import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Blocks; @@ -11,19 +12,17 @@ import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.PowerBlock; import io.anuke.mindustry.world.blocks.power.Battery; import io.anuke.mindustry.world.blocks.power.PowerGenerator; -import io.anuke.mindustry.world.modules.ConsumeModule; -import io.anuke.mindustry.world.modules.ItemModule; -import io.anuke.mindustry.world.modules.LiquidModule; -import io.anuke.mindustry.world.modules.PowerModule; +import io.anuke.mindustry.world.modules.*; import org.junit.jupiter.api.BeforeAll; import java.lang.reflect.Field; -/** This class provides objects commonly used by power related unit tests. - * For now, this is a helper with static methods, but this might change. - * - * Note: All tests which subclass this will run with a fixed delta of 0.5! - * */ +/** + * This class provides objects commonly used by power related unit tests. + * For now, this is a helper with static methods, but this might change. + *

+ * Note: All tests which subclass this will run with a fixed delta of 0.5! + */ public class PowerTestFixture{ public static final float smallRoundingTolerance = Mathf.FLOAT_ROUNDING_ERROR; public static final float mediumRoundingTolerance = Mathf.FLOAT_ROUNDING_ERROR * 10; @@ -34,6 +33,7 @@ public class PowerTestFixture{ Core.graphics = new FakeGraphics(); Vars.content = new ContentLoader(); Vars.content.load(); + Log.setUseColors(false); Time.setDeltaProvider(() -> 0.5f); } @@ -60,10 +60,11 @@ public class PowerTestFixture{ consumes.powerBuffered(capacity, ticksToFill); }}; } + /** * Creates a fake tile on the given location using the given block. - * @param x The X coordinate. - * @param y The y coordinate. + * @param x The X coordinate. + * @param y The y coordinate. * @param block The block on the tile. * @return The created tile or null in case of exceptions. */ @@ -71,11 +72,16 @@ public class PowerTestFixture{ try{ Tile tile = new Tile(x, y); + //workaround since init() is not called for custom blocks + if(block.consumes.all() == null){ + block.consumes.init(); + } + // Using the Tile(int, int, byte, byte) constructor would require us to register any fake block or tile we create // Since this part shall not be part of the test and would require more work anyway, we manually set the block and floor // through reflections and then simulate part of what the changed() method does. - Field field = Tile.class.getDeclaredField("wall"); + Field field = Tile.class.getDeclaredField("block"); field.setAccessible(true); field.set(tile, block); diff --git a/tests/src/test/java/power/PowerTests.java b/tests/src/test/java/power/PowerTests.java index a722e4ed69..c52a9532f3 100644 --- a/tests/src/test/java/power/PowerTests.java +++ b/tests/src/test/java/power/PowerTests.java @@ -30,25 +30,27 @@ public class PowerTests extends PowerTestFixture{ @Nested class PowerGraphTests{ - /** Tests the satisfaction of a single consumer after a single update of the power graph which contains a single producer. - * - * Assumption: When the consumer requests zero power, satisfaction does not change. Default is 0.0f. + /** + * Tests the satisfaction of a single consumer after a single update of the power graph which contains a single producer. + *

+ * Assumption: When the consumer requests zero power, satisfaction does not change. Default is 0.0f. */ @TestFactory DynamicTest[] directConsumerSatisfactionIsAsExpected(){ return new DynamicTest[]{ - // Note: Unfortunately, the display names are not yet output through gradle. See https://github.com/gradle/gradle/issues/5975 - // That's why we inject the description into the test method for now. - // Additional Note: If you don't see any labels in front of the values supplied as function parameters, use a better IDE like IntelliJ IDEA. - dynamicTest("01", () -> simulateDirectConsumption(0.0f, 1.0f, 0.0f, "0.0 produced, 1.0 consumed (no power available)")), - dynamicTest("02", () -> simulateDirectConsumption(0.0f, 0.0f, 1.0f, "0.0 produced, 0.0 consumed (no power anywhere)")), - dynamicTest("03", () -> simulateDirectConsumption(1.0f, 0.0f, 1.0f, "1.0 produced, 0.0 consumed (no power requested)")), - dynamicTest("04", () -> simulateDirectConsumption(1.0f, 1.0f, 1.0f, "1.0 produced, 1.0 consumed (stable consumption)")), - dynamicTest("05", () -> simulateDirectConsumption(0.5f, 1.0f, 0.5f, "0.5 produced, 1.0 consumed (power shortage)")), - dynamicTest("06", () -> simulateDirectConsumption(1.0f, 0.5f, 1.0f, "1.0 produced, 0.5 consumed (power excess)")), - dynamicTest("07", () -> simulateDirectConsumption(0.09f, 0.09f - Mathf.FLOAT_ROUNDING_ERROR / 10.0f, 1.0f, "floating point inaccuracy (stable consumption)")) + // Note: Unfortunately, the display names are not yet output through gradle. See https://github.com/gradle/gradle/issues/5975 + // That's why we inject the description into the test method for now. + // Additional Note: If you don't see any labels in front of the values supplied as function parameters, use a better IDE like IntelliJ IDEA. + dynamicTest("01", () -> simulateDirectConsumption(0.0f, 1.0f, 0.0f, "0.0 produced, 1.0 consumed (no power available)")), + dynamicTest("02", () -> simulateDirectConsumption(0.0f, 0.0f, 0.0f, "0.0 produced, 0.0 consumed (no power anywhere)")), + dynamicTest("03", () -> simulateDirectConsumption(1.0f, 0.0f, 1.0f, "1.0 produced, 0.0 consumed (no power requested)")), + dynamicTest("04", () -> simulateDirectConsumption(1.0f, 1.0f, 1.0f, "1.0 produced, 1.0 consumed (stable consumption)")), + dynamicTest("05", () -> simulateDirectConsumption(0.5f, 1.0f, 0.5f, "0.5 produced, 1.0 consumed (power shortage)")), + dynamicTest("06", () -> simulateDirectConsumption(1.0f, 0.5f, 1.0f, "1.0 produced, 0.5 consumed (power excess)")), + dynamicTest("07", () -> simulateDirectConsumption(0.09f, 0.09f - Mathf.FLOAT_ROUNDING_ERROR / 10.0f, 1.0f, "floating point inaccuracy (stable consumption)")) }; } + void simulateDirectConsumption(float producedPower, float requiredPower, float expectedSatisfaction, String parameterDescription){ Tile producerTile = createFakeTile(0, 0, createFakeProducerBlock(producedPower)); producerTile.entity().productionEfficiency = 1f; @@ -70,29 +72,30 @@ public class PowerTests extends PowerTestFixture{ @TestFactory DynamicTest[] bufferedConsumerSatisfactionIsAsExpected(){ return new DynamicTest[]{ - // Note: powerPerTick may not be 0 in any of the test cases. This would equal a "ticksToFill" of infinite. - // Note: Due to a fixed delta of 0.5, only half of what is defined here will in fact be produced/consumed. Keep this in mind when defining expectedSatisfaction! - dynamicTest("01", () -> simulateBufferedConsumption(0.0f, 0.0f, 0.1f, 0.0f, 0.0f, "Empty Buffer, No power anywhere")), - dynamicTest("02", () -> simulateBufferedConsumption(0.0f, 1.0f, 0.1f, 0.0f, 0.0f, "Empty Buffer, No power provided")), - dynamicTest("03", () -> simulateBufferedConsumption(1.0f, 0.0f, 0.1f, 0.0f, 0.0f, "Empty Buffer, No power requested")), - dynamicTest("04", () -> simulateBufferedConsumption(1.0f, 1.0f, 1.0f, 0.0f, 0.5f, "Empty Buffer, Stable Power, One tick to fill")), - dynamicTest("05", () -> simulateBufferedConsumption(2.0f, 1.0f, 2.0f, 0.0f, 1.0f, "Empty Buffer, Stable Power, One delta to fill")), - dynamicTest("06", () -> simulateBufferedConsumption(1.0f, 1.0f, 0.1f, 0.0f, 0.05f, "Empty Buffer, Stable Power, multiple ticks to fill")), - dynamicTest("07", () -> simulateBufferedConsumption(1.2f, 0.5f, 1.0f, 0.0f, 1.0f, "Empty Buffer, Power excess, one delta to fill")), - dynamicTest("08", () -> simulateBufferedConsumption(1.0f, 0.5f, 0.1f, 0.0f, 0.1f, "Empty Buffer, Power excess, multiple ticks to fill")), - dynamicTest("09", () -> simulateBufferedConsumption(1.0f, 1.0f, 2.0f, 0.0f, 0.5f, "Empty Buffer, Power shortage, one delta to fill")), - dynamicTest("10", () -> simulateBufferedConsumption(0.5f, 1.0f, 0.1f, 0.0f, 0.05f, "Empty Buffer, Power shortage, multiple ticks to fill")), - dynamicTest("11", () -> simulateBufferedConsumption(0.0f, 1.0f, 0.1f, 0.5f, 0.5f, "Unchanged buffer with no power produced")), - dynamicTest("12", () -> simulateBufferedConsumption(1.0f, 1.0f, 0.1f, 1.0f, 1.0f, "Unchanged buffer when already full")), - dynamicTest("13", () -> simulateBufferedConsumption(0.2f, 1.0f, 0.5f, 0.5f, 0.6f, "Half buffer, power shortage")), - dynamicTest("14", () -> simulateBufferedConsumption(1.0f, 1.0f, 0.5f, 0.9f, 1.0f, "Buffer does not get exceeded")), - dynamicTest("15", () -> simulateBufferedConsumption(2.0f, 1.0f, 1.0f, 0.5f, 1.0f, "Half buffer, filled with excess")) + // Note: powerPerTick may not be 0 in any of the test cases. This would equal a "ticksToFill" of infinite. + // Note: Due to a fixed delta of 0.5, only half of what is defined here will in fact be produced/consumed. Keep this in mind when defining expectedSatisfaction! + dynamicTest("01", () -> simulateBufferedConsumption(0.0f, 0.0f, 0.1f, 0.0f, 0.0f, "Empty Buffer, No power anywhere")), + dynamicTest("02", () -> simulateBufferedConsumption(0.0f, 1.0f, 0.1f, 0.0f, 0.0f, "Empty Buffer, No power provided")), + dynamicTest("03", () -> simulateBufferedConsumption(1.0f, 0.0f, 0.1f, 0.0f, 0.0f, "Empty Buffer, No power requested")), + dynamicTest("04", () -> simulateBufferedConsumption(1.0f, 1.0f, 1.0f, 0.0f, 0.5f, "Empty Buffer, Stable Power, One tick to fill")), + dynamicTest("05", () -> simulateBufferedConsumption(2.0f, 1.0f, 2.0f, 0.0f, 1.0f, "Empty Buffer, Stable Power, One delta to fill")), + dynamicTest("06", () -> simulateBufferedConsumption(1.0f, 1.0f, 0.1f, 0.0f, 0.05f, "Empty Buffer, Stable Power, multiple ticks to fill")), + dynamicTest("07", () -> simulateBufferedConsumption(1.2f, 0.5f, 1.0f, 0.0f, 1.0f, "Empty Buffer, Power excess, one delta to fill")), + dynamicTest("08", () -> simulateBufferedConsumption(1.0f, 0.5f, 0.1f, 0.0f, 0.1f, "Empty Buffer, Power excess, multiple ticks to fill")), + dynamicTest("09", () -> simulateBufferedConsumption(1.0f, 1.0f, 2.0f, 0.0f, 0.5f, "Empty Buffer, Power shortage, one delta to fill")), + dynamicTest("10", () -> simulateBufferedConsumption(0.5f, 1.0f, 0.1f, 0.0f, 0.05f, "Empty Buffer, Power shortage, multiple ticks to fill")), + dynamicTest("11", () -> simulateBufferedConsumption(0.0f, 1.0f, 0.1f, 0.5f, 0.5f, "Unchanged buffer with no power produced")), + dynamicTest("12", () -> simulateBufferedConsumption(1.0f, 1.0f, 0.1f, 1.0f, 1.0f, "Unchanged buffer when already full")), + dynamicTest("13", () -> simulateBufferedConsumption(0.2f, 1.0f, 0.5f, 0.5f, 0.6f, "Half buffer, power shortage")), + dynamicTest("14", () -> simulateBufferedConsumption(1.0f, 1.0f, 0.5f, 0.9f, 1.0f, "Buffer does not get exceeded")), + dynamicTest("15", () -> simulateBufferedConsumption(2.0f, 1.0f, 1.0f, 0.5f, 1.0f, "Half buffer, filled with excess")) }; } + void simulateBufferedConsumption(float producedPower, float maxBuffer, float powerConsumedPerTick, float initialSatisfaction, float expectedSatisfaction, String parameterDescription){ Tile producerTile = createFakeTile(0, 0, createFakeProducerBlock(producedPower)); producerTile.entity().productionEfficiency = 1f; - Tile bufferedConsumerTile = createFakeTile(0, 1, createFakeBufferedConsumer(maxBuffer, maxBuffer > 0.0f ? maxBuffer/powerConsumedPerTick : 1.0f)); + Tile bufferedConsumerTile = createFakeTile(0, 1, createFakeBufferedConsumer(maxBuffer, maxBuffer > 0.0f ? maxBuffer / powerConsumedPerTick : 1.0f)); bufferedConsumerTile.entity.power.satisfaction = initialSatisfaction; PowerGraph powerGraph = new PowerGraph(); @@ -113,24 +116,26 @@ public class PowerTests extends PowerTestFixture{ assertEquals(expectedSatisfaction, bufferedConsumerTile.entity.power.satisfaction, Mathf.FLOAT_ROUNDING_ERROR, parameterDescription + ": Satisfaction of buffered consumer did not match"); } - /** Tests the satisfaction of a single direct consumer after a single update of the power graph which contains a single producer and a single battery. - * The used battery is created with a maximum capacity of 100 and receives ten power per tick. + /** + * Tests the satisfaction of a single direct consumer after a single update of the power graph which contains a single producer and a single battery. + * The used battery is created with a maximum capacity of 100 and receives ten power per tick. */ @TestFactory DynamicTest[] batteryCapacityIsAsExpected(){ return new DynamicTest[]{ - // Note: expectedBatteryCapacity is currently adjusted to a delta of 0.5! (FakeThreadHandler sets it to that) - dynamicTest("01", () -> simulateDirectConsumptionWithBattery(10.0f, 0.0f, 0.0f, 5.0f, 0.0f, "Empty battery, no consumer")), - dynamicTest("02", () -> simulateDirectConsumptionWithBattery(10.0f, 0.0f, 94.999f, 99.999f, 0.0f, "Battery almost full after update, no consumer")), - dynamicTest("03", () -> simulateDirectConsumptionWithBattery(10.0f, 0.0f, 100.0f, 100.0f, 0.0f, "Full battery, no consumer")), - dynamicTest("04", () -> simulateDirectConsumptionWithBattery(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, "No producer, no consumer, empty battery")), - dynamicTest("05", () -> simulateDirectConsumptionWithBattery(0.0f, 0.0f, 100.0f, 100.0f, 0.0f, "No producer, no consumer, full battery")), - dynamicTest("06", () -> simulateDirectConsumptionWithBattery(0.0f, 10.0f, 0.0f, 0.0f, 0.0f, "No producer, empty battery")), - dynamicTest("07", () -> simulateDirectConsumptionWithBattery(0.0f, 10.0f, 100.0f, 95.0f, 1.0f, "No producer, full battery")), - dynamicTest("08", () -> simulateDirectConsumptionWithBattery(0.0f, 10.0f, 2.5f, 0.0f, 0.5f, "No producer, low battery")), - dynamicTest("09", () -> simulateDirectConsumptionWithBattery(5.0f, 10.0f, 5.0f, 0.0f, 1.0f, "Producer + Battery = Consumed")), + // Note: expectedBatteryCapacity is currently adjusted to a delta of 0.5! (FakeThreadHandler sets it to that) + dynamicTest("01", () -> simulateDirectConsumptionWithBattery(10.0f, 0.0f, 0.0f, 5.0f, 0.0f, "Empty battery, no consumer")), + dynamicTest("02", () -> simulateDirectConsumptionWithBattery(10.0f, 0.0f, 94.999f, 99.999f, 0.0f, "Battery almost full after update, no consumer")), + dynamicTest("03", () -> simulateDirectConsumptionWithBattery(10.0f, 0.0f, 100.0f, 100.0f, 0.0f, "Full battery, no consumer")), + dynamicTest("04", () -> simulateDirectConsumptionWithBattery(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, "No producer, no consumer, empty battery")), + dynamicTest("05", () -> simulateDirectConsumptionWithBattery(0.0f, 0.0f, 100.0f, 100.0f, 0.0f, "No producer, no consumer, full battery")), + dynamicTest("06", () -> simulateDirectConsumptionWithBattery(0.0f, 10.0f, 0.0f, 0.0f, 0.0f, "No producer, empty battery")), + dynamicTest("07", () -> simulateDirectConsumptionWithBattery(0.0f, 10.0f, 100.0f, 95.0f, 1.0f, "No producer, full battery")), + dynamicTest("08", () -> simulateDirectConsumptionWithBattery(0.0f, 10.0f, 2.5f, 0.0f, 0.5f, "No producer, low battery")), + dynamicTest("09", () -> simulateDirectConsumptionWithBattery(5.0f, 10.0f, 5.0f, 0.0f, 1.0f, "Producer + Battery = Consumed")), }; } + void simulateDirectConsumptionWithBattery(float producedPower, float requestedPower, float initialBatteryCapacity, float expectedBatteryCapacity, float expectedSatisfaction, String parameterDescription){ PowerGraph powerGraph = new PowerGraph(); @@ -145,7 +150,7 @@ public class PowerTests extends PowerTestFixture{ powerGraph.add(directConsumerTile); } float maxCapacity = 100f; - Tile batteryTile = createFakeTile(0, 2, createFakeBattery(maxCapacity, 10 )); + Tile batteryTile = createFakeTile(0, 2, createFakeBattery(maxCapacity, 10)); batteryTile.entity.power.satisfaction = initialBatteryCapacity / maxCapacity; powerGraph.add(batteryTile); @@ -176,9 +181,9 @@ public class PowerTests extends PowerTestFixture{ powerGraph.update(); assertEquals(0.0f, consumerTile.entity.power.satisfaction, Mathf.FLOAT_ROUNDING_ERROR); - if(consumerTile.block().consumes.has(ConsumePower.class)){ - ConsumePower consumePower = consumerTile.block().consumes.get(ConsumePower.class); - assertFalse(consumePower.valid(consumerTile.block(), consumerTile.entity())); + if(consumerTile.block().consumes.hasPower()){ + ConsumePower consumePower = consumerTile.block().consumes.getPower(); + assertFalse(consumePower.valid(consumerTile.entity())); } } } diff --git a/tools/build.gradle b/tools/build.gradle index 11c12fa338..c161ff6ea1 100644 --- a/tools/build.gradle +++ b/tools/build.gradle @@ -1,20 +1,19 @@ apply plugin: "java" sourceCompatibility = 1.8 -sourceSets.main.java.srcDirs = [ "src/" ] +sourceSets.main.java.srcDirs = ["src/"] import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.tools.texturepacker.TexturePacker import javax.imageio.ImageIO -import java.awt.image.BufferedImage +import java.awt.image.BufferedImage def outFolder = "../core/assets-raw/sprites_out/" def genFolder = "../core/assets-raw/sprites_out/generated/" -def packFile = "../core/assets-raw/sprites/pack.json" def doAntialias = !project.hasProperty("disableAntialias") -def antialias = {File file -> +def antialias = { File file -> if(!doAntialias || file.lastModified() <= 1000) return def image = ImageIO.read(file) @@ -29,7 +28,7 @@ def antialias = {File file -> def sum = new Color() def suma = new Color() - for (int x = 0; x < image.getWidth(); x++){ + for(int x = 0; x < image.getWidth(); x++){ for(int y = 0; y < image.getHeight(); y++){ int A = getRGB(x - 1, y + 1), @@ -42,28 +41,28 @@ def antialias = {File file -> H = getRGB(x, y - 1), I = getRGB(x + 1, y - 1) - int p1=E, p2=E, p3=E, p4=E, p5=E, p6=E, p7=E, p8=E, p9=E - if (D==B && D!=H && B!=F) p1=D - if ((D==B && D!=H && B!=F && E!=C) || (B==F && B!=D && F!=H && E!=A)) p2=B - if (B==F && B!=D && F!=H) p3=F - if ((H==D && H!=F && D!=B && E!=A) || (D==B && D!=H && B!=F && E!=G)) p4=D - p5=E - if ((B==F && B!=D && F!=H && E!=I) || (F==H && F!=B && H!=D && E!=C)) p6=F - if (H==D && H!=F && D!=B) p7=D - if ((F==H && F!=B && H!=D && E!=G) || (H==D && H!=F && D!=B && E!=I)) p8=H - if (F==H && F!=B && H!=D) p9=F + int p1 = E, p2 = E, p3 = E, p4 = E, p5 = E, p6 = E, p7 = E, p8 = E, p9 = E + if(D == B && D != H && B != F) p1 = D + if((D == B && D != H && B != F && E != C) || (B == F && B != D && F != H && E != A)) p2 = B + if(B == F && B != D && F != H) p3 = F + if((H == D && H != F && D != B && E != A) || (D == B && D != H && B != F && E != G)) p4 = D + p5 = E + if((B == F && B != D && F != H && E != I) || (F == H && F != B && H != D && E != C)) p6 = F + if(H == D && H != F && D != B) p7 = D + if((F == H && F != B && H != D && E != G) || (H == D && H != F && D != B && E != I)) p8 = H + if(F == H && F != B && H != D) p9 = F suma.set(0) [p1, p2, p3, p4, p5, p6, p7, p8, p9].each{ val -> Color.argb8888ToColor(color, val) - suma.r += color.r*color.a - suma.g += color.g*color.a - suma.b += color.b*color.a + suma.r += color.r * color.a + suma.g += color.g * color.a + suma.b += color.b * color.a suma.a += color.a } - suma.mul(suma.a <= 0.001f ? 0f : (float)(1f / suma.a)) + suma.mul(suma.a <= 0.001f ? 0f : (float) (1f / suma.a)) float total = 0 sum.set(0) @@ -71,7 +70,7 @@ def antialias = {File file -> [p1, p2, p3, p4, p5, p6, p7, p8, p9].each{ val -> Color.argb8888ToColor(color, val) float a = color.a - color.lerp(suma, (float)(1f - a)) + color.lerp(suma, (float) (1f - a)) sum.r += color.r sum.g += color.g sum.b += color.b @@ -79,7 +78,7 @@ def antialias = {File file -> total += 1f } - sum.mul((float)(1f / total)) + sum.mul((float) (1f / total)) int result = Color.argb8888(sum) out.setRGB(x, y, result) sum.set(0) @@ -91,25 +90,25 @@ def antialias = {File file -> task swapColors(){ doLast{ - if (project.hasProperty("colors")) { + if(project.hasProperty("colors")){ def carr = new File(getProperty("colors")).text.split("\n") def map = [:] def swaps = 0 - carr.each{str -> map[Color.argb8888(Color.valueOf(str.split("=")[0]))] = Color.argb8888(Color.valueOf(str.split("=")[1]))} + carr.each{ str -> map[Color.argb8888(Color.valueOf(str.split("=")[0]))] = Color.argb8888(Color.valueOf(str.split("=")[1])) } def tmpc = new Color() - fileTree(dir: '../core/assets-raw/sprites', include: "**/*.png").visit { file -> + fileTree(dir: '../core/assets-raw/sprites', include: "**/*.png").visit{ file -> if(file.isDirectory()) return - swaps ++ + swaps++ def img = ImageIO.read(file.file) - for (x in (0..img.getWidth()-1)) { - for (y in (0..img.getHeight()-1)) { + for(x in (0..img.getWidth() - 1)){ + for(y in (0..img.getHeight() - 1)){ def c = img.getRGB(x, y) Color.argb8888ToColor(tmpc, c) if(tmpc.a < 0.1f) continue if(map.containsKey(c)){ - img.setRGB(x, y, (int)map.get(c)) + img.setRGB(x, y, (int) map.get(c)) } } } @@ -124,10 +123,10 @@ task swapColors(){ task scaleSprites4x(){ doLast{ - fileTree(dir: '../core/assets-raw/sprites_out/', include: "**/*.png").visit { file -> + fileTree(dir: '../core/assets-raw/sprites_out/', include: "**/*.png").visit{ file -> if(file.isDirectory() || file.toString().contains("/ui/")) return - for(int iteration in 0..1) { + for(int iteration in 0..1){ def image = ImageIO.read(file.file) def scaled = new BufferedImage(image.getWidth() * 2, image.getHeight() * 2, BufferedImage.TYPE_INT_ARGB) @@ -136,8 +135,8 @@ task scaleSprites4x(){ return image.getRGB(Math.max(Math.min(ix, image.width - 1), 0), Math.max(Math.min(iy, image.height - 1), 0)) } - for (int x = 0; x < image.getWidth(); x++) { - for (int y = 0; y < image.getHeight(); y++) { + for(int x = 0; x < image.getWidth(); x++){ + for(int y = 0; y < image.getHeight(); y++){ int p = image.getRGB(x, y) int p1 = p, p2 = p, p3 = p, p4 = p @@ -149,16 +148,16 @@ task scaleSprites4x(){ F = getRGB(x + 1, y), G = getRGB(x - 1, y - 1), H = getRGB(x, y - 1), - I = getRGB(x + 1, y - 1), + I = getRGB(x + 1, y - 1), J = getRGB(x, y + 2), K = getRGB(x - 2, y), L = getRGB(x + 2, y), - M = getRGB(x, y - 2); + M = getRGB(x, y - 2) - if (B==D && B!=F && D!=H && (E!=A || E==C || E==G || A==J || A==K)) p1 = B - if (B==F & B!=D & F!=H && (E!=C || E==A || E==I || C==J || C==L)) p2 = F - if (D==H & B!=D & F!=H && (E!=G || E==A || E==I || G==K || G==M)) p3 = D - if (F==H & B!=F & D!=H && (E!=I || E==C || E==G || I==L || I==M)) p4 = H + if(B == D && B != F && D != H && (E != A || E == C || E == G || A == J || A == K)) p1 = B + if(B == F & B != D & F != H && (E != C || E == A || E == I || C == J || C == L)) p2 = F + if(D == H & B != D & F != H && (E != G || E == A || E == I || G == K || G == M)) p3 = D + if(F == H & B != F & D != H && (E != I || E == C || E == G || I == L || I == M)) p4 = H scaled.setRGB(x * 2, y * 2 + 1, p1) scaled.setRGB(x * 2 + 1, y * 2 + 1, p2) @@ -184,7 +183,7 @@ task scaleSprites(){ into "../core/assets-raw/sprites_out/" } } - + dependsOn 'scaleSprites4x' } @@ -201,13 +200,26 @@ task pack(){ } 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 { + doLast{ + delete{ delete genFolder delete outFolder } @@ -238,16 +250,16 @@ task antialiasGen(){ } } -task genSprites(dependsOn: classes, type: JavaExec) { +task genSprites(dependsOn: classes, type: JavaExec){ finalizedBy 'antialiasGen' - + main = "io.anuke.mindustry.ImagePacker" classpath = sourceSets.main.runtimeClasspath standardInput = System.in workingDir = genFolder } -task updateBundles(dependsOn: classes, type: JavaExec) { +task updateBundles(dependsOn: classes, type: JavaExec){ file(genFolder).mkdirs() main = "io.anuke.mindustry.BundleLauncher" diff --git a/tools/src/io/anuke/mindustry/BundleLauncher.java b/tools/src/io/anuke/mindustry/BundleLauncher.java index 8732638b89..69b0e525b9 100644 --- a/tools/src/io/anuke/mindustry/BundleLauncher.java +++ b/tools/src/io/anuke/mindustry/BundleLauncher.java @@ -4,18 +4,13 @@ import io.anuke.arc.collection.Array; import io.anuke.arc.collection.OrderedMap; import io.anuke.arc.function.BiFunction; import io.anuke.arc.util.Log; +import io.anuke.arc.util.Strings; import io.anuke.arc.util.io.PropertiesUtils; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; +import java.io.*; +import java.nio.file.*; -public class BundleLauncher { +public class BundleLauncher{ public static void main(String[] args) throws Exception{ File file = new File("bundle.properties"); @@ -24,13 +19,14 @@ public class BundleLauncher { Array removals = new Array<>(); Files.walk(Paths.get("")).forEach(child -> { - try { - if (child.getFileName().toString().equals("bundle.properties") || Files.isDirectory(child) || child.toString().contains("output")) return; + try{ + if(child.getFileName().toString().equals("bundle.properties") || Files.isDirectory(child) || child.toString().contains("output")) + return; Log.info("Parsing bundle: {0}", child); OrderedMap other = new OrderedMap<>(); - PropertiesUtils.load(other, Files.newBufferedReader(child, StandardCharsets.UTF_8)); + PropertiesUtils.load(other, Files.newBufferedReader(child, Strings.utf8)); removals.clear(); for(String key : other.orderedKeys()){ @@ -49,7 +45,7 @@ public class BundleLauncher { for(String key : base.orderedKeys()){ if(!other.containsKey(key) || other.get(key).trim().isEmpty()){ other.put(key, base.get(key)); - added ++; + added++; Log.info("&lc- Adding missing key '{0}'...", key); } } @@ -68,9 +64,9 @@ public class BundleLauncher { other.remove(key); } - Files.write(child, result.toString().getBytes(StandardCharsets.UTF_8)); + Files.write(child, result.toString().getBytes(Strings.utf8)); - }catch (IOException e){ + }catch(IOException e){ throw new RuntimeException(e); } }); diff --git a/tools/src/io/anuke/mindustry/Generators.java b/tools/src/io/anuke/mindustry/Generators.java index 5989906d99..0ef8513a3e 100644 --- a/tools/src/io/anuke/mindustry/Generators.java +++ b/tools/src/io/anuke/mindustry/Generators.java @@ -6,10 +6,7 @@ import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Log; import io.anuke.mindustry.ImagePacker.GenRegion; -import io.anuke.mindustry.type.ContentType; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.Mech; -import io.anuke.mindustry.type.UnitType; +import io.anuke.mindustry.type.*; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block.Icon; import io.anuke.mindustry.world.blocks.Floor; @@ -22,7 +19,7 @@ import java.nio.file.Paths; import static io.anuke.mindustry.Vars.content; import static io.anuke.mindustry.Vars.tilesize; -public class Generators { +public class Generators{ public static void generate(){ @@ -54,16 +51,15 @@ public class Generators { Image last = null; if(block.outlineIcon){ int radius = 3; - GenRegion region = (GenRegion)regions[regions.length-1]; + GenRegion region = (GenRegion)regions[regions.length - 1]; Image base = ImagePacker.get(region); Image out = last = new Image(region.getWidth(), region.getHeight()); for(int x = 0; x < out.width(); x++){ for(int y = 0; y < out.height(); y++){ Color color = base.getColor(x, y); - if(color.a >= 0.01f){ - out.draw(x, y, color); - }else{ + out.draw(x, y, color); + if(color.a < 1f){ boolean found = false; outer: for(int rx = -radius; rx <= radius; rx++){ @@ -94,7 +90,7 @@ public class Generators { int i = 0; for(TextureRegion region : regions){ - i ++; + i++; if(i != regions.length || last == null){ image.draw(region); }else{ @@ -125,6 +121,11 @@ public class Generators { } } average.mul(1f / (image.width() * image.height())); + if(block instanceof Floor){ + average.mul(0.8f); + }else{ + average.mul(1.1f); + } average.a = 1f; colors.draw(block.id, 0, average); }catch(IllegalArgumentException e){ @@ -151,7 +152,6 @@ public class Generators { ImagePacker.generate("mech-icons", () -> { for(Mech mech : content.getBy(ContentType.mech)){ - mech.load(); mech.weapon.load(); @@ -164,7 +164,7 @@ public class Generators { image.drawCenter(mech.region); } - int off = image.width()/2 - mech.weapon.region.getWidth()/2; + int off = image.width() / 2 - mech.weapon.region.getWidth() / 2; image.draw(mech.weapon.region, -(int)mech.weaponOffsetX + off, (int)mech.weaponOffsetY + off, false, false); image.draw(mech.weapon.region, (int)mech.weaponOffsetX + off, (int)mech.weaponOffsetY + off, true, false); @@ -175,9 +175,7 @@ public class Generators { }); ImagePacker.generate("unit-icons", () -> { - for(UnitType type : content.getBy(ContentType.unit)){ - if(type.isFlying) continue; - + content.getBy(ContentType.unit).each(type -> !type.isFlying, type -> { type.load(); type.weapon.load(); @@ -190,31 +188,28 @@ public class Generators { for(boolean b : Mathf.booleans){ image.draw(type.weapon.region, - (int)(Mathf.sign(b) * type.weapon.width / Draw.scl + image.width()/2 - type.weapon.region.getWidth()/2), - (int)(type.weaponOffsetY / Draw.scl + image.height()/2f - type.weapon.region.getHeight()/2f), + (int)(Mathf.sign(b) * type.weapon.width / Draw.scl + image.width() / 2 - type.weapon.region.getWidth() / 2), + (int)(type.weaponOffsetY / Draw.scl + image.height() / 2f - type.weapon.region.getHeight() / 2f), b, false); } image.save("unit-icon-" + type.name); - } + }); }); ImagePacker.generate("ore-icons", () -> { - for(Block block : content.blocks()){ - if(!(block instanceof OreBlock)) continue; - - OreBlock ore = (OreBlock)block; + content.blocks().each(b -> b instanceof OreBlock, ore -> { Item item = ore.itemDrop; - for (int i = 0; i < 3; i++) { + for(int i = 0; i < 3; i++){ //get base image to draw on Image image = new Image(32, 32); - Image shadow = ImagePacker.get(item.name + (i+1)); + Image shadow = ImagePacker.get(item.name + (i + 1)); - int offset = image.width()/tilesize; + int offset = image.width() / tilesize; - for (int x = 0; x < image.width(); x++) { - for (int y = offset; y < image.height(); y++) { + for(int x = 0; x < image.width(); x++){ + for(int y = offset; y < image.height(); y++){ Color color = shadow.getColor(x, y - offset); //draw semi transparent background @@ -225,30 +220,27 @@ public class Generators { } } - image.draw(ImagePacker.get(item.name + (i+1))); - image.save("../blocks/environment/ore-" + item.name + (i+1)); - image.save("../editor/editor-ore-" + item.name + (i+1)); + image.draw(ImagePacker.get(item.name + (i + 1))); + image.save("../blocks/environment/ore-" + item.name + (i + 1)); + image.save("../editor/editor-ore-" + item.name + (i + 1)); //save icons - image.save(block.name + "-icon-full"); + image.save(ore.name + "-icon-full"); for(Icon icon : Icon.values()){ 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(ore.name + "-icon-" + icon.name()); } } - } + }); }); ImagePacker.generate("edges", () -> { - for(Block block : content.blocks()){ - if(!(block instanceof Floor)) continue; - - Floor floor = (Floor)block; + content.blocks().each(b -> b instanceof Floor, floor -> { if(ImagePacker.has(floor.name + "-edge") || floor.blendGroup != floor){ - continue; + return; } try{ @@ -265,7 +257,7 @@ public class Generators { result.save("../blocks/environment/" + floor.name + "-edge"); }catch(Exception ignored){} - } + }); }); } diff --git a/tools/src/io/anuke/mindustry/Image.java b/tools/src/io/anuke/mindustry/Image.java index d64214501c..5759f5ba68 100644 --- a/tools/src/io/anuke/mindustry/Image.java +++ b/tools/src/io/anuke/mindustry/Image.java @@ -12,7 +12,7 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; -class Image { +class Image{ private static ArrayList toDispose = new ArrayList<>(); private BufferedImage image; @@ -63,31 +63,31 @@ class Image { graphics.fillRect(x, y, 1, 1); } - /**Draws a region at the top left corner.*/ + /** Draws a region at the top left corner. */ void draw(TextureRegion region){ draw(region, 0, 0, false, false); } - /**Draws a region at the center.*/ + /** Draws a region at the center. */ void drawCenter(TextureRegion region){ - draw(region, (width() - region.getWidth())/2, (height() - region.getHeight())/2, false, false); + draw(region, (width() - region.getWidth()) / 2, (height() - region.getHeight()) / 2, false, false); } - /**Draws a region at the center.*/ + /** Draws a region at the center. */ void drawCenter(TextureRegion region, boolean flipx, boolean flipy){ - draw(region, (width() - region.getWidth())/2, (height() - region.getHeight())/2, flipx, flipy); + draw(region, (width() - region.getWidth()) / 2, (height() - region.getHeight()) / 2, flipx, flipy); } void drawScaled(Image image){ graphics.drawImage(image.image.getScaledInstance(width(), height(), java.awt.Image.SCALE_AREA_AVERAGING), 0, 0, width(), height(), null); } - /**Draws an image at the top left corner.*/ + /** Draws an image at the top left corner. */ void draw(Image image){ draw(image, 0, 0); } - /**Draws an image at the coordinates specified.*/ + /** Draws an image at the coordinates specified. */ void draw(Image image, int x, int y){ graphics.drawImage(image.image, x, y, null); } @@ -102,21 +102,21 @@ class Image { int ofx = 0, ofy = 0; graphics.drawImage(ImagePacker.get(region).image, - x, y, - x + region.getWidth(), - y + region.getHeight(), - (flipx ? region.getWidth() : 0) + ofx, - (flipy ? region.getHeight() : 0) + ofy, - (flipx ? 0 : region.getWidth()) + ofx, - (flipy ? 0 : region.getHeight()) + ofy, - null); + x, y, + x + region.getWidth(), + y + region.getHeight(), + (flipx ? region.getWidth() : 0) + ofx, + (flipy ? region.getHeight() : 0) + ofy, + (flipx ? 0 : region.getWidth()) + ofx, + (flipy ? 0 : region.getHeight()) + ofy, + null); } - /** @param name Name of texture file name to create, without any extensions.*/ + /** @param name Name of texture file name to create, without any extensions. */ void save(String name){ - try { + try{ ImageIO.write(image, "png", new File(name + ".png")); - }catch (IOException e){ + }catch(IOException e){ throw new RuntimeException(e); } } diff --git a/tools/src/io/anuke/mindustry/ImagePacker.java b/tools/src/io/anuke/mindustry/ImagePacker.java index 6ec867511a..119e4d217e 100644 --- a/tools/src/io/anuke/mindustry/ImagePacker.java +++ b/tools/src/io/anuke/mindustry/ImagePacker.java @@ -2,23 +2,17 @@ package io.anuke.mindustry; import io.anuke.arc.Core; import io.anuke.arc.collection.ObjectMap; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.TextureAtlas; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.graphics.g2d.TextureAtlas.AtlasRegion; -import io.anuke.arc.graphics.g2d.TextureRegion; -import io.anuke.arc.util.Log; +import io.anuke.arc.util.*; import io.anuke.arc.util.Log.LogHandler; import io.anuke.arc.util.Log.NoopLogHandler; -import io.anuke.arc.util.Strings; -import io.anuke.arc.util.Time; import io.anuke.mindustry.core.ContentLoader; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; +import java.nio.file.*; public class ImagePacker{ static ObjectMap regionCache = new ObjectMap<>(); @@ -91,12 +85,12 @@ public class ImagePacker{ } @Override - public boolean has(String s) { + public boolean has(String s){ return regionCache.containsKey(s); } }; - Draw.scl = 1f/Core.atlas.find("scale_marker").getWidth(); + Draw.scl = 1f / Core.atlas.find("scale_marker").getWidth(); Time.mark(); Generators.generate();