diff --git a/TRANSLATING.md b/TRANSLATING.md index b40c0c79d1..efea047a75 100644 --- a/TRANSLATING.md +++ b/TRANSLATING.md @@ -18,7 +18,7 @@ Once this is done, all you need to do is wait for me to approve your changes. If a translation bundle for your language *doesn't* exist, you need to create one yourself. In the folder with all the bundles in it, click the *'create new file'* button, and name it `bundle_(locale code here).properties`. -Then, copy-paste the entire contents of the [English translation bundle](https://raw.githubusercontent.com/Anuken/Mindustry/master/core/assets/bundles/bundle.propertie) into the file, and translate all the necessary text to your language. +Then, copy-paste the entire contents of the [English translation bundle](https://raw.githubusercontent.com/Anuken/Mindustry/master/core/assets/bundles/bundle.properties) into the file, and translate all the necessary text to your language. Once you are done, press the *propose new file* button at the bottom, then 'create pull request twice'. #### Useful Information @@ -36,4 +36,4 @@ There are two ways to test the translation bundle: **And that's it.** -*(...of course, that's never really it. Bother me on Discord when something inevatably goes wrong.)* \ No newline at end of file +*(...of course, that's never really it. Bother me on Discord when something inevitably goes wrong.)* diff --git a/android/build.gradle b/android/build.gradle index a2d912a486..ef46301699 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -24,7 +24,6 @@ dependencies { natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-arm64-v8a" natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86" natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86_64" - implementation "com.badlogicgames.gdx:gdx-ai:$aiVersion" implementation "com.badlogicgames.gdx:gdx-controllers-android:$gdxVersion" } diff --git a/android/src/io/anuke/mindustry/AndroidLauncher.java b/android/src/io/anuke/mindustry/AndroidLauncher.java index 0f6ab0924b..30253a1d85 100644 --- a/android/src/io/anuke/mindustry/AndroidLauncher.java +++ b/android/src/io/anuke/mindustry/AndroidLauncher.java @@ -12,7 +12,6 @@ import android.provider.Settings.Secure; import android.telephony.TelephonyManager; import android.util.Log; import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.backends.android.AndroidApplication; import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.utils.Base64Coder; @@ -25,8 +24,8 @@ import io.anuke.kryonet.KryoClient; import io.anuke.kryonet.KryoServer; import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.core.ThreadHandler.ThreadProvider; -import io.anuke.mindustry.io.SaveIO; 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.ucore.function.Consumer; @@ -48,19 +47,16 @@ import java.util.Locale; import static io.anuke.mindustry.Vars.*; -public class AndroidLauncher extends AndroidApplication{ +public class AndroidLauncher extends PatchedAndroidApplication{ public static final int PERMISSION_REQUEST_CODE = 1; - boolean doubleScaleTablets = true; FileChooser chooser; @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); - AndroidApplicationConfiguration config = new AndroidApplicationConfiguration(); config.useImmersiveMode = true; - Platform.instance = new Platform(){ DateFormat format = SimpleDateFormat.getDateTimeInstance(); @@ -108,19 +104,15 @@ public class AndroidLauncher extends AndroidApplication{ public String getUUID(){ try{ String s = Secure.getString(getContext().getContentResolver(), - Secure.ANDROID_ID); - + Secure.ANDROID_ID); 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) - + Character.digit(s.charAt(i + 1), 16)); + + Character.digit(s.charAt(i + 1), 16)); } - String result = new String(Base64Coder.encode(data)); - if(result.equals("AAAAAAAAAOA=")) throw new RuntimeException("Bad UUID."); - return result; }catch(Exception e){ return super.getUUID(); @@ -129,28 +121,23 @@ public class AndroidLauncher extends AndroidApplication{ @Override public void shareFile(FileHandle file){ - } @Override public void showFileChooser(String text, String content, Consumer cons, boolean open, String filetype){ chooser = new FileChooser(text, file -> file.extension().equalsIgnoreCase(filetype), open, cons); - if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M || (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED && - checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)){ + checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)){ chooser.show(); chooser = null; }else{ ArrayList perms = new ArrayList<>(); - if(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){ perms.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); } - 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); } } @@ -170,7 +157,6 @@ public class AndroidLauncher extends AndroidApplication{ return true; } }; - try{ ProviderInstaller.installIfNeeded(this); }catch(GooglePlayServicesRepairableException e){ @@ -179,18 +165,13 @@ public class AndroidLauncher extends AndroidApplication{ }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()); - initialize(new Mindustry(), config); - checkFiles(getIntent()); } @@ -200,7 +181,6 @@ public class AndroidLauncher extends AndroidApplication{ for(int i : grantResults){ if(i != PackageManager.PERMISSION_GRANTED) return; } - if(chooser != null){ chooser.show(); } @@ -220,21 +200,16 @@ public class AndroidLauncher extends AndroidApplication{ //error return; } - boolean save = uri.getPath().endsWith(saveExtension); boolean map = uri.getPath().endsWith(mapExtension); - InputStream inStream; if(myFile != null) inStream = new FileInputStream(myFile); else inStream = getContentResolver().openInputStream(uri); - Gdx.app.postRunnable(() -> { - if(save){ //open save System.out.println("Opening save."); FileHandle file = Gdx.files.local("temp-save." + saveExtension); file.write(inStream, false); - if(SaveIO.isSaveValid(file)){ try{ SaveSlot slot = control.getSaves().importSave(file); @@ -245,20 +220,17 @@ public class AndroidLauncher extends AndroidApplication{ }else{ ui.showError("$text.save.import.invalid"); } - }else if(map){ //open map Gdx.app.postRunnable(() -> { System.out.println("Opening map."); if(!ui.editor.isShown()){ ui.editor.show(); } - ui.editor.beginEditMap(inStream); }); } }); } - }catch(IOException e){ e.printStackTrace(); } diff --git a/android/src/io/anuke/mindustry/PatchedAndroidApplication.java b/android/src/io/anuke/mindustry/PatchedAndroidApplication.java new file mode 100644 index 0000000000..3ed0df141e --- /dev/null +++ b/android/src/io/anuke/mindustry/PatchedAndroidApplication.java @@ -0,0 +1,20 @@ +package io.anuke.mindustry; + +import com.badlogic.gdx.backends.android.AndroidApplication; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class PatchedAndroidApplication extends AndroidApplication { + private final ExecutorService exec = Executors.newSingleThreadExecutor(); + + @Override + protected void onPause () { + if(useImmersiveMode) { + exec.submit(() -> { + try {Thread.sleep(100);} catch (InterruptedException ignored) {} + graphics.onDrawFrame(null); + }); + } + super.onPause(); + } +} \ No newline at end of file diff --git a/annotations/src/io/anuke/annotations/Annotations.java b/annotations/src/io/anuke/annotations/Annotations.java index cc60478fee..eeef7c2599 100644 --- a/annotations/src/io/anuke/annotations/Annotations.java +++ b/annotations/src/io/anuke/annotations/Annotations.java @@ -80,9 +80,6 @@ public class Annotations{ */ boolean unreliable() default false; - /** The simple class name where this method is placed. */ - String in() default "Call"; - /** Priority of this event. */ PacketPriority priority() default PacketPriority.normal; } diff --git a/annotations/src/io/anuke/annotations/RemoteMethodAnnotationProcessor.java b/annotations/src/io/anuke/annotations/RemoteMethodAnnotationProcessor.java index b0402b2c55..879cf1f202 100644 --- a/annotations/src/io/anuke/annotations/RemoteMethodAnnotationProcessor.java +++ b/annotations/src/io/anuke/annotations/RemoteMethodAnnotationProcessor.java @@ -35,6 +35,8 @@ 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.*/ + private static final String callLocation = "Call"; /** Processing round number. */ private int round; @@ -102,15 +104,15 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor{ } //get and create class entry if needed - if(!classMap.containsKey(annotation.in())){ - ClassEntry clas = new ClassEntry(annotation.in()); - classMap.put(annotation.in(), clas); + if(!classMap.containsKey(callLocation)){ + ClassEntry clas = new ClassEntry(callLocation); + classMap.put(callLocation, clas); classes.add(clas); Utils.messager.printMessage(Kind.NOTE, "Generating class '" + clas.name + "'."); } - ClassEntry entry = classMap.get(annotation.in()); + ClassEntry entry = classMap.get(callLocation); //create and add entry MethodEntry method = new MethodEntry(entry.name, Utils.getMethodName(element), annotation.targets(), annotation.variants(), diff --git a/build.gradle b/build.gradle index ddef997065..cc3e3674b4 100644 --- a/build.gradle +++ b/build.gradle @@ -26,8 +26,7 @@ allprojects { appName = 'Mindustry' gdxVersion = '1.9.8' roboVMVersion = '2.3.0' - aiVersion = '1.8.1' - uCoreVersion = 'b93d02efe3fdbe1a10b33d59597da8693d4f7de3' + uCoreVersion = '239e6a5bad' getVersionString = { String buildVersion = getBuildVersion() @@ -97,7 +96,6 @@ project(":desktop") { compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop" compile "com.badlogicgames.gdx:gdx-controllers-lwjgl3:$gdxVersion" compile 'com.github.MinnDevelopment:java-discord-rpc:v2.0.0' - compile 'com.yuvimasory:orange-extensions:1.3.0' } } @@ -113,13 +111,10 @@ project(":html") { compile "com.badlogicgames.gdx:gdx-backend-gwt:$gdxVersion" compile "com.badlogicgames.gdx:gdx:$gdxVersion:sources" compile "com.badlogicgames.gdx:gdx-backend-gwt:$gdxVersion:sources" - compile "com.badlogicgames.gdx:gdx-ai:$aiVersion:sources" compile "com.badlogicgames.gdx:gdx-controllers:$gdxVersion:sources" compile "com.badlogicgames.gdx:gdx-controllers-gwt:$gdxVersion" compile "com.badlogicgames.gdx:gdx-controllers-gwt:$gdxVersion:sources" - compile "com.sksamuel.gwt:gwt-websockets:1.0.4" - compile "com.sksamuel.gwt:gwt-websockets:1.0.4:sources" } compileJava.options.compilerArgs = [ @@ -154,13 +149,9 @@ project(":core") { compileOnly project(":annotations") build.finalizedBy(finish) - boolean comp = System.properties["release"] == null || System.properties["release"] == "false" + def comp = System.properties["release"] == null || System.properties["release"] == "false" - if(!comp){ - println("NOTICE: Compiling release build.") - }else{ - println("Compiling DEBUG build.") - } + if(!comp) println("Note: Compiling release build.") if(new File(projectDir.parent, '../uCore').exists() && comp){ compile project(":uCore") @@ -220,7 +211,6 @@ project(":kryonet") { dependencies { compile project(":core") compile 'com.github.crykn:kryonet:2.22.1' - compile "org.java-websocket:Java-WebSocket:1.3.7" } } diff --git a/core/assets-raw/sprites/blocks/distribution/mass-driver-turret.png b/core/assets-raw/sprites/blocks/distribution/mass-driver-turret.png index 350e7c66f4..dc80819cd5 100644 Binary files a/core/assets-raw/sprites/blocks/distribution/mass-driver-turret.png and b/core/assets-raw/sprites/blocks/distribution/mass-driver-turret.png differ diff --git a/core/assets-raw/sprites/blocks/distribution/mass-driver.png b/core/assets-raw/sprites/blocks/distribution/mass-driver.png index f1d779149d..cde1d754f9 100644 Binary files a/core/assets-raw/sprites/blocks/distribution/mass-driver.png and b/core/assets-raw/sprites/blocks/distribution/mass-driver.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 a1f5d3765f..48de6544b7 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/extra/shadow-round-3.png b/core/assets-raw/sprites/blocks/extra/shadow-round-3.png new file mode 100644 index 0000000000..f2b116ff67 Binary files /dev/null and b/core/assets-raw/sprites/blocks/extra/shadow-round-3.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/rotary-pump.png b/core/assets-raw/sprites/blocks/liquid/rotary-pump.png index 10a877f3ae..8f774bef86 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/rotary-pump.png and b/core/assets-raw/sprites/blocks/liquid/rotary-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 786b6861d5..6fe78e5277 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/thermal-generator.png b/core/assets-raw/sprites/blocks/power/thermal-generator.png index 388654a481..10347e1bc4 100644 Binary files a/core/assets-raw/sprites/blocks/power/thermal-generator.png and b/core/assets-raw/sprites/blocks/power/thermal-generator.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/duo.png b/core/assets-raw/sprites/blocks/turrets/turrets/duo.png index 7bae2646f3..4489cd4d0a 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/turrets/duo.png and b/core/assets-raw/sprites/blocks/turrets/turrets/duo.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/hail.png b/core/assets-raw/sprites/blocks/turrets/turrets/hail.png index 075325a110..5f60ab935c 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/turrets/hail.png and b/core/assets-raw/sprites/blocks/turrets/turrets/hail.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/scatter.png b/core/assets-raw/sprites/blocks/turrets/turrets/scatter.png index 075325a110..dbf3c6b1e3 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/turrets/scatter.png and b/core/assets-raw/sprites/blocks/turrets/turrets/scatter.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/scorch-shoot.png b/core/assets-raw/sprites/blocks/turrets/turrets/scorch-shoot.png index c03ba1b198..4440fa71db 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/turrets/scorch-shoot.png and b/core/assets-raw/sprites/blocks/turrets/turrets/scorch-shoot.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/scorch.png b/core/assets-raw/sprites/blocks/turrets/turrets/scorch.png index 91338f693f..f87936dd22 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/turrets/scorch.png and b/core/assets-raw/sprites/blocks/turrets/turrets/scorch.png differ diff --git a/core/assets-raw/sprites/blocks/units/command-center.png b/core/assets-raw/sprites/blocks/units/command-center.png new file mode 100644 index 0000000000..5896dc84ee Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/command-center.png differ diff --git a/core/assets-raw/sprites/blocks/units/dagger-pad-top-open.png b/core/assets-raw/sprites/blocks/units/dagger-pad-top-open.png new file mode 100644 index 0000000000..812083edcb Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/dagger-pad-top-open.png differ diff --git a/core/assets-raw/sprites/blocks/units/dagger-pad-top.png b/core/assets-raw/sprites/blocks/units/dagger-pad-top.png new file mode 100644 index 0000000000..5fbc8a10d5 Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/dagger-pad-top.png differ diff --git a/core/assets-raw/sprites/blocks/units/dagger-pad.png b/core/assets-raw/sprites/blocks/units/dagger-pad.png new file mode 100644 index 0000000000..f6c0760212 Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/dagger-pad.png differ diff --git a/core/assets-raw/sprites/blocks/units/drone-factory-top-open.png b/core/assets-raw/sprites/blocks/units/drone-pad-top-open.png similarity index 100% rename from core/assets-raw/sprites/blocks/units/drone-factory-top-open.png rename to core/assets-raw/sprites/blocks/units/drone-pad-top-open.png diff --git a/core/assets-raw/sprites/blocks/units/drone-factory-top.png b/core/assets-raw/sprites/blocks/units/drone-pad-top.png similarity index 100% rename from core/assets-raw/sprites/blocks/units/drone-factory-top.png rename to core/assets-raw/sprites/blocks/units/drone-pad-top.png diff --git a/core/assets-raw/sprites/blocks/units/drone-factory.png b/core/assets-raw/sprites/blocks/units/drone-pad.png similarity index 100% rename from core/assets-raw/sprites/blocks/units/drone-factory.png rename to core/assets-raw/sprites/blocks/units/drone-pad.png diff --git a/core/assets-raw/sprites/blocks/units/fabricator-factory-top-open.png b/core/assets-raw/sprites/blocks/units/fabricator-pad-top-open.png similarity index 100% rename from core/assets-raw/sprites/blocks/units/fabricator-factory-top-open.png rename to core/assets-raw/sprites/blocks/units/fabricator-pad-top-open.png diff --git a/core/assets-raw/sprites/blocks/units/fabricator-factory-top.png b/core/assets-raw/sprites/blocks/units/fabricator-pad-top.png similarity index 100% rename from core/assets-raw/sprites/blocks/units/fabricator-factory-top.png rename to core/assets-raw/sprites/blocks/units/fabricator-pad-top.png diff --git a/core/assets-raw/sprites/blocks/units/fabricator-factory.png b/core/assets-raw/sprites/blocks/units/fabricator-pad.png similarity index 100% rename from core/assets-raw/sprites/blocks/units/fabricator-factory.png rename to core/assets-raw/sprites/blocks/units/fabricator-pad.png diff --git a/core/assets-raw/sprites/blocks/units/interceptor-pad-top-open.png b/core/assets-raw/sprites/blocks/units/interceptor-pad-top-open.png new file mode 100644 index 0000000000..50fc9d3746 Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/interceptor-pad-top-open.png differ diff --git a/core/assets-raw/sprites/blocks/units/interceptor-pad-top.png b/core/assets-raw/sprites/blocks/units/interceptor-pad-top.png new file mode 100644 index 0000000000..e716019aa3 Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/interceptor-pad-top.png differ diff --git a/core/assets-raw/sprites/blocks/units/interceptor-pad.png b/core/assets-raw/sprites/blocks/units/interceptor-pad.png new file mode 100644 index 0000000000..636a7900b9 Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/interceptor-pad.png differ diff --git a/core/assets-raw/sprites/blocks/units/monsoon-pad-top-open.png b/core/assets-raw/sprites/blocks/units/monsoon-pad-top-open.png new file mode 100644 index 0000000000..56cb95da79 Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/monsoon-pad-top-open.png differ diff --git a/core/assets-raw/sprites/blocks/units/monsoon-pad-top.png b/core/assets-raw/sprites/blocks/units/monsoon-pad-top.png new file mode 100644 index 0000000000..13539369f0 Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/monsoon-pad-top.png differ diff --git a/core/assets-raw/sprites/blocks/units/monsoon-pad.png b/core/assets-raw/sprites/blocks/units/monsoon-pad.png new file mode 100644 index 0000000000..fe6b8fa3ea Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/monsoon-pad.png differ diff --git a/core/assets-raw/sprites/blocks/units/titan-pad-top-open.png b/core/assets-raw/sprites/blocks/units/titan-pad-top-open.png new file mode 100644 index 0000000000..56cb95da79 Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/titan-pad-top-open.png differ diff --git a/core/assets-raw/sprites/blocks/units/titan-pad-top.png b/core/assets-raw/sprites/blocks/units/titan-pad-top.png new file mode 100644 index 0000000000..13539369f0 Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/titan-pad-top.png differ diff --git a/core/assets-raw/sprites/blocks/units/titan-pad.png b/core/assets-raw/sprites/blocks/units/titan-pad.png new file mode 100644 index 0000000000..cdc1dd92c7 Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/titan-pad.png differ diff --git a/core/assets-raw/sprites/effects/command-attack.png b/core/assets-raw/sprites/effects/command-attack.png new file mode 100644 index 0000000000..98d8c8ebbb Binary files /dev/null and b/core/assets-raw/sprites/effects/command-attack.png differ diff --git a/core/assets-raw/sprites/effects/command-idle.png b/core/assets-raw/sprites/effects/command-idle.png new file mode 100644 index 0000000000..4e5da45157 Binary files /dev/null and b/core/assets-raw/sprites/effects/command-idle.png differ diff --git a/core/assets-raw/sprites/effects/command-retreat.png b/core/assets-raw/sprites/effects/command-retreat.png new file mode 100644 index 0000000000..fc1aec99f2 Binary files /dev/null and b/core/assets-raw/sprites/effects/command-retreat.png differ diff --git a/core/assets-raw/sprites/units/scout-base.png b/core/assets-raw/sprites/units/dagger-base.png similarity index 100% rename from core/assets-raw/sprites/units/scout-base.png rename to core/assets-raw/sprites/units/dagger-base.png diff --git a/core/assets-raw/sprites/units/scout-leg.png b/core/assets-raw/sprites/units/dagger-leg.png similarity index 100% rename from core/assets-raw/sprites/units/scout-leg.png rename to core/assets-raw/sprites/units/dagger-leg.png diff --git a/core/assets-raw/sprites/units/scout.png b/core/assets-raw/sprites/units/dagger.png similarity index 100% rename from core/assets-raw/sprites/units/scout.png rename to core/assets-raw/sprites/units/dagger.png diff --git a/core/assets-raw/sprites/units/vtol.png b/core/assets-raw/sprites/units/interceptor.png similarity index 100% rename from core/assets-raw/sprites/units/vtol.png rename to core/assets-raw/sprites/units/interceptor.png diff --git a/core/assets-raw/sprites/units/vtol-flame.png b/core/assets-raw/sprites/units/vtol-flame.png deleted file mode 100644 index b4fdd7a0c2..0000000000 Binary files a/core/assets-raw/sprites/units/vtol-flame.png and /dev/null differ diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index c6b07c292d..0f1077b6ad 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -1,4 +1,4 @@ -text.about=Created by [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[] +text.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!) text.credits=Credits text.discord=Join the mindustry discord! text.link.discord.description=the official Mindustry discord chatroom @@ -11,11 +11,11 @@ text.link.wiki.description=official Mindustry wiki text.linkfail=Failed to open link!\nThe URL has been copied to your cliboard. text.editor.web=The web version does not support the editor!\nDownload the game to use it. text.web.unsupported=The web version does not support this feature! Download the game to use it. -text.multiplayer.web=The web version of the game does not support multiplayer!\nUse the downloadable PC, Android or iOS versions. -text.host.web=The web version does not support hosting games! Download the game to use this feature. -text.gameover=The core was destroyed. -text.highscore=[YELLOW]New highscore! -text.lasted=You lasted until wave +text.gameover=Your core has been destroyed +text.sector.gameover=This sector has been lost. Re-deploy? +text.sector.retry=Retry +text.highscore=[accent]New highscore! +text.wave.lasted=You lasted until wave [accent]{0}[]. text.level.highscore=High Score: [accent]{0} text.level.delete.title=Confirm Delete text.map.delete=Are you sure you want to delete the map "[orange]{0}[]"? @@ -50,13 +50,19 @@ text.addplayers=Add/Remove Players text.customgame=Custom Game text.campaign=Campaign text.sectors=Sectors -text.sector=Selected Sector: [LIGHT_GRAY]{0} +text.sector=Sector: [LIGHT_GRAY]{0} text.sector.time=Time: [LIGHT_GRAY]{0} text.sector.deploy=Deploy text.sector.resume=Resume -text.sector.unlocked=Sector completed! text.sector.locked=[scarlet][[Incomplete] text.sector.unexplored=[accent][[Unexplored] +text.mission=Mission:[LIGHT_GRAY] {0} +text.mission.complete=Mission complete! +text.mission.complete.body=Sector {0},{1} has been conquered. +text.mission.wave=Survive [accent]{0}[] waves. +text.mission.battle=Destroy the enemy base. +text.mission.resource=Obtain {0} x{1} +text.none= text.close=Close text.quit=Quit text.maps=Maps @@ -80,7 +86,7 @@ text.server.kicked.nameInUse=There is someone with that name\nalready on this se text.server.kicked.nameEmpty=Your name must contain at least one character or number. text.server.kicked.idInUse=You are already on this server! Connecting with two accounts is not permitted. text.server.kicked.customClient=This server does not support custom builds. Download an official version. -text.host.info=The [accent]host[] button hosts a server on ports [scarlet]6567[] and [scarlet]6568.[]\nAnybody on the same [LIGHT_GRAY]wifi or local network[] should be able to see your server in their server list.\n\nIf you want people to be able to connect from anywhere by IP, [accent]port forwarding[] is required.\n\n[LIGHT_GRAY]Note: If someone is experiencing trouble connecting to your LAN game, make sure you have allowed Mindustry access to your local network in your firewall settings. +text.host.info=The [accent]host[] button hosts a server on port [scarlet]6567[]. \nAnybody on the same [LIGHT_GRAY]wifi or local network[] should be able to see your server in their server list.\n\nIf you want people to be able to connect from anywhere by IP, [accent]port forwarding[] is required.\n\n[LIGHT_GRAY]Note: If someone is experiencing trouble connecting to your LAN game, make sure you have allowed Mindustry access to your local network in your firewall settings. text.join.info=Here, you can enter a [accent]server IP[] to connect to, or discover [accent]local network[] servers to connect to.\nBoth LAN and WAN multiplayer is supported.\n\n[LIGHT_GRAY]Note: There is no automatic global server list; if you want to connect to someone by IP, you would need to ask the host for their IP. text.hostserver=Host Server text.host=Host @@ -149,6 +155,7 @@ text.save.rename.text=New name: text.selectslot=Select a save. text.slot=[accent]Slot {0} text.save.corrupted=[orange]Save file corrupted or invalid!\nIf you have just updated your game, this is probably a change in the save format and [scarlet]not[] a bug. +text.sector.corrupted=[orange]A save file for this sector was found, but loading failed.\nA new one has been created. text.empty= text.on=On text.off=Off @@ -253,9 +260,6 @@ text.settings.controls=Controls text.settings.game=Game text.settings.sound=Sound text.settings.graphics=Graphics -text.upgrades=Upgrades -text.purchased=[LIME]Created! -text.weapons=Weapons text.paused=Paused text.yes=Yes text.no=No @@ -320,6 +324,9 @@ text.category.liquids=Liquids text.category.items=Items text.category.crafting=Crafting text.category.shooting=Shooting +setting.fpscap.name=Max FPS +setting.fpscap.none=None +setting.fpscap.text={0} FPS setting.difficulty.easy=easy setting.difficulty.normal=normal setting.difficulty.hard=hard @@ -343,41 +350,27 @@ setting.musicvol.name=Music Volume setting.mutemusic.name=Mute Music setting.sfxvol.name=SFX Volume setting.mutesound.name=Mute Sound -map.maze.name=maze -map.fortress.name=fortress -map.sinkhole.name=sinkhole -map.caves.name=caves -map.volcano.name=volcano -map.caldera.name=caldera -map.scorch.name=scorch -map.desert.name=desert -map.island.name=island -map.grassland.name=grassland -map.tundra.name=tundra -map.spiral.name=spiral -map.tutorial.name=tutorial text.keybind.title=Rebind Keys -keybind.move_x.name=move_x -keybind.move_y.name=move_y -keybind.select.name=select -keybind.break.name=break -keybind.shoot.name=shoot -keybind.zoom_hold.name=zoom_hold -keybind.zoom.name=zoom -keybind.block_info.name=block_info -keybind.menu.name=menu -keybind.pause.name=pause -keybind.dash.name=dash -keybind.chat.name=chat -keybind.player_list.name=player_list +keybind.move_x.name=Move x +keybind.move_y.name=Move y +keybind.select.name=Select +keybind.break.name=Break +keybind.shoot.name=Shoot +keybind.zoom_hold.name=Zoom Hold +keybind.zoom.name=Zoom +keybind.menu.name=Menu +keybind.pause.name=Pause +keybind.dash.name=Dash +keybind.chat.name=Chat +keybind.player_list.name=Player list keybind.console.name=console -keybind.rotate_alt.name=rotate_alt -keybind.rotate.name=rotate +keybind.rotate.name=Rotate mode.text.help.title=Description of modes mode.waves.name=waves mode.waves.description=the normal mode. limited resources and automatic incoming waves. mode.sandbox.name=sandbox mode.sandbox.description=infinite resources and no timer for waves. +mode.sandbox.warning=Note that blocks cannot be used in sandbox mode until they are unlocked in other modes.\n\n[LIGHT_GRAY]If you have not unlocked any blocks, none will appear. mode.freebuild.name=freebuild mode.freebuild.description=limited resources and no timer for waves. @@ -426,6 +419,9 @@ text.item.radioactivity=[LIGHT_GRAY]Radioactivity: {0} text.item.fluxiness=[LIGHT_GRAY]Flux Power: {0} text.item.hardness=[LIGHT_GRAY]Hardness: {0} +text.unit.health=[LIGHT_GRAY]Health: {0} +text.unit.speed=[LIGHT_GRAY]Speed: {0} + text.liquid.heatcapacity=[LIGHT_GRAY]Heat Capacity: {0} text.liquid.viscosity=[LIGHT_GRAY]Viscosity: {0} text.liquid.temperature=[LIGHT_GRAY]Temperature: {0} @@ -479,9 +475,9 @@ block.carbide-drill.name=Carbide Drill block.laser-drill.name=Laser Drill block.water-extractor.name=Water Extractor block.cultivator.name=Cultivator -block.dart-ship-factory.name=Dart Ship Factory -block.delta-mech-factory.name=Delta Mech Factory -block.dronefactory.name=Drone Factory +block.dart-ship-factory.name=Dart Ship Reconstructor +block.delta-mech-factory.name=Delta Mech Reconstructor +block.javelin-ship-factory.name=Javelin Ship Reconstructor block.repairpoint.name=Repair Point block.resupplypoint.name=Resupply Point block.conduit.name=Conduit @@ -512,9 +508,10 @@ block.solidifer.name=Solidifer block.solar-panel.name=Solar Panel block.solar-panel-large.name=Large Solar Panel block.oil-extractor.name=Oil Extractor -block.javelin-ship-factory.name=Javelin Ship factory -block.drone-factory.name=Drone Factory -block.fabricator-factory.name=Fabricator Factory +block.drone-pad.name=Drone Pad +block.fabricator-pad.name=Fabricator Pad +block.interceptor-pad.name=Interceptor Pad +block.monsoon-pad.name=Monsoon Pad block.repair-point.name=Repair Point block.resupply-point.name=Resupply Point block.pulse-conduit.name=Pulse Conduit @@ -525,3 +522,23 @@ block.liquid-junction.name=Liquid Junction block.bridge-conduit.name=Bridge Conduit block.rotary-pump.name=Rotary Pump block.nuclear-reactor.name=Nuclear Reactor +block.command-center.name=Command Center +block.mass-driver.name=Mass Driver +block.blast-drill.name=Blast Drill +block.thermal-pump.name=Thermal Pump +block.dagger-pad.name=Dagger Pad +block.titan-pad.name=Titan Pad +block.thermal-generator.name=Thermal Generator + +unit.drone.name=Drone +unit.drone.description=The starter drone unit. Spawns in the core by default. Automatically mines ores, collects items and repairs blocks. +unit.fabricator.name=Fabricator +unit.fabricator.description=An advanced drone unit. Automatically mines ores, collects items and repairs blocks. Significantly more effective than a drone. +unit.scout.name=Scout +unit.scout.description=A basic ground unit. Uses lead as ammo. +unit.titan.name=Titan +unit.titan.description=An advanced armored ground unit. Uses carbide as ammo. Attacks both ground and air targets. +unit.monsoon.name=Monsoon +unit.monsoon.description=A heavy carpet bomber. Uses blast compound or pyratite as ammo. +unit.interceptor.name=Interceptor +unit.interceptor.description=A fast, hit-and-run strike unit. Uses lead as ammo. \ No newline at end of file diff --git a/core/assets/bundles/bundle_de.properties b/core/assets/bundles/bundle_de.properties index c77d8c4232..d4a6c10095 100644 --- a/core/assets/bundles/bundle_de.properties +++ b/core/assets/bundles/bundle_de.properties @@ -1,8 +1,6 @@ -text.about=Erstellt von [ROYAL] Anuken. [] \nUrsprünglich ein Eintrag im [orange] GDL [] MM Jam.\n\nCredits: \n- SFX gemacht mit [yellow] bfxr [] - Musik gemacht von [green] RoccoW [] / gefunden auf [lime] FreeMusicArchive.org [] \n\nBesonderer Dank geht an: \n- [coral] MitchellFJN []: Umfangreicher Spieletest und Feedback \n- [sky] Luxray5474 []: Wiki-Arbeit, Code-Beiträge \n- Alle Beta-Tester auf itch.io und Google Play\n text.discord=Trete dem Mindustry Discord bei! text.gameover=Der Kern wurde zerstört. text.highscore=[YELLOW] Neuer Highscore! -text.lasted=Du hast bis zur folgenden Welle überlebt text.level.highscore=High Score: [accent] {0} text.level.delete.title=Löschen bestätigen text.level.select=Level Auswahl @@ -111,9 +109,6 @@ text.settings.controls=Steuerung text.settings.game=Spiel text.settings.sound=Audio text.settings.graphics=Grafiken -text.upgrades=Verbesserungen -text.purchased=[LIME] Erstellt! -text.weapons=Waffen text.paused=Pausiert text.error.title=[crimson] Ein Fehler ist aufgetreten text.error.crashtitle=EIn Fehler ist aufgetreten! @@ -153,19 +148,6 @@ setting.musicvol.name=Musiklautstärke setting.mutemusic.name=Musik stummschalten setting.sfxvol.name=Audioeffekte Lautstärke setting.mutesound.name=Audioeffekte stummschalten -map.maze.name=Labyrinth -map.fortress.name=Festung -map.sinkhole.name=Sinkloch -map.caves.name=Höhlen -map.volcano.name=Vulkan -map.caldera.name=Lavakessel -map.scorch.name=Flammen -map.desert.name=Wüste -map.island.name=Insel -map.grassland.name=Grasland -map.tundra.name=Kältesteppe -map.spiral.name=Spirale -map.tutorial.name=Tutorial keybind.move_x.name=bewege_x keybind.move_y.name=bewege_y keybind.select.name=wählen @@ -176,7 +158,6 @@ keybind.zoom.name=zoomen keybind.menu.name=Menü keybind.pause.name=Pause keybind.dash.name=Bindestrich -keybind.rotate_alt.name=drehen_alt keybind.rotate.name=Drehen mode.waves.name=Wellen mode.sandbox.name=Sandkasten @@ -211,8 +192,6 @@ text.link.wiki.description=official Mindustry wiki text.linkfail=Failed to open link!\nThe URL has been copied to your cliboard. text.editor.web=The web version does not support the editor!\nDownload the game to use it. text.web.unsupported=The web version does not support this feature! Download the game to use it. -text.multiplayer.web=This version of the game does not support multiplayer!\nTo play multiplayer from your browser, use the "multiplayer web version" link at the itch.io page. -text.host.web=The web version does not support hosting games! Download the game to use this feature. text.map.delete=Are you sure you want to delete the map "[orange]{0}[]"? text.construction.title=Block Construction Guide text.construction=You've just selected [accent]block construction mode[].\n\nTo begin placing, simply tap a valid location near your ship.\nOnce you have selected some blocks, press the checkbox to confirm, and your ship will begin constructing them.\n\n- [accent]Remove blocks[] from your selection by tapping them.\n- [accent]Shift the selection[] by holding and dragging any block in the selection.\n- [accent]Place blocks in a line[] by tapping and holding an empty spot, then dragging in a direction.\n- [accent]Cancel construction or selection[] by pressing the X at the bottom left. @@ -359,7 +338,6 @@ setting.fullscreen.name=Fullscreen setting.multithread.name=Multithreading setting.minimap.name=Show Minimap text.keybind.title=Rebind Keys -keybind.block_info.name=block_info keybind.chat.name=chat keybind.player_list.name=player_list keybind.console.name=console @@ -447,7 +425,6 @@ block.water-extractor.name=Water Extractor block.cultivator.name=Cultivator block.dart-ship-factory.name=Dart Ship Factory block.delta-mech-factory.name=Delta Mech Factory -block.dronefactory.name=Drone Factory block.repairpoint.name=Repair Point block.resupplypoint.name=Resupply Point block.liquidtank.name=Liquid Tank @@ -475,8 +452,6 @@ block.solar-panel.name=Solar Panel block.solar-panel-large.name=Large Solar Panel block.oil-extractor.name=Oil Extractor block.javelin-ship-factory.name=Javelin Ship factory -block.drone-factory.name=Drone Factory -block.fabricator-factory.name=Fabricator Factory block.repair-point.name=Repair Point block.resupply-point.name=Resupply Point block.pulse-conduit.name=Pulse Conduit @@ -495,9 +470,49 @@ text.sector=Selected Sector: [LIGHT_GRAY]{0} text.sector.time=Time: [LIGHT_GRAY]{0} text.sector.deploy=Deploy text.sector.resume=Resume -text.sector.unlocked=Sector completed! text.sector.locked=[scarlet][[Incomplete] text.sector.unexplored=[accent][[Unexplored] text.close=Close text.save.playtime=Playtime: {0} text.editor.brush=Brush +text.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!) +text.sector.gameover=This sector has been lost. Re-deploy? +text.sector.retry=Retry +text.wave.lasted=You lasted until wave [accent]{0}[]. +setting.fpscap.name=Max FPS +setting.fpscap.none=None +setting.fpscap.text={0} FPS +block.command-center.name=Command Center +text.mission=Mission:[LIGHT_GRAY] {0} +text.mission.wave=Survive [accent]{0}[] waves. +text.mission.battle=Destroy the enemy base. +text.none= +text.sector.corrupted=[orange]A save file for this sector was found, but loading failed.\nA new one has been created. +text.mission.complete=Mission complete! +text.mission.complete.body=Sector {0},{1} has been conquered. +text.mission.resource=Obtain {0} x{1} +text.unit.health=[LIGHT_GRAY]Health: {0} +text.unit.speed=[LIGHT_GRAY]Speed: {0} +block.drone-pad.name=Drone Pad +block.fabricator-pad.name=Fabricator Pad +block.interceptor-pad.name=Interceptor Pad +block.monsoon-pad.name=Monsoon Pad +block.mass-driver.name=Mass Driver +block.blast-drill.name=Blast Drill +unit.drone.name=Drone +unit.drone.description=The starter drone unit. Spawns in the core by default. Automatically mines ores, collects items and repairs blocks. +unit.fabricator.name=Fabricator +unit.fabricator.description=An advanced drone unit. Automatically mines ores, collects items and repairs blocks. Significantly more effective than a drone. +unit.scout.name=Scout +unit.scout.description=A basic ground unit. Uses lead as ammo. +unit.titan.name=Titan +unit.titan.description=An advanced armored ground unit. Uses carbide as ammo. Attacks both ground and air targets. +unit.monsoon.name=Monsoon +unit.monsoon.description=A heavy carpet bomber. Uses blast compound or pyratite as ammo. +unit.interceptor.name=Interceptor +unit.interceptor.description=A fast, hit-and-run strike unit. Uses lead as ammo. +mode.sandbox.warning=Note that blocks cannot be used in sandbox mode until they are unlocked in other modes.\n\n[LIGHT_GRAY]If you have not unlocked any blocks, none will appear. +block.thermal-pump.name=Thermal Pump +block.dagger-pad.name=Dagger Pad +block.titan-pad.name=Titan Pad +block.thermal-generator.name=Thermal Generator diff --git a/core/assets/bundles/bundle_es.properties b/core/assets/bundles/bundle_es.properties index 0342feb773..291b4de50c 100644 --- a/core/assets/bundles/bundle_es.properties +++ b/core/assets/bundles/bundle_es.properties @@ -1,4 +1,3 @@ -text.about=Creado por [ROYAL]Anuken [] - [SKY] anukendev@gmail.com [] Originalmente una entrada en el [naranja] GDL [] Metal Monstrosity Jam. Créditos: - SFX hecho con [AMARILLO] bfxr [] - Música hecha por [VERDE] RoccoW [] / encontrado en [lime] FreeMusicArchive.org [] Agradecimientos especiales a: - [coral] MitchellFJN []: extensa prueba de juego y comentarios - [cielo] Luxray5474 []: trabajo wiki, contribuciones de código - [lime] Epowerj []: sistema de compilación de código, icono - Todos los probadores beta en itch.io y Google Play\n text.credits=Créditos text.discord=¡Únete al Discord de Mindustry! text.link.discord.description=La sala oficial del discord de Mindustry @@ -10,10 +9,8 @@ text.link.google-play.description=Listado en la tienda de Google Play text.link.wiki.description=Wiki oficial de Mindustry text.linkfail=¡Error al abrir el enlace!\nLa URL ha sido copiada a su portapapeles text.editor.web=¡La versión web no es compatible con el editor!\nDescargue el juego para usarlo. -text.multiplayer.web=¡Esta versión del juego no admite multijugador!\nPara jugar al modo multijugador desde su navegador, use el enlace "versión de varios jugadores" en la página itch.io. text.gameover=El núcleo fue destruido. text.highscore=[YELLOW]¡Nueva mejor puntuación! -text.lasted=Duró hasta la ronda text.level.highscore=Puntuación màs alta: [accent] text.level.delete.title=Confirmar Eliminación text.level.select=Selección de nivel @@ -165,9 +162,6 @@ text.settings.controls=Controles text.settings.game=Juego text.settings.sound=Sonido text.settings.graphics=Gráficos -text.upgrades=Mejoras -text.purchased=[LIME] Creado! -text.weapons=Armas text.paused=Pausado text.info.title=[acento] Información text.error.title=[carmesí] Se ha producido un error @@ -210,19 +204,6 @@ setting.musicvol.name=Volumen de la música setting.mutemusic.name=Apagar música setting.sfxvol.name=Volumen de los efectos de sonido setting.mutesound.name=Apagar sonidos -map.maze.name=Laberinto -map.fortress.name=Fortaleza -map.sinkhole.name=Sumidero -map.caves.name=Cuevas -map.volcano.name=Volcán -map.caldera.name=Caldera -map.scorch.name=Desierto volcánico -map.desert.name=Desierto -map.island.name=Isla -map.grassland.name=Pastizal -map.tundra.name=Tundra -map.spiral.name=Espiral -map.tutorial.name=Tutorial text.keybind.title=Vuelva a conectar las llaves keybind.move_x.name=mover_x keybind.move_y.name=mover_y @@ -231,14 +212,12 @@ keybind.break.name=Romper keybind.shoot.name=¡Dispara! keybind.zoom_hold.name=Enfoque_Mantener keybind.zoom.name=Enfoquè -keybind.block_info.name=Bloque_informacion keybind.menu.name=Menú keybind.pause.name=Pausa keybind.dash.name=Deslizar keybind.chat.name=Chat keybind.player_list.name=Jugadores_lista keybind.console.name=Console -keybind.rotate_alt.name=Rotacion_alt keybind.rotate.name=Girar mode.text.help.title=Descripción de modos mode.waves.name=Hordas @@ -266,7 +245,6 @@ block.liquidjunction.name=Unión líquida block.sorter.name=Clasificador block.smelter.name=horno de fundición text.web.unsupported=The web version does not support this feature! Download the game to use it. -text.host.web=The web version does not support hosting games! Download the game to use this feature. text.map.delete=Are you sure you want to delete the map "[orange]{0}[]"? text.construction.title=Block Construction Guide text.construction=You've just selected [accent]block construction mode[].\n\nTo begin placing, simply tap a valid location near your ship.\nOnce you have selected some blocks, press the checkbox to confirm, and your ship will begin constructing them.\n\n- [accent]Remove blocks[] from your selection by tapping them.\n- [accent]Shift the selection[] by holding and dragging any block in the selection.\n- [accent]Place blocks in a line[] by tapping and holding an empty spot, then dragging in a direction.\n- [accent]Cancel construction or selection[] by pressing the X at the bottom left. @@ -447,7 +425,6 @@ block.water-extractor.name=Water Extractor block.cultivator.name=Cultivator block.dart-ship-factory.name=Dart Ship Factory block.delta-mech-factory.name=Delta Mech Factory -block.dronefactory.name=Drone Factory block.repairpoint.name=Repair Point block.resupplypoint.name=Resupply Point block.liquidtank.name=Liquid Tank @@ -475,8 +452,6 @@ block.solar-panel.name=Solar Panel block.solar-panel-large.name=Large Solar Panel block.oil-extractor.name=Oil Extractor block.javelin-ship-factory.name=Javelin Ship factory -block.drone-factory.name=Drone Factory -block.fabricator-factory.name=Fabricator Factory block.repair-point.name=Repair Point block.resupply-point.name=Resupply Point block.pulse-conduit.name=Pulse Conduit @@ -495,9 +470,49 @@ text.sector=Selected Sector: [LIGHT_GRAY]{0} text.sector.time=Time: [LIGHT_GRAY]{0} text.sector.deploy=Deploy text.sector.resume=Resume -text.sector.unlocked=Sector completed! text.sector.locked=[scarlet][[Incomplete] text.sector.unexplored=[accent][[Unexplored] text.close=Close text.save.playtime=Playtime: {0} text.editor.brush=Brush +text.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!) +text.sector.gameover=This sector has been lost. Re-deploy? +text.sector.retry=Retry +text.wave.lasted=You lasted until wave [accent]{0}[]. +setting.fpscap.name=Max FPS +setting.fpscap.none=None +setting.fpscap.text={0} FPS +block.command-center.name=Command Center +text.mission=Mission:[LIGHT_GRAY] {0} +text.mission.wave=Survive [accent]{0}[] waves. +text.mission.battle=Destroy the enemy base. +text.none= +text.sector.corrupted=[orange]A save file for this sector was found, but loading failed.\nA new one has been created. +text.mission.complete=Mission complete! +text.mission.complete.body=Sector {0},{1} has been conquered. +text.mission.resource=Obtain {0} x{1} +text.unit.health=[LIGHT_GRAY]Health: {0} +text.unit.speed=[LIGHT_GRAY]Speed: {0} +block.drone-pad.name=Drone Pad +block.fabricator-pad.name=Fabricator Pad +block.interceptor-pad.name=Interceptor Pad +block.monsoon-pad.name=Monsoon Pad +block.mass-driver.name=Mass Driver +block.blast-drill.name=Blast Drill +unit.drone.name=Drone +unit.drone.description=The starter drone unit. Spawns in the core by default. Automatically mines ores, collects items and repairs blocks. +unit.fabricator.name=Fabricator +unit.fabricator.description=An advanced drone unit. Automatically mines ores, collects items and repairs blocks. Significantly more effective than a drone. +unit.scout.name=Scout +unit.scout.description=A basic ground unit. Uses lead as ammo. +unit.titan.name=Titan +unit.titan.description=An advanced armored ground unit. Uses carbide as ammo. Attacks both ground and air targets. +unit.monsoon.name=Monsoon +unit.monsoon.description=A heavy carpet bomber. Uses blast compound or pyratite as ammo. +unit.interceptor.name=Interceptor +unit.interceptor.description=A fast, hit-and-run strike unit. Uses lead as ammo. +mode.sandbox.warning=Note that blocks cannot be used in sandbox mode until they are unlocked in other modes.\n\n[LIGHT_GRAY]If you have not unlocked any blocks, none will appear. +block.thermal-pump.name=Thermal Pump +block.dagger-pad.name=Dagger Pad +block.titan-pad.name=Titan Pad +block.thermal-generator.name=Thermal Generator diff --git a/core/assets/bundles/bundle_fr.properties b/core/assets/bundles/bundle_fr.properties index c4d1a6238c..05733570dc 100644 --- a/core/assets/bundles/bundle_fr.properties +++ b/core/assets/bundles/bundle_fr.properties @@ -1,8 +1,6 @@ -text.about=Créé par [ROYAL]Anuken.[]\nA l'origine une entrée dans le [orange]GDL[] MM Jam.\n\nCrédits: \n- SFX réalisé avec [yellow]bfxr[] \n- Musique faite par [lime]RoccoW[] / trouvé sur [lime]FreeMusicArchive.org[] \n\nRemerciements particuliers à:\n- [coral]MitchellFJN[]: nombreux tests et retours d'expérience \n- [sky]Luxray5474[]: travail wiki, contributions de code \n- [lime]Epowerj[]: système de compilation de code, icône \n- Tous les beta testeurs sont sur itch.io et Google Play\n text.discord=Rejoignez le discord de Mindustry text.gameover=Le noyau a été détruit. text.highscore=[YELLOW]Nouveau meilleur score! -text.lasted=Vous avez duré jusqu'à la vague text.level.highscore=Meilleur score: [accent]{0} text.level.delete.title=Confirmer text.level.select=Sélection de niveau @@ -147,9 +145,6 @@ text.settings.controls=Contrôles text.settings.game=Jeu text.settings.sound=Son text.settings.graphics=Graphique -text.upgrades=Améliorations -text.purchased=[VERT]Créé! -text.weapons=Armes text.paused=Pause text.info.title=[accent]Info text.error.title=[crimson]Une erreur est survenue @@ -192,19 +187,6 @@ setting.musicvol.name=volume musique setting.mutemusic.name=Musique muette setting.sfxvol.name=Volume SFX setting.mutesound.name=Son muet -map.maze.name=Labyrinthe -map.fortress.name=forteresse -map.sinkhole.name=gouffre -map.caves.name=cavernes -map.volcano.name=volcan -map.caldera.name=chaudron -map.scorch.name=brûlure -map.desert.name=désert -map.island.name=Île -map.grassland.name=prairie -map.tundra.name=toundra -map.spiral.name=spirale -map.tutorial.name=tutoriel text.keybind.title=Relier le clés keybind.move_x.name=mouvement x keybind.move_y.name=mouvement y @@ -213,14 +195,12 @@ keybind.break.name=Pause keybind.shoot.name=tirer keybind.zoom_hold.name=tenir le zoom keybind.zoom.name=zoom -keybind.block_info.name=bloc_info keybind.menu.name=menu keybind.pause.name=Pause keybind.dash.name=attaque frontal keybind.chat.name=chat keybind.player_list.name=Liste des joueurs keybind.console.name=console -keybind.rotate_alt.name=tourner_alt keybind.rotate.name=Tourner mode.waves.name=Vagues mode.sandbox.name=bac à sable @@ -254,8 +234,6 @@ text.link.wiki.description=official Mindustry wiki text.linkfail=Failed to open link!\nThe URL has been copied to your cliboard. text.editor.web=The web version does not support the editor!\nDownload the game to use it. text.web.unsupported=The web version does not support this feature! Download the game to use it. -text.multiplayer.web=This version of the game does not support multiplayer!\nTo play multiplayer from your browser, use the "multiplayer web version" link at the itch.io page. -text.host.web=The web version does not support hosting games! Download the game to use this feature. text.map.delete=Are you sure you want to delete the map "[orange]{0}[]"? text.construction.title=Block Construction Guide text.construction=You've just selected [accent]block construction mode[].\n\nTo begin placing, simply tap a valid location near your ship.\nOnce you have selected some blocks, press the checkbox to confirm, and your ship will begin constructing them.\n\n- [accent]Remove blocks[] from your selection by tapping them.\n- [accent]Shift the selection[] by holding and dragging any block in the selection.\n- [accent]Place blocks in a line[] by tapping and holding an empty spot, then dragging in a direction.\n- [accent]Cancel construction or selection[] by pressing the X at the bottom left. @@ -447,7 +425,6 @@ block.water-extractor.name=Water Extractor block.cultivator.name=Cultivator block.dart-ship-factory.name=Dart Ship Factory block.delta-mech-factory.name=Delta Mech Factory -block.dronefactory.name=Drone Factory block.repairpoint.name=Repair Point block.resupplypoint.name=Resupply Point block.liquidtank.name=Liquid Tank @@ -475,8 +452,6 @@ block.solar-panel.name=Solar Panel block.solar-panel-large.name=Large Solar Panel block.oil-extractor.name=Oil Extractor block.javelin-ship-factory.name=Javelin Ship factory -block.drone-factory.name=Drone Factory -block.fabricator-factory.name=Fabricator Factory block.repair-point.name=Repair Point block.resupply-point.name=Resupply Point block.pulse-conduit.name=Pulse Conduit @@ -495,9 +470,49 @@ text.sector=Selected Sector: [LIGHT_GRAY]{0} text.sector.time=Time: [LIGHT_GRAY]{0} text.sector.deploy=Deploy text.sector.resume=Resume -text.sector.unlocked=Sector completed! text.sector.locked=[scarlet][[Incomplete] text.sector.unexplored=[accent][[Unexplored] text.close=Close text.save.playtime=Playtime: {0} text.editor.brush=Brush +text.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!) +text.sector.gameover=This sector has been lost. Re-deploy? +text.sector.retry=Retry +text.wave.lasted=You lasted until wave [accent]{0}[]. +setting.fpscap.name=Max FPS +setting.fpscap.none=None +setting.fpscap.text={0} FPS +block.command-center.name=Command Center +text.mission=Mission:[LIGHT_GRAY] {0} +text.mission.wave=Survive [accent]{0}[] waves. +text.mission.battle=Destroy the enemy base. +text.none= +text.sector.corrupted=[orange]A save file for this sector was found, but loading failed.\nA new one has been created. +text.mission.complete=Mission complete! +text.mission.complete.body=Sector {0},{1} has been conquered. +text.mission.resource=Obtain {0} x{1} +text.unit.health=[LIGHT_GRAY]Health: {0} +text.unit.speed=[LIGHT_GRAY]Speed: {0} +block.drone-pad.name=Drone Pad +block.fabricator-pad.name=Fabricator Pad +block.interceptor-pad.name=Interceptor Pad +block.monsoon-pad.name=Monsoon Pad +block.mass-driver.name=Mass Driver +block.blast-drill.name=Blast Drill +unit.drone.name=Drone +unit.drone.description=The starter drone unit. Spawns in the core by default. Automatically mines ores, collects items and repairs blocks. +unit.fabricator.name=Fabricator +unit.fabricator.description=An advanced drone unit. Automatically mines ores, collects items and repairs blocks. Significantly more effective than a drone. +unit.scout.name=Scout +unit.scout.description=A basic ground unit. Uses lead as ammo. +unit.titan.name=Titan +unit.titan.description=An advanced armored ground unit. Uses carbide as ammo. Attacks both ground and air targets. +unit.monsoon.name=Monsoon +unit.monsoon.description=A heavy carpet bomber. Uses blast compound or pyratite as ammo. +unit.interceptor.name=Interceptor +unit.interceptor.description=A fast, hit-and-run strike unit. Uses lead as ammo. +mode.sandbox.warning=Note that blocks cannot be used in sandbox mode until they are unlocked in other modes.\n\n[LIGHT_GRAY]If you have not unlocked any blocks, none will appear. +block.thermal-pump.name=Thermal Pump +block.dagger-pad.name=Dagger Pad +block.titan-pad.name=Titan Pad +block.thermal-generator.name=Thermal Generator diff --git a/core/assets/bundles/bundle_in_ID.properties b/core/assets/bundles/bundle_in_ID.properties index fe8a068392..e69195ed9e 100644 --- a/core/assets/bundles/bundle_in_ID.properties +++ b/core/assets/bundles/bundle_in_ID.properties @@ -1,8 +1,6 @@ -text.about=Dibuat oleh [ROYAL]Anuken.[]\nAwalnya masuk di [orange]GDL[] MM Jam.\n\nKredit:\n- SFX dibuat dengan [YELLOW]bfxr[]\n- Musik dibuat oleh [GREEN]RoccoW[] / ditemukan di [lime]FreeMusicArchive.org[]\n\nTerima kasih khusus kepada:\n- [coral]MitchellFJN[]: playtesting dan umpan balik yang luas\n- [sky]Luxray5474[]: pekerjaan wiki, kontribusi kode\n- Semua penguji beta di itch.io dan Google Play\n text.discord=Bergabunglah dengan Discord Mindustry! text.gameover=Intinya hancur. text.highscore=[YELLOW]Rekor baru! -text.lasted=Anda bertahan sampai gelombang text.level.highscore=Skor Tinggi: [accent]{0} text.level.delete.title=Konfirmasi Hapus text.level.select=Pilih Level @@ -117,9 +115,6 @@ text.settings.controls=Kontrol text.settings.game=Permainan text.settings.sound=Suara text.settings.graphics=Grafis -text.upgrades=Perbaruan -text.purchased=[LIME]Dibuat! -text.weapons=Senjata text.paused=Jeda text.info.title=[accent]Info text.error.title=[crimson]Telah terjadi kesalahan @@ -161,19 +156,6 @@ setting.musicvol.name=Volume Musik setting.mutemusic.name=Bisukan Musik setting.sfxvol.name=Volume Suara setting.mutesound.name=Bisukan Suara -map.maze.name=labirin -map.fortress.name=benteng -map.sinkhole.name=lubang pembuangan -map.caves.name=gua -map.volcano.name=gunung berapi -map.caldera.name=kaldera -map.scorch.name=penghangusan -map.desert.name=gurun -map.island.name=pulau -map.grassland.name=padang rumput -map.tundra.name=tundra -map.spiral.name=spiral -map.tutorial.name=tutorial keybind.move_x.name=gerak_x keybind.move_y.name=gerak_y keybind.select.name=pilih @@ -184,7 +166,6 @@ keybind.zoom.name=perbesar keybind.menu.name=menu keybind.pause.name=jeda keybind.dash.name=berlari -keybind.rotate_alt.name=putar_alt keybind.rotate.name=putar mode.waves.name=gelombang mode.sandbox.name=sandbox @@ -219,8 +200,6 @@ text.link.wiki.description=official Mindustry wiki text.linkfail=Failed to open link!\nThe URL has been copied to your cliboard. text.editor.web=The web version does not support the editor!\nDownload the game to use it. text.web.unsupported=The web version does not support this feature! Download the game to use it. -text.multiplayer.web=This version of the game does not support multiplayer!\nTo play multiplayer from your browser, use the "multiplayer web version" link at the itch.io page. -text.host.web=The web version does not support hosting games! Download the game to use this feature. text.map.delete=Are you sure you want to delete the map "[orange]{0}[]"? text.construction.title=Block Construction Guide text.construction=You've just selected [accent]block construction mode[].\n\nTo begin placing, simply tap a valid location near your ship.\nOnce you have selected some blocks, press the checkbox to confirm, and your ship will begin constructing them.\n\n- [accent]Remove blocks[] from your selection by tapping them.\n- [accent]Shift the selection[] by holding and dragging any block in the selection.\n- [accent]Place blocks in a line[] by tapping and holding an empty spot, then dragging in a direction.\n- [accent]Cancel construction or selection[] by pressing the X at the bottom left. @@ -359,7 +338,6 @@ text.category.shooting=Shooting setting.multithread.name=Multithreading setting.minimap.name=Show Minimap text.keybind.title=Rebind Keys -keybind.block_info.name=block_info keybind.chat.name=chat keybind.player_list.name=player_list keybind.console.name=console @@ -447,7 +425,6 @@ block.water-extractor.name=Water Extractor block.cultivator.name=Cultivator block.dart-ship-factory.name=Dart Ship Factory block.delta-mech-factory.name=Delta Mech Factory -block.dronefactory.name=Drone Factory block.repairpoint.name=Repair Point block.resupplypoint.name=Resupply Point block.liquidtank.name=Liquid Tank @@ -475,8 +452,6 @@ block.solar-panel.name=Solar Panel block.solar-panel-large.name=Large Solar Panel block.oil-extractor.name=Oil Extractor block.javelin-ship-factory.name=Javelin Ship factory -block.drone-factory.name=Drone Factory -block.fabricator-factory.name=Fabricator Factory block.repair-point.name=Repair Point block.resupply-point.name=Resupply Point block.pulse-conduit.name=Pulse Conduit @@ -495,9 +470,49 @@ text.sector=Selected Sector: [LIGHT_GRAY]{0} text.sector.time=Time: [LIGHT_GRAY]{0} text.sector.deploy=Deploy text.sector.resume=Resume -text.sector.unlocked=Sector completed! text.sector.locked=[scarlet][[Incomplete] text.sector.unexplored=[accent][[Unexplored] text.close=Close text.save.playtime=Playtime: {0} text.editor.brush=Brush +text.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!) +text.sector.gameover=This sector has been lost. Re-deploy? +text.sector.retry=Retry +text.wave.lasted=You lasted until wave [accent]{0}[]. +setting.fpscap.name=Max FPS +setting.fpscap.none=None +setting.fpscap.text={0} FPS +block.command-center.name=Command Center +text.mission=Mission:[LIGHT_GRAY] {0} +text.mission.wave=Survive [accent]{0}[] waves. +text.mission.battle=Destroy the enemy base. +text.none= +text.sector.corrupted=[orange]A save file for this sector was found, but loading failed.\nA new one has been created. +text.mission.complete=Mission complete! +text.mission.complete.body=Sector {0},{1} has been conquered. +text.mission.resource=Obtain {0} x{1} +text.unit.health=[LIGHT_GRAY]Health: {0} +text.unit.speed=[LIGHT_GRAY]Speed: {0} +block.drone-pad.name=Drone Pad +block.fabricator-pad.name=Fabricator Pad +block.interceptor-pad.name=Interceptor Pad +block.monsoon-pad.name=Monsoon Pad +block.mass-driver.name=Mass Driver +block.blast-drill.name=Blast Drill +unit.drone.name=Drone +unit.drone.description=The starter drone unit. Spawns in the core by default. Automatically mines ores, collects items and repairs blocks. +unit.fabricator.name=Fabricator +unit.fabricator.description=An advanced drone unit. Automatically mines ores, collects items and repairs blocks. Significantly more effective than a drone. +unit.scout.name=Scout +unit.scout.description=A basic ground unit. Uses lead as ammo. +unit.titan.name=Titan +unit.titan.description=An advanced armored ground unit. Uses carbide as ammo. Attacks both ground and air targets. +unit.monsoon.name=Monsoon +unit.monsoon.description=A heavy carpet bomber. Uses blast compound or pyratite as ammo. +unit.interceptor.name=Interceptor +unit.interceptor.description=A fast, hit-and-run strike unit. Uses lead as ammo. +mode.sandbox.warning=Note that blocks cannot be used in sandbox mode until they are unlocked in other modes.\n\n[LIGHT_GRAY]If you have not unlocked any blocks, none will appear. +block.thermal-pump.name=Thermal Pump +block.dagger-pad.name=Dagger Pad +block.titan-pad.name=Titan Pad +block.thermal-generator.name=Thermal Generator diff --git a/core/assets/bundles/bundle_ita.properties b/core/assets/bundles/bundle_ita.properties index bae794f424..d290c38c7b 100644 --- a/core/assets/bundles/bundle_ita.properties +++ b/core/assets/bundles/bundle_ita.properties @@ -1,4 +1,3 @@ -text.about=Creato da [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[]\nOriginariamente parte del [orange]GDL[] Metal Monstrosity Jam.\n\n Crediti:\n - SFX realizzato con [YELLOW]bfxr [] \n - Musica creata da [GREEN]RoccoW[] / trovata su [lime]FreeMusicArchive.org[]\n\n Un ringraziamento speciale a:\n - [coral]MitchellFJN []: esteso test del gioco e feedback\n - [sky]Luxray5474 []: sviluppo della wiki, contributi col codice\n - [lime]Epowerj []: sistema di costruzione del codice, icone\n - Tutti i beta tester su itch.io e Google Play\n - [SCARLET] Ludovico Vaghi [], [SCARLET] Enrico Franciscono [] e [SCARLET] Luca Deluigi [] per la traduzione italiana\n text.credits=Crediti text.discord=Unisciti sul server discord di mindustry! text.link.discord.description=la chatroom ufficiale del server discord di Mindustry @@ -10,10 +9,8 @@ text.link.google-play.description=Elenco di Google Play Store text.link.wiki.description=wiki ufficiale di Mindustry text.linkfail=Impossibile aprire il link! L'URL è stato copiato nella tua bacheca. text.editor.web=La versione web non supporta l'editor! Scarica il gioco per usarlo. -text.multiplayer.web=Questa versione del gioco non supporta il multiplayer! Per giocare in multiplayer dal tuo browser, usa il link "versione web multiplayer" nella pagina itch.io. text.gameover=Il nucleo è stato distrutto. text.highscore=[YELLOW]Nuovo record! -text.lasted=Sei durato fino all'ondata text.level.highscore=Miglior punteggio: [accent]{0} text.level.delete.title=Conferma Eliminazione text.level.select=Selezione del livello @@ -165,9 +162,6 @@ text.settings.controls=Controlli text.settings.game=Gioco text.settings.sound=Suono text.settings.graphics=Grafica -text.upgrades=Miglioramenti -text.purchased=[LIME]Creato! -text.weapons=Armi text.paused=In pausa text.info.title=[Accent]Info text.error.title=[crimson]Si è verificato un errore @@ -210,19 +204,6 @@ setting.musicvol.name=Volume Musica setting.mutemusic.name=Silenzia musica setting.sfxvol.name=Volume SFX setting.mutesound.name=Togli suoni -map.maze.name=labirinto -map.fortress.name=fortezza -map.sinkhole.name=dolina -map.caves.name=grotte -map.volcano.name=vulcano -map.caldera.name=caldera -map.scorch.name=bruciatura -map.desert.name=deserto -map.island.name=isola -map.grassland.name=prateria -map.tundra.name=tundra -map.spiral.name=spirale -map.tutorial.name=tutorial text.keybind.title=Configurazione Tasti keybind.move_x.name=Sposta_x keybind.move_y.name=Sposta_y @@ -231,14 +212,12 @@ keybind.break.name=rompi keybind.shoot.name=spara keybind.zoom_hold.name=zoom_hold keybind.zoom.name=zoom -keybind.block_info.name=Informazioni blocco keybind.menu.name=menu keybind.pause.name=pausa keybind.dash.name=Scatto keybind.chat.name=Chat keybind.player_list.name=lista_giocatori keybind.console.name=console -keybind.rotate_alt.name=rotate_alt keybind.rotate.name=Ruotare mode.text.help.title=Descrizione delle modalità mode.waves.name=ondate @@ -500,4 +479,4 @@ block.liquid-tank.name=Tanica d'acqua block.liquid-junction.name=Giunzione liquida block.bridge-conduit.name=Condotta forzata sopraelevata block.rotary-pump.name=Pompa a turbina -block.nuclear-reactor.name=Reattore nucleare +block.nuclear-reactor.name=Reattore nucleare \ No newline at end of file diff --git a/core/assets/bundles/bundle_ko.properties b/core/assets/bundles/bundle_ko.properties index aad7d24b6a..ae4d3937d5 100644 --- a/core/assets/bundles/bundle_ko.properties +++ b/core/assets/bundles/bundle_ko.properties @@ -1,4 +1,3 @@ -text.about=제작자 : [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[] text.credits=제작자 text.discord=Mindustry Discord 에 참여하세요! text.link.discord.description=공식 Mindustry Discord 채팅방 @@ -11,11 +10,8 @@ text.link.wiki.description=공식 Mindustry 위키 text.linkfail=링크를 여는데 실패했습니다!URL이 기기의 클립보드에 복사되었습니다. text.editor.web=HTML5 버전은 에디터 기능을 지원하지 않습니다!게임을 다운로드 한 뒤에 사용 해 주세요. text.web.unsupported=HTML5 버전은 이 기능을 지원하지 않습니다!게임을 다운로드 한 뒤에 사용 해 주세요. -text.multiplayer.web=이 버전은 멀티플레이를 지원하지 않습니다!멀티플레이를 웹 브라우저에서 즐기고 싶다면, itch.io 페이지에서 "multiplayer web version" 링크로 들어가면 됩니다. -text.host.web=HTML5 버전은 게임 호스팅을 지원하지 않습니다!게임을 다운로드 한 뒤에 사용 해 주세요. text.gameover=코어가 터졌습니다. 게임 오버! text.highscore=[YELLOW]최고점수 달성! -text.lasted=마지막으로 달성한 웨이브 text.level.highscore=최고 점수 : [accent]{0} text.level.delete.title=삭제 확인 text.map.delete=정말로 "[orange]{0}[]" 맵을 삭제하시겠습니까? @@ -223,9 +219,6 @@ text.settings.controls=컨트롤 text.settings.game=게임 text.settings.sound=소리 text.settings.graphics=화면 -text.upgrades=강화 -text.purchased=[LIME]생성됨! -text.weapons=무기 text.paused=일시 정지 text.yes=예 text.no=아니오 @@ -311,19 +304,6 @@ setting.musicvol.name=음악 크기 setting.mutemusic.name=음소거 setting.sfxvol.name=효과음 크기 setting.mutesound.name=소리 끄기 -map.maze.name=미로 -map.fortress.name=요새 -map.sinkhole.name=싱크홀 -map.caves.name=동굴 -map.volcano.name=화산 -map.caldera.name=칼데라 -map.scorch.name=타버림 -map.desert.name=사막 -map.island.name=섬 -map.grassland.name=목초지 -map.tundra.name=툰트라 -map.spiral.name=나선 -map.tutorial.name=게임 방법 text.keybind.title=키 바인딩 keybind.move_x.name=오른쪽/왼쪽 이동 keybind.move_y.name=위쪽/아래쪽 이동 @@ -332,14 +312,12 @@ keybind.break.name=파괴 keybind.shoot.name=사격 keybind.zoom_hold.name=길게눌러 확대 keybind.zoom.name=확대 -keybind.block_info.name=블럭 정보 keybind.menu.name=메뉴 keybind.pause.name=일시중지 keybind.dash.name=달리기 keybind.chat.name=채팅 keybind.player_list.name=플레이어 목록 keybind.console.name=콘솔 -keybind.rotate_alt.name=rotate_alt keybind.rotate.name=회전 mode.text.help.title=도움말 mode.waves.name=웨이브 @@ -443,7 +421,6 @@ block.water-extractor.name=물 추출기 block.cultivator.name=경운기 block.dart-ship-factory.name=다트 선박 공장 block.delta-mech-factory.name=델타 메크 공장 -block.dronefactory.name=드론 공장 block.repairpoint.name=수리 포인트 block.resupplypoint.name=재공급 포인트 block.conduit.name=도관 @@ -475,8 +452,6 @@ block.solar-panel.name=태양 전지 패널 block.solar-panel-large.name=대형 태양 전지판 block.oil-extractor.name=오일 추출기 block.javelin-ship-factory.name=창 던지기 선박 공장 -block.drone-factory.name=드론 팩토리 -block.fabricator-factory.name=Fabricator 공장 block.repair-point.name=수리 점 block.resupply-point.name=재 공급 포인트 block.pulse-conduit.name=펄스 도관 @@ -495,9 +470,49 @@ text.sector=Selected Sector: [LIGHT_GRAY]{0} text.sector.time=Time: [LIGHT_GRAY]{0} text.sector.deploy=Deploy text.sector.resume=Resume -text.sector.unlocked=Sector completed! text.sector.locked=[scarlet][[Incomplete] text.sector.unexplored=[accent][[Unexplored] text.close=Close text.save.playtime=Playtime: {0} text.editor.brush=Brush +text.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!) +text.sector.gameover=This sector has been lost. Re-deploy? +text.sector.retry=Retry +text.wave.lasted=You lasted until wave [accent]{0}[]. +setting.fpscap.name=Max FPS +setting.fpscap.none=None +setting.fpscap.text={0} FPS +block.command-center.name=Command Center +text.mission=Mission:[LIGHT_GRAY] {0} +text.mission.wave=Survive [accent]{0}[] waves. +text.mission.battle=Destroy the enemy base. +text.none= +text.sector.corrupted=[orange]A save file for this sector was found, but loading failed.\nA new one has been created. +text.mission.complete=Mission complete! +text.mission.complete.body=Sector {0},{1} has been conquered. +text.mission.resource=Obtain {0} x{1} +text.unit.health=[LIGHT_GRAY]Health: {0} +text.unit.speed=[LIGHT_GRAY]Speed: {0} +block.drone-pad.name=Drone Pad +block.fabricator-pad.name=Fabricator Pad +block.interceptor-pad.name=Interceptor Pad +block.monsoon-pad.name=Monsoon Pad +block.mass-driver.name=Mass Driver +block.blast-drill.name=Blast Drill +unit.drone.name=Drone +unit.drone.description=The starter drone unit. Spawns in the core by default. Automatically mines ores, collects items and repairs blocks. +unit.fabricator.name=Fabricator +unit.fabricator.description=An advanced drone unit. Automatically mines ores, collects items and repairs blocks. Significantly more effective than a drone. +unit.scout.name=Scout +unit.scout.description=A basic ground unit. Uses lead as ammo. +unit.titan.name=Titan +unit.titan.description=An advanced armored ground unit. Uses carbide as ammo. Attacks both ground and air targets. +unit.monsoon.name=Monsoon +unit.monsoon.description=A heavy carpet bomber. Uses blast compound or pyratite as ammo. +unit.interceptor.name=Interceptor +unit.interceptor.description=A fast, hit-and-run strike unit. Uses lead as ammo. +mode.sandbox.warning=Note that blocks cannot be used in sandbox mode until they are unlocked in other modes.\n\n[LIGHT_GRAY]If you have not unlocked any blocks, none will appear. +block.thermal-pump.name=Thermal Pump +block.dagger-pad.name=Dagger Pad +block.titan-pad.name=Titan Pad +block.thermal-generator.name=Thermal Generator diff --git a/core/assets/bundles/bundle_pl.properties b/core/assets/bundles/bundle_pl.properties index 1b60094901..87f3227356 100644 --- a/core/assets/bundles/bundle_pl.properties +++ b/core/assets/bundles/bundle_pl.properties @@ -1,8 +1,6 @@ -text.about=Stworzony przez [ROYAL] Anuken. []\nPierwotnie wpis w [orange] GDL [] MM Jam.\n\nNapisy:\n- SFX wykonane z pomocą [YELLOW] bfxr []\n- Muzyka wykonana przez [GREEN] RoccoW [] / znaleziona na [lime] FreeMusicArchive.org []\n\nSpecjalne podziękowania dla:\n- [coral] MitchellFJN []: obszerne testowanie i feedback\n- [niebo] Luxray5474 []: prace związane z wiki, pomoc z kodem\n- Wszystkich beta testerów na itch.io i Google Play\n text.discord=Odwiedź nasz serwer Discord text.gameover=Rdzeń został zniszczony. text.highscore=[YELLOW] Nowy rekord! -text.lasted=Wytrwałeś do fali text.level.highscore=Rekord: [accent]{0} text.level.delete.title=Potwierdź usuwanie text.level.select=Wybrany poziom @@ -117,9 +115,6 @@ text.settings.controls=Sterowanie text.settings.game=Gra text.settings.sound=Dźwięk text.settings.graphics=Grafika -text.upgrades=Ulepszenia -text.purchased=[LIME]Stworzono! -text.weapons=Bronie text.paused=Wstrzymano text.info.title=[accent]Informacje text.error.title=[crimson]Wystąpił błąd @@ -160,19 +155,6 @@ setting.musicvol.name=Głośność muzyki setting.mutemusic.name=Wycisz muzykę setting.sfxvol.name=Głośność dźwięków setting.mutesound.name=Wycisz dźwięki -map.maze.name=labirynt -map.fortress.name=twierdza -map.sinkhole.name=wgłębienie -map.caves.name=jaskinie -map.volcano.name=wulkan -map.caldera.name=kaldera -map.scorch.name=opalacz -map.desert.name=pustynia -map.island.name=wyspa -map.grassland.name=łąka -map.tundra.name=tundra -map.spiral.name=spirala -map.tutorial.name=Poradnik keybind.move_x.name=Poruszanie w poziomie keybind.move_y.name=Poruszanie w pionie keybind.select.name=Wybieranie @@ -183,7 +165,6 @@ keybind.zoom.name=Przybliżanie keybind.menu.name=menu keybind.pause.name=pauza keybind.dash.name=przyśpieszenie -keybind.rotate_alt.name=Obracanie (1) keybind.rotate.name=Obracanie (2) mode.waves.name=Fale mode.sandbox.name=sandbox @@ -218,8 +199,6 @@ text.link.wiki.description=Oficjana Wiki Mindustry text.linkfail=Nie udało się otworzyć linku!\nURL został skopiowany. text.editor.web=Wersja przeglądarkowa nie wspomaga edytora map!\nPobierz grę aby użyć edytora. text.web.unsupported=Wersja przeglądarkowa nie wspomaga tej fukcji!\nPobierz grę aby użyć tej funkcji. -text.multiplayer.web=Ta wersja gry nie wspomaga gry wieloosobowej!\nAby zagrać w grę wieloosobową, użyj wersji "wieloosobowa gra przeglądarkowa" na stronie itch.io. -text.host.web=Wersja przglądarkowa nie wspomaga tworzenia serwerów!\nPobierz grę aby użyć tej funkcji. text.map.delete=Jesteś pewny, że chcesz usunąć "[orange]{0}[]"? text.construction.title=Poradnik tworzenia bloków text.construction=Wybrałeś [accent]tryb tworzenia bloków[].\n\nAby zacząć stawiać bloki, po prostu kliknij na dostępne pole obot twojego statku.\nKiedy wybrałeś kilka bloków, kliknij ptaszek i twój statek zacznie budować bloki.\n\n- [accent]Anuluj bloki[] z twojej kolekcji przez klikanie ich(?).\n- [accent]Przesuwaj bloki w kolekcji[] przez przeciąganie ich w opowiednim kierunku.\n- [accent]Stawiaj bloki w lini[] przez kliknięcie w wybranym miejscu i przesuięcie palca.\n- [accent]Anuluj konstrukcję lub kolekcję [] przez kliknięcie X w lewym dolnym rogu. @@ -359,7 +338,6 @@ setting.fullscreen.name=Pełny ekran setting.multithread.name=Wielowątkowość setting.minimap.name=Pokaż Minimapę text.keybind.title=Zmień ustawienia przycisków -keybind.block_info.name=Informacje o bloku keybind.chat.name=Chat keybind.player_list.name=Lista graczy keybind.console.name=Konsola @@ -447,7 +425,6 @@ block.water-extractor.name=Wodny Ekstraktor block.cultivator.name=Spluchniacz block.dart-ship-factory.name=Fabryka Staktów "DART" block.delta-mech-factory.name=Fabryka Mecha "DELTA" -block.dronefactory.name=Fabryka Dronów block.repairpoint.name=Punkt Naprawy block.resupplypoint.name=Punkt Uzupełniania Amunicji block.liquidtank.name=Zbiornik na Płyny @@ -473,8 +450,6 @@ block.solar-panel.name=Panel Słoneczny block.solar-panel-large.name=Duży Panel Słoneczny block.oil-extractor.name=Ekstraktor Ropy block.javelin-ship-factory.name=Fabryka Statków "JAVELIN" -block.drone-factory.name=Fabryka Dronów -block.fabricator-factory.name=Fabryka Dronów Budowlanych block.repair-point.name=Punkt Napraw block.resupply-point.name=Punkt Uzupełniania Amunicji block.pulse-conduit.name=Rura Pulsacyjna @@ -493,7 +468,6 @@ text.sector=Wybrany Sektor: [LIGHT_GRAY]{0} text.sector.time=Czas: [LIGHT_GRAY]{0} text.sector.deploy=Wejdź text.sector.resume=Wznów -text.sector.unlocked=Sektor ukończony! text.sector.locked=[scarlet][[Niegotowy] text.sector.unexplored=[accent][[Nieodkryty] text.close=Zamknij @@ -501,3 +475,44 @@ text.save.playtime=Czas gry: {0} text.editor.brush=Pędzel block.itemvoid.name=Item Void block.powervoid.name=Power Void +text.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!) +text.sector.gameover=This sector has been lost. Re-deploy? +text.sector.retry=Retry +text.wave.lasted=You lasted until wave [accent]{0}[]. +setting.fpscap.name=Max FPS +setting.fpscap.none=None +setting.fpscap.text={0} FPS +block.command-center.name=Command Center +text.mission=Mission:[LIGHT_GRAY] {0} +text.mission.wave=Survive [accent]{0}[] waves. +text.mission.battle=Destroy the enemy base. +text.none= +text.sector.corrupted=[orange]A save file for this sector was found, but loading failed.\nA new one has been created. +text.mission.complete=Mission complete! +text.mission.complete.body=Sector {0},{1} has been conquered. +text.mission.resource=Obtain {0} x{1} +text.unit.health=[LIGHT_GRAY]Health: {0} +text.unit.speed=[LIGHT_GRAY]Speed: {0} +block.drone-pad.name=Drone Pad +block.fabricator-pad.name=Fabricator Pad +block.interceptor-pad.name=Interceptor Pad +block.monsoon-pad.name=Monsoon Pad +block.mass-driver.name=Mass Driver +block.blast-drill.name=Blast Drill +unit.drone.name=Drone +unit.drone.description=The starter drone unit. Spawns in the core by default. Automatically mines ores, collects items and repairs blocks. +unit.fabricator.name=Fabricator +unit.fabricator.description=An advanced drone unit. Automatically mines ores, collects items and repairs blocks. Significantly more effective than a drone. +unit.scout.name=Scout +unit.scout.description=A basic ground unit. Uses lead as ammo. +unit.titan.name=Titan +unit.titan.description=An advanced armored ground unit. Uses carbide as ammo. Attacks both ground and air targets. +unit.monsoon.name=Monsoon +unit.monsoon.description=A heavy carpet bomber. Uses blast compound or pyratite as ammo. +unit.interceptor.name=Interceptor +unit.interceptor.description=A fast, hit-and-run strike unit. Uses lead as ammo. +mode.sandbox.warning=Note that blocks cannot be used in sandbox mode until they are unlocked in other modes.\n\n[LIGHT_GRAY]If you have not unlocked any blocks, none will appear. +block.thermal-pump.name=Thermal Pump +block.dagger-pad.name=Dagger Pad +block.titan-pad.name=Titan Pad +block.thermal-generator.name=Thermal Generator diff --git a/core/assets/bundles/bundle_pt_BR.properties b/core/assets/bundles/bundle_pt_BR.properties index 2e28e9c87c..eb0579d4d2 100644 --- a/core/assets/bundles/bundle_pt_BR.properties +++ b/core/assets/bundles/bundle_pt_BR.properties @@ -1,8 +1,6 @@ -text.about=Criado por [ROYAL]Anuken.[]\nOriginalmente uma entrada para a [orange]GDL[] MM Jam.\n\nCredits:\n- SFX feito com [YELLOW]bfxr[]\n- Música feita por [GREEN]RoccoW[] / encontrada em [lime]FreeMusicArchive.org[]\n\nAgradecimento especial para:\n- [coral]MitchellFJN[]: playtesting extensivo e feedback\n- [sky]Luxray5474[]: wiki work e contribuições com código\n- Todos os beta testers do itch.io e Google Play\n text.discord=Junte-se ao Discord do Mindustry! (Lá nós falamos em inglês) text.gameover=O núcleo foi destruído. text.highscore=[YELLOW]Novo recorde! -text.lasted=Você durou até a horda text.level.highscore=Melhor\npontuação: [accent] {0} text.level.delete.title=Confirmar exclusão text.level.select=Seleção de Fase @@ -48,7 +46,7 @@ text.editor.saveimage=Salvar\nImagem text.editor.unsaved=[scarlet]Você tem alterações não salvas![]\nTem certeza que quer sair? text.editor.resizemap=Redimensionar Mapa text.editor.mapname=Nome do Mapa: -text.editor.overwrite=[accent]Aviso!\nIsso sobrescreve um mapa existente. +text.editor.overwrite=[accent]Aviso!\nIsso Subistitui um mapa existente. text.editor.selectmap=Selecione uma mapa para carregar: text.width=Largura: text.height=Altura: @@ -66,12 +64,9 @@ text.settings.controls=Controles text.settings.game=Jogo text.settings.sound=Som text.settings.graphics=Gráficos -text.upgrades=Melhorias -text.purchased=[LIME]Comprado! -text.weapons=Arsenal text.paused=Pausado -text.error.title=[crimson]Um erro ocorreu -text.error.crashtitle=Um erro ocorreu. +text.error.title=[crimson]Ocorreu um Erro. +text.error.crashtitle=Ocorreu um Erro text.blocks.blockinfo=Informação do Bloco text.blocks.powercapacity=Capacidade de Energia text.blocks.powershot=Energia/tiro @@ -92,7 +87,7 @@ setting.difficulty.hard=Difícil setting.difficulty.name=Dificuldade setting.screenshake.name=Balanço da Tela setting.indicators.name=Indicadores de Inimigos -setting.effects.name=Particulas +setting.effects.name=Efeitos setting.sensitivity.name=Sensibilidade do Controle setting.fps.name=Mostrar FPS setting.vsync.name=VSync @@ -102,19 +97,6 @@ setting.musicvol.name=Volume da Música setting.mutemusic.name=Desligar Musica setting.sfxvol.name=Volume de Efeitos setting.mutesound.name=Desligar Som -map.maze.name=maze -map.fortress.name=fortress -map.sinkhole.name=sinkhole -map.caves.name=caves -map.volcano.name=volcano -map.caldera.name=caldera -map.scorch.name=scorch -map.desert.name=desert -map.island.name=island -map.grassland.name=grassland -map.tundra.name=tundra -map.spiral.name=spiral -map.tutorial.name=tutorial keybind.move_x.name=move_x keybind.move_y.name=move_y keybind.select.name=selecionar @@ -124,7 +106,6 @@ keybind.zoom.name=zoom keybind.menu.name=menu keybind.pause.name=pausar keybind.dash.name=Correr -keybind.rotate_alt.name=girar_alt* keybind.rotate.name=girar mode.waves.name=hordas mode.sandbox.name=sandbox @@ -149,310 +130,305 @@ block.liquidjunction.name=Junção de líquido block.sorter.name=Ordenador block.sorter.description=[interact]Aperte no bloco para configurar[] block.smelter.name=Fornalha -text.credits=Credits -text.link.discord.description=the official Mindustry discord chatroom +text.credits=Creditos +text.link.discord.description=O discord oficial do Mindustry text.link.github.description=Game source code -text.link.dev-builds.description=Unstable development builds -text.link.trello.description=Official trello board for planned features -text.link.itch.io.description=itch.io page with PC downloads and web version +text.link.dev-builds.description=Desenvolvimentos Instaveis +text.link.trello.description=Trello Oficial para Updates Planejados +text.link.itch.io.description=Pagina da Itch.io com os Downloads text.link.google-play.description=Google Play store listing -text.link.wiki.description=official Mindustry wiki -text.linkfail=Failed to open link!\nThe URL has been copied to your cliboard. -text.editor.web=The web version does not support the editor!\nDownload the game to use it. -text.web.unsupported=The web version does not support this feature! Download the game to use it. -text.multiplayer.web=This version of the game does not support multiplayer!\nTo play multiplayer from your browser, use the "multiplayer web version" link at the itch.io page. -text.host.web=The web version does not support hosting games! Download the game to use this feature. -text.map.delete=Are you sure you want to delete the map "[orange]{0}[]"? -text.construction.title=Block Construction Guide +text.link.wiki.description=Wiki oficial do Mindustry +text.linkfail=Falha ao abrir o link\nO Url foi copiado +text.editor.web=A versão web não suporta o editor!\nBaixe o jogo para usar. +text.web.unsupported=A versão web não suporta este recurso! Baixe o jogo para usar. +text.map.delete=Certeza que quer deletar o mapa "[orange]{0}[]"? +text.construction.title=Guia de contrução de blocos text.construction=You've just selected [accent]block construction mode[].\n\nTo begin placing, simply tap a valid location near your ship.\nOnce you have selected some blocks, press the checkbox to confirm, and your ship will begin constructing them.\n\n- [accent]Remove blocks[] from your selection by tapping them.\n- [accent]Shift the selection[] by holding and dragging any block in the selection.\n- [accent]Place blocks in a line[] by tapping and holding an empty spot, then dragging in a direction.\n- [accent]Cancel construction or selection[] by pressing the X at the bottom left. text.deconstruction.title=Block Deconstruction Guide text.deconstruction=You've just selected [accent]block deconstruction mode[].\n\nTo begin breaking, simply tap a block near your ship.\nOnce you have selected some blocks, press the checkbox to confirm, and your ship will begin de-constructing them.\n\n- [accent]Remove blocks[] from your selection by tapping them.\n- [accent]Remove blocks in an area[] by tapping and holding an empty spot, then dragging in a direction.\n- [accent]Cancel deconstruction or selection[] by pressing the X at the bottom left. -text.showagain=Don't show again next session -text.unlocks=Unlocks -text.joingame=Join Game -text.addplayers=Add/Remove Players -text.maps=Maps -text.maps.none=[LIGHT_GRAY]No maps found! -text.about.button=About -text.name=Name: -text.unlocked=New Block Unlocked! -text.unlocked.plural=New Blocks Unlocked! -text.players={0} players online -text.players.single={0} player online -text.server.mismatch=Packet error: possible client/server version mismatch.\nMake sure you and the host have the\nlatest version of Mindustry! -text.server.closing=[accent]Closing server... -text.server.kicked.kick=You have been kicked from the server! -text.server.kicked.fastShoot=You are shooting too quickly. -text.server.kicked.invalidPassword=Invalid password! -text.server.kicked.clientOutdated=Outdated client! Update your game! -text.server.kicked.serverOutdated=Outdated server! Ask the host to update! -text.server.kicked.banned=You are banned on this server. -text.server.kicked.recentKick=You have been kicked recently.\nWait before connecting again. -text.server.kicked.nameInUse=There is someone with that name\nalready on this server. -text.server.kicked.nameEmpty=Your name must contain at least one character or number. -text.server.kicked.idInUse=You are already on this server! Connecting with two accounts is not permitted. -text.server.kicked.customClient=This server does not support custom builds. Download an official version. -text.host.info=The [accent]host[] button hosts a server on ports [scarlet]6567[] and [scarlet]6568.[]\nAnybody on the same [LIGHT_GRAY]wifi or local network[] should be able to see your server in their server list.\n\nIf you want people to be able to connect from anywhere by IP, [accent]port forwarding[] is required.\n\n[LIGHT_GRAY]Note: If someone is experiencing trouble connecting to your LAN game, make sure you have allowed Mindustry access to your local network in your firewall settings. -text.join.info=Here, you can enter a [accent]server IP[] to connect to, or discover [accent]local network[] servers to connect to.\nBoth LAN and WAN multiplayer is supported.\n\n[LIGHT_GRAY]Note: There is no automatic global server list; if you want to connect to someone by IP, you would need to ask the host for their IP. -text.hostserver=Host Server -text.host=Host -text.hosting=[accent]Opening server... -text.hosts.refresh=Refresh -text.hosts.discovering=Discovering LAN games -text.server.refreshing=Refreshing server -text.hosts.none=[lightgray]No LAN games found! -text.host.invalid=[scarlet]Can't connect to host. -text.trace=Trace Player -text.trace.playername=Player name: [accent]{0} +text.showagain=Não mostrar na proxima sessão +text.unlocks=Desbloqueados +text.joingame=Entrar no Jogo +text.addplayers=Adicionar/Remover Jogador +text.maps=Mapas +text.maps.none=[LIGHT_GRAY]Nenhum Mapa Encontrado! +text.about.button=Sobre +text.name=Nome: +text.unlocked=Novo bloco Desbloqueado! +text.unlocked.plural=Novos Blocos desbloqueados! +text.players={0} Jogadores Ativos +text.players.single={0} Jogador Ativo +text.server.mismatch=Packet error: Versão do Cliente/Servidor Incompativel.\nTenha certeza Que Host tem\nA ultima versão de Mindustry! +text.server.closing=[accent]Fechando servidor... +text.server.kicked.kick=Voce foi expulso do servidor! +text.server.kicked.fastShoot=Voce esta atirando rapido demais. +text.server.kicked.invalidPassword=Senha Incorreta! +text.server.kicked.clientOutdated=Cliente desatualizado! Atualize seu jogo! +text.server.kicked.serverOutdated=Servidor desatualiado! Peca ao dono para atualizar! +text.server.kicked.banned=Voce foi banido do servidor. +text.server.kicked.recentKick=Voce foi banido recentemente.\nEspere para conectar de novo. +text.server.kicked.nameInUse=Este nome ja esta sendo usado\nneste servidor. +text.server.kicked.nameEmpty=Voce deve ter pelo menos uma letra ou numero. +text.server.kicked.idInUse=Voce ja esta neste servidor! Conectar com duas contas não é permitido. +text.server.kicked.customClient=Este servidor não suporta construções customizadas. Baixe a versão original. +text.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 +text.hostserver=Hospedar servidor +text.host=Hospedar +text.hosting=[accent]Abrindo server... +text.hosts.refresh=atualizar +text.hosts.discovering=Descobrindo jogos em lan +text.server.refreshing=Atualizando servidor +text.hosts.none=[lightgray]Nenhum jogo lan encontrado! +text.host.invalid=[scarlet]Não foi possivel Hospedar. +text.trace=Traçar jogador +text.trace.playername=Nome do jogador: [accent]{0} text.trace.ip=IP: [accent]{0} text.trace.id=Unique ID: [accent]{0} -text.trace.android=Android Client: [accent]{0} -text.trace.modclient=Custom Client: [accent]{0} -text.trace.totalblocksbroken=Total blocks broken: [accent]{0} -text.trace.structureblocksbroken=Structure blocks broken: [accent]{0} -text.trace.lastblockbroken=Last block broken: [accent]{0} -text.trace.totalblocksplaced=Total blocks placed: [accent]{0} -text.trace.lastblockplaced=Last block placed: [accent]{0} -text.invalidid=Invalid client ID! Submit a bug report. -text.server.bans=Bans -text.server.bans.none=No banned players found! -text.server.admins=Admins -text.server.admins.none=No admins found! -text.server.add=Add Server -text.server.delete=Are you sure you want to delete this server? -text.server.hostname=Host: {0} -text.server.edit=Edit Server -text.server.outdated=[crimson]Outdated Server![] -text.server.outdated.client=[crimson]Outdated Client![] -text.server.version=[lightgray]Version: {0} -text.server.custombuild=[yellow]Custom Build -text.confirmban=Are you sure you want to ban this player? -text.confirmunban=Are you sure you want to unban this player? -text.confirmadmin=Are you sure you want to make this player an admin? -text.confirmunadmin=Are you sure you want to remove admin status from this player? -text.joingame.title=Join Game +text.trace.android=Cliente Androide: [accent]{0} +text.trace.modclient=Cliente Customizado: [accent]{0} +text.trace.totalblocksbroken=Blocos totais quebrados: [accent]{0} +text.trace.structureblocksbroken=Blocos de estrutura quebrados: [accent]{0} +text.trace.lastblockbroken=Ultimo bloco quebrado: [accent]{0} +text.trace.totalblocksplaced=Blocos totais Colocados: [accent]{0} +text.trace.lastblockplaced=Ultimo bloco colocado: [accent]{0} +text.invalidid=ID do cliente invalido! Reporte o bug. +text.server.bans=Banidos +text.server.bans.none=Nenhum jogador banido encontrado! +text.server.admins=Administradores +text.server.admins.none=Nenhum administrador encontrado! +text.server.add=Adicionar servidor +text.server.delete=Certeza que quer deletar o servidor? +text.server.hostname=Hospedar: {0} +text.server.edit=Editar servidor +text.server.outdated=[crimson]Servidor desatualizado![] +text.server.outdated.client=[crimson]Cliente desatualiado![] +text.server.version=[lightgray]Versão: {0} +text.server.custombuild=[yellow]Construção customizada +text.confirmban=Certeza que quer banir este jogador? +text.confirmunban=Certeza que quer desbanir este jogador? +text.confirmadmin=Certeza que quer fazer este jogador um administrador? +text.confirmunadmin=Certeza que quer remover o estatus de adminstrador deste jogador? +text.joingame.title=Entrar no jogo text.joingame.ip=IP: -text.disconnect=Disconnected. -text.disconnect.data=Failed to load world data! -text.connecting=[accent]Connecting... -text.connecting.data=[accent]Loading world data... -text.connectfail=[crimson]Failed to connect to server: [orange]{0} -text.server.port=Port: -text.server.addressinuse=Address already in use! -text.server.invalidport=Invalid port number! -text.server.error=[crimson]Error hosting server: [orange]{0} -text.save.new=New Save -text.save.none=No saves found! -text.save.delete.confirm=Are you sure you want to delete this save? -text.save.delete=Delete -text.save.export=Export Save -text.save.import.invalid=[orange]This save is invalid! -text.save.import.fail=[crimson]Failed to import save: [orange]{0} -text.save.export.fail=[crimson]Failed to export save: [orange]{0} -text.save.import=Import Save -text.save.newslot=Save name: -text.save.rename=Rename -text.save.rename.text=New name: -text.on=On -text.off=Off -text.save.autosave=Autosave: {0} -text.save.map=Map: {0} -text.save.difficulty=Difficulty: {0} -text.copylink=Copy Link +text.disconnect=Desconectado. +text.disconnect.data=Falha ao abrir a data do mundo! +text.connecting=[accent]Conectando... +text.connecting.data=[accent]Carregando data do mundo... +text.connectfail=[crimson]Falha ao entrar no servidor: [orange]{0} +text.server.port=Porte: +text.server.addressinuse=Senha em uso! +text.server.invalidport=Numero de port invalido! +text.server.error=[crimson]Erro ao hospedar o servidor: [orange]{0} +text.save.new=Novo Save +text.save.none=Nenhum save encontrado! +text.save.delete.confirm=Certeza que quer deletar este save? +text.save.delete=Deletar +text.save.export=Exportar save +text.save.import.invalid=[orange]Este save é invalido! +text.save.import.fail=[crimson]Falha ao importar save: [orange]{0} +text.save.export.fail=[crimson]Falha ao Exportar save: [orange]{0} +text.save.import=Importar save +text.save.newslot=Nome do save: +text.save.rename=Renomear +text.save.rename.text=Novo jogo: +text.on=Ligado +text.off=Desligado +text.save.autosave=Autosalvar: {0} +text.save.map=Mapa: {0} +text.save.difficulty=Dificuldade: {0} +text.copylink=Copiar link text.changelog.title=Changelog -text.changelog.loading=Getting changelog... -text.changelog.error.android=[orange]Note that the changelog sometimes does not work on Android 4.4 and below!\nThis is due to an internal Android bug. -text.changelog.error.ios=[orange]The changelog is currently not supported in iOS. -text.changelog.error=[scarlet]Error getting changelog!\nCheck your internet connection. -text.changelog.current=[yellow][[Current version] -text.changelog.latest=[orange][[Latest version] -text.saving=[accent]Saving... -text.unknown=Unknown -text.custom=Custom +text.changelog.loading=Coletando changelog... +text.changelog.error.android=[orange]Note que a Changelog as vezes Funciona no android 4.4 e abaixo!\nIsso é por causa de um erro interno no sistema android. +text.changelog.error.ios=[orange]A changelog não é suportada no IOS. +text.changelog.error=[scarlet]Erro ao coletar Changelog!\nCheque a Conexão com a internet. +text.changelog.current=[yellow][[Primeira versão] +text.changelog.latest=[orange][[Ultima versão] +text.saving=[accent]Salvando... +text.unknown=Desconhecido +text.custom=Customizado text.builtin=Built-In -text.map.delete.confirm=Are you sure you want to delete this map? This action cannot be undone! -text.map.random=[accent]Random Map -text.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. +text.map.delete.confirm=Certeza que quer deletar este mapa? Isto não pode ser desfeito! +text.map.random=[accent]Mapa aleatório +text.map.nospawn=Esse mapa não contém um [yellow]core[] para o jogador Nascer! [ROYAL]blue[] Coloque um [yellow]core[] no editor de mapa. text.editor.slope=\\ -text.editor.openin=Open In Editor -text.editor.oregen=Ore Generation -text.editor.oregen.info=Ore Generation: -text.editor.mapinfo=Map Info -text.editor.author=Author: -text.editor.description=Description: -text.editor.name=Name: -text.editor.teams=Teams -text.editor.elevation=Elevation -text.editor.saved=Saved! -text.editor.save.noname=Your map does not have a name! Set one in the 'map info' menu. -text.editor.save.overwrite=Your map overwrites a built-in map! Pick a different name in the 'map info' menu. -text.editor.import.exists=[scarlet]Unable to import:[] a built-in map named '{0}' already exists! -text.editor.import=Import... -text.editor.importmap=Import Map -text.editor.importmap.description=Import an already existing map -text.editor.importfile=Import File -text.editor.importfile.description=Import an external map file -text.editor.importimage=Import Terrain Image -text.editor.importimage.description=Import an external map image file -text.editor.export=Export... -text.editor.exportfile=Export File -text.editor.exportfile.description=Export a map file -text.editor.exportimage=Export Terrain Image -text.editor.exportimage.description=Export a map image file -text.editor.overwrite.confirm=[scarlet]Warning![] A map with this name already exists. Are you sure you want to overwrite it? +text.editor.openin=Abrir no Editor +text.editor.oregen=Geração de minério +text.editor.oregen.info=Geração de minério: +text.editor.mapinfo=Informação do mapa +text.editor.author=Autor: +text.editor.description=Descrição: +text.editor.name=Nome: +text.editor.teams=Time +text.editor.elevation=Elevação +text.editor.saved=Salvo! +text.editor.save.noname=Seu mapa não tem um nome! Coloque um no menu de "Informação do mapa" +text.editor.save.overwrite=O seu mapa Substitui um mapa já construído! Coloque um nome diferente no menu "Informação do mapa" +text.editor.import.exists=[scarlet]Não foi possivel importar:[] Um mapa Construído chamado '{0}' Já existe! +text.editor.import=Importando... +text.editor.importmap=Importar Mapa +text.editor.importmap.description=Importar um mapa existente +text.editor.importfile=Importar arquivo +text.editor.importfile.description=Importar um arquivo externo +text.editor.importimage=Importar imagem do terreno +text.editor.importimage.description=Importar uma imagem de terreno externa +text.editor.export=Exportando... +text.editor.exportfile=Exportar arquivo +text.editor.exportfile.description=Exportar um arquivo de mapa +text.editor.exportimage=Exportar imagem de terreno +text.editor.exportimage.description=Exportar um arquivo de imagem de mapa +text.editor.overwrite.confirm=[scarlet]Aviso![] Um mapa com esse nome já existe. Tem certeza que deseja substituir? text.fps=FPS: {0} text.tps=TPS: {0} text.ping=Ping: {0}ms -text.language.restart=Please restart your game for the language settings to take effect. -text.settings.language=Language -text.settings.rebind=Rebind -text.yes=Yes -text.no=No -text.info.title=[accent]Info -text.blocks.targetsair=Targets Air -text.blocks.itemspeed=Units Moved -text.blocks.shootrange=Range -text.blocks.poweruse=Power Use -text.blocks.inputitemcapacity=Input Item Capacity -text.blocks.outputitemcapacity=Input Item Capacity -text.blocks.maxpowergeneration=Max Power Generation -text.blocks.powertransferspeed=Power Transfer -text.blocks.craftspeed=Production Speed -text.blocks.inputliquidaux=Aux Liquid -text.blocks.inputitems=Input Items -text.blocks.outputitem=Output Item -text.blocks.drilltier=Drillables -text.blocks.drillspeed=Base Drill Speed -text.blocks.liquidoutput=Liquid Output -text.blocks.liquiduse=Liquid Use -text.blocks.coolant=Coolant -text.blocks.coolantuse=Coolant Use -text.blocks.inputliquidfuel=Fuel Liquid -text.blocks.liquidfueluse=Liquid Fuel Use -text.blocks.reload=Reload -text.blocks.inputfuel=Fuel -text.blocks.fuelburntime=Fuel Burn Time -text.blocks.inputcapacity=Input capacity -text.blocks.outputcapacity=Output capacity -text.unit.blocks=blocks -text.unit.powersecond=power units/second -text.unit.liquidsecond=liquid units/second -text.unit.itemssecond=items/second -text.unit.pixelssecond=pixels/second -text.unit.liquidunits=liquid units -text.unit.powerunits=power units -text.unit.degrees=degrees -text.unit.seconds=seconds +text.language.restart=Por favor Reinicie seu jogo para a tradução tomar efeito. +text.settings.language=Linguagem +text.settings.rebind=Religar +text.yes=Sim +text.no=Não +text.info.title=[accent]Informação +text.blocks.targetsair=Mirar no ar +text.blocks.itemspeed=Unidades mobilizadas +text.blocks.shootrange=Alcance +text.blocks.poweruse=Uso de energia +text.blocks.inputitemcapacity=Configurar capacidade de itens +text.blocks.outputitemcapacity=Configurar capacidade de itens +text.blocks.maxpowergeneration=Geração maxima de energia +text.blocks.powertransferspeed=Transferência de energia +text.blocks.craftspeed=Velocidade de produção +text.blocks.inputliquidaux=Líquido auxiliar +text.blocks.inputitems=Itens de entrada +text.blocks.outputitem=Itens de saida +text.blocks.drilltier=Furaveis +text.blocks.drillspeed=Velocidade da furadeira base +text.blocks.liquidoutput=Saida de liquido +text.blocks.liquiduse=Uso de liquido +text.blocks.coolant=Esfriador +text.blocks.coolantuse=Uso do esfriador +text.blocks.inputliquidfuel=Liquido de combustivel +text.blocks.liquidfueluse=Uso do liquido de combustivel +text.blocks.reload=Recarregar +text.blocks.inputfuel=Combustivel +text.blocks.fuelburntime=Tempo de queima de combustivel +text.blocks.inputcapacity=Capacidade de entrada +text.blocks.outputcapacity=Capacidade de saída +text.unit.blocks=blocos +text.unit.powersecond=Unidades de energia/segundo +text.unit.liquidsecond=Unidades de líquido/segundo +text.unit.itemssecond=itens/segundo +text.unit.pixelssecond=pixeis/segundo +text.unit.liquidunits=Unidades de liquido +text.unit.powerunits=Unidades de energia +text.unit.degrees=Graus +text.unit.seconds=segundos text.unit.none= -text.unit.items=items -text.category.general=General -text.category.power=Power -text.category.liquids=Liquids -text.category.items=Items -text.category.crafting=Crafting -text.category.shooting=Shooting -setting.difficulty.insane=insane +text.unit.items=itens +text.category.general=Geral +text.category.power=Poder +text.category.liquids=Liquidos +text.category.items=Itens +text.category.crafting=Construindo +text.category.shooting=Atirando +setting.difficulty.insane=insano setting.difficulty.purge=purge -setting.saveinterval.name=Autosave Interval -setting.seconds={0} Seconds -setting.fullscreen.name=Fullscreen +setting.saveinterval.name=Intervalo de autosalvamento +setting.seconds={0} Segundos +setting.fullscreen.name=Tela Cheia setting.multithread.name=Multithreading -setting.minimap.name=Show Minimap -text.keybind.title=Rebind Keys -keybind.shoot.name=shoot -keybind.block_info.name=block_info -keybind.chat.name=chat -keybind.player_list.name=player_list +setting.minimap.name=Mostrar minimapa +text.keybind.title=Refazer teclas +keybind.shoot.name=Atirar +keybind.chat.name=Conversa +keybind.player_list.name=Lista_de_jogadores keybind.console.name=console -mode.text.help.title=Description of modes -mode.waves.description=the normal mode. limited resources and automatic incoming waves. -mode.sandbox.description=infinite resources and no timer for waves. -mode.freebuild.description=limited resources and no timer for waves. -content.item.name=Items -content.liquid.name=Liquids -content.unit-type.name=Units -content.recipe.name=Blocks -item.stone.description=A common raw material. Used for separating and refining into other materials, or melting into lava. -item.tungsten.name=Tungsten -item.tungsten.description=A common, but very useful structure material. Used in drills and heat-resistant blocks such as generators and smelteries. -item.lead.name=Lead -item.lead.description=A basic starter material. Used extensively in electronics and liquid transportation blocks. -item.coal.description=A common and readily available fuel. -item.carbide.name=Carbide -item.carbide.description=A tough alloy made with tungsten and carbon. Used in advanced transportation blocks and high-tier drills. -item.titanium.description=A rare super-light metal used extensively in liquid transportation, drills and aircraft. +mode.text.help.title=Descrição dos modos +mode.waves.description=O modo normal. Recursos limitados E os ataques vem automaticamente. +mode.sandbox.description=Recursos infinitos E sem tempo para Ataques. +mode.freebuild.description=recursos limitados e Sem tempo para Ataques. +content.item.name=Itens +content.liquid.name=Liquidos +content.unit-type.name=Unidades +content.recipe.name=Blocos +item.stone.description=Um Material Incomum Cru. Usado para separar e refinar Em outros materiais,Ou Derreter em Lava. +item.tungsten.name=Tungstenio +item.tungsten.description=Comum, Mas muito util Material de estrutura. Usado em blocos anti-Aquecimento e blocos com geradores E ferrarias. +item.lead.name=Chumbo +item.lead.description=Material de comeco basico. usado intensivamente em Blocos de transporte de liquidos e eletronicos. +item.coal.description=Combustivel pronto. +item.carbide.name=Carboneto +item.carbide.description=Uma aliança dura feita com Tugstenio e Carbono. Usado em blocos de transportação avançados E brocas de alto nivel. +item.titanium.description=Um Material raro super leve, metal usado intensivamente na transportação de líquidos, Brocas e Aeronaves. item.thorium.description=A dense, radioactive metal used as structural support and nuclear fuel. -item.silicon.name=Silicon -item.silcion.description=An extremely useful semiconductor, with applications in solar panels and many complex electronics. -item.plastanium.name=Plastanium -item.plastanium.description=A light, ductile material used in advanced aircraft and fragmentation ammunition. -item.phase-matter.name=Phase Matter -item.surge-alloy.name=Surge Alloy -item.biomatter.name=Biomatter +item.silicon.name=Sílicio +item.silcion.description=Condutor extremamente importante,Com aplicação em paneis solares e dispositivos complexos. +item.plastanium.name=Plastanio +item.plastanium.description=Leve, Material dutil Usado em aeronaves Avançadas E munição de fragmentação. +item.phase-matter.name=Materia fase +item.surge-alloy.name=Liga de surto +item.biomatter.name=Biomateria item.biomatter.description=A clump of organic mush; used for conversion into oil or as a basic fuel. -item.sand.name=Sand -item.sand.description=A common material that is used extensively in smelting, both in alloying and as a flux. -item.blast-compound.name=Blast Compound -item.blast-compound.description=A volatile compound used in bombs and explosives. While it can burned as fuel, this is not advised. -item.pyratite.name=Pyratite -item.pyratite.description=An extremely flammable substance used in incendiary weapons. -liquid.cryofluid.name=Cryofluid -text.item.explosiveness=[LIGHT_GRAY]Explosiveness: {0} -text.item.flammability=[LIGHT_GRAY]Flammability: {0} -text.item.radioactivity=[LIGHT_GRAY]Radioactivity: {0} -text.item.fluxiness=[LIGHT_GRAY]Flux Power: {0} -text.item.hardness=[LIGHT_GRAY]Hardness: {0} -text.liquid.heatcapacity=[LIGHT_GRAY]Heat Capacity: {0} -text.liquid.viscosity=[LIGHT_GRAY]Viscosity: {0} -text.liquid.temperature=[LIGHT_GRAY]Temperature: {0} -block.tungsten-wall.name=Tungsten Wall -block.tungsten-wall-large.name=Large Tungsten Wall -block.carbide-wall.name=Carbide Wall -block.carbide-wall-large.name=Large Carbide Wall -block.thorium-wall.name=Thorium Wall -block.thorium-wall-large.name=Large Thorium Wall -block.duo.name=Duo -block.scorch.name=Scorch +item.sand.name=Areia +item.sand.description=Um material comum Que é usado intensivamente em derretimento, Tanto em ligas como fluxo. +item.blast-compound.name=Composto de explosão +item.blast-compound.description=Um composto volatil usado em bombas em bombas em explosivos. Enquanto pode ser queimado como combustivel, Isso não é recomendado. +item.pyratite.name=piratita +item.pyratite.description=Substancia extremamente inflamavel usado em armas incendiarias. +liquid.cryofluid.name=Crio Fluido +text.item.explosiveness=[LIGHT_GRAY]Explosividade: {0} +text.item.flammability=[LIGHT_GRAY]Inflamabilidade: {0} +text.item.radioactivity=[LIGHT_GRAY]RadioAtividade: {0} +text.item.fluxiness=[LIGHT_GRAY]Poder do fluxo: {0} +text.item.hardness=[LIGHT_GRAY]Dureza: {0} +text.liquid.heatcapacity=[LIGHT_GRAY]Capacidade de aquecimento: {0} +text.liquid.viscosity=[LIGHT_GRAY]Viscosidade: {0} +text.liquid.temperature=[LIGHT_GRAY]Temperatura: {0} +block.tungsten-wall.name=Parede de tugstenio +block.tungsten-wall-large.name=Parede larga de Tugstenio +block.carbide-wall.name=Parede de carboneto +block.carbide-wall-large.name=Parede de Carboneto +block.thorium-wall.name=Parede de tório +block.thorium-wall-large.name=Parede larga de tório +block.duo.name=Duplo +block.scorch.name=Quimar block.hail.name=Hail block.lancer.name=Lancer -block.titanium-conveyor.name=Titanium Conveyor -block.splitter.name=Splitter -block.splitter.description=Outputs items into two opposite directions immediately after they are recieved. -block.distributor.name=Distributor -block.distributor.description=A splitter that can split items into 8 directions. -block.overflow-gate.name=Overflow Gate -block.overflow-gate.description=A combination splitter and router that only outputs to the left and right if the front path is blocked. -block.bridgeconveyor.name=Bridge Conveyor -block.bridgeconveyor.description=A conveyor that can go over other blocks, for up to two total blocks. -block.arc-smelter.name=Arc Smelter -block.silicon-smelter.name=Silicon Smelter -block.phase-weaver.name=Phase Weaver -block.pulverizer.name=Pulverizer -block.cryofluidmixer.name=Cryofluid Mixer -block.melter.name=Melter -block.incinerator.name=Incinerator -block.biomattercompressor.name=Biomatter Compressor -block.separator.name=Separator -block.centrifuge.name=Centrifuge -block.power-node.name=Power Node -block.power-node-large.name=Large Power Node -block.battery.name=Battery -block.battery-large.name=Large Battery -block.combustion-generator.name=Combustion Generator -block.turbine-generator.name=Turbine Generator -block.tungsten-drill.name=Tungsten Drill -block.carbide-drill.name=Carbide Drill -block.laser-drill.name=Laser Drill -block.water-extractor.name=Water Extractor -block.cultivator.name=Cultivator +block.titanium-conveyor.name=Esteira de Titanio +block.splitter.name=Divisor +block.splitter.description=Manda os itens em duas direções diferentes imediatamente quando chegam. +block.distributor.name=Distribuidor +block.distributor.description=Um divisor que pode dividir itens em 8. +block.overflow-gate.name=Portão Sobrecarregado +block.overflow-gate.description=Uma combinação de roteador e divisor Que apenas manda para a esquerda e Direita se a frente estiver bloqueada. +block.bridgeconveyor.name=Esteira de ponte +block.bridgeconveyor.description=Uma esteira que pode ir acima de outros blocos, No total de 2 blocos. +block.arc-smelter.name=Fundidora Arc +block.silicon-smelter.name=Fundidora de silicio +block.phase-weaver.name=Palheta de fase +block.pulverizer.name=Pulverizador +block.cryofluidmixer.name=Misturador de Crio Fluido +block.melter.name=Aparelho de fusão +block.incinerator.name=Incinerador +block.biomattercompressor.name=Compressor de bio-matéria +block.separator.name=Separador +block.centrifuge.name=Centrifuga +block.power-node.name=Célula de energia +block.power-node-large.name=Célula de energia Grande +block.battery.name=Bateria +block.battery-large.name=Bateria Grande +block.combustion-generator.name=Gerador de combustão +block.turbine-generator.name=Gerador de Turbina +block.tungsten-drill.name=Broca de Tungstenio +block.carbide-drill.name=Broca de Carboneto +block.laser-drill.name=Broca a Laser +block.water-extractor.name=Extrator de Agua +block.cultivator.name=Cultivador block.dart-ship-factory.name=Dart Ship Factory -block.delta-mech-factory.name=Delta Mech Factory -block.dronefactory.name=Drone Factory -block.repairpoint.name=Repair Point -block.resupplypoint.name=Resupply Point -block.liquidtank.name=Liquid Tank -block.bridgeconduit.name=Bridge Conduit -block.mechanical-pump.name=Mechanical Pump +block.delta-mech-factory.name=Fabrica de Mecha Delta +block.repairpoint.name=Ponto de Reparo +block.resupplypoint.name=Ponto de Reabesticento +block.liquidtank.name=Tanque de líquido +block.bridgeconduit.name=Conduto Ponte +block.mechanical-pump.name=Bomba Mecanica block.itemsource.name=Item Source block.itemvoid.name=Item Void block.liquidsource.name=Liquid Source @@ -460,44 +436,83 @@ block.powervoid.name=Power Void block.powerinfinite.name=Power Infinite block.unloader.name=Unloader block.sortedunloader.name=Sorted Unloader -block.vault.name=Vault +block.vault.name=Cofre block.wave.name=Wave block.swarmer.name=Swarmer block.salvo.name=Salvo block.ripple.name=Ripple -block.phase-conveyor.name=Phase Conveyor -block.bridge-conveyor.name=Bridge Conveyor -block.plastanium-compressor.name=Plastanium Compressor -block.pyratite-mixer.name=Pyratite Mixer +block.phase-conveyor.name=Esteira de Fases +block.bridge-conveyor.name=Esteira-Ponte +block.plastanium-compressor.name=Compressor de Plastanio +block.pyratite-mixer.name=Misturador de Piratita block.blast-mixer.name=Blast Mixer -block.solidifer.name=Solidifer -block.solar-panel.name=Solar Panel -block.solar-panel-large.name=Large Solar Panel -block.oil-extractor.name=Oil Extractor -block.javelin-ship-factory.name=Javelin Ship factory -block.drone-factory.name=Drone Factory -block.fabricator-factory.name=Fabricator Factory -block.repair-point.name=Repair Point -block.resupply-point.name=Resupply Point -block.pulse-conduit.name=Pulse Conduit -block.phase-conduit.name=Phase Conduit -block.liquid-router.name=Liquid Router -block.liquid-tank.name=Liquid Tank -block.liquid-junction.name=Liquid Junction -block.bridge-conduit.name=Bridge Conduit -block.rotary-pump.name=Rotary Pump -block.nuclear-reactor.name=Nuclear Reactor -text.save.old=This save is for an older version of the game, and can no longer be used.\n\n[LIGHT_GRAY]Save backwards compatibility will be implemented in the full 4.0 release. -text.customgame=Custom Game -text.campaign=Campaign -text.sectors=Sectors -text.sector=Selected Sector: [LIGHT_GRAY]{0} -text.sector.time=Time: [LIGHT_GRAY]{0} -text.sector.deploy=Deploy -text.sector.resume=Resume -text.sector.unlocked=Sector completed! +block.solidifer.name=Solidificador +block.solar-panel.name=Painel Solar +block.solar-panel-large.name=Painel Solar Grande +block.oil-extractor.name=Extrator de Oleo +block.javelin-ship-factory.name=Fabrica de Nave Javelin +block.repair-point.name=Ponto de Reparo +block.resupply-point.name=Ponto de Reabastecimento +block.pulse-conduit.name=Conduto de Pulso +block.phase-conduit.name=Conduto de Fase +block.liquid-router.name=Roteador de Líquido +block.liquid-tank.name=Tanque de Líquido +block.liquid-junction.name=Junção de Líquido +block.bridge-conduit.name=Conduto-Ponte +block.rotary-pump.name=Bomba Rotatoria +block.nuclear-reactor.name=Reator Nuclear +text.save.old=Este save é para uma versão antiga do jogo, E não pode ser usado.\n\n[LIGHT_GRAY]Salvar Versões antigas vai ser Implementado Na versão 4.0 completa +text.customgame=Jogo Customizado +text.campaign=Campanha +text.sectors=Setores +text.sector=Setor Selecionado: [LIGHT_GRAY]{0} +text.sector.time=Tempo: [LIGHT_GRAY]{0} +text.sector.deploy=Soltar +text.sector.resume=Voltar text.sector.locked=[scarlet][[Incomplete] text.sector.unexplored=[accent][[Unexplored] -text.close=Close +text.close=Fechar text.save.playtime=Playtime: {0} text.editor.brush=Brush +text.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!) +text.sector.gameover=Esse setor foi perdido! Soltar Novamente? +text.sector.retry=Tentar novamente? +text.wave.lasted=Você sobreviveu até a onda [accent]{0}[]. +setting.fpscap.name=FPS Maximo +setting.fpscap.none=Nenhum +setting.fpscap.text={0} FPS +block.command-center.name=Centro De Comando +text.mission=Missão:[LIGHT_GRAY] {0} +text.mission.wave=Sobrevive [accent]{0}[] Onda. +text.mission.battle=Destrua a base inimiga. +text.none= +text.sector.corrupted=[orange]Um arquivo de save Foi encontrado neste setor, Mas o login falhou.\nUm novo foi criado. +text.mission.complete=Mission complete! +text.mission.complete.body=Sector {0},{1} has been conquered. +text.mission.resource=Obtain {0} x{1} +text.join.info=Here, you can enter a [accent]server IP[] to connect to, or discover [accent]local network[] servers to connect to.\nBoth LAN and WAN multiplayer is supported.\n\n[LIGHT_GRAY]Note: There is no automatic global server list; if you want to connect to someone by IP, you would need to ask the host for their IP. +text.unit.health=[LIGHT_GRAY]Health: {0} +text.unit.speed=[LIGHT_GRAY]Speed: {0} +block.drone-pad.name=Drone Pad +block.fabricator-pad.name=Fabricator Pad +block.interceptor-pad.name=Interceptor Pad +block.monsoon-pad.name=Monsoon Pad +block.mass-driver.name=Mass Driver +block.blast-drill.name=Blast Drill +unit.drone.name=Drone +unit.drone.description=The starter drone unit. Spawns in the core by default. Automatically mines ores, collects items and repairs blocks. +unit.fabricator.name=Fabricator +unit.fabricator.description=An advanced drone unit. Automatically mines ores, collects items and repairs blocks. Significantly more effective than a drone. +unit.scout.name=Scout +unit.scout.description=A basic ground unit. Uses lead as ammo. +unit.titan.name=Titan +unit.titan.description=An advanced armored ground unit. Uses carbide as ammo. Attacks both ground and air targets. +unit.monsoon.name=Monsoon +unit.monsoon.description=A heavy carpet bomber. Uses blast compound or pyratite as ammo. +unit.interceptor.name=Interceptor +unit.interceptor.description=A fast, hit-and-run strike unit. Uses lead as ammo. +mode.sandbox.warning=Note that blocks cannot be used in sandbox mode until they are unlocked in other modes.\n\n[LIGHT_GRAY]If you have not unlocked any blocks, none will appear. +block.thermal-pump.name=Thermal Pump +block.dagger-pad.name=Dagger Pad +block.titan-pad.name=Titan Pad +block.thermal-generator.name=Thermal Generator diff --git a/core/assets/bundles/bundle_ru.properties b/core/assets/bundles/bundle_ru.properties index 188ef80076..d71d768572 100644 --- a/core/assets/bundles/bundle_ru.properties +++ b/core/assets/bundles/bundle_ru.properties @@ -1,6 +1,6 @@ -text.about=Создатель [ROYAL] Anuken. [] \nИзначально игра была создана для участия в [orange] GDL [] MM Jam. \n\nАвторы: \n- Звуковые эффекты, сделаны с помощью [YELLOW] bfxr [] \n- Музыка, создана [GREEN] RoccoW [] / найденная на [lime] FreeMusicArchive.org [] \n\nОсобая благодарность: \n- [coral] MitchellFJN []: в тестировании и отзывах \n- [sky] Luxray5474 []: работа в вики, помощь в разработке \n- Все бета-тестеры на itch.io и Google Play\n\nИгра переведена полностью на русский язык [GREEN]krocotavus[] и [GREEN]lexa1549. Дополнил перевод [GREEN]Prosta4ok_ua[]\n +text.credits.text=Создатель [ROYAL] Anuken. - [SKY]anukendev@gmail.com[]\n\nЕсть недороботки в переводе?\nПишите в офф. discord-сервер mindustry в канал #русский. text.credits=Авторы -text.discord=Присоединяйтесь к нашему Discord чату! +text.discord=Присоединяйтесь к нашему Discord! text.link.discord.description=официальный discord-сервер Mindustry text.link.github.description=Исходный код игры text.link.dev-builds.description=Нестабильные разработки @@ -10,23 +10,54 @@ text.link.google-play.description=Google Play список магазинов text.link.wiki.description=официальная вики Mindustry text.linkfail=Не удалось открыть ссылку!\nURL-адрес был скопирован в буфер обмена. text.editor.web=Веб-версия не поддерживает редактор!\nЗагрузите игру, чтобы использовать ее. -text.multiplayer.web=Эта версия игры не поддерживает многопользовательскую игру! \n Чтобы играть в мультиплеер из своего браузера, используйте ссылку «Многопользовательская веб-версия» на странице itch.io. +text.web.unsupported=Веб-версия не поддерживает эту функцию! Загрузите игру, чтобы использовать её. text.gameover=Ядро было уничтожено. +text.sector.gameover=Этот сектор потерян. Разблокировать повторно? +text.sector.retry=Повторить попытку text.highscore=[YELLOW]Новый рекорд! -text.lasted=Вы продержались до волны +text.wave.lasted=Вы продержались до волны [accent]{0}[]. text.level.highscore=Рекорд: [accent]{0} text.level.delete.title=Подтвердите удаление +text.map.delete=Вы действительно хотите удалить карту "[orange]{0}[]"? text.level.select=Выбор уровня text.level.mode=Режим игры: +text.construction.title=Руководство по строительству блоков +text.construction=Вы только что выбрали режим строительства [accent]блоков[].\n\nЧтобы начать размещение, просто коснитесь действительного местоположения рядом с вашим кораблем.\nПосле того, как вы выбрали несколько блоков, установите флажок, чтобы подтвердить, и ваш корабль начнет их строить.\n\n- [accent]Удалите блоки [] из вашего выбора, нажав на них.n- [accent]Shift выделение [], удерживая и перетаскивая любой блок в выборе.\n- [accent]Поместите блоки в линию [], нажимая и удерживая пустое место, а затем перетаскивая его в направлении.\n- [accent]Отмените строительство или выбор [], нажав X в левом нижнем углу. +text.deconstruction.title=Руководство по разрушении блоков +text.deconstruction=Вы только что выбрали режим удаления[accent] блока.[].\n\nЧтобы начать ломать, просто нажмите на блок рядом с вашим кораблем.\nПосле того как вы выбрали некоторые блоки, установите флажок, чтобы подтвердить, и ваш корабль начнет их деконструкцию.\n\n- [accent]Удалите блоки [] из вашего выбора, нажав на них.\n- [accent]Удалите блоки в области [], нажав и удерживая пустое место, а затем перетащив его в направлении.\n- [accent]Отмените деконструкцию или выбор [], нажав X в левом нижнем углу. +text.showagain=Не показывать снова до следующей сессии +text.unlocks=Разблокированные text.savegame=Сохранить игру text.loadgame=Загрузить игру text.joingame=Присоединиться +text.addplayers=Доб/удалить игроков +text.customgame=Пользовательская игра +text.campaign=Кампания +text.sectors=Секторы +text.sector=Выбранный сектор: [LIGHT_GRAY]{0} +text.sector.time=Время: [LIGHT_GRAY]{0} +text.sector.deploy=Высадиться +text.sector.resume=Продолжить +text.sector.locked=[scarlet][[Не завершено] +text.sector.unexplored=[accent][[Не изучено] +text.mission=Миссия:[LIGHT_GRAY] {0} +text.mission.complete=Миссия выполнена! +text.mission.complete.body=Сектор {0},{1} был завоёван. +text.mission.wave=Пережено следующее количество волн:[accent]{0}[]. +text.mission.battle=Уничтожьте базу противника. +text.mission.resource=Приобретено {0} x{1} +text.none=<ничего> +text.close=Закрыть text.quit=Выход +text.maps=Карты +text.maps.none=[LIGHT_GRAY]Карты не найдены! text.about.button=Об игре -text.name=Название: +text.name=Ник: +text.unlocked=Новый блок разблокирован! +text.unlocked.plural=Новые блоки разблокированы! text.players=Игроков на сервере: {0} text.players.single={0} игрок на сервере -text.server.mismatch=Ошибка пакета: возможное несоответствие версии клиента / сервера. Убедитесь, что у вас и у создателя сервера установлена ​​последняя версия Mindustry! +text.server.mismatch=Ошибка пакета: возможное несоответствие версии клиента/сервера. Убедитесь, что у вас и у создателя сервера установлена последняя версия Mindustry! text.server.closing=[accent]Закрытие сервера... text.server.kicked.kick=Вас выгнали с сервера! text.server.kicked.fastShoot=Вы стреляете слишком быстро. @@ -35,8 +66,12 @@ text.server.kicked.clientOutdated=Устаревший клиент! Обнов text.server.kicked.serverOutdated=Устаревший сервер! Попросите хост обновить! text.server.kicked.banned=Вы заблокированы на этом сервере. text.server.kicked.recentKick=Вы недавно были кикнуты.\n Подождите немного перед следующим подключением -text.host.info=The [accent]host[] button hosts a server on ports [scarlet]6567[] and [scarlet]6568.[]\nAnybody on the same [LIGHT_GRAY]wifi or local network[] should be able to see your server in their server list.\n\nIf you want people to be able to connect from anywhere by IP, [accent]port forwarding[] is required.\n\n[LIGHT_GRAY]Note: If someone is experiencing trouble connecting to your LAN game, make sure you have allowed Mindustry access to your local network in your firewall settings. -text.join.info=Here, you can enter a [accent]server IP[] to connect to, or discover [accent]local network[] servers to connect to.\nBoth LAN and WAN multiplayer is supported.\n\n[LIGHT_GRAY]Note: There is no automatic global server list; if you want to connect to someone by IP, you would need to ask the host for their IP. +text.server.kicked.nameInUse=На этом сервере есть кто-то с этим именем. +text.server.kicked.nameEmpty=Ваше имя должно содержать хотя бы один символ или цифру. +text.server.kicked.idInUse=Вы уже на этом сервере! Соединение с двумя учетными записями не разрешено. +text.server.kicked.customClient=Этот сервер не поддерживает пользовательские сборки. Загрузите официальную версию. +text.host.info=Кнопка [accent] Сервер [] размещает сервер на порт [accent]6567[].[]\nЛюбой пользователь в той же [LIGHT_GRAY]сети или локальной сети [] должен иметь возможность видеть ваш сервер в своём списке серверов.\n\nЕсли вы хотите, чтобы люди могли подключаться из любого места по IP, то требуется переадресация(проброс) портов.[].\n\n[LIGHT_GRAY] Примечание. Если у кого-то возникают проблемы с подключением к вашей локальной сети, убедитесь, что вы разрешили Mindustry доступ к вашей локальной сети в настройках брандмауэра. +text.join.info=Здесь вы можете ввести IP-адрес [accent]сервера[] для подключения или открыть [accent]локальную сеть [] для подключения к серверам.\nПоддерживается многопользовательский режим LAN и WAN.\n\n[LIGHT_GRAY] Примечание: это не является автоматическим глобальным списком серверов; если вы хотите подключиться к кому-то по IP, вам нужно будет спросить хост о его IP-адресе. text.hostserver=Запустить сервер text.host=Сервер text.hosting=[accent]Открытие сервера... @@ -52,6 +87,7 @@ text.trace.id=Уникальный идентификатор: [accent]{0} text.trace.android=Клиент Android: [accent]{0} text.trace.modclient=Пользовательский клиент: [accent]{0} text.trace.totalblocksbroken=Всего разбитых блоков: [accent]{0} +text.trace.structureblocksbroken=Структурных блоков сломано: [accent]{0} text.trace.lastblockbroken=Последний сломанный блок:[accent]{0} text.trace.totalblocksplaced=Всего размещено блоков: [accent]{0} text.trace.lastblockplaced=Последний размещенный блок: [accent]{0} @@ -83,6 +119,7 @@ text.server.port=Порт: text.server.addressinuse=Адрес уже используется! text.server.invalidport=Неверный номер порта! text.server.error=[crimson]Ошибка создания сервера: [orange] {0} +text.save.old=Это сохранение для более старой версии игры и больше не может использоваться.\n\n[LIGHT_GRAY]Сохранение обратной совместимости будет реализовано в полной версии 4.0. text.save.new=Новое сохранение text.save.overwrite=Вы уверены,что хотите перезаписать этот слот для сохранения? text.overwrite=Перезаписать @@ -91,7 +128,7 @@ text.saveload=[accent]Сохранение... text.savefail=Не удалось сохранить игру! text.save.delete.confirm=Вы уверены,что хотите удалить это сохранение? text.save.delete=Удалить -text.save.export=Отправить сохранение +text.save.export=Экспортировать сохранение text.save.import.invalid=[orange]Это сохранение недействительно! text.save.import.fail=[crimson]Не удалось импортировать сохранение: [orange] {0} text.save.export.fail=[crimson]Не удалось отправить сохранение: [orange] {0} @@ -101,7 +138,8 @@ text.save.rename=Переименовывать text.save.rename.text=Новое название: text.selectslot=Выберите сохранение. text.slot=[accent]Слот {0} -text.save.corrupted=[orange]Файл сохранения поврежден или имеет недействительный формат! +text.save.corrupted=[orange]Сохранённый файл повреждён или имеет недействительный формат!\nЕсли вы только что обновили свою игру, это, вероятно, изменение формата сохранения[scarlet], а не []ошибка. +text.sector.corrupted=[orange] Файл сохранения для этого сектора был найден, но загрузка не удалась.\nСоздан новый. text.empty=<Пусто> text.on=Вкл text.off=Выкл @@ -110,6 +148,7 @@ text.save.map=Карта: {0} text.save.wave=Волна: {0} text.save.difficulty=Сложность: {0} text.save.date=Последнее сохранение: {0} +text.save.playtime=Время в игре: {0} text.confirm=Подтвердить text.delete=Удалить text.ok=ОК @@ -127,6 +166,7 @@ text.changelog.error=[scarlet]Ошибка при получении измен text.changelog.current=[yellow][[Текущая версия] text.changelog.latest=[orange][[Последняя версия] text.loading=[accent] Загрузка... +text.saving=[accent]Сохранение.. text.wave=[orange]Волна {0} text.wave.waiting=Волна через {0} text.waiting=Ожидание... @@ -134,6 +174,23 @@ text.enemies={0} Противников text.enemies.single={0} Противник text.loadimage=Загрузить изображение text.saveimage=Сохранить изображение +text.unknown=Неизвестный +text.custom=Клиентский +text.builtin=Встроенный +text.map.delete.confirm=Вы действительно хотите удалить эту карту? Это действие не может быть отменено! +text.map.random=[accent]Случайная карта +text.map.nospawn=Эта карта не имеет ядер, в которых игрок может появиться! Добавьте [ROYAL]blue[] ядро в эту карте в редакторе карт. +text.editor.brush=Кисть +text.editor.slope=\\ +text.editor.openin=Открыть в редакторе +text.editor.oregen=Генерация Руд +text.editor.oregen.info=Генерация Руд: +text.editor.mapinfo=Информация о карте +text.editor.author=Автор: +text.editor.description=Описание: +text.editor.name=Ник: +text.editor.teams=Команды +text.editor.elevation=возвышение text.editor.badsize=[orange]Недопустимый формат изображения! [] \nДопустимый формат карты: {0} text.editor.errorimageload=Ошибка загрузки изображения: [orange] {0} text.editor.errorimagesave=Ошибка сохранения изображения: [orange] {0} @@ -141,12 +198,29 @@ text.editor.generate=Создать text.editor.resize=Изменить \nразмер text.editor.loadmap=Загрузить\nкарту text.editor.savemap=Сохранить\nкарту +text.editor.saved=Сохранено! +text.editor.save.noname=У вашей карты нет названия! Установите его в меню «Информация о карте». +text.editor.save.overwrite=Ваша карта перезаписывает встроенную карту! Выберите другое имя в меню 'Информация о карте'. +text.editor.import.exists=[scarlet]Не удалось импортировать: [] уже существует встроенная карта с именем '{0}' ! +text.editor.import=Импорт... +text.editor.importmap=Импорт карты +text.editor.importmap.description=Импортировать уже существующую карту +text.editor.importfile=Импорт файла +text.editor.importfile.description=Импортировать внешний файл карты +text.editor.importimage=Импортировать изображение ландшафта +text.editor.importimage.description=Импорт внешнего файла изображения карты +text.editor.export=Экспорт... +text.editor.exportfile=Экспортировать файл +text.editor.exportfile.description=Экспорт файла карты +text.editor.exportimage=Экспортировать изображение ландшафта +text.editor.exportimage.description=Экспортировать файл изображения карты text.editor.loadimage=Загрузить \nизображение text.editor.saveimage=Сохранить \nизображение -text.editor.unsaved=[scarlet]У вас есть не сохраненные изменения![] \nВы уверены,что хотите выйти? +text.editor.unsaved=[scarlet]У вас есть несохраненные изменения![] \nВы уверены,что хотите выйти? text.editor.resizemap=Изменить размер карты text.editor.mapname=Название карты: text.editor.overwrite=[accent]Внимание! \nЭто перезапишет уже существующую карту. +text.editor.overwrite.confirm=[scarlet]Осторожно![] Карта с таким названием уже существует. Вы действительно хотите её перезаписать? text.editor.selectmap=Выберите карту для загрузки: text.width=Ширина: text.height=Высота: @@ -154,6 +228,9 @@ text.menu=Меню text.play=Играть text.load=Загрузить text.save=Сохранить +text.fps=FPS: {0} +text.tps=TPS: {0} +text.ping=Пинг: {0} мс text.language.restart=Перезагрузите игру, чтобы настройки языка вступили в силу. text.settings.language=Язык text.settings=Настройки @@ -162,39 +239,82 @@ text.editor=Редактор text.mapeditor=Редактор карт text.donate=Донат text.settings.reset=Сбросить по умолчанию +text.settings.rebind=Переназначить text.settings.controls=Управление text.settings.game=Игра text.settings.sound=Звук text.settings.graphics=Графика -text.upgrades=Улучшения -text.purchased=[LIME]Создан! -text.weapons=Оружие text.paused=Пауза +text.yes=Да +text.no=Нет text.info.title=[accent]Информация text.error.title=[crimson]Произошла ошибка text.error.crashtitle=Произошла ошибка text.blocks.blockinfo=Информация о блоке text.blocks.powercapacity=Вместимость энергии -text.blocks.powershot=Энергия / выстрел +text.blocks.powershot=Энергия/выстрел +text.blocks.targetsair=Атакует воздуш. юнитов? +text.blocks.itemspeed=Перемещение единиц +text.blocks.shootrange=Радиус действия text.blocks.size=Размер text.blocks.liquidcapacity=Вместимость жидкости -text.blocks.maxitemssecond=Макс. Количество предметов / в секунду +text.blocks.maxitemssecond=Макс. количество предметов/секунду text.blocks.powerrange=Диапазон мощности энергии +text.blocks.poweruse=Энергии используется +text.blocks.inputitemcapacity=Ёмкость входных элементов +text.blocks.outputitemcapacity=Ёмкость выходных элементов text.blocks.itemcapacity=Вместимость предметов +text.blocks.maxpowergeneration=Максимальная мощность +text.blocks.powertransferspeed=Передача энергии +text.blocks.craftspeed=Скорость производства text.blocks.inputliquid=Прием жидкости -text.blocks.inputitem=Прием предмета +text.blocks.inputliquidaux=Вспом. жидкость +text.blocks.inputitem=Входной предмет +text.blocks.inputitems=Входные предметы +text.blocks.outputitem=Выходной предмет +text.blocks.drilltier=Добывает +text.blocks.drillspeed=Базовая скорость сверления +text.blocks.liquidoutput=Выходная жидкость +text.blocks.liquiduse=Используется жидкости +text.blocks.coolant=Охлаждающая жидкость +text.blocks.coolantuse=Охлажд. жидк. используется +text.blocks.inputliquidfuel=Жидкое топливо +text.blocks.liquidfueluse=Жидкого топлива используется text.blocks.explosive=Взрывоопасно! text.blocks.health=Здоровье text.blocks.inaccuracy=Разброс text.blocks.shots=Выстрелы +text.blocks.reload=Перезарядка +text.blocks.inputfuel=Принимает топливо +text.blocks.fuelburntime=Время горения топлива text.blocks.inputcapacity=Вместимость ввода text.blocks.outputcapacity=Вместимость вывода +text.unit.blocks=блоки +text.unit.powersecond=единиц энергии/секунду +text.unit.liquidsecond=жидкостных единиц/секунду +text.unit.itemssecond=предметов/секунду +text.unit.pixelssecond=пикселей/секунду +text.unit.liquidunits=жидкостных единиц +text.unit.powerunits=энерг. единиц +text.unit.degrees=град. +text.unit.seconds=сек. +text.unit.none= +text.unit.items=предм. +text.category.general=Общие +text.category.power=Энергия +text.category.liquids=Жидкости +text.category.items=Предметы +text.category.crafting=Создание +text.category.shooting=Cтрельба +setting.fpscap.name=Макс. FPS +setting.fpscap.none=Ничто +setting.fpscap.text={0} FPS setting.difficulty.easy=легко setting.difficulty.normal=нормально setting.difficulty.hard=тяжело -setting.difficulty.insane=нереально +setting.difficulty.insane=безумно setting.difficulty.purge=зачистка -setting.difficulty.name=Сложность +setting.difficulty.name=Сложность: setting.screenshake.name=Дрожание экрана setting.indicators.name=Индикаторы противников setting.effects.name=Эффекты на экране @@ -207,297 +327,196 @@ setting.fps.name=Показать FPS setting.vsync.name=Верт. синхронизация setting.lasers.name=Показывать энергетические лазеры setting.healthbars.name=Показать полоски здоровья объекта +setting.minimap.name=Показать миникарту setting.musicvol.name=Громкость музыки setting.mutemusic.name=Заглушить музыку setting.sfxvol.name=Громкость звуковых эффектов setting.mutesound.name=Заглушить звук -map.maze.name=лабиринт -map.fortress.name=крепость -map.sinkhole.name=раковина -map.caves.name=пещеры -map.volcano.name=вулкан -map.caldera.name=кальдера -map.scorch.name=горение -map.desert.name=пустыня -map.island.name=остров -map.grassland.name=луг -map.tundra.name=тундра -map.spiral.name=спираль -map.tutorial.name=обучение text.keybind.title=Переназначить клавиши -keybind.move_x.name=движение_x -keybind.move_y.name=движение_y +keybind.move_x.name=Движение x +keybind.move_y.name=Движение y keybind.select.name=выбрать keybind.break.name=Разрушить -keybind.shoot.name=стрельба -keybind.zoom_hold.name=удержание_зума +keybind.shoot.name=Выстрел +keybind.zoom_hold.name=Удержание зума keybind.zoom.name=Приблизить -keybind.block_info.name=инфо_о_блоке keybind.menu.name=Меню keybind.pause.name=Пауза keybind.dash.name=Рывок keybind.chat.name=Чат -keybind.player_list.name=список_игроков -keybind.console.name=консоль -keybind.rotate_alt.name=вращать_alt -keybind.rotate.name=вращать +keybind.player_list.name=Список игроков +keybind.console.name=Консоль +keybind.rotate.name=Вращать mode.text.help.title=Описание режимов mode.waves.name=волны mode.waves.description=в нормальном режиме. ограниченные ресурсы и автоматические наступающие волны. mode.sandbox.name=песочница mode.sandbox.description=бесконечные ресурсы и нет таймера для волн. +mode.sandbox.warning=Обратите внимание, что блоки нельзя использовать в режиме песочницы, пока они не будут разблокированы в других режимах.\n\n[LIGHT_GRAY] Если вы не разблокировали какие-либо блоки, ни один из них не появится. mode.freebuild.name=свободная\nстройка mode.freebuild.description=ограниченные ресурсы и нет таймера для волн. -item.stone.name=камень +content.item.name=Предметы +content.liquid.name=Жидкости +content.unit-type.name=Боевые единицы +content.recipe.name=Блоки +item.stone.name=Камень +item.stone.description=Обычное сырье. Используется для разделения и переработки в другие материалы или плавления в лаву. +item.tungsten.name=Вольфрам +item.tungsten.description=Обычный, но очень полезный строительный материал . Используется в бурах и теплостойких блоках, таких как генераторы и плавильные печи. +item.lead.name=Свинец +item.lead.description=Основной начальный материал. Широко используется в блоках электроники и транспортировки жидкости. item.coal.name=Уголь -item.titanium.name=титан -item.thorium.name=уран -item.sand.name=песок +item.coal.description=Распростанённое и легкодоступное топливо. +item.carbide.name=Карбид +item.carbide.description=Жёсткий сплав, изготовленный из вольфрама и угля. Используется в передовых транспортных блоках и высокоуровневых бурах. +item.titanium.name=Титан +item.titanium.description=Редкий сверхлёгкий металл широко используется в транспортировке, бурах и самолётах. +item.thorium.name=Торий +item.thorium.description=Плотный радиоактивный металл используется в качестве структурной поддержки и ядерного топлива. +item.silicon.name=Кремень +item.silcion.description=Очень полезный полупроводник с применениями в солнечных батареях и множестве сложной электроники. +item.plastanium.name=Пластиний +item.plastanium.description=Легкий, пластичный материал, используемый в современных самолетах и боеприпасах для фрагментации. +item.phase-matter.name=Фазовая материя +item.surge-alloy.name=Волнистый сплав +item.biomatter.name=Биоматерия +item.biomatter.description=Скопление органической каши; используется для превращения в нефть или в качестве основного топлива. +item.sand.name=Песок +item.sand.description=Обычный материал, который широко используется при плавке как в сплаве, так и в виде шлака. +item.blast-compound.name=Взрывоопасное соединение +item.blast-compound.description=Летучее соединение, используемое в бомбах и взрывчатых веществах. Хотя это может сгореть в качестве топлива, но не рекомендуется этого делать. +item.pyratite.name=Пиротит +item.pyratite.description=Очень огнеопасное вещество, используемое в зажигательном оружии. liquid.water.name=Вода -liquid.lava.name=лава +liquid.lava.name=Лава liquid.oil.name=Нефть -block.door.name=дверь -block.door-large.name=большая дверь -block.conduit.name=трубопровод -block.pulseconduit.name=импульсный трубопровод -block.liquidrouter.name=Маршрутизатор житкостей -block.conveyor.name=конвейер +liquid.cryofluid.name=Криогенная жидкость +text.item.explosiveness=[LIGHT_GRAY]Взрывоопасность: {0} +text.item.flammability=[LIGHT_GRAY]Воспламеняемость: {0} +text.item.radioactivity=[LIGHT_GRAY]Радиоактивность: {0} +text.item.fluxiness=[LIGHT_GRAY]Осадочность: {0} +text.item.hardness=[LIGHT_GRAY]Прочность: {0} +text.unit.health=[LIGHT_GRAY]Здоровье: {0} +text.unit.speed=[LIGHT_GRAY]Скорость: {0} +text.liquid.heatcapacity=[LIGHT_GRAY]Теплоёмкость: {0} +text.liquid.viscosity=[LIGHT_GRAY]Вязкость: {0} +text.liquid.temperature=[LIGHT_GRAY]Температура: {0} +block.tungsten-wall.name=Вольфрамовая стена +block.tungsten-wall-large.name=Большая вольфрамовая стена +block.carbide-wall.name=Карбидная стена +block.carbide-wall-large.name=Большая карбидная стена +block.thorium-wall.name=Ториевая стена +block.thorium-wall-large.name=Большая ториевая стена +block.door.name=Дверь +block.door-large.name=Большая дверь +block.duo.name=Двойная +block.scorch.name=Обжигатель +block.hail.name=Град +block.lancer.name=Копейщик +block.conveyor.name=Конвейер +block.titanium-conveyor.name=Титановый конвейер +block.junction.name=Перекрёсток +block.splitter.name=Разветвитель +block.splitter.description=Выводит предметы на два противоположных направления сразу после их получения. block.router.name=Маршрутизатор -block.junction.name=Перекресток -block.liquidjunction.name=Перекресток для жидкостей -block.sorter.name=сортировщик +block.router.description=Распределяет предметы во все 4 направления. Может хранить элементы как буфера. +block.distributor.name=Распределитель +block.distributor.description=Разветвитель, который может распределять предметы на 8 направлений. +block.sorter.name=Сортировщик +block.sorter.description=Сортирует предметы. Если предмет соответствует выбранному, то ему можно пройти. В противном случае элемент выводится слева и справа. +block.overflow-gate.name=Избыточный затвор +block.overflow-gate.description=Комбинированный разветвитель и маршрутизатор, который выводится только слева и справа, если передний путь заблокирован. +block.bridgeconveyor.name=Мостовой конвейер +block.bridgeconveyor.description=Конвейер, который может переходить через другие блоки, до двух блоков в сумме. block.smelter.name=Плавильный завод -text.web.unsupported=The web version does not support this feature! Download the game to use it. -text.host.web=The web version does not support hosting games! Download the game to use this feature. -text.map.delete=Are you sure you want to delete the map "[orange]{0}[]"? -text.construction.title=Block Construction Guide -text.construction=You've just selected [accent]block construction mode[].\n\nTo begin placing, simply tap a valid location near your ship.\nOnce you have selected some blocks, press the checkbox to confirm, and your ship will begin constructing them.\n\n- [accent]Remove blocks[] from your selection by tapping them.\n- [accent]Shift the selection[] by holding and dragging any block in the selection.\n- [accent]Place blocks in a line[] by tapping and holding an empty spot, then dragging in a direction.\n- [accent]Cancel construction or selection[] by pressing the X at the bottom left. -text.deconstruction.title=Block Deconstruction Guide -text.deconstruction=You've just selected [accent]block deconstruction mode[].\n\nTo begin breaking, simply tap a block near your ship.\nOnce you have selected some blocks, press the checkbox to confirm, and your ship will begin de-constructing them.\n\n- [accent]Remove blocks[] from your selection by tapping them.\n- [accent]Remove blocks in an area[] by tapping and holding an empty spot, then dragging in a direction.\n- [accent]Cancel deconstruction or selection[] by pressing the X at the bottom left. -text.showagain=Don't show again next session -text.unlocks=Unlocks -text.addplayers=Add/Remove Players -text.maps=Maps -text.maps.none=[LIGHT_GRAY]No maps found! -text.unlocked=New Block Unlocked! -text.unlocked.plural=New Blocks Unlocked! -text.server.kicked.nameInUse=There is someone with that name\nalready on this server. -text.server.kicked.nameEmpty=Your name must contain at least one character or number. -text.server.kicked.idInUse=You are already on this server! Connecting with two accounts is not permitted. -text.server.kicked.customClient=This server does not support custom builds. Download an official version. -text.trace.structureblocksbroken=Structure blocks broken: [accent]{0} -text.saving=[accent]Saving... -text.unknown=Unknown -text.custom=Custom -text.builtin=Built-In -text.map.delete.confirm=Are you sure you want to delete this map? This action cannot be undone! -text.map.random=[accent]Random Map -text.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. -text.editor.slope=\\ -text.editor.openin=Open In Editor -text.editor.oregen=Ore Generation -text.editor.oregen.info=Ore Generation: -text.editor.mapinfo=Map Info -text.editor.author=Author: -text.editor.description=Description: -text.editor.name=Name: -text.editor.teams=Teams -text.editor.elevation=Elevation -text.editor.saved=Saved! -text.editor.save.noname=Your map does not have a name! Set one in the 'map info' menu. -text.editor.save.overwrite=Your map overwrites a built-in map! Pick a different name in the 'map info' menu. -text.editor.import.exists=[scarlet]Unable to import:[] a built-in map named '{0}' already exists! -text.editor.import=Import... -text.editor.importmap=Import Map -text.editor.importmap.description=Import an already existing map -text.editor.importfile=Import File -text.editor.importfile.description=Import an external map file -text.editor.importimage=Import Terrain Image -text.editor.importimage.description=Import an external map image file -text.editor.export=Export... -text.editor.exportfile=Export File -text.editor.exportfile.description=Export a map file -text.editor.exportimage=Export Terrain Image -text.editor.exportimage.description=Export a map image file -text.editor.overwrite.confirm=[scarlet]Warning![] A map with this name already exists. Are you sure you want to overwrite it? -text.fps=FPS: {0} -text.tps=TPS: {0} -text.ping=Ping: {0}ms -text.settings.rebind=Rebind -text.yes=Yes -text.no=No -text.blocks.targetsair=Targets Air -text.blocks.itemspeed=Units Moved -text.blocks.shootrange=Range -text.blocks.poweruse=Power Use -text.blocks.inputitemcapacity=Input Item Capacity -text.blocks.outputitemcapacity=Input Item Capacity -text.blocks.maxpowergeneration=Max Power Generation -text.blocks.powertransferspeed=Power Transfer -text.blocks.craftspeed=Production Speed -text.blocks.inputliquidaux=Aux Liquid -text.blocks.inputitems=Input Items -text.blocks.outputitem=Output Item -text.blocks.drilltier=Drillables -text.blocks.drillspeed=Base Drill Speed -text.blocks.liquidoutput=Liquid Output -text.blocks.liquiduse=Liquid Use -text.blocks.coolant=Coolant -text.blocks.coolantuse=Coolant Use -text.blocks.inputliquidfuel=Fuel Liquid -text.blocks.liquidfueluse=Liquid Fuel Use -text.blocks.reload=Reload -text.blocks.inputfuel=Fuel -text.blocks.fuelburntime=Fuel Burn Time -text.unit.blocks=blocks -text.unit.powersecond=power units/second -text.unit.liquidsecond=liquid units/second -text.unit.itemssecond=items/second -text.unit.pixelssecond=pixels/second -text.unit.liquidunits=liquid units -text.unit.powerunits=power units -text.unit.degrees=degrees -text.unit.seconds=seconds -text.unit.none= -text.unit.items=items -text.category.general=General -text.category.power=Power -text.category.liquids=Liquids -text.category.items=Items -text.category.crafting=Crafting -text.category.shooting=Shooting -setting.minimap.name=Show Minimap -content.item.name=Items -content.liquid.name=Liquids -content.unit-type.name=Units -content.recipe.name=Blocks -item.stone.description=A common raw material. Used for separating and refining into other materials, or melting into lava. -item.tungsten.name=Tungsten -item.tungsten.description=A common, but very useful structure material. Used in drills and heat-resistant blocks such as generators and smelteries. -item.lead.name=Lead -item.lead.description=A basic starter material. Used extensively in electronics and liquid transportation blocks. -item.coal.description=A common and readily available fuel. -item.carbide.name=Carbide -item.carbide.description=A tough alloy made with tungsten and carbon. Used in advanced transportation blocks and high-tier drills. -item.titanium.description=A rare super-light metal used extensively in liquid transportation, drills and aircraft. -item.thorium.description=A dense, radioactive metal used as structural support and nuclear fuel. -item.silicon.name=Silicon -item.silcion.description=An extremely useful semiconductor, with applications in solar panels and many complex electronics. -item.plastanium.name=Plastanium -item.plastanium.description=A light, ductile material used in advanced aircraft and fragmentation ammunition. -item.phase-matter.name=Phase Matter -item.surge-alloy.name=Surge Alloy -item.biomatter.name=Biomatter -item.biomatter.description=A clump of organic mush; used for conversion into oil or as a basic fuel. -item.sand.description=A common material that is used extensively in smelting, both in alloying and as a flux. -item.blast-compound.name=Blast Compound -item.blast-compound.description=A volatile compound used in bombs and explosives. While it can burned as fuel, this is not advised. -item.pyratite.name=Pyratite -item.pyratite.description=An extremely flammable substance used in incendiary weapons. -liquid.cryofluid.name=Cryofluid -text.item.explosiveness=[LIGHT_GRAY]Explosiveness: {0} -text.item.flammability=[LIGHT_GRAY]Flammability: {0} -text.item.radioactivity=[LIGHT_GRAY]Radioactivity: {0} -text.item.fluxiness=[LIGHT_GRAY]Flux Power: {0} -text.item.hardness=[LIGHT_GRAY]Hardness: {0} -text.liquid.heatcapacity=[LIGHT_GRAY]Heat Capacity: {0} -text.liquid.viscosity=[LIGHT_GRAY]Viscosity: {0} -text.liquid.temperature=[LIGHT_GRAY]Temperature: {0} -block.tungsten-wall.name=Tungsten Wall -block.tungsten-wall-large.name=Large Tungsten Wall -block.carbide-wall.name=Carbide Wall -block.carbide-wall-large.name=Large Carbide Wall -block.thorium-wall.name=Thorium Wall -block.thorium-wall-large.name=Large Thorium Wall -block.duo.name=Duo -block.scorch.name=Scorch -block.hail.name=Hail -block.lancer.name=Lancer -block.titanium-conveyor.name=Titanium Conveyor -block.splitter.name=Splitter -block.splitter.description=Outputs items into two opposite directions immediately after they are recieved. -block.router.description=Splits items into all 4 directions. Can store items as a buffer. -block.distributor.name=Distributor -block.distributor.description=A splitter that can split items into 8 directions. -block.sorter.description=Sorts items. If an item matches the selection, it is allowed to pass. Otherwise, the item is outputted to the left and right. -block.overflow-gate.name=Overflow Gate -block.overflow-gate.description=A combination splitter and router that only outputs to the left and right if the front path is blocked. -block.bridgeconveyor.name=Bridge Conveyor -block.bridgeconveyor.description=A conveyor that can go over other blocks, for up to two total blocks. -block.arc-smelter.name=Arc Smelter -block.silicon-smelter.name=Silicon Smelter -block.phase-weaver.name=Phase Weaver -block.pulverizer.name=Pulverizer -block.cryofluidmixer.name=Cryofluid Mixer -block.melter.name=Melter -block.incinerator.name=Incinerator -block.biomattercompressor.name=Biomatter Compressor -block.separator.name=Separator -block.centrifuge.name=Centrifuge -block.power-node.name=Power Node -block.power-node-large.name=Large Power Node -block.battery.name=Battery -block.battery-large.name=Large Battery -block.combustion-generator.name=Combustion Generator -block.turbine-generator.name=Turbine Generator -block.tungsten-drill.name=Tungsten Drill -block.carbide-drill.name=Carbide Drill -block.laser-drill.name=Laser Drill -block.water-extractor.name=Water Extractor -block.cultivator.name=Cultivator -block.dart-ship-factory.name=Dart Ship Factory -block.delta-mech-factory.name=Delta Mech Factory -block.dronefactory.name=Drone Factory -block.repairpoint.name=Repair Point -block.resupplypoint.name=Resupply Point -block.liquidtank.name=Liquid Tank -block.bridgeconduit.name=Bridge Conduit -block.mechanical-pump.name=Mechanical Pump -block.itemsource.name=Item Source -block.itemvoid.name=Item Void -block.liquidsource.name=Liquid Source -block.powervoid.name=Power Void -block.powerinfinite.name=Power Infinite -block.unloader.name=Unloader -block.sortedunloader.name=Sorted Unloader -block.vault.name=Vault -block.wave.name=Wave -block.swarmer.name=Swarmer -block.salvo.name=Salvo -block.ripple.name=Ripple -block.phase-conveyor.name=Phase Conveyor -block.bridge-conveyor.name=Bridge Conveyor -block.plastanium-compressor.name=Plastanium Compressor -block.pyratite-mixer.name=Pyratite Mixer -block.blast-mixer.name=Blast Mixer -block.solidifer.name=Solidifer -block.solar-panel.name=Solar Panel -block.solar-panel-large.name=Large Solar Panel -block.oil-extractor.name=Oil Extractor -block.javelin-ship-factory.name=Javelin Ship factory -block.drone-factory.name=Drone Factory -block.fabricator-factory.name=Fabricator Factory -block.repair-point.name=Repair Point -block.resupply-point.name=Resupply Point -block.pulse-conduit.name=Pulse Conduit -block.phase-conduit.name=Phase Conduit -block.liquid-router.name=Liquid Router -block.liquid-tank.name=Liquid Tank -block.liquid-junction.name=Liquid Junction -block.bridge-conduit.name=Bridge Conduit -block.rotary-pump.name=Rotary Pump -block.nuclear-reactor.name=Nuclear Reactor -text.save.old=This save is for an older version of the game, and can no longer be used.\n\n[LIGHT_GRAY]Save backwards compatibility will be implemented in the full 4.0 release. -text.customgame=Custom Game -text.campaign=Campaign -text.sectors=Sectors -text.sector=Selected Sector: [LIGHT_GRAY]{0} -text.sector.time=Time: [LIGHT_GRAY]{0} -text.sector.deploy=Deploy -text.sector.resume=Resume -text.sector.unlocked=Sector completed! -text.sector.locked=[scarlet][[Incomplete] -text.sector.unexplored=[accent][[Unexplored] -text.close=Close -text.save.playtime=Playtime: {0} -text.editor.brush=Brush +block.arc-smelter.name=Дуговая печь +block.silicon-smelter.name=Кремниевый плавильный завод +block.phase-weaver.name=Фазовый ткач +block.pulverizer.name=Распылитель +block.cryofluidmixer.name=Смеситель для криогенных жидкостей +block.melter.name=Плавильня +block.incinerator.name=Мусоросжигательная печь +block.biomattercompressor.name=Компрессор биоматерии +block.separator.name=Разделитель +block.centrifuge.name=Центрифуга +block.power-node.name=Силовой узел +block.power-node-large.name=Большой силовой узел +block.battery.name=Аккумулятор +block.battery-large.name=Большой аккумулятор +block.combustion-generator.name=Генератор внутреннего сгорания +block.turbine-generator.name=Турбинный генератор +block.tungsten-drill.name=Вольфрамовый бур +block.carbide-drill.name=Карбидовый бур +block.laser-drill.name=Лазерный бур +block.water-extractor.name=Экстрактор воды +block.cultivator.name=Культиватор +block.dart-ship-factory.name=Завод дротиковых самолётов +block.delta-mech-factory.name=Завод механического дельта броневика +block.repairpoint.name=Ремонтная точка +block.resupplypoint.name=Точка снабжения +block.conduit.name=Трубопровод +block.pulseconduit.name=Импульсный трубопровод +block.liquidrouter.name=Маршрутизатор жидкостей +block.liquidtank.name=Жидкостный резервуар +block.liquidjunction.name=Перекресток для жидкостей +block.bridgeconduit.name=Мостовой трубопровод +block.mechanical-pump.name=Механическая помпа +block.itemsource.name=Источник предметов +block.itemvoid.name=Предметный вакуум +block.liquidsource.name=Источник жидкостей +block.powervoid.name=Энергитический вакуум +block.powerinfinite.name=Бесконечная энергия +block.unloader.name=Разгрузчик +block.sortedunloader.name=Сортированный разгрузчик +block.vault.name=Хранилище +block.wave.name=Волна +block.swarmer.name=Зерг +block.salvo.name=Залп +block.ripple.name=Волнистость +block.phase-conveyor.name=Фазовый конвейер +block.bridge-conveyor.name=Мостовой конвейер +block.plastanium-compressor.name=Пластиниевый компрессор +block.pyratite-mixer.name=Смеситель пиротита +block.blast-mixer.name=Смеситель взрывоопасного соединения +block.solidifer.name=Отвердитель +block.solar-panel.name=Солнечная панель +block.solar-panel-large.name=Большая солнечная панель +block.oil-extractor.name=Нефтяной экстрактор +block.drone-pad.name=Стартовая площадка дронов +block.fabricator-pad.name=Стартовая площадка сборщиков +block.interceptor-pad.name=Стартовая площадка истребителей-перехватчиков +block.monsoon-pad.name=Стартовая площадка муссонов +block.javelin-ship-factory.name=Фабрика кораблей класса "Копьё" +block.repair-point.name=Ремонтный пункт +block.resupply-point.name=Точка снабжения +block.pulse-conduit.name=Импульсный трубопровод +block.phase-conduit.name=Фазовый трубопровод +block.liquid-router.name=Жидкостный маршрутизатор +block.liquid-tank.name=Жидкостный резервуар +block.liquid-junction.name=Жидкое соединение +block.bridge-conduit.name=Мостовой трубопровод +block.rotary-pump.name=Роторный насос +block.nuclear-reactor.name=Ядерный реактор +block.command-center.name=Командный центр +block.mass-driver.name=Электромагнитная катапульта +block.blast-drill.name=Буровая установка +block.thermal-pump.name=Тепловой насос +block.dagger-pad.name=Стартовая площадка "Кинжал" +block.titan-pad.name=Стартовая площадка титанов +block.thermal-generator.name=Термальный генератор +unit.drone.name=Дрон +unit.drone.description=Начальный дрон. По умолчанию появляется из ядра. Автоматически добывает руды, собирает предметы, ремонтирует блоки. +unit.fabricator.name=Сборщик +unit.fabricator.description=Продвинутый дрон. Автоматически добывает руды, собирает предметы, ремонтирует блоки. Значительнее эффективней нежели обычный дрон +unit.scout.name=Разведчик +unit.scout.description=Основная наземная боевая единица. Использует свинец как боеприпасы. +unit.titan.name=Титан +unit.titan.description=Улучшенная бронированная наземная боевая единица. Использует карбид в качестве боеприпасов. Атакует наземные и воздушные цели. +unit.monsoon.name=Муссон +unit.monsoon.description=Тяжелый ковровый бомбардировщик. Использует взрывоопасное соединение или пиратит в качестве боеприпасов. +unit.interceptor.name=Истребитель-перехватчик +unit.interceptor.description=Быстрая и ударная боевая единица, которая использует набег с отскоком. Использует свинец как боеприпасы. +block.thermal-pump.name=Thermal Pump +block.dagger-pad.name=Dagger Pad +block.titan-pad.name=Titan Pad +block.thermal-generator.name=Thermal Generator diff --git a/core/assets/bundles/bundle_tk.properties b/core/assets/bundles/bundle_tk.properties index 6760fdf413..0d4ec3fd11 100644 --- a/core/assets/bundles/bundle_tk.properties +++ b/core/assets/bundles/bundle_tk.properties @@ -1,4 +1,3 @@ -text.about=[ROYAL] Anuken tarafından oluşturuldu [] - [SKY] anukendev@gmail.com [] Aslen [turuncu] GDL [] Metal Monstrosity Jam. Kredi: - [SARI] ile yapılan SFX bfxr [] - [YEŞİL] RoccoW tarafından yapılan müzik [] / [kireç] bulunan FreeMusicArchive.org [] Özel teşekkürler: - [mercan] MitchellFJN []: Kapsamlı oyun testi ve geri bildirim - [sky] Luxray5474 []: wiki çalışması, kod katkıları - [kireç] Epowerj []: kod sistemi yapılandırması, icon - itch.io ve Google Play'deki tüm beta test kullanıcıları\n text.credits=Yapımcılar text.discord=Mindustry Discord'una katılın! text.link.discord.description=Resmi Mindustry Discord iletişim kanalı @@ -10,10 +9,8 @@ text.link.google-play.description=Google Play mağaza sayfası text.link.wiki.description=Resmi Mindustry Wikipedi'si text.linkfail=Bağlantı açılamadı! URL, yazı tahtanıza kopyalandı. text.editor.web=Web sürümü editörü desteklemiyor! Editörü kullanmak için oyunu indirin. -text.multiplayer.web=Oyunun bu sürümü çok oyunculuyu desteklemiyor! Tarayıcınızdan çok oyunculu oynamak için, itch.io sayfasındaki "çok oyunculu web sürümü" bağlantısını kullanın. text.gameover=Çekirdek yok edildi. text.highscore=[SARI] Yeni yüksek puan! -text.lasted=Dalgaya kadar sürdün text.level.highscore=Yüksek Puan: [accent] {0} text.level.delete.title=Silmeyi onaylayın text.level.select=Seviye Seç @@ -165,9 +162,6 @@ text.settings.controls=kontroller text.settings.game=Oyun text.settings.sound=Ses text.settings.graphics=Grafik -text.upgrades=Geliştirmeler -text.purchased=[KİREÇ] Yap၊ld၊ -text.weapons=Silahlar text.paused=Duraklatıldı text.info.title=[Vurgu] Bilgi text.error.title=[crimson] Bir hata oluştu @@ -210,19 +204,6 @@ setting.musicvol.name=Müzik sesi setting.mutemusic.name=Müziği Kapat setting.sfxvol.name=SFX Hacmi setting.mutesound.name=Sesi kapat -map.maze.name=Labirent -map.fortress.name=Kale -map.sinkhole.name=düden -map.caves.name=mağaralar -map.volcano.name=volkan -map.caldera.name=kaldera -map.scorch.name=alazlamak -map.desert.name=çöl -map.island.name=ada -map.grassland.name=Çayır -map.tundra.name=tundra -map.spiral.name=sarmal -map.tutorial.name=Eğitim text.keybind.title=Tuşları yeniden ayarla keybind.move_x.name=sağ / sol keybind.move_y.name=yukarı / aşağı @@ -231,14 +212,12 @@ keybind.break.name=kırmak keybind.shoot.name=ateş etme keybind.zoom_hold.name=tut ve büyüt keybind.zoom.name=Yakınlaştır -keybind.block_info.name=blok bilgisi keybind.menu.name=menü keybind.pause.name=duraklatma keybind.dash.name=tire keybind.chat.name=Sohbet keybind.player_list.name=oyuncu listesi keybind.console.name=KONTROL MASASI -keybind.rotate_alt.name=rotate_alt keybind.rotate.name=Döndür mode.text.help.title=Modların açıklaması mode.waves.name=dalgalar @@ -266,7 +245,6 @@ block.liquidjunction.name=sıvı bağlantı block.sorter.name=ayrıştırıcı block.smelter.name=dökümcü text.web.unsupported=The web version does not support this feature! Download the game to use it. -text.host.web=The web version does not support hosting games! Download the game to use this feature. text.map.delete=Are you sure you want to delete the map "[orange]{0}[]"? text.construction.title=Block Construction Guide text.construction=You've just selected [accent]block construction mode[].\n\nTo begin placing, simply tap a valid location near your ship.\nOnce you have selected some blocks, press the checkbox to confirm, and your ship will begin constructing them.\n\n- [accent]Remove blocks[] from your selection by tapping them.\n- [accent]Shift the selection[] by holding and dragging any block in the selection.\n- [accent]Place blocks in a line[] by tapping and holding an empty spot, then dragging in a direction.\n- [accent]Cancel construction or selection[] by pressing the X at the bottom left. @@ -447,7 +425,6 @@ block.water-extractor.name=Water Extractor block.cultivator.name=Cultivator block.dart-ship-factory.name=Dart Ship Factory block.delta-mech-factory.name=Delta Mech Factory -block.dronefactory.name=Drone Factory block.repairpoint.name=Repair Point block.resupplypoint.name=Resupply Point block.liquidtank.name=Liquid Tank @@ -475,8 +452,6 @@ block.solar-panel.name=Solar Panel block.solar-panel-large.name=Large Solar Panel block.oil-extractor.name=Oil Extractor block.javelin-ship-factory.name=Javelin Ship factory -block.drone-factory.name=Drone Factory -block.fabricator-factory.name=Fabricator Factory block.repair-point.name=Repair Point block.resupply-point.name=Resupply Point block.pulse-conduit.name=Pulse Conduit @@ -495,9 +470,49 @@ text.sector=Selected Sector: [LIGHT_GRAY]{0} text.sector.time=Time: [LIGHT_GRAY]{0} text.sector.deploy=Deploy text.sector.resume=Resume -text.sector.unlocked=Sector completed! text.sector.locked=[scarlet][[Incomplete] text.sector.unexplored=[accent][[Unexplored] text.close=Close text.save.playtime=Playtime: {0} text.editor.brush=Brush +text.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!) +text.sector.gameover=This sector has been lost. Re-deploy? +text.sector.retry=Retry +text.wave.lasted=You lasted until wave [accent]{0}[]. +setting.fpscap.name=Max FPS +setting.fpscap.none=None +setting.fpscap.text={0} FPS +block.command-center.name=Command Center +text.mission=Mission:[LIGHT_GRAY] {0} +text.mission.wave=Survive [accent]{0}[] waves. +text.mission.battle=Destroy the enemy base. +text.none= +text.sector.corrupted=[orange]A save file for this sector was found, but loading failed.\nA new one has been created. +text.mission.complete=Mission complete! +text.mission.complete.body=Sector {0},{1} has been conquered. +text.mission.resource=Obtain {0} x{1} +text.unit.health=[LIGHT_GRAY]Health: {0} +text.unit.speed=[LIGHT_GRAY]Speed: {0} +block.drone-pad.name=Drone Pad +block.fabricator-pad.name=Fabricator Pad +block.interceptor-pad.name=Interceptor Pad +block.monsoon-pad.name=Monsoon Pad +block.mass-driver.name=Mass Driver +block.blast-drill.name=Blast Drill +unit.drone.name=Drone +unit.drone.description=The starter drone unit. Spawns in the core by default. Automatically mines ores, collects items and repairs blocks. +unit.fabricator.name=Fabricator +unit.fabricator.description=An advanced drone unit. Automatically mines ores, collects items and repairs blocks. Significantly more effective than a drone. +unit.scout.name=Scout +unit.scout.description=A basic ground unit. Uses lead as ammo. +unit.titan.name=Titan +unit.titan.description=An advanced armored ground unit. Uses carbide as ammo. Attacks both ground and air targets. +unit.monsoon.name=Monsoon +unit.monsoon.description=A heavy carpet bomber. Uses blast compound or pyratite as ammo. +unit.interceptor.name=Interceptor +unit.interceptor.description=A fast, hit-and-run strike unit. Uses lead as ammo. +mode.sandbox.warning=Note that blocks cannot be used in sandbox mode until they are unlocked in other modes.\n\n[LIGHT_GRAY]If you have not unlocked any blocks, none will appear. +block.thermal-pump.name=Thermal Pump +block.dagger-pad.name=Dagger Pad +block.titan-pad.name=Titan Pad +block.thermal-generator.name=Thermal Generator diff --git a/core/assets/bundles/bundle_uk_UA.properties b/core/assets/bundles/bundle_uk_UA.properties index 6c60ca5897..b93b558fc4 100644 --- a/core/assets/bundles/bundle_uk_UA.properties +++ b/core/assets/bundles/bundle_uk_UA.properties @@ -1,8 +1,6 @@ -text.about=Створено [ROYAL] Anuken. []\nСпочатку запис у [orange] GDL [] MM Jam.\nТворці:\n- SFX зроблено з [YELLOW] bfxr []\n- Музика зроблена [GREEN] RoccoW [] / Знайдено на [lime] FreeMusicArchive.org [] \nОсоблива подяка:\n- [coral] MitchellFJN []: екстенсивне тестування та відгуки\n- [sky] Luxray5474 []: робота з вікі, вклади коду\n- Всі бета-тестери на itch.io та Google Play\n text.discord=Приєднуйтесь до нашого Discord! text.gameover=Ядро було зруйновано. text.highscore=[YELLOW] Новий рекорд! -text.lasted=Ви тримались до хвилі text.level.highscore=Рекорд: [accent] {0} text.level.delete.title=Підтвердьте видалення text.level.select=Вибір рівня @@ -118,9 +116,6 @@ text.settings.controls=Елементи управління text.settings.game=Гра text.settings.sound=Звук text.settings.graphics=Графіка -text.upgrades=Оновлення -text.purchased=[LIME] Створено! -text.weapons=Зброя text.paused=Пауза text.info.title=[accent] інформація text.error.title=[crimson] Виникла помилка @@ -163,19 +158,6 @@ setting.musicvol.name=Гучність музики setting.mutemusic.name=Вимкнути музику setting.sfxvol.name=Гучність ефектів setting.mutesound.name=Вимкнути звук -map.maze.name=Лабіринт -map.fortress.name=Фортеця -map.sinkhole.name=Свердловина -map.caves.name=Печери -map.volcano.name=Вулкан -map.caldera.name=Кальдера -map.scorch.name=Мертва земля -map.desert.name=Пустеля -map.island.name=Острів -map.grassland.name=Пасовища -map.tundra.name=Тундра -map.spiral.name=Спіраль -map.tutorial.name=Навчання text.keybind.title=Ключ перемотки keybind.move_x.name=move_x keybind.move_y.name=move_y @@ -184,14 +166,12 @@ keybind.break.name={0}break{/0}{1}; {/1} keybind.shoot.name=Постріл keybind.zoom_hold.name=zoom_hold keybind.zoom.name=Збільшити -keybind.block_info.name=Інформація про блок keybind.menu.name=Меню keybind.pause.name=Пауза keybind.dash.name=Тире keybind.chat.name=Чат keybind.player_list.name=Список гравців keybind.console.name=// Консоль 1 -keybind.rotate_alt.name=rotate_alt keybind.rotate.name=Повернути mode.waves.name=Хвилі mode.sandbox.name=Пісочниця @@ -226,8 +206,6 @@ text.link.wiki.description=official Mindustry wiki text.linkfail=Failed to open link!\nThe URL has been copied to your cliboard. text.editor.web=The web version does not support the editor!\nDownload the game to use it. text.web.unsupported=The web version does not support this feature! Download the game to use it. -text.multiplayer.web=This version of the game does not support multiplayer!\nTo play multiplayer from your browser, use the "multiplayer web version" link at the itch.io page. -text.host.web=The web version does not support hosting games! Download the game to use this feature. text.map.delete=Are you sure you want to delete the map "[orange]{0}[]"? text.construction.title=Block Construction Guide text.construction=You've just selected [accent]block construction mode[].\n\nTo begin placing, simply tap a valid location near your ship.\nOnce you have selected some blocks, press the checkbox to confirm, and your ship will begin constructing them.\n\n- [accent]Remove blocks[] from your selection by tapping them.\n- [accent]Shift the selection[] by holding and dragging any block in the selection.\n- [accent]Place blocks in a line[] by tapping and holding an empty spot, then dragging in a direction.\n- [accent]Cancel construction or selection[] by pressing the X at the bottom left. @@ -447,7 +425,6 @@ block.water-extractor.name=Water Extractor block.cultivator.name=Cultivator block.dart-ship-factory.name=Dart Ship Factory block.delta-mech-factory.name=Delta Mech Factory -block.dronefactory.name=Drone Factory block.repairpoint.name=Repair Point block.resupplypoint.name=Resupply Point block.liquidtank.name=Liquid Tank @@ -475,8 +452,6 @@ block.solar-panel.name=Solar Panel block.solar-panel-large.name=Large Solar Panel block.oil-extractor.name=Oil Extractor block.javelin-ship-factory.name=Javelin Ship factory -block.drone-factory.name=Drone Factory -block.fabricator-factory.name=Fabricator Factory block.repair-point.name=Repair Point block.resupply-point.name=Resupply Point block.pulse-conduit.name=Pulse Conduit @@ -495,9 +470,49 @@ text.sector=Selected Sector: [LIGHT_GRAY]{0} text.sector.time=Time: [LIGHT_GRAY]{0} text.sector.deploy=Deploy text.sector.resume=Resume -text.sector.unlocked=Sector completed! text.sector.locked=[scarlet][[Incomplete] text.sector.unexplored=[accent][[Unexplored] text.close=Close text.save.playtime=Playtime: {0} text.editor.brush=Brush +text.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!) +text.sector.gameover=This sector has been lost. Re-deploy? +text.sector.retry=Retry +text.wave.lasted=You lasted until wave [accent]{0}[]. +setting.fpscap.name=Max FPS +setting.fpscap.none=None +setting.fpscap.text={0} FPS +block.command-center.name=Command Center +text.mission=Mission:[LIGHT_GRAY] {0} +text.mission.wave=Survive [accent]{0}[] waves. +text.mission.battle=Destroy the enemy base. +text.none= +text.sector.corrupted=[orange]A save file for this sector was found, but loading failed.\nA new one has been created. +text.mission.complete=Mission complete! +text.mission.complete.body=Sector {0},{1} has been conquered. +text.mission.resource=Obtain {0} x{1} +text.unit.health=[LIGHT_GRAY]Health: {0} +text.unit.speed=[LIGHT_GRAY]Speed: {0} +block.drone-pad.name=Drone Pad +block.fabricator-pad.name=Fabricator Pad +block.interceptor-pad.name=Interceptor Pad +block.monsoon-pad.name=Monsoon Pad +block.mass-driver.name=Mass Driver +block.blast-drill.name=Blast Drill +unit.drone.name=Drone +unit.drone.description=The starter drone unit. Spawns in the core by default. Automatically mines ores, collects items and repairs blocks. +unit.fabricator.name=Fabricator +unit.fabricator.description=An advanced drone unit. Automatically mines ores, collects items and repairs blocks. Significantly more effective than a drone. +unit.scout.name=Scout +unit.scout.description=A basic ground unit. Uses lead as ammo. +unit.titan.name=Titan +unit.titan.description=An advanced armored ground unit. Uses carbide as ammo. Attacks both ground and air targets. +unit.monsoon.name=Monsoon +unit.monsoon.description=A heavy carpet bomber. Uses blast compound or pyratite as ammo. +unit.interceptor.name=Interceptor +unit.interceptor.description=A fast, hit-and-run strike unit. Uses lead as ammo. +mode.sandbox.warning=Note that blocks cannot be used in sandbox mode until they are unlocked in other modes.\n\n[LIGHT_GRAY]If you have not unlocked any blocks, none will appear. +block.thermal-pump.name=Thermal Pump +block.dagger-pad.name=Dagger Pad +block.titan-pad.name=Titan Pad +block.thermal-generator.name=Thermal Generator diff --git a/core/assets/bundles/bundle_zh_CN.properties b/core/assets/bundles/bundle_zh_CN.properties new file mode 100644 index 0000000000..a26b822571 --- /dev/null +++ b/core/assets/bundles/bundle_zh_CN.properties @@ -0,0 +1,518 @@ +text.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!) +text.credits=致谢 +text.discord=加入 Mindustry 的 Discord! +text.link.discord.description=官方 Mindustry discord 聊天室 +text.link.github.description=游戏源码 +text.link.dev-builds.description=不稳定开发版 +text.link.trello.description=Trello board 上的官方计划表 +text.link.itch.io.description=PC版下载和网页版(itch.io) +text.link.google-play.description=从谷歌商店获取安卓版 +text.link.wiki.description=官方 Mindustry 维基 +text.linkfail=打开链接失败!\nURL 已经复制到剪贴板。 +text.editor.web=网页版不支持地图编辑器!\n下载以使用编辑器。 +text.web.unsupported=网页版不支持此功能,请下载以使用此功能。 +text.gameover=你的核心被摧毁了! +text.sector.gameover=这个区域失守了,要重新部署吗? +text.sector.retry=重试 +text.highscore=[accent]新纪录! +text.wave.lasted=你坚持到了第 [accent]{0}[] 波。 +text.level.highscore=最高分: [accent]{0} +text.level.delete.title=确认删除 +text.map.delete=确定要删除 "[orange]{0}[]" 地图吗? +text.level.select=选择关卡 +text.level.mode=游戏模式: +text.construction.title=方块建造指导 +text.construction=你选择了 [accent]建造模式[].\n\n点击你附近的有效位置以放置\n选择了方块以后, 点击复选框就会开始建造。\n\n- [accent]移除方块-[] 点击想要删除的方块。\n- [accent]直线放置方块-[] 按住一个空点然后拖到目的地。\n- [accent]取消建造或选择-[] 按左下角的X。 +text.deconstruction.title=方块删除指导 +text.deconstruction=你选择了 [accent]删除模式[]。\n\n点击你附近的有效位置以删除\n选择了方块以后,点击复选框就会开始删除。\n\n- [accent]移除方块-[] 点击想要删除的方块。\n- [accent]移除选中部分-[] 按住并拖动以选中一个区域。\n- [accent]取消删除或选择-[] 按左下角的X. +text.showagain=不再显示 +text.unlocks=已解锁 +text.savegame=保存游戏 +text.loadgame=载入游戏 +text.joingame=加入游戏 +text.addplayers=增加/删除玩家 +text.customgame=自定义游戏 +text.campaign=战役 +text.sectors=区域 +text.sector=区域: [LIGHT_GRAY]{0} +text.sector.time=时间: [LIGHT_GRAY]{0} +text.sector.deploy=部署 +text.sector.resume=继续 +text.sector.locked=[scarlet][[Incomplete] +text.sector.unexplored=[accent][[Unexplored] +text.mission=任务[LIGHT_GRAY] {0} +text.mission.wave=存活了 [accent]{0}[] 波。 +text.mission.battle=摧毁敌方基地。 +text.mission.resource=获得 {0} x{1} +text.none= +text.close=关闭 +text.quit=退出 +text.maps=地图 +text.maps.none=[LIGHT_GRAY]未发现地图! +text.about.button=关于 +text.name=名字: +text.unlocked=新方块解锁! +text.unlocked.plural=新方块解锁! +text.players={0} 玩家在线 +text.players.single={0} 玩家在线 +text.server.mismatch=Packet error: 可能是客户端/服务器版本不匹配\n请确保你和房主\n都安装了最新版 Mindustry! +text.server.closing=[accent]正在关闭服务器... +text.server.kicked.kick=你被踢出服务器了! +text.server.kicked.fastShoot=你发射得太快了! +text.server.kicked.invalidPassword=无效的密码! +text.server.kicked.clientOutdated=客户端版本过旧!请升级! +text.server.kicked.serverOutdated=服务器版本过旧!请联系房主升级! +text.server.kicked.banned=你被这个服务器拉黑了。 +text.server.kicked.recentKick=你刚刚被踢出服务器\n请稍后再重新连接! +text.server.kicked.nameInUse=服务器中已经\n有相同的名字了。 +text.server.kicked.nameEmpty=你的名字必须至少包含一个字母或数字。 +text.server.kicked.idInUse=你已经在服务器中了!不允许用两个账号。 +text.server.kicked.customClient=这个服务器不支持修改版连接,请下载官方版本。 +text.host.info=[accent]创建局域网游戏[] 按钮会在 [scarlet]6567[] 端口运行一个服务器并且 [scarlet]6568.[]\n任何在同一个 [LIGHT_GRAY]wifi或本地网络[] 下的人都将在服务器列表中看到你的服务器。\n\n如果你想让别人在任何地方都能通过ip地址连接, 那么需要[accent]端口转发[]。\n\n[LIGHT_GRAY]请注意:如果某人无法连接到你的局域网游戏,请确保你在防火墙设置里允许了 Mindustry 连接本地网络。 +text.join.info=你可以在这里输入[accent]服务器的IP地址[]以连接,或寻找[accent]本地网络[]中的服务器以连接。\n支持局域网或广域网多人游戏。\n\n[LIGHT_GRAY]请注意:没有全球服务器列表;如果你想通过IP地址连接某个服务器,你需要向房主询问IP地址。 +text.hostserver=服务器 +text.host=创建服务器 +text.hosting=[accent]正在打开服务器... +text.hosts.refresh=刷新 +text.hosts.discovering=正在搜索局域网服务器 +text.server.refreshing=正在刷新服务器 +text.hosts.none=[lightgray]未发现局域网游戏! +text.host.invalid=[scarlet]无法连接服务器。 +text.trace=跟踪玩家 +text.trace.playername=玩家名字: [accent]{0} +text.trace.ip=IP地址: [accent]{0} +text.trace.id=ID: [accent]{0} +text.trace.android=安卓客户端: [accent]{0} +text.trace.modclient=修改版客户端: [accent]{0} +text.trace.totalblocksbroken=总共破坏了 [accent]{0} 个方块。 +text.trace.structureblocksbroken=总共破坏了 [accent]{0} 个结构。 +text.trace.lastblockbroken=最后破坏的方块: [accent]{0} +text.trace.totalblocksplaced=总共放置了 [accent]{0} 个方块。 +text.trace.lastblockplaced=最后放置的方块: [accent]{0} +text.invalidid=无效的客户端ID!请提交 bug 报告。 +text.server.bans=黑名单 +text.server.bans.none=没有被拉黑的玩家! +text.server.admins=管理员 +text.server.admins.none=没有管理员! +text.server.add=添加服务器 +text.server.delete=确定要删除这个服务器吗? +text.server.hostname=主机: {0} +text.server.edit=编辑服务器 +text.server.outdated=[crimson]服务器过旧![] +text.server.outdated.client=[crimson]客户端过旧![] +text.server.version=[lightgray]版本: {0} +text.server.custombuild=[yellow]修改版 +text.confirmban=确认拉黑这个玩家? +text.confirmunban=确认要取消拉黑这个玩家吗? +text.confirmadmin=确认要添加这个玩家为管理员吗? +text.confirmunadmin=确认要取消这个玩家的管理员身份吗? +text.joingame.title=加入游戏 +text.joingame.ip=IP: +text.disconnect=已断开 +text.disconnect.data=载入世界失败! +text.connecting=[accent]连接中... +text.connecting.data=[accent]加载世界中... +text.connectfail=[crimson]服务器连接失败: [orange]{0} +text.server.port=端口: +text.server.addressinuse=地址已经使用! +text.server.invalidport=无效的端口! +text.server.error=[crimson]创建服务器错误:[orange]{0} +text.save.old=这个存档属于旧版本游戏,无法继续使用了。\n\n[LIGHT_GRAY]存档向下兼容将在 4.0 版本中实现。 +text.save.new=新存档 +text.save.overwrite=确认要\n覆盖这个存档吗? +text.overwrite=覆盖 +text.save.none=没有存档! +text.saveload=[accent]保存中... +text.savefail=保存失败! +text.save.delete.confirm=确认要删除这个存档吗? +text.save.delete=删除 +text.save.export=导出存档 +text.save.import.invalid=[orange]存档无效! +text.save.import.fail=[crimson]导入存档:[orange]{0} 失败 +text.save.export.fail=[crimson]导出存档“[orange]{0} 失败 +text.save.import=导入存档 +text.save.newslot=保存游戏: +text.save.rename=重命名 +text.save.rename.text=新名字: +text.selectslot=选择一个存档 +text.slot=[accent]存档 {0} +text.save.corrupted=[orange]存档损坏或无效!\n如果你刚刚升级了游戏,那么这可能是因为存档格式改变了而[scarlet]不是[] bug 。 +text.sector.corrupted=[orange]发现了一个此区域的保存文件,但是加载失败。\n已经创建了一个新的。 +text.empty= +text.on=开 +text.off=关 +text.save.autosave=自动保存:{0} +text.save.map=地图:{0} +text.save.wave=第 {0} 波 +text.save.difficulty=难度: {0} +text.save.date=最后保存日期:{0} +text.save.playtime=游戏时间:{0} +text.confirm=确认 +text.delete=删除 +text.ok=好的 +text.open=打开 +text.cancel=取消 +text.openlink=打开链接 +text.copylink=删除链接 +text.back=返回 +text.quit.confirm=确认要退出? +text.changelog.title=更新日志 +text.changelog.loading=正在获取更新日志... +text.changelog.error.android=[orange]请注意更新日志有时在安卓 4.4 以下不工作。\n这是因为安卓系统的一个 bug 。 +text.changelog.error.ios=[orange]iOS还不支持更新日志。 +text.changelog.error=[scarlet]获取更新日志失败!\n请检查你的网络。 +text.changelog.current=[yellow][[Current version] +text.changelog.latest=[orange][[Latest version] +text.loading=[accent]加载中... +text.saving=[accent]保存中... +text.wave=[orange]第 {0} 波 +text.wave.waiting=下一波将在 {0} 秒后到来 +text.waiting=等待中... +text.enemies={0} 个敌人 +text.enemies.single={0} 个敌人 +text.loadimage=加载图片 +text.saveimage=保存图片 +text.unknown=未知 +text.custom=自定义 +text.builtin=内建的 +text.map.delete.confirm=确认要删除地图吗?这个操作无法撤销! +text.map.random=[accent]随机地图 +text.map.nospawn=这个地图没有核心!请在编辑器中添加一个[ROYAL]蓝色[]的核心。 +text.editor.brush=笔刷 +text.editor.slope=\\ +text.editor.openin=在编辑器中打开 +text.editor.oregen=生成矿石 +text.editor.oregen.info=生成矿石: +text.editor.mapinfo=地图详情 +text.editor.author=作者: +text.editor.description=描述: +text.editor.name=名字: +text.editor.teams=团队 +text.editor.elevation=高度 +text.editor.badsize=[orange]图片尺寸无效![]\n正确的尺寸:{0} +text.editor.errorimageload=载入文件出错:\n[orange]{0} +text.editor.errorimagesave=保存文件出错:\n[orange]{0} +text.editor.generate=生成 +text.editor.resize=调整 +text.editor.loadmap=载入地图 +text.editor.savemap=保存地图 +text.editor.saved=已保存! +text.editor.save.noname=你的地图还没有名字!在“地图信息”菜单里设置一个名字。 +text.editor.save.overwrite=你的地图覆盖了一个内建的地图!在“地图信息”菜单里重新设置一个。 +text.editor.import.exists=[scarlet]无法导入:[] 一个叫 '{0}' 的内建地图已经存在。 +text.editor.import=导入... +text.editor.importmap=导入地图 +text.editor.importmap.description=导入一个已经存在的地图 +text.editor.importfile=导入文件 +text.editor.importfile.description=导入一个外置的地图文件 +text.editor.importimage=导入地形图像 +text.editor.importimage.description=导入外置地图图像文件 +text.editor.export=导出... +text.editor.exportfile=导出文件 +text.editor.exportfile.description=导出一个地图文件 +text.editor.exportimage=导出一个地形文件 +text.editor.exportimage.description=导出一个地图图像文件 +text.editor.loadimage=导入地形 +text.editor.saveimage=导出地形 +text.editor.unsaved=[scarlet]你有未保存的更改![]\n确定要退出? +text.editor.resizemap=调整地图 +text.editor.mapname=地图名字: +text.editor.overwrite=[accent]警告!\n这将会覆盖一个已经存在的地图。 +text.editor.overwrite.confirm=[scarlet]警告![] 存在同名地图,确定要覆盖? +text.editor.selectmap=选择一个地图加载: +text.width=宽度: +text.height=高度: +text.menu=菜单 +text.play=开始游戏 +text.load=载入游戏 +text.save=保存 +text.fps=FPS: {0} +text.tps=TPS: {0} +text.ping=Ping: {0}ms +text.language.restart=为了使语言设置生效请重启游戏。 +text.settings.language=语言 +text.settings=设置 +text.tutorial=教程 +text.editor=编辑器 +text.mapeditor=地图编辑器 +text.donate=捐赠 +text.settings.reset=恢复默认 +text.settings.rebind=重新绑定 +text.settings.controls=控制 +text.settings.game=游戏 +text.settings.sound=声音 +text.settings.graphics=图像 +text.paused=暂停 +text.yes=是 +text.no=不 +text.info.title=[accent]详情 +text.error.title=[crimson]发生了一个错误 +text.error.crashtitle=发生了一个错误 +text.blocks.blockinfo=方块详情 +text.blocks.powercapacity=能量容量 +text.blocks.powershot=能量/发射 +text.blocks.targetsair=攻击空中单位 +text.blocks.itemspeed=移动速度 +text.blocks.shootrange=范围 +text.blocks.size=尺寸 +text.blocks.liquidcapacity=液体容量 +text.blocks.maxitemssecond=最大物品数量 +text.blocks.powerrange=能量范围 +text.blocks.poweruse=能量使用 +text.blocks.inputitemcapacity=最大输入 +text.blocks.outputitemcapacity=最大输出 +text.blocks.itemcapacity=物品容量 +text.blocks.maxpowergeneration=最大能量 +text.blocks.powertransferspeed=能量传输 +text.blocks.craftspeed=生产速度 +text.blocks.inputliquid=输入液体 +text.blocks.inputliquidaux=Aux 液体 +text.blocks.inputitem=输入物品 +text.blocks.inputitems=输入物品 +text.blocks.outputitem=输出物品 +text.blocks.drilltier=可钻探矿物 +text.blocks.drillspeed=基础钻探速度 +text.blocks.liquidoutput=液体输出速度 +text.blocks.liquiduse=使用液体 +text.blocks.coolant=冷却剂 +text.blocks.coolantuse=使用冷却剂 +text.blocks.inputliquidfuel=使用燃料 +text.blocks.liquidfueluse=使用液体燃料 +text.blocks.explosive=高度易燃易爆! +text.blocks.health=生命值 +text.blocks.inaccuracy=误差 +text.blocks.shots=发射 +text.blocks.reload=重新装弹 +text.blocks.inputfuel=燃料 +text.blocks.fuelburntime=燃料燃烧时间 +text.blocks.inputcapacity=输入容量 +text.blocks.outputcapacity=输出容量 +text.unit.blocks=方块 +text.unit.powersecond=能量单位/秒 +text.unit.liquidsecond=液体单位/秒 +text.unit.itemssecond=物品/秒 +text.unit.pixelssecond=像素/秒 +text.unit.liquidunits=液体单位 +text.unit.powerunits=能量单位 +text.unit.degrees=度 +text.unit.seconds=秒 +text.unit.none= +text.unit.items=物品 +text.category.general=普通 +text.category.power=能量 +text.category.liquids=液体 +text.category.items=物品 +text.category.crafting=制造速度 +text.category.shooting=射速 +setting.fpscap.name=最高 FPS +setting.fpscap.none=None +setting.fpscap.text={0} FPS +setting.difficulty.easy=简单 +setting.difficulty.normal=普通 +setting.difficulty.hard=困难 +setting.difficulty.insane=疯狂 +setting.difficulty.purge=清除 +setting.difficulty.name=难度: +setting.screenshake.name=屏幕抖动 +setting.indicators.name=指出敌人 +setting.effects.name=显示效果 +setting.sensitivity.name=控制器灵敏度 +setting.saveinterval.name=自动保存间隔 +setting.seconds={0} 秒 +setting.fullscreen.name=全屏 +setting.multithread.name=多线程 +setting.fps.name=显示 FPS +setting.vsync.name=帧同步 +setting.lasers.name=显示能量射线 +setting.healthbars.name=显示生命值 +setting.minimap.name=显示小地图 +setting.musicvol.name=音乐音量 +setting.mutemusic.name=静音 +setting.sfxvol.name=音效音量 +setting.mutesound.name=静音 +text.keybind.title=重新绑定按键 +keybind.move_x.name=X轴移动 +keybind.move_y.name=Y轴移动 +keybind.select.name=选择 +keybind.break.name=破坏 +keybind.shoot.name=射击 +keybind.zoom_hold.name=保持缩放 +keybind.zoom.name=缩放 +keybind.menu.name=菜单 +keybind.pause.name=暂停 +keybind.dash.name=冲刺 +keybind.chat.name=聊天 +keybind.player_list.name=玩家列表 +keybind.console.name=控制台 +keybind.rotate.name=旋转 +mode.text.help.title=模式说明 +mode.waves.name=普通 +mode.waves.description=普通模式,有限的资源和自动生成敌人。 +mode.sandbox.name=沙盒 +mode.sandbox.description=无限的资源,不会自动生成敌人。 +mode.freebuild.name=自由建造 +mode.freebuild.description=有限的资源,不会自动生成敌人。 +content.item.name=物品 +content.liquid.name=液体 +content.unit-type.name=单位 +content.recipe.name=方块 +item.stone.name=石头 +item.stone.description=一种常见的原料。用于分离和提炼成其他材料,或熔化成熔岩。 +item.tungsten.name=钨 +item.tungsten.description=一种常见但非常有用的结构材料。用于钻头和耐热方块,比如发电机和冶炼器。 +item.lead.name=铅 +item.lead.description=基本的起始材料。被广泛用于电气和液体运输方块。 +item.coal.name=煤 +item.coal.description=一种常见并容易获得的燃料。 +item.carbide.name=电石 +item.carbide.description=由钨和碳制成的坚韧合金。被用在高级的运输方块和高层钻机。 +item.titanium.name=钛 +item.titanium.description=一种罕见的超轻金属,被广泛运用于液体运输,钻机和飞机。 +item.thorium.name=钍 +item.thorium.description=一种致密的放射性金属,用作支撑结构和核燃料。 +item.silicon.name=硅 +item.silcion.description=非常有用的半导体,被用于太阳能电池板和很多复杂的电子设备。 +item.plastanium.name=塑料 +item.plastanium.description=一种轻质,可延展的材料,用于高级的飞机和碎片弹药。 +item.phase-matter.name=相位问题 +item.surge-alloy.name=巨浪合金 +item.biomatter.name=生物质 +item.biomatter.description=一种有机糊;用于转化为油或作为基本燃料。 +item.sand.name=沙子 +item.sand.description=一种常见的材料,广泛用于冶炼,制作合金和助熔剂。 +item.blast-compound.name=爆炸混合物 +item.blast-compound.description=一种用于炸弹和炸药的挥发性化合物。虽然它可以作为燃料燃烧,但不建议这样做。 +item.pyratite.name=硫 +item.pyratite.description=燃烧武器中使用的极易燃物质。 +liquid.water.name=水 +liquid.lava.name=岩浆 +liquid.oil.name=石油 +liquid.cryofluid.name=冷冻液 +text.item.explosiveness=[LIGHT_GRAY]爆炸威力:{0} +text.item.flammability=[LIGHT_GRAY]易燃性:{0} +text.item.radioactivity=[LIGHT_GRAY]放射性:{0} +text.item.fluxiness=[LIGHT_GRAY]流通力:{0} +text.item.hardness=[LIGHT_GRAY]硬度:{0} +text.unit.health=[LIGHT_GRAY]生命值: {0} +text.unit.speed=[LIGHT_GRAY]速度: {0} +text.liquid.heatcapacity=[LIGHT_GRAY]热容量:{0} +text.liquid.viscosity=[LIGHT_GRAY]粘度:{0} +text.liquid.temperature=[LIGHT_GRAY]温度:{0} +block.tungsten-wall.name=钨墙 +block.tungsten-wall-large.name=大型钨墙 +block.carbide-wall.name=电石 +block.carbide-wall-large.name=大型电石墙 +block.thorium-wall.name=钍墙 +block.thorium-wall-large.name=大型钍墙 +block.door.name=门 +block.door-large.name=大门 +block.duo.name=炮 +block.scorch.name=灼烧炮 +block.hail.name=Hail +block.lancer.name=枪骑兵 +block.conveyor.name=传送带 +block.titanium-conveyor.name=钛传送带 +block.junction.name=连接点 +block.splitter.name=分离器 +block.splitter.description=将物品输出到三个不同的方向。 +block.router.name=路由器 +block.router.description=将物品分配到 4 个方向。可以作为缓冲区储存物品。 +block.distributor.name=分配器 +block.distributor.description=把物品分到 8 个方向的分配器。 +block.sorter.name=分类器 +block.sorter.description=对物品进行分类。如果物品与所选种类,则允许其通过。否则,物品将从左边和右边输出。 +block.overflow-gate.name=溢流门 +block.overflow-gate.description=分离器和路由器的组合,如果前面被挡住,则向从左和右输出。 +block.bridgeconveyor.name=传送桥 +block.bridgeconveyor.description=一种传送带,可以越过其他方块,最多两个方块。 +block.smelter.name=冶炼厂 +block.arc-smelter.name=电弧冶炼厂 +block.silicon-smelter.name=硅冶炼厂 +block.phase-weaver.name=相位编织器 +block.pulverizer.name=粉碎机 +block.cryofluidmixer.name=冷冻液混合器 +block.melter.name=熔炉 +block.incinerator.name=焚化炉 +block.biomattercompressor.name=生物质压缩机 +block.separator.name=分离机 +block.centrifuge.name=离心机 +block.power-node.name=能量节点 +block.power-node-large.name=大型能量节点 +block.battery.name=电池 +block.battery-large.name=大型电池 +block.combustion-generator.name=燃烧发电机 +block.turbine-generator.name=涡轮发电机 +block.tungsten-drill.name=钨钻头 +block.carbide-drill.name=电石钻头 +block.laser-drill.name=激光钻头 +block.water-extractor.name=抽水机 +block.cultivator.name=耕种机 +block.dart-ship-factory.name=飞船制造工厂 +block.delta-mech-factory.name=机械制造工厂 +block.repairpoint.name=维修点 +block.resupplypoint.name=补给点 +block.conduit.name=导管 +block.pulseconduit.name=脉冲导管 +block.liquidrouter.name=液体路由器 +block.liquidtank.name=储液罐 +block.liquidjunction.name=液体连接点 +block.bridgeconduit.name=导管桥 +block.mechanical-pump.name=机械泵 +block.itemsource.name=物品源 +block.itemvoid.name=Item Void +block.liquidsource.name=液体源 +block.powervoid.name=Power Void +block.powerinfinite.name=无限能源 +block.unloader.name=装卸器 +block.sortedunloader.name=分类装卸器 +block.vault.name=仓库 +block.wave.name=波浪 +block.swarmer.name=蜂群 +block.salvo.name=齐射炮 +block.ripple.name=波纹 +block.phase-conveyor.name=相位传送带 +block.bridge-conveyor.name=传送带桥 +block.plastanium-compressor.name=塑料压缩机 +block.pyratite-mixer.name=硫混合器 +block.blast-mixer.name=爆炸混合器 +block.solidifer.name=凝固剂 +block.solar-panel.name=太阳能电池 +block.solar-panel-large.name=大型太阳能电池 +block.oil-extractor.name=石油钻井 +block.javelin-ship-factory.name=标枪船工厂 +block.repair-point.name=维修点 +block.resupply-point.name=供应点 +block.pulse-conduit.name=脉冲导管 +block.phase-conduit.name=相位导管 +block.liquid-router.name=液体路由器 +block.liquid-tank.name=储液罐 +block.liquid-junction.name=液体连接点 +block.bridge-conduit.name=导管桥 +block.rotary-pump.name=回旋泵 +block.nuclear-reactor.name=核反应堆 +block.command-center.name=指令中心 +block.mass-driver.name=质量驱动器 +block.blast-drill.name=爆破钻头 +unit.drone.name=无人机 +unit.drone.description=初始的无人机单位.自动在核心生成,自动采矿,收集物品,修复方块 +unit.fabricator.name=装配工 +unit.fabricator.description=高级无人机单位,自动采矿,收集物品和修复方块.比普通无人机快很多. +unit.scout.name=侦察机 +unit.scout.description=基础地面单位,使用钨作为弹药. +unit.titan.name=泰坦 +unit.titan.description=高级的有武装地面单位,使用电石作为弹药.攻击地面单位和空中单位. +unit.monsoon.name=狂风 +unit.monsoon.description=重型地毯式轰炸机,使用爆炸混合物或硫作为弹药。 +text.mission.complete=Mission complete! +text.mission.complete.body=Sector {0},{1} has been conquered. +block.drone-pad.name=Drone Pad +block.fabricator-pad.name=Fabricator Pad +block.interceptor-pad.name=Interceptor Pad +block.monsoon-pad.name=Monsoon Pad +unit.interceptor.name=Interceptor +unit.interceptor.description=A fast, hit-and-run strike unit. Uses lead as ammo. +mode.sandbox.warning=Note that blocks cannot be used in sandbox mode until they are unlocked in other modes.\n\n[LIGHT_GRAY]If you have not unlocked any blocks, none will appear. +block.thermal-pump.name=Thermal Pump +block.dagger-pad.name=Dagger Pad +block.titan-pad.name=Titan Pad +block.thermal-generator.name=Thermal Generator diff --git a/core/assets/bundles/bundle_zh_TW.properties b/core/assets/bundles/bundle_zh_TW.properties index 6d14067994..0bfaf23406 100644 --- a/core/assets/bundles/bundle_zh_TW.properties +++ b/core/assets/bundles/bundle_zh_TW.properties @@ -1,4 +1,3 @@ -text.about=開發者 [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[]\n最初構想於 [orange]GDL[] Metal Monstrosity Jam.\n\n銘謝:\n- 音效作者 [YELLOW]bfxr[]\n- 音樂作者 [GREEN]a beat a day[]\n\n特別感謝:\n- [coral]MitchellFJN[]:大量的測試與回饋\n- [sky]Luxray5474[]:維基編纂、程式碼貢獻\n- [lime]Epowerj[]: 撰寫建造系統、繪製圖示\n- 所有在 itch.io 與 Google Play 上的測試版玩家\n text.credits=致謝名單 text.discord=加入 Mindustry 的 Discord 聊天室 text.link.discord.description=官方 Mindustry Discord 聊天室 @@ -10,10 +9,8 @@ text.link.google-play.description=Google Play 商店頁面 text.link.wiki.description=官方 Mindustry 維基 text.linkfail=無法打開連結!我們已將該網址複製到您的剪貼簿。\n text.editor.web=線上版本不支援地圖編輯器!請下載遊戲已使用這項功能。\n -text.multiplayer.web=此遊戲版本不支援多人連線!請在 itch.io 頁面使用「多人線上版」連結以進入多人遊戲。 text.gameover=核心已被摧毀。 text.highscore=[YELLOW]新的高分紀錄! -text.lasted=您存活到波次 text.level.highscore=最高分:[accent] {0} text.level.delete.title=確認刪除 text.level.select=選擇關卡 @@ -167,9 +164,6 @@ text.settings.controls=操作 text.settings.game=遊戲 text.settings.sound=音效 text.settings.graphics=圖形 -text.upgrades=升級 -text.purchased=[LIME]已建立! -text.weapons=武器 text.paused=已暫停 text.info.title=[accent]資訊 text.error.title=[crimson]發生錯誤 @@ -212,19 +206,6 @@ setting.musicvol.name=音樂音量 setting.mutemusic.name=靜音 setting.sfxvol.name=音效音量 setting.mutesound.name=靜音 -map.maze.name=迷宮 -map.fortress.name=堡壘 -map.sinkhole.name=天坑 -map.caves.name=洞窟 -map.volcano.name=火山 -map.caldera.name=火山口 -map.scorch.name=焦土 -map.desert.name=沙漠 -map.island.name=島嶼 -map.grassland.name=草原 -map.tundra.name=凍原 -map.spiral.name=螺旋 -map.tutorial.name=教學 text.keybind.title=重新綁定按鍵 keybind.move_x.name=水平移動 keybind.move_y.name=垂直移動 @@ -233,14 +214,12 @@ keybind.break.name=拆除 keybind.shoot.name=射擊 keybind.zoom_hold.name=按住縮放 keybind.zoom.name=縮放 -keybind.block_info.name=方塊資訊 keybind.menu.name=主選單 keybind.pause.name=暫停遊戲 keybind.dash.name=衝刺 keybind.chat.name=聊天 keybind.player_list.name=玩家列表 keybind.console.name=終端機 -keybind.rotate_alt.name=反向旋轉 keybind.rotate.name=旋轉 mode.text.help.title=模式說明 mode.waves.name=一般 @@ -268,7 +247,6 @@ block.liquidjunction.name=液體樞紐 block.sorter.name=分類器 block.smelter.name=煉鋼廠 text.web.unsupported=The web version does not support this feature! Download the game to use it. -text.host.web=The web version does not support hosting games! Download the game to use this feature. text.map.delete=Are you sure you want to delete the map "[orange]{0}[]"? text.construction.title=Block Construction Guide text.construction=You've just selected [accent]block construction mode[].\n\nTo begin placing, simply tap a valid location near your ship.\nOnce you have selected some blocks, press the checkbox to confirm, and your ship will begin constructing them.\n\n- [accent]Remove blocks[] from your selection by tapping them.\n- [accent]Shift the selection[] by holding and dragging any block in the selection.\n- [accent]Place blocks in a line[] by tapping and holding an empty spot, then dragging in a direction.\n- [accent]Cancel construction or selection[] by pressing the X at the bottom left. @@ -448,7 +426,6 @@ block.water-extractor.name=Water Extractor block.cultivator.name=Cultivator block.dart-ship-factory.name=Dart Ship Factory block.delta-mech-factory.name=Delta Mech Factory -block.dronefactory.name=Drone Factory block.repairpoint.name=Repair Point block.resupplypoint.name=Resupply Point block.liquidtank.name=Liquid Tank @@ -476,8 +453,6 @@ block.solar-panel.name=Solar Panel block.solar-panel-large.name=Large Solar Panel block.oil-extractor.name=Oil Extractor block.javelin-ship-factory.name=Javelin Ship factory -block.drone-factory.name=Drone Factory -block.fabricator-factory.name=Fabricator Factory block.repair-point.name=Repair Point block.resupply-point.name=Resupply Point block.pulse-conduit.name=Pulse Conduit @@ -495,9 +470,49 @@ text.sector=Selected Sector: [LIGHT_GRAY]{0} text.sector.time=Time: [LIGHT_GRAY]{0} text.sector.deploy=Deploy text.sector.resume=Resume -text.sector.unlocked=Sector completed! text.sector.locked=[scarlet][[Incomplete] text.sector.unexplored=[accent][[Unexplored] text.close=Close text.save.playtime=Playtime: {0} text.editor.brush=Brush +text.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!) +text.sector.gameover=This sector has been lost. Re-deploy? +text.sector.retry=Retry +text.wave.lasted=You lasted until wave [accent]{0}[]. +setting.fpscap.name=Max FPS +setting.fpscap.none=None +setting.fpscap.text={0} FPS +block.command-center.name=Command Center +text.mission=Mission:[LIGHT_GRAY] {0} +text.mission.wave=Survive [accent]{0}[] waves. +text.mission.battle=Destroy the enemy base. +text.none= +text.sector.corrupted=[orange]A save file for this sector was found, but loading failed.\nA new one has been created. +text.mission.complete=Mission complete! +text.mission.complete.body=Sector {0},{1} has been conquered. +text.mission.resource=Obtain {0} x{1} +text.unit.health=[LIGHT_GRAY]Health: {0} +text.unit.speed=[LIGHT_GRAY]Speed: {0} +block.drone-pad.name=Drone Pad +block.fabricator-pad.name=Fabricator Pad +block.interceptor-pad.name=Interceptor Pad +block.monsoon-pad.name=Monsoon Pad +block.mass-driver.name=Mass Driver +block.blast-drill.name=Blast Drill +unit.drone.name=Drone +unit.drone.description=The starter drone unit. Spawns in the core by default. Automatically mines ores, collects items and repairs blocks. +unit.fabricator.name=Fabricator +unit.fabricator.description=An advanced drone unit. Automatically mines ores, collects items and repairs blocks. Significantly more effective than a drone. +unit.scout.name=Scout +unit.scout.description=A basic ground unit. Uses lead as ammo. +unit.titan.name=Titan +unit.titan.description=An advanced armored ground unit. Uses carbide as ammo. Attacks both ground and air targets. +unit.monsoon.name=Monsoon +unit.monsoon.description=A heavy carpet bomber. Uses blast compound or pyratite as ammo. +unit.interceptor.name=Interceptor +unit.interceptor.description=A fast, hit-and-run strike unit. Uses lead as ammo. +mode.sandbox.warning=Note that blocks cannot be used in sandbox mode until they are unlocked in other modes.\n\n[LIGHT_GRAY]If you have not unlocked any blocks, none will appear. +block.thermal-pump.name=Thermal Pump +block.dagger-pad.name=Dagger Pad +block.titan-pad.name=Titan Pad +block.thermal-generator.name=Thermal Generator diff --git a/core/assets/maps/sandbox.mmap b/core/assets/maps/sandbox.mmap new file mode 100644 index 0000000000..3536178e03 Binary files /dev/null and b/core/assets/maps/sandbox.mmap differ diff --git a/core/assets/maps/test.mmap b/core/assets/maps/test.mmap deleted file mode 100644 index ab8f0627af..0000000000 Binary files a/core/assets/maps/test.mmap and /dev/null differ diff --git a/core/assets/sprites/sprites.atlas b/core/assets/sprites/sprites.atlas index 4f08351452..be2ce57e94 100644 --- a/core/assets/sprites/sprites.atlas +++ b/core/assets/sprites/sprites.atlas @@ -13,1113 +13,1120 @@ background index: -1 bridge-conveyor-arrow rotate: false - xy: 353, 15 + xy: 833, 268 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 bridge-conveyor-bridge rotate: false - xy: 363, 25 + xy: 833, 258 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 bridge-conveyor-end rotate: false - xy: 353, 5 + xy: 833, 248 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conveyor-0-1 rotate: false - xy: 987, 355 + xy: 853, 276 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conveyor-0-2 rotate: false - xy: 997, 355 + xy: 853, 266 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conveyor-0-3 rotate: false - xy: 987, 345 + xy: 863, 273 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conveyor-1-0 rotate: false - xy: 997, 345 + xy: 853, 256 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conveyor-1-1 rotate: false - xy: 1007, 349 + xy: 863, 263 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conveyor-1-2 rotate: false - xy: 1007, 339 + xy: 873, 273 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conveyor-1-3 rotate: false - xy: 409, 48 + xy: 853, 246 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conveyor-2-0 rotate: false - xy: 409, 38 + xy: 863, 253 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conveyor-2-1 rotate: false - xy: 961, 336 + xy: 873, 263 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conveyor-2-2 rotate: false - xy: 971, 336 + xy: 883, 273 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conveyor-2-3 rotate: false - xy: 413, 28 + xy: 853, 236 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conveyor-3-0 rotate: false - xy: 413, 18 + xy: 863, 243 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conveyor-3-1 rotate: false - xy: 413, 8 + xy: 873, 253 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conveyor-3-2 rotate: false - xy: 981, 335 + xy: 883, 263 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conveyor-3-3 rotate: false - xy: 991, 335 + xy: 893, 273 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conveyor-4-0 rotate: false - xy: 701, 161 + xy: 853, 226 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conveyor-4-1 rotate: false - xy: 711, 161 + xy: 863, 233 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conveyor-4-2 rotate: false - xy: 721, 161 + xy: 873, 243 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conveyor-4-3 rotate: false - xy: 731, 161 + xy: 883, 253 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium-conveyor-0-1 rotate: false - xy: 663, 68 + xy: 514, 138 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium-conveyor-0-2 rotate: false - xy: 673, 68 + xy: 524, 148 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium-conveyor-0-3 rotate: false - xy: 562, 58 + xy: 514, 128 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium-conveyor-1-0 rotate: false - xy: 572, 58 + xy: 524, 138 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium-conveyor-1-1 rotate: false - xy: 582, 58 + xy: 524, 128 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium-conveyor-1-2 rotate: false - xy: 592, 58 + xy: 534, 148 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium-conveyor-1-3 rotate: false - xy: 602, 58 + xy: 534, 138 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium-conveyor-2-0 rotate: false - xy: 612, 58 + xy: 534, 128 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium-conveyor-2-1 rotate: false - xy: 622, 58 + xy: 544, 149 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium-conveyor-2-2 rotate: false - xy: 632, 58 + xy: 544, 139 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium-conveyor-2-3 rotate: false - xy: 642, 58 + xy: 544, 129 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium-conveyor-3-0 rotate: false - xy: 652, 58 + xy: 554, 149 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium-conveyor-3-1 rotate: false - xy: 662, 58 + xy: 554, 139 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium-conveyor-3-2 rotate: false - xy: 672, 58 + xy: 554, 129 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium-conveyor-3-3 rotate: false - xy: 683, 88 + xy: 479, 118 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium-conveyor-4-0 rotate: false - xy: 683, 78 + xy: 489, 118 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium-conveyor-4-1 rotate: false - xy: 683, 68 + xy: 499, 118 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium-conveyor-4-2 rotate: false - xy: 682, 58 + xy: 509, 118 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium-conveyor-4-3 rotate: false - xy: 893, 331 + xy: 519, 118 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 +mass-driver-turret + rotate: false + xy: 737, 368 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 phase-conveyor-arrow rotate: false - xy: 523, 81 + xy: 267, 11 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 phase-conveyor-bridge rotate: false - xy: 533, 91 + xy: 267, 1 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 phase-conveyor-end rotate: false - xy: 523, 71 + xy: 277, 11 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 warp-gate-top rotate: false - xy: 702, 257 + xy: 767, 290 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 blast-drill rotate: false - xy: 925, 419 + xy: 764, 420 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 blast-drill-rim rotate: false - xy: 951, 419 + xy: 790, 420 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 blast-drill-rotator rotate: false - xy: 713, 319 + xy: 703, 394 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 blast-drill-top rotate: false - xy: 739, 328 + xy: 729, 394 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 carbide-drill rotate: false - xy: 363, 15 + xy: 833, 238 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 carbide-drill-rotator rotate: false - xy: 373, 25 + xy: 833, 228 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 carbide-drill-top rotate: false - xy: 363, 5 + xy: 833, 218 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 laser-drill rotate: false - xy: 202, 99 + xy: 267, 117 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 laser-drill-rotator rotate: false - xy: 184, 81 + xy: 285, 117 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 laser-drill-top rotate: false - xy: 220, 99 + xy: 303, 117 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 oil-extractor rotate: false - xy: 639, 232 + xy: 789, 368 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 oil-extractor-liquid rotate: false - xy: 587, 206 + xy: 789, 342 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 oil-extractor-rotator rotate: false - xy: 613, 206 + xy: 793, 316 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 oil-extractor-top rotate: false - xy: 639, 206 + xy: 807, 394 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 plasma-drill rotate: false - xy: 889, 445 + xy: 887, 445 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plasma-drill-rim rotate: false - xy: 923, 445 + xy: 921, 445 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plasma-drill-rotator rotate: false - xy: 957, 445 + xy: 955, 445 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plasma-drill-top rotate: false - xy: 991, 437 + xy: 819, 422 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 tungsten-drill rotate: false - xy: 913, 311 + xy: 483, 108 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 tungsten-drill-rotator rotate: false - xy: 903, 301 + xy: 483, 98 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 tungsten-drill-top rotate: false - xy: 913, 301 + xy: 493, 108 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 water-extractor rotate: false - xy: 184, 63 + xy: 265, 81 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 water-extractor-liquid rotate: false - xy: 202, 63 + xy: 301, 99 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 water-extractor-rotator rotate: false - xy: 220, 63 + xy: 283, 81 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 water-extractor-top rotate: false - xy: 238, 63 + xy: 319, 99 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 blackrock1 rotate: false - xy: 692, 425 + xy: 1015, 401 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-blackrock rotate: false - xy: 692, 425 + xy: 1015, 401 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blackrockshadow1 rotate: false - xy: 171, 107 + xy: 1015, 391 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blackstone1 rotate: false - xy: 411, 106 + xy: 175, 23 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-blackstone rotate: false - xy: 411, 106 + xy: 175, 23 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blackstone2 rotate: false - xy: 957, 359 + xy: 1015, 381 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blackstone3 rotate: false - xy: 957, 349 + xy: 1015, 371 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blackstoneedge rotate: false - xy: 977, 431 + xy: 937, 337 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 coal1 rotate: false - xy: 373, 15 + xy: 833, 208 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 coal2 rotate: false - xy: 383, 25 + xy: 833, 198 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 coal3 rotate: false - xy: 373, 5 + xy: 833, 188 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 dirt2 rotate: false - xy: 517, 181 + xy: 883, 243 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 dirt3 rotate: false - xy: 527, 181 + xy: 893, 253 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 dirtedge rotate: false - xy: 1011, 359 + xy: 398, 73 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 generic-cliff-edge rotate: false - xy: 567, 181 + xy: 903, 253 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ice-cliff-edge rotate: false - xy: 567, 181 + xy: 903, 253 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 generic-cliff-edge-1 rotate: false - xy: 555, 171 + xy: 913, 263 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ice-cliff-edge-1 rotate: false - xy: 555, 171 + xy: 913, 263 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 generic-cliff-edge-2 rotate: false - xy: 565, 171 + xy: 923, 273 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ice-cliff-edge-2 rotate: false - xy: 565, 171 + xy: 923, 273 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 generic-cliff-side rotate: false - xy: 522, 161 + xy: 853, 196 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ice-cliff-side rotate: false - xy: 522, 161 + xy: 853, 196 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 grass-cliff-edge rotate: false - xy: 552, 161 + xy: 883, 223 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 grass-cliff-edge-1 rotate: false - xy: 562, 161 + xy: 893, 233 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 grass-cliff-edge-2 rotate: false - xy: 522, 151 + xy: 903, 243 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 grass-cliff-side rotate: false - xy: 520, 141 + xy: 913, 253 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 grass2 rotate: false - xy: 532, 161 + xy: 863, 203 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 grass3 rotate: false - xy: 542, 161 + xy: 873, 213 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 grassedge rotate: false - xy: 209, 1 + xy: 891, 307 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 ice2 rotate: false - xy: 532, 151 + xy: 933, 273 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ice3 rotate: false - xy: 530, 141 + xy: 873, 203 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 iceedge rotate: false - xy: 237, 1 + xy: 919, 307 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 icerock2 rotate: false - xy: 527, 131 + xy: 883, 213 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 icerockshadow1 rotate: false - xy: 542, 151 + xy: 893, 223 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 rockshadow1 rotate: false - xy: 542, 151 + xy: 893, 223 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 icerockshadow2 rotate: false - xy: 540, 141 + xy: 903, 233 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 rockshadow2 rotate: false - xy: 540, 141 + xy: 903, 233 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 lavaedge rotate: false - xy: 265, 1 + xy: 877, 293 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 lead1 rotate: false - xy: 607, 178 + xy: 933, 213 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 lead2 rotate: false - xy: 617, 178 + xy: 933, 203 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 lead3 rotate: false - xy: 627, 178 + xy: 853, 186 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 metalfloor2 rotate: false - xy: 582, 158 + xy: 873, 183 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 metalfloor3 rotate: false - xy: 592, 158 + xy: 883, 183 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 metalfloor4 rotate: false - xy: 602, 158 + xy: 893, 183 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 metalfloor5 rotate: false - xy: 612, 158 + xy: 903, 183 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 metalfloor6 rotate: false - xy: 622, 158 + xy: 913, 183 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 metalflooredge rotate: false - xy: 847, 302 + xy: 961, 303 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 oiledge rotate: false - xy: 892, 369 + xy: 989, 303 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 rock2 rotate: false - xy: 563, 88 + xy: 386, 53 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 sand2 rotate: false - xy: 573, 88 + xy: 406, 53 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 sand3 rotate: false - xy: 573, 78 + xy: 416, 53 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 sandedge rotate: false - xy: 920, 369 + xy: 961, 289 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 shrubshadow rotate: false - xy: 613, 88 + xy: 327, 1 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 snow2 rotate: false - xy: 613, 78 + xy: 1003, 171 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 snow3 rotate: false - xy: 623, 88 + xy: 1013, 171 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 snowedge rotate: false - xy: 879, 353 + xy: 989, 289 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 spaceedge rotate: false - xy: 879, 339 + xy: 411, 87 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 stone-cliff-edge rotate: false - xy: 563, 68 + xy: 474, 128 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 stone-cliff-edge-1 rotate: false - xy: 573, 68 + xy: 484, 138 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 stone-cliff-edge-2 rotate: false - xy: 583, 68 + xy: 494, 148 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 stone-cliff-side rotate: false - xy: 593, 68 + xy: 484, 128 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 stone2 rotate: false - xy: 673, 88 + xy: 474, 138 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 stone3 rotate: false - xy: 673, 78 + xy: 484, 148 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 stoneedge rotate: false - xy: 893, 355 + xy: 412, 73 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 thorium1 rotate: false - xy: 603, 68 + xy: 494, 138 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 thorium2 rotate: false - xy: 613, 68 + xy: 504, 148 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 thorium3 rotate: false - xy: 623, 68 + xy: 494, 128 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium1 rotate: false - xy: 633, 68 + xy: 504, 138 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium2 rotate: false - xy: 643, 68 + xy: 514, 148 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium3 rotate: false - xy: 653, 68 + xy: 504, 128 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 tungsten1 rotate: false - xy: 899, 321 + xy: 539, 118 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 tungsten2 rotate: false - xy: 909, 321 + xy: 549, 119 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 tungsten3 rotate: false - xy: 903, 311 + xy: 559, 119 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 water-cliff-edge rotate: false - xy: 893, 297 + xy: 493, 98 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 water-cliff-edge-1 rotate: false - xy: 919, 325 + xy: 503, 108 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 water-cliff-edge-2 rotate: false - xy: 929, 325 + xy: 503, 98 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 water-cliff-side rotate: false - xy: 939, 325 + xy: 513, 108 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 wateredge rotate: false - xy: 907, 341 + xy: 199, 19 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 block-border rotate: false - xy: 728, 271 + xy: 1005, 327 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-elevation rotate: false - xy: 728, 261 + xy: 1015, 321 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 combustion-generator-top rotate: false - xy: 728, 261 + xy: 1015, 321 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-middle rotate: false - xy: 333, 15 + xy: 823, 218 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 pump-liquid rotate: false - xy: 333, 15 + xy: 823, 218 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-slope rotate: false - xy: 343, 25 + xy: 813, 198 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 border rotate: false - xy: 333, 5 + xy: 823, 208 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conduit-liquid rotate: false - xy: 517, 131 + xy: 863, 283 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 cross-1 rotate: false - xy: 775, 302 + xy: 893, 263 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 cross-2 rotate: false - xy: 357, 117 + xy: 863, 321 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 cross-3 rotate: false - xy: 385, 135 + xy: 609, 204 size: 24, 24 orig: 24, 24 offset: 0, 0 @@ -1133,105 +1140,105 @@ cross-4 index: -1 enemyspawn rotate: false - xy: 545, 171 + xy: 893, 243 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 nuclearreactor-shadow rotate: false - xy: 765, 356 + xy: 586, 282 size: 26, 26 orig: 26, 26 offset: 0, 0 index: -1 place-arrow rotate: false - xy: 522, 61 + xy: 277, 1 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 playerspawn rotate: false - xy: 533, 81 + xy: 287, 11 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ripples rotate: false - xy: 416, 58 + xy: 319, 41 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 rubble-1-0 rotate: false - xy: 256, 81 + xy: 466, 184 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 rubble-1-1 rotate: false - xy: 292, 99 + xy: 463, 166 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 rubble-2-0 rotate: false - xy: 274, 81 + xy: 175, 99 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 rubble-2-1 rotate: false - xy: 310, 99 + xy: 193, 99 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 rubble-3-0 rotate: false - xy: 691, 231 + xy: 819, 316 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 rubble-3-1 rotate: false - xy: 691, 231 + xy: 819, 316 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 shadow-1 rotate: false - xy: 452, 56 + xy: 331, 55 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 shadow-2 rotate: false - xy: 447, 176 + xy: 157, 149 size: 18, 18 orig: 18, 18 offset: 0, 0 index: -1 shadow-3 rotate: false - xy: 845, 417 + xy: 614, 282 size: 26, 26 orig: 26, 26 offset: 0, 0 index: -1 shadow-4 rotate: false - xy: 37, 6 + xy: 1, 6 size: 34, 34 orig: 34, 34 offset: 0, 0 @@ -1252,301 +1259,308 @@ shadow-6 index: -1 shadow-corner rotate: false - xy: 464, 56 + xy: 331, 43 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 shadow-round-1 rotate: false - xy: 476, 56 + xy: 343, 55 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 shadow-round-2 rotate: false - xy: 467, 182 + xy: 157, 129 size: 18, 18 orig: 18, 18 offset: 0, 0 index: -1 +shadow-round-3 + rotate: false + xy: 642, 282 + size: 26, 26 + orig: 26, 26 + offset: 0, 0 + index: -1 shadow-rounded-2 rotate: false - xy: 161, 3 + xy: 833, 402 size: 18, 18 orig: 18, 18 offset: 0, 0 index: -1 bridge-conduit-arrow rotate: false - xy: 343, 15 + xy: 813, 188 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 bridge-conduit-bridge rotate: false - xy: 353, 25 + xy: 823, 198 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 bridge-conduit-end rotate: false - xy: 343, 5 + xy: 823, 188 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conduit-bottom rotate: false - xy: 383, 15 + xy: 843, 248 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conduit-bottom-0 rotate: false - xy: 393, 25 + xy: 843, 238 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conduit-bottom-1 rotate: false - xy: 383, 5 + xy: 843, 228 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conduit-bottom-2 rotate: false - xy: 393, 15 + xy: 843, 218 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conduit-bottom-3 rotate: false - xy: 393, 5 + xy: 843, 208 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conduit-bottom-4 rotate: false - xy: 403, 25 + xy: 843, 198 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conduit-bottom-5 rotate: false - xy: 403, 15 + xy: 843, 188 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conduit-bottom-6 rotate: false - xy: 403, 5 + xy: 853, 286 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conduit-top-0 rotate: false - xy: 517, 121 + xy: 873, 283 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conduit-top-1 rotate: false - xy: 517, 111 + xy: 883, 283 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conduit-top-2 rotate: false - xy: 517, 101 + xy: 893, 283 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conduit-top-3 rotate: false - xy: 967, 356 + xy: 903, 283 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conduit-top-4 rotate: false - xy: 977, 356 + xy: 913, 283 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conduit-top-5 rotate: false - xy: 967, 346 + xy: 923, 283 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conduit-top-6 rotate: false - xy: 977, 346 + xy: 933, 283 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 liquid-router rotate: false - xy: 615, 168 + xy: 913, 193 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 liquid-router-bottom rotate: false - xy: 625, 168 + xy: 923, 193 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 liquid-router-liquid rotate: false - xy: 635, 168 + xy: 933, 193 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 liquid-router-top rotate: false - xy: 572, 158 + xy: 863, 183 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 liquid-tank-bottom rotate: false - xy: 624, 258 + xy: 661, 204 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 liquid-tank-liquid rotate: false - xy: 650, 258 + xy: 711, 368 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 liquid-tank-top rotate: false - xy: 676, 257 + xy: 711, 342 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 phase-conduit-arrow rotate: false - xy: 881, 295 + xy: 247, 1 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 phase-conduit-bridge rotate: false - xy: 893, 307 + xy: 257, 11 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 phase-conduit-end rotate: false - xy: 523, 91 + xy: 257, 1 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 pulse-conduit-top-0 rotate: false - xy: 543, 91 + xy: 287, 1 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 pulse-conduit-top-1 rotate: false - xy: 533, 71 + xy: 297, 11 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 pulse-conduit-top-2 rotate: false - xy: 532, 61 + xy: 297, 1 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 pulse-conduit-top-3 rotate: false - xy: 543, 81 + xy: 307, 11 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 pulse-conduit-top-4 rotate: false - xy: 553, 91 + xy: 307, 1 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 pulse-conduit-top-5 rotate: false - xy: 543, 71 + xy: 317, 11 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 pulse-conduit-top-6 rotate: false - xy: 542, 61 + xy: 317, 1 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 battery rotate: false - xy: 115, 5 + xy: 113, 5 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-battery rotate: false - xy: 115, 5 + xy: 113, 5 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 battery-large rotate: false - xy: 899, 419 + xy: 738, 420 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-icon-battery-large rotate: false - xy: 899, 419 + xy: 738, 420 size: 24, 24 orig: 24, 24 offset: 0, 0 @@ -1609,588 +1623,658 @@ fusion-reactor-top index: -1 nuclear-reactor-center rotate: false - xy: 587, 232 + xy: 741, 316 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 nuclear-reactor-lights rotate: false - xy: 613, 232 + xy: 767, 316 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 rtg-generator-top rotate: false - xy: 563, 78 + xy: 396, 53 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 turbine-generator-top rotate: false - xy: 364, 81 + xy: 247, 81 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 alloy-fuser rotate: false - xy: 873, 419 + xy: 712, 420 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-icon-alloy-fuser rotate: false - xy: 873, 419 + xy: 712, 420 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 alloy-smelter rotate: false - xy: 125, 1 + xy: 123, 1 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-alloy-smelter rotate: false - xy: 125, 1 + xy: 123, 1 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 arc-smelter rotate: false - xy: 143, 1 + xy: 141, 1 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-arc-smelter rotate: false - xy: 143, 1 + xy: 141, 1 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 arc-smelter-top rotate: false - xy: 507, 191 + xy: 813, 298 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 silicon-smelter-top rotate: false - xy: 507, 191 + xy: 813, 298 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 biomattercompressor rotate: false - xy: 525, 191 + xy: 427, 178 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 biomattercompressor-frame0 rotate: false - xy: 543, 191 + xy: 445, 178 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 biomattercompressor-frame1 rotate: false - xy: 561, 191 + xy: 831, 298 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 biomattercompressor-frame2 rotate: false - xy: 713, 301 + xy: 159, 5 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 biomattercompressor-liquid rotate: false - xy: 710, 283 + xy: 679, 285 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 biomattercompressor-top rotate: false - xy: 739, 310 + xy: 697, 285 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 blast-mixer rotate: false - xy: 977, 413 + xy: 685, 267 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-blast-mixer rotate: false - xy: 977, 413 + xy: 685, 267 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 centrifuge-liquid rotate: false - xy: 321, 117 + xy: 883, 339 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 cryofluidmixer-bottom rotate: false - xy: 375, 117 + xy: 881, 321 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 cryofluidmixer-liquid rotate: false - xy: 393, 117 + xy: 899, 321 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 cryofluidmixer-top rotate: false - xy: 411, 116 + xy: 919, 339 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 cultivator rotate: false - xy: 429, 122 + xy: 917, 321 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 cultivator-middle rotate: false - xy: 447, 122 + xy: 949, 353 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 cultivator-top rotate: false - xy: 465, 122 + xy: 967, 353 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 lavasmelter rotate: false - xy: 597, 178 + xy: 923, 203 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 oilrefinery rotate: false - xy: 645, 168 + xy: 973, 279 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 phase-weaver rotate: false - xy: 202, 81 + xy: 321, 117 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 phase-weaver-bottom rotate: false - xy: 238, 99 + xy: 339, 117 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 phase-weaver-weave rotate: false - xy: 220, 81 + xy: 357, 117 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 plastanium-compressor-top rotate: false - xy: 256, 99 + xy: 375, 117 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 poweralloysmelter-top rotate: false - xy: 238, 81 + xy: 393, 117 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 pulverizer rotate: false - xy: 553, 81 + xy: 473, 102 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 pulverizer-rotator rotate: false - xy: 553, 71 + xy: 473, 92 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 separator-liquid rotate: false - xy: 603, 88 + xy: 331, 23 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 core-open rotate: false - xy: 359, 135 + xy: 635, 230 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +core-top + rotate: false + xy: 583, 204 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 sortedunloader rotate: false - xy: 643, 78 + xy: 521, 158 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-1 rotate: false - xy: 728, 291 + xy: 1005, 337 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-1-top rotate: false - xy: 728, 281 + xy: 1015, 331 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-2 rotate: false - xy: 995, 419 + xy: 703, 267 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-2-top rotate: false - xy: 995, 401 + xy: 721, 272 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-3 rotate: false - xy: 765, 330 + xy: 755, 394 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-3-top rotate: false - xy: 586, 284 + xy: 781, 394 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-4 rotate: false - xy: 180, 161 + xy: 819, 456 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-4-top rotate: false - xy: 214, 161 + xy: 37, 8 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 arc rotate: false - xy: 1013, 425 + xy: 841, 390 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 arc-heat rotate: false - xy: 1013, 413 + xy: 841, 342 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 cyclone rotate: false - xy: 572, 258 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -mass-driver-turret - rotate: false - xy: 572, 258 + xy: 635, 204 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 duo rotate: false - xy: 557, 181 + xy: 883, 233 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 fuse rotate: false - xy: 598, 258 + xy: 661, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 spectre rotate: false - xy: 598, 258 + xy: 661, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 hail rotate: false - xy: 933, 357 - size: 10, 10 - orig: 10, 10 + xy: 923, 263 + size: 8, 8 + orig: 8, 8 offset: 0, 0 index: -1 scatter rotate: false - xy: 933, 357 - size: 10, 10 - orig: 10, 10 + xy: 923, 263 + size: 8, 8 + orig: 8, 8 offset: 0, 0 index: -1 hail-heat rotate: false - xy: 933, 345 + xy: 853, 342 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 lancer rotate: false - xy: 166, 71 + xy: 231, 117 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 lancer-heat rotate: false - xy: 184, 99 + xy: 249, 117 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 meltdown rotate: false - xy: 855, 445 + xy: 853, 445 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ripple rotate: false - xy: 665, 231 + xy: 815, 368 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 ripple-heat rotate: false - xy: 665, 205 + xy: 815, 342 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 salvo rotate: false - xy: 292, 81 + xy: 175, 81 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 salvo-heat rotate: false - xy: 328, 99 + xy: 211, 99 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 salvo-panel-left rotate: false - xy: 310, 81 + xy: 193, 81 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 salvo-panel-right rotate: false - xy: 346, 99 + xy: 229, 99 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 scorch rotate: false - xy: 428, 56 - size: 10, 10 - orig: 10, 10 + xy: 321, 31 + size: 8, 8 + orig: 8, 8 offset: 0, 0 index: -1 scorch-shoot rotate: false - xy: 440, 56 - size: 10, 10 - orig: 10, 10 + xy: 321, 21 + size: 8, 8 + orig: 8, 8 offset: 0, 0 index: -1 swarmer rotate: false - xy: 328, 81 + xy: 211, 81 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 wave rotate: false - xy: 256, 63 + xy: 301, 81 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 wave-liquid rotate: false - xy: 274, 63 + xy: 337, 99 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -drone-factory-top +dagger-pad-top rotate: false - xy: 831, 380 + xy: 985, 353 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -drone-factory-top-open +dagger-pad-top-open rotate: false - xy: 849, 381 + xy: 687, 249 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -fabricator-factory-top +drone-pad-top rotate: false - xy: 828, 362 + xy: 705, 231 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -fabricator-factory-top-open +drone-pad-top-open rotate: false - xy: 829, 344 + xy: 705, 213 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +fabricator-pad-top + rotate: false + xy: 723, 254 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +fabricator-pad-top-open + rotate: false + xy: 723, 236 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +interceptor-pad-top + rotate: false + xy: 177, 117 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +interceptor-pad-top-open + rotate: false + xy: 195, 117 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 mech-factory rotate: false - xy: 793, 362 + xy: 737, 342 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 dart-ship-factory-open rotate: false - xy: 483, 122 + xy: 687, 231 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 delta-mech-factory-open rotate: false - xy: 831, 398 + xy: 687, 213 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 javelin-ship-factory-open rotate: false - xy: 166, 89 + xy: 213, 117 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 +monsoon-pad + rotate: false + xy: 763, 368 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +monsoon-pad-top + rotate: false + xy: 763, 342 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +titan-pad-top + rotate: false + xy: 763, 342 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +monsoon-pad-top-open + rotate: false + xy: 715, 316 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +titan-pad-top-open + rotate: false + xy: 715, 316 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 reconstructor-open rotate: false - xy: 274, 99 + xy: 795, 188 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 repair-point-turret rotate: false - xy: 552, 61 + xy: 376, 51 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ship-factory rotate: false - xy: 691, 205 + xy: 715, 290 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +titan-pad + rotate: false + xy: 741, 290 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 door-large-open rotate: false - xy: 849, 399 + xy: 705, 249 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 door-open rotate: false - xy: 535, 171 + xy: 873, 223 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -2211,2737 +2295,2793 @@ beam-end index: -1 blank rotate: false - xy: 572, 168 + xy: 486, 209 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 bullet rotate: false - xy: 692, 435 + xy: 572, 245 size: 9, 9 orig: 9, 9 offset: 0, 0 index: -1 bullet-back rotate: false - xy: 400, 106 + xy: 343, 44 size: 9, 9 orig: 9, 9 offset: 0, 0 index: -1 casing rotate: false - xy: 991, 431 + xy: 845, 318 size: 2, 4 orig: 2, 4 offset: 0, 0 index: -1 clear rotate: false - xy: 567, 138 + xy: 566, 287 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 +command-attack + rotate: false + xy: 841, 278 + size: 8, 8 + orig: 8, 8 + offset: 0, 0 + index: -1 +command-idle + rotate: false + xy: 843, 268 + size: 8, 8 + orig: 8, 8 + offset: 0, 0 + index: -1 +command-retreat + rotate: false + xy: 843, 258 + size: 8, 8 + orig: 8, 8 + offset: 0, 0 + index: -1 enemyarrow rotate: false - xy: 845, 445 + xy: 425, 87 size: 8, 7 orig: 8, 7 offset: 0, 0 index: -1 error rotate: false - xy: 717, 189 + xy: 849, 296 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 laser rotate: false - xy: 1022, 485 + xy: 816, 432 size: 1, 12 orig: 1, 12 offset: 0, 0 index: -1 laser-end rotate: false - xy: 157, 129 + xy: 151, 107 size: 18, 18 orig: 18, 18 offset: 0, 0 index: -1 laserfull rotate: false - xy: 791, 388 + xy: 466, 202 size: 18, 18 orig: 18, 18 offset: 0, 0 index: -1 minelaser rotate: false - xy: 1022, 471 + xy: 1022, 485 size: 1, 12 orig: 1, 12 offset: 0, 0 index: -1 minelaser-end rotate: false - xy: 811, 388 + xy: 566, 290 size: 18, 18 orig: 18, 18 offset: 0, 0 index: -1 missile rotate: false - xy: 481, 158 + xy: 486, 198 size: 9, 9 orig: 9, 9 offset: 0, 0 index: -1 missile-back rotate: false - xy: 488, 57 + xy: 497, 198 size: 9, 9 orig: 9, 9 offset: 0, 0 index: -1 scorch1 rotate: false - xy: 717, 230 + xy: 670, 283 size: 7, 25 orig: 7, 25 offset: 0, 0 index: -1 scorch2 rotate: false - xy: 819, 361 + xy: 676, 256 size: 7, 25 orig: 7, 25 offset: 0, 0 index: -1 scorch3 rotate: false - xy: 717, 203 + xy: 418, 168 size: 7, 25 orig: 7, 25 offset: 0, 0 index: -1 scorch4 rotate: false - xy: 418, 168 + xy: 411, 134 size: 7, 25 orig: 7, 25 offset: 0, 0 index: -1 scorch5 rotate: false - xy: 411, 134 + xy: 166, 80 size: 7, 25 orig: 7, 25 offset: 0, 0 index: -1 shell rotate: false - xy: 974, 366 + xy: 508, 198 size: 9, 9 orig: 9, 9 offset: 0, 0 index: -1 shell-back rotate: false - xy: 512, 82 + xy: 519, 198 size: 9, 9 orig: 9, 9 offset: 0, 0 index: -1 shot rotate: false - xy: 603, 78 + xy: 327, 11 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 transfer rotate: false - xy: 805, 330 + xy: 1022, 471 size: 1, 12 orig: 1, 12 offset: 0, 0 index: -1 transfer-arrow rotate: false - xy: 903, 331 + xy: 529, 118 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 transfer-end rotate: false - xy: 487, 189 + xy: 793, 296 size: 18, 18 orig: 18, 18 offset: 0, 0 index: -1 blackstone-cliff-edge rotate: false - xy: 921, 335 + xy: 1015, 361 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blackstone-cliff-edge-1 rotate: false - xy: 931, 335 + xy: 1015, 351 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blackstone-cliff-edge-2 rotate: false - xy: 941, 335 + xy: 1005, 347 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blackstone-cliff-side rotate: false - xy: 951, 335 + xy: 1015, 341 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-arc rotate: false - xy: 151, 107 - size: 18, 18 - orig: 18, 18 + xy: 739, 272 + size: 16, 16 + orig: 16, 16 offset: 0, 0 index: -1 block-icon-biomattercompressor rotate: false - xy: 427, 158 + xy: 757, 272 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-blast-drill rotate: false - xy: 612, 284 + xy: 177, 135 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-icon-bridge-conduit rotate: false - xy: 728, 251 + xy: 1005, 317 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 bridge-conduit rotate: false - xy: 728, 251 + xy: 1005, 317 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-bridge-conveyor rotate: false - xy: 726, 241 + xy: 1015, 311 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 bridge-conveyor rotate: false - xy: 726, 241 + xy: 1015, 311 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-carbide-drill rotate: false - xy: 726, 231 + xy: 1015, 301 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-carbide-wall rotate: false - xy: 726, 221 + xy: 1015, 291 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 carbide-wall rotate: false - xy: 726, 221 + xy: 1015, 291 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-carbide-wall-large rotate: false - xy: 445, 158 + xy: 775, 272 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 carbide-wall-large rotate: false - xy: 445, 158 + xy: 775, 272 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-centrifuge rotate: false - xy: 420, 140 + xy: 793, 278 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 centrifuge rotate: false - xy: 420, 140 + xy: 793, 278 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-combustion-generator rotate: false - xy: 726, 211 + xy: 1015, 281 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 combustion-generator rotate: false - xy: 726, 211 + xy: 1015, 281 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 +block-icon-command-center + rotate: false + xy: 427, 160 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +command-center + rotate: false + xy: 427, 160 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 block-icon-conduit rotate: false - xy: 863, 309 + xy: 530, 199 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-conveyor rotate: false - xy: 861, 299 + xy: 540, 199 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 conveyor-0-0 rotate: false - xy: 861, 299 + xy: 540, 199 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-core rotate: false - xy: 638, 284 + xy: 203, 135 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 core rotate: false - xy: 638, 284 + xy: 203, 135 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-icon-cryofluidmixer rotate: false - xy: 438, 140 + xy: 445, 160 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-cultivator rotate: false - xy: 757, 310 + xy: 420, 142 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-cyclone rotate: false - xy: 685, 309 - size: 26, 26 - orig: 26, 26 + xy: 229, 135 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +block-icon-dagger-pad + rotate: false + xy: 438, 142 + size: 16, 16 + orig: 16, 16 offset: 0, 0 index: -1 block-icon-dart-ship-factory rotate: false - xy: 775, 312 + xy: 853, 393 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 dart-ship-factory rotate: false - xy: 775, 312 + xy: 853, 393 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-deepwater rotate: false - xy: 289, 53 + xy: 484, 188 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 deepwater rotate: false - xy: 289, 53 + xy: 484, 188 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-deflector-wall rotate: false - xy: 289, 43 + xy: 494, 188 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 deflector-wall rotate: false - xy: 289, 43 + xy: 494, 188 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 phase-wall rotate: false - xy: 289, 43 + xy: 494, 188 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-phase-wall rotate: false - xy: 289, 43 + xy: 494, 188 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-deflector-wall-large rotate: false - xy: 487, 171 + xy: 871, 393 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 deflector-wall-large rotate: false - xy: 487, 171 + xy: 871, 393 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 phase-wall-large rotate: false - xy: 487, 171 + xy: 871, 393 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-phase-wall-large rotate: false - xy: 487, 171 + xy: 871, 393 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-delta-mech-factory rotate: false - xy: 579, 188 + xy: 889, 393 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 delta-mech-factory rotate: false - xy: 579, 188 + xy: 889, 393 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-dirt rotate: false - xy: 289, 33 + xy: 504, 188 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 dirt1 rotate: false - xy: 289, 33 + xy: 504, 188 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-distributor rotate: false - xy: 597, 188 + xy: 907, 393 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 distributor rotate: false - xy: 597, 188 + xy: 907, 393 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-door rotate: false - xy: 299, 55 + xy: 514, 188 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 door rotate: false - xy: 299, 55 + xy: 514, 188 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-door-large rotate: false - xy: 615, 188 + xy: 925, 393 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 door-large rotate: false - xy: 615, 188 + xy: 925, 393 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -block-icon-drone-factory +block-icon-drone-pad rotate: false - xy: 633, 188 + xy: 943, 389 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-drop-point rotate: false - xy: 309, 55 + xy: 524, 188 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 drop-point rotate: false - xy: 309, 55 + xy: 524, 188 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-duo rotate: false - xy: 1013, 401 - size: 10, 10 - orig: 10, 10 + xy: 534, 189 + size: 8, 8 + orig: 8, 8 offset: 0, 0 index: -1 -block-icon-fabricator-factory +block-icon-fabricator-pad rotate: false - xy: 665, 187 + xy: 961, 389 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-fuse rotate: false - xy: 763, 384 - size: 26, 26 - orig: 26, 26 + xy: 255, 135 + size: 24, 24 + orig: 24, 24 offset: 0, 0 index: -1 block-icon-fusion-reactor rotate: false - xy: 248, 161 + xy: 180, 161 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-icon-grass rotate: false - xy: 299, 45 + xy: 544, 189 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 grass1 rotate: false - xy: 299, 45 + xy: 544, 189 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-hail rotate: false - xy: 962, 371 - size: 10, 10 - orig: 10, 10 + xy: 484, 178 + size: 8, 8 + orig: 8, 8 offset: 0, 0 index: -1 block-icon-ice rotate: false - xy: 319, 55 + xy: 494, 178 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ice1 rotate: false - xy: 319, 55 + xy: 494, 178 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-icerock rotate: false - xy: 299, 35 + xy: 504, 178 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 icerock1 rotate: false - xy: 299, 35 + xy: 504, 178 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-incinerator rotate: false - xy: 309, 45 + xy: 514, 178 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 incinerator rotate: false - xy: 309, 45 + xy: 514, 178 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 +block-icon-interceptor-pad + rotate: false + xy: 979, 389 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 block-icon-itemsource rotate: false - xy: 329, 55 + xy: 524, 178 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 itemsource rotate: false - xy: 329, 55 + xy: 524, 178 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-itemvoid rotate: false - xy: 309, 35 + xy: 534, 179 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 itemvoid rotate: false - xy: 309, 35 + xy: 534, 179 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-javelin-ship-factory rotate: false - xy: 683, 187 + xy: 997, 393 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 javelin-ship-factory rotate: false - xy: 683, 187 + xy: 997, 393 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-junction rotate: false - xy: 319, 45 + xy: 544, 179 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 junction rotate: false - xy: 319, 45 + xy: 544, 179 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-lancer rotate: false - xy: 466, 202 - size: 18, 18 - orig: 18, 18 + xy: 420, 124 + size: 16, 16 + orig: 16, 16 offset: 0, 0 index: -1 block-icon-laser-drill rotate: false - xy: 456, 140 + xy: 438, 124 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-lava rotate: false - xy: 339, 55 + xy: 481, 168 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 lava rotate: false - xy: 339, 55 + xy: 481, 168 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-liquid-junction rotate: false - xy: 319, 35 + xy: 491, 168 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 liquid-junction rotate: false - xy: 319, 35 + xy: 491, 168 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-liquid-router rotate: false - xy: 329, 45 + xy: 501, 168 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-liquid-tank rotate: false - xy: 684, 283 + xy: 281, 135 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-icon-liquidsource rotate: false - xy: 349, 55 + xy: 511, 168 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 liquidsource rotate: false - xy: 349, 55 + xy: 511, 168 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-mass-driver rotate: false - xy: 177, 135 + xy: 307, 135 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 mass-driver rotate: false - xy: 177, 135 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -core-top - rotate: false - xy: 177, 135 + xy: 307, 135 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-icon-mechanical-pump rotate: false - xy: 329, 35 + xy: 521, 168 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 mechanical-pump rotate: false - xy: 329, 35 + xy: 521, 168 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-meltdown rotate: false - xy: 1, 6 - size: 34, 34 - orig: 34, 34 + xy: 214, 161 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 block-icon-melter rotate: false - xy: 339, 45 + xy: 531, 168 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 melter rotate: false - xy: 339, 45 + xy: 531, 168 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-metalfloor rotate: false - xy: 359, 55 + xy: 541, 169 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 metalfloor1 rotate: false - xy: 359, 55 + xy: 541, 169 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 +block-icon-monsoon-pad + rotate: false + xy: 333, 135 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 block-icon-nuclear-reactor rotate: false - xy: 203, 135 + xy: 359, 135 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 nuclear-reactor rotate: false - xy: 203, 135 + xy: 359, 135 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-icon-oil rotate: false - xy: 339, 35 + xy: 551, 169 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 oil rotate: false - xy: 339, 35 + xy: 551, 169 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-oil-extractor rotate: false - xy: 229, 135 + xy: 385, 135 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-icon-overflow-gate rotate: false - xy: 349, 45 + xy: 356, 59 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 overflow-gate rotate: false - xy: 349, 45 + xy: 356, 59 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-phase-conduit rotate: false - xy: 369, 55 + xy: 366, 59 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 phase-conduit rotate: false - xy: 369, 55 + xy: 366, 59 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-phase-conveyor rotate: false - xy: 349, 35 + xy: 376, 61 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 phase-conveyor rotate: false - xy: 349, 35 + xy: 376, 61 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-phase-weaver rotate: false - xy: 463, 158 + xy: 841, 372 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-plasma-drill rotate: false - xy: 282, 161 + xy: 248, 161 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-icon-plastanium-compressor rotate: false - xy: 474, 140 + xy: 841, 354 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 plastanium-compressor rotate: false - xy: 474, 140 + xy: 841, 354 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-power-node rotate: false - xy: 359, 45 + xy: 386, 63 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 power-node rotate: false - xy: 359, 45 + xy: 386, 63 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-power-node-large rotate: false - xy: 793, 344 + xy: 859, 375 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 power-node-large rotate: false - xy: 793, 344 + xy: 859, 375 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-powerinfinite rotate: false - xy: 379, 55 + xy: 396, 63 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 powerinfinite rotate: false - xy: 379, 55 + xy: 396, 63 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-powervoid rotate: false - xy: 359, 35 + xy: 406, 63 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 powervoid rotate: false - xy: 359, 35 + xy: 406, 63 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-pulse-conduit rotate: false - xy: 369, 45 + xy: 416, 63 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-pulverizer rotate: false - xy: 389, 55 + xy: 426, 65 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-pyratite-mixer rotate: false - xy: 793, 312 + xy: 859, 357 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 pyratite-mixer rotate: false - xy: 793, 312 + xy: 859, 357 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-reconstructor rotate: false - xy: 811, 343 + xy: 877, 375 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -drone-factory +dagger-pad rotate: false - xy: 811, 343 + xy: 877, 375 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -fabricator-factory +drone-pad rotate: false - xy: 811, 343 + xy: 877, 375 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +fabricator-pad + rotate: false + xy: 877, 375 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +interceptor-pad + rotate: false + xy: 877, 375 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 reconstructor rotate: false - xy: 811, 343 + xy: 877, 375 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-repair-point rotate: false - xy: 369, 35 + xy: 355, 49 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 repair-point rotate: false - xy: 369, 35 + xy: 355, 49 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-resupply-point rotate: false - xy: 379, 45 + xy: 365, 49 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 resupply-point rotate: false - xy: 379, 45 + xy: 365, 49 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-ripple rotate: false - xy: 737, 354 - size: 26, 26 - orig: 26, 26 + xy: 572, 256 + size: 24, 24 + orig: 24, 24 offset: 0, 0 index: -1 block-icon-rock rotate: false - xy: 379, 35 + xy: 354, 39 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 rock1 rotate: false - xy: 379, 35 + xy: 354, 39 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-rotary-pump rotate: false - xy: 177, 117 + xy: 877, 357 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 rotary-pump rotate: false - xy: 177, 117 + xy: 877, 357 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-rtg-generator rotate: false - xy: 389, 45 + xy: 364, 39 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 rtg-generator rotate: false - xy: 389, 45 + xy: 364, 39 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-salvo rotate: false - xy: 566, 290 - size: 18, 18 - orig: 18, 18 + xy: 895, 375 + size: 16, 16 + orig: 16, 16 offset: 0, 0 index: -1 block-icon-sand rotate: false - xy: 389, 35 + xy: 813, 288 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 sand1 rotate: false - xy: 389, 35 + xy: 813, 288 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-scorch rotate: false - xy: 921, 357 - size: 10, 10 - orig: 10, 10 + xy: 823, 288 + size: 8, 8 + orig: 8, 8 offset: 0, 0 index: -1 block-icon-separator rotate: false - xy: 399, 55 + xy: 811, 278 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 separator rotate: false - xy: 399, 55 + xy: 811, 278 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-shrub rotate: false - xy: 399, 45 + xy: 833, 288 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 shrub rotate: false - xy: 399, 45 + xy: 833, 288 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-silicon-smelter rotate: false - xy: 195, 117 + xy: 895, 357 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 silicon-smelter rotate: false - xy: 195, 117 + xy: 895, 357 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-smelter rotate: false - xy: 399, 35 + xy: 821, 278 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 smelter rotate: false - xy: 399, 35 + xy: 821, 278 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-snow rotate: false - xy: 293, 23 + xy: 813, 268 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 snow1 rotate: false - xy: 293, 23 + xy: 813, 268 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-solar-panel rotate: false - xy: 293, 13 + xy: 831, 278 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 solar-panel rotate: false - xy: 293, 13 + xy: 831, 278 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-solar-panel-large rotate: false - xy: 255, 135 + xy: 598, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 solar-panel-large rotate: false - xy: 255, 135 + xy: 598, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-icon-solidifer rotate: false - xy: 293, 3 + xy: 813, 258 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 solidifer rotate: false - xy: 293, 3 + xy: 813, 258 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-sorter rotate: false - xy: 303, 25 + xy: 823, 268 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 sorter rotate: false - xy: 303, 25 + xy: 823, 268 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-space rotate: false - xy: 303, 15 + xy: 813, 248 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 space rotate: false - xy: 303, 15 + xy: 813, 248 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-spectre rotate: false - xy: 819, 454 - size: 34, 34 - orig: 34, 34 + xy: 282, 161 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 block-icon-splitter rotate: false - xy: 313, 25 + xy: 823, 258 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 splitter rotate: false - xy: 313, 25 + xy: 823, 258 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-stone rotate: false - xy: 303, 5 + xy: 813, 238 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 stone1 rotate: false - xy: 303, 5 + xy: 813, 238 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-swarmer rotate: false - xy: 157, 149 - size: 18, 18 - orig: 18, 18 + xy: 913, 375 + size: 16, 16 + orig: 16, 16 offset: 0, 0 index: -1 block-icon-thermal-generator rotate: false - xy: 213, 117 + xy: 913, 357 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 thermal-generator rotate: false - xy: 213, 117 + xy: 913, 357 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-thermal-pump rotate: false - xy: 231, 117 + xy: 931, 363 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 thermal-pump rotate: false - xy: 231, 117 + xy: 931, 363 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-thorium-wall rotate: false - xy: 313, 15 + xy: 823, 248 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 thorium-wall rotate: false - xy: 313, 15 + xy: 823, 248 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-thorium-wall-large rotate: false - xy: 249, 117 + xy: 949, 371 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 thorium-wall-large rotate: false - xy: 249, 117 + xy: 949, 371 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 +block-icon-titan-pad + rotate: false + xy: 624, 256 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 block-icon-titanium-conveyor rotate: false - xy: 323, 25 + xy: 813, 228 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium-conveyor-0-0 rotate: false - xy: 323, 25 + xy: 813, 228 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanium-conveyor rotate: false - xy: 323, 25 + xy: 813, 228 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-tungsten-drill rotate: false - xy: 313, 5 + xy: 823, 238 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-tungsten-wall rotate: false - xy: 323, 15 + xy: 813, 218 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 tungsten-wall rotate: false - xy: 323, 15 + xy: 813, 218 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-tungsten-wall-large rotate: false - xy: 267, 117 + xy: 967, 371 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 tungsten-wall-large rotate: false - xy: 267, 117 + xy: 967, 371 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-turbine-generator rotate: false - xy: 285, 117 + xy: 985, 371 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 turbine-generator rotate: false - xy: 285, 117 + xy: 985, 371 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-unloader rotate: false - xy: 333, 25 + xy: 823, 228 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 unloader rotate: false - xy: 333, 25 + xy: 823, 228 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-vault rotate: false - xy: 281, 135 + xy: 650, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 vault rotate: false - xy: 281, 135 + xy: 650, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-icon-warp-gate rotate: false - xy: 307, 135 + xy: 583, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 warp-gate rotate: false - xy: 307, 135 + xy: 583, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-icon-water rotate: false - xy: 323, 5 + xy: 813, 208 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 water rotate: false - xy: 323, 5 + xy: 813, 208 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-water-extractor rotate: false - xy: 303, 117 + xy: 845, 324 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icon-wave rotate: false - xy: 664, 290 - size: 18, 18 - orig: 18, 18 + xy: 865, 339 + size: 16, 16 + orig: 16, 16 offset: 0, 0 index: -1 deepwater-cliff-edge rotate: false - xy: 785, 302 + xy: 903, 273 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 deepwater-cliff-edge-1 rotate: false - xy: 795, 302 + xy: 853, 216 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 deepwater-cliff-edge-2 rotate: false - xy: 507, 181 + xy: 863, 223 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 deepwater-cliff-side rotate: false - xy: 505, 171 + xy: 873, 233 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 dirt-cliff-edge rotate: false - xy: 515, 171 + xy: 903, 263 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 dirt-cliff-edge-1 rotate: false - xy: 537, 181 + xy: 913, 273 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 dirt-cliff-edge-2 rotate: false - xy: 525, 171 + xy: 853, 206 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 dirt-cliff-side rotate: false - xy: 547, 181 + xy: 863, 213 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 lava-cliff-edge rotate: false - xy: 557, 111 + xy: 933, 233 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 lava-cliff-edge-1 rotate: false - xy: 557, 101 + xy: 913, 203 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 lava-cliff-edge-2 rotate: false - xy: 577, 178 + xy: 923, 213 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 lava-cliff-side rotate: false - xy: 587, 178 + xy: 933, 223 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 liquid-icon-cryofluid rotate: false - xy: 575, 168 + xy: 873, 193 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 liquid-icon-lava rotate: false - xy: 585, 168 + xy: 883, 193 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 liquid-icon-oil rotate: false - xy: 595, 168 + xy: 893, 193 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 liquid-icon-water rotate: false - xy: 605, 168 + xy: 903, 193 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 mech-icon-alpha-mech rotate: false - xy: 279, 1 + xy: 891, 293 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 mech-icon-dart-ship rotate: false - xy: 492, 141 + xy: 905, 293 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 mech-icon-delta-mech rotate: false - xy: 506, 141 + xy: 919, 293 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 mech-icon-halberd-ship rotate: false - xy: 508, 155 + xy: 933, 293 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 mech-icon-trident-ship rotate: false - xy: 508, 155 + xy: 933, 293 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 mech-icon-omega-mech rotate: false - xy: 863, 319 + xy: 947, 303 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 mech-icon-tau-mech rotate: false - xy: 863, 319 + xy: 947, 303 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 metalfloor-cliff-edge rotate: false - xy: 632, 158 + xy: 923, 183 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 metalfloor-cliff-edge-1 rotate: false - xy: 572, 148 + xy: 933, 183 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 metalfloor-cliff-edge-2 rotate: false - xy: 582, 148 + xy: 943, 279 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 metalfloor-cliff-side rotate: false - xy: 592, 148 + xy: 953, 279 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 oil-cliff-edge rotate: false - xy: 602, 148 + xy: 943, 269 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 oil-cliff-edge-1 rotate: false - xy: 612, 148 + xy: 963, 279 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 oil-cliff-edge-2 rotate: false - xy: 622, 148 + xy: 943, 259 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 oil-cliff-side rotate: false - xy: 632, 148 + xy: 953, 269 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-blackstone1 rotate: false - xy: 655, 168 + xy: 943, 249 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-blackstone2 rotate: false - xy: 642, 158 + xy: 953, 259 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-blackstone3 rotate: false - xy: 642, 148 + xy: 963, 269 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-grass1 rotate: false - xy: 652, 158 + xy: 983, 279 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-grass2 rotate: false - xy: 652, 148 + xy: 993, 279 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-grass3 rotate: false - xy: 570, 138 + xy: 943, 239 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-ice1 rotate: false - xy: 580, 138 + xy: 953, 249 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-ice2 rotate: false - xy: 590, 138 + xy: 963, 259 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-ice3 rotate: false - xy: 600, 138 + xy: 973, 269 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-sand1 rotate: false - xy: 610, 138 + xy: 943, 229 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-sand2 rotate: false - xy: 620, 138 + xy: 953, 239 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-sand3 rotate: false - xy: 630, 138 + xy: 963, 249 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-snow1 rotate: false - xy: 640, 138 + xy: 973, 259 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-snow2 rotate: false - xy: 650, 138 + xy: 983, 269 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-snow3 rotate: false - xy: 567, 128 + xy: 943, 219 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-stone1 rotate: false - xy: 567, 118 + xy: 953, 229 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-stone2 rotate: false - xy: 577, 128 + xy: 963, 239 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-stone3 rotate: false - xy: 567, 108 + xy: 973, 249 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-blackstone1 rotate: false - xy: 577, 118 + xy: 983, 259 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-blackstone2 rotate: false - xy: 587, 128 + xy: 993, 269 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-blackstone3 rotate: false - xy: 577, 108 + xy: 1003, 271 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-grass1 rotate: false - xy: 587, 118 + xy: 943, 209 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-grass2 rotate: false - xy: 597, 128 + xy: 953, 219 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-grass3 rotate: false - xy: 587, 108 + xy: 963, 229 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-ice1 rotate: false - xy: 597, 118 + xy: 973, 239 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-ice2 rotate: false - xy: 607, 128 + xy: 983, 249 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-ice3 rotate: false - xy: 597, 108 + xy: 993, 259 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-sand1 rotate: false - xy: 607, 118 + xy: 1003, 261 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-sand2 rotate: false - xy: 617, 128 + xy: 1013, 271 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-sand3 rotate: false - xy: 607, 108 + xy: 943, 199 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-snow1 rotate: false - xy: 617, 118 + xy: 953, 209 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-snow2 rotate: false - xy: 627, 128 + xy: 963, 219 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-snow3 rotate: false - xy: 617, 108 + xy: 973, 229 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-stone1 rotate: false - xy: 627, 118 + xy: 983, 239 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-stone2 rotate: false - xy: 637, 128 + xy: 993, 249 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-stone3 rotate: false - xy: 627, 108 + xy: 1003, 251 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-blackstone1 rotate: false - xy: 637, 118 + xy: 1013, 261 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-blackstone2 rotate: false - xy: 647, 128 + xy: 943, 189 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-blackstone3 rotate: false - xy: 637, 108 + xy: 953, 199 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-grass1 rotate: false - xy: 647, 118 + xy: 963, 209 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-grass2 rotate: false - xy: 647, 108 + xy: 973, 219 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-grass3 rotate: false - xy: 567, 98 + xy: 983, 229 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-ice1 rotate: false - xy: 577, 98 + xy: 993, 239 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-ice2 rotate: false - xy: 587, 98 + xy: 1003, 241 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-ice3 rotate: false - xy: 597, 98 + xy: 1013, 251 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-sand1 rotate: false - xy: 607, 98 + xy: 953, 189 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-sand2 rotate: false - xy: 617, 98 + xy: 963, 199 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-sand3 rotate: false - xy: 627, 98 + xy: 973, 209 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-snow1 rotate: false - xy: 637, 98 + xy: 983, 219 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-snow2 rotate: false - xy: 647, 98 + xy: 993, 229 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-snow3 rotate: false - xy: 662, 158 + xy: 1003, 231 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-stone1 rotate: false - xy: 662, 148 + xy: 1013, 241 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-stone2 rotate: false - xy: 660, 138 + xy: 963, 189 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-stone3 rotate: false - xy: 657, 128 + xy: 973, 199 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-blackstone1 rotate: false - xy: 657, 118 + xy: 983, 209 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-blackstone2 rotate: false - xy: 657, 108 + xy: 993, 219 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-blackstone3 rotate: false - xy: 657, 98 + xy: 1003, 221 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-grass1 rotate: false - xy: 672, 159 + xy: 1013, 231 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-grass2 rotate: false - xy: 682, 159 + xy: 973, 189 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-grass3 rotate: false - xy: 672, 149 + xy: 983, 199 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-ice1 rotate: false - xy: 682, 149 + xy: 993, 209 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-ice2 rotate: false - xy: 667, 128 + xy: 1003, 211 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-ice3 rotate: false - xy: 667, 118 + xy: 1013, 221 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-sand1 rotate: false - xy: 667, 108 + xy: 983, 189 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-sand2 rotate: false - xy: 667, 98 + xy: 993, 199 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-sand3 rotate: false - xy: 670, 138 + xy: 1003, 201 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-snow1 rotate: false - xy: 680, 139 + xy: 1013, 211 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-snow2 rotate: false - xy: 677, 128 + xy: 993, 189 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-snow3 rotate: false - xy: 677, 118 + xy: 1003, 191 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-stone1 rotate: false - xy: 677, 108 + xy: 1013, 201 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-stone2 rotate: false - xy: 677, 98 + xy: 1013, 191 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-stone3 rotate: false - xy: 889, 317 + xy: 943, 179 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-tungsten-blackstone1 rotate: false - xy: 512, 61 + xy: 953, 179 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-tungsten-blackstone2 rotate: false - xy: 736, 241 + xy: 963, 179 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-tungsten-blackstone3 rotate: false - xy: 736, 231 + xy: 973, 179 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-tungsten-grass1 rotate: false - xy: 736, 221 + xy: 983, 179 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-tungsten-grass2 rotate: false - xy: 736, 211 + xy: 993, 179 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-tungsten-grass3 rotate: false - xy: 731, 201 + xy: 1003, 181 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-tungsten-ice1 rotate: false - xy: 731, 191 + xy: 1013, 181 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-tungsten-ice2 rotate: false - xy: 741, 201 + xy: 177, 9 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-tungsten-ice3 rotate: false - xy: 741, 191 + xy: 187, 9 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-tungsten-sand1 rotate: false - xy: 737, 181 + xy: 197, 9 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-tungsten-sand2 rotate: false - xy: 737, 171 + xy: 207, 9 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-tungsten-sand3 rotate: false - xy: 741, 161 + xy: 217, 11 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-tungsten-snow1 rotate: false - xy: 747, 181 + xy: 217, 1 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-tungsten-snow2 rotate: false - xy: 747, 171 + xy: 227, 11 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-tungsten-snow3 rotate: false - xy: 751, 161 + xy: 227, 1 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-tungsten-stone1 rotate: false - xy: 873, 305 + xy: 237, 11 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-tungsten-stone2 rotate: false - xy: 883, 305 + xy: 237, 1 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-tungsten-stone3 rotate: false - xy: 871, 295 + xy: 247, 11 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 sand-cliff-edge rotate: false - xy: 583, 88 + xy: 426, 55 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 sand-cliff-edge-1 rotate: false - xy: 583, 78 + xy: 436, 65 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 sand-cliff-edge-2 rotate: false - xy: 593, 88 + xy: 436, 55 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 sand-cliff-side rotate: false - xy: 593, 78 + xy: 331, 33 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 snow-cliff-edge rotate: false - xy: 623, 78 + xy: 481, 158 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 snow-cliff-edge-1 rotate: false - xy: 633, 88 + xy: 491, 158 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 snow-cliff-edge-2 rotate: false - xy: 633, 78 + xy: 501, 158 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 snow-cliff-side rotate: false - xy: 643, 88 + xy: 511, 158 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 space-cliff-edge rotate: false - xy: 653, 88 + xy: 531, 158 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 space-cliff-edge-1 rotate: false - xy: 653, 78 + xy: 541, 159 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 space-cliff-edge-2 rotate: false - xy: 663, 88 + xy: 551, 159 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 space-cliff-side rotate: false - xy: 663, 78 + xy: 474, 148 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 -unit-icon-scout +unit-icon-dagger rotate: false - xy: 893, 341 + xy: 185, 19 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 unit-icon-titan rotate: false - xy: 382, 81 + xy: 283, 99 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -unit-icon-vtol - rotate: false - xy: 907, 355 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -vtol - rotate: false - xy: 907, 355 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 item-biomatter rotate: false - xy: 552, 151 + xy: 933, 263 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 item-blast-compound rotate: false - xy: 550, 141 + xy: 883, 203 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 item-carbide rotate: false - xy: 527, 111 + xy: 893, 213 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 item-coal rotate: false - xy: 537, 121 + xy: 903, 223 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 item-lead rotate: false - xy: 547, 131 + xy: 913, 233 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 item-phase-matter rotate: false - xy: 562, 151 + xy: 923, 243 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 item-plastanium rotate: false - xy: 560, 141 + xy: 933, 253 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 item-pyratite rotate: false - xy: 527, 101 + xy: 893, 203 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 item-sand rotate: false - xy: 537, 111 + xy: 903, 213 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 item-silicon rotate: false - xy: 547, 121 + xy: 913, 223 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 item-stone rotate: false - xy: 557, 131 + xy: 923, 233 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 item-surge-alloy rotate: false - xy: 537, 101 + xy: 933, 243 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 item-thorium rotate: false - xy: 547, 111 + xy: 903, 203 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 item-titanium rotate: false - xy: 557, 121 + xy: 913, 213 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 item-tungsten rotate: false - xy: 547, 101 + xy: 923, 223 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 liquid-icon rotate: false - xy: 637, 178 + xy: 863, 193 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 alpha-mech rotate: false - xy: 73, 1 + xy: 71, 1 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 alpha-mech-base rotate: false - xy: 87, 1 + xy: 85, 1 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 delta-mech-base rotate: false - xy: 87, 1 + xy: 85, 1 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 omega-mech-base rotate: false - xy: 87, 1 + xy: 85, 1 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 tau-mech-base rotate: false - xy: 87, 1 + xy: 85, 1 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 -scout-base +dagger-base rotate: false - xy: 87, 1 + xy: 85, 1 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 alpha-mech-leg rotate: false - xy: 101, 1 + xy: 99, 1 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 omega-mech-leg rotate: false - xy: 101, 1 + xy: 99, 1 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 tau-mech-leg rotate: false - xy: 101, 1 + xy: 99, 1 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 -scout-leg +dagger-leg rotate: false - xy: 101, 1 + xy: 99, 1 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 delta-mech rotate: false - xy: 1011, 387 + xy: 370, 71 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 delta-mech-leg rotate: false - xy: 1011, 373 + xy: 384, 73 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 omega-mech rotate: false - xy: 906, 369 + xy: 947, 289 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 tau-mech rotate: false - xy: 906, 369 + xy: 947, 289 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 dart-ship rotate: false - xy: 791, 330 + xy: 356, 69 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 halberd-ship rotate: false - xy: 223, 1 + xy: 905, 307 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 trident-ship rotate: false - xy: 223, 1 + xy: 905, 307 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 javelin-ship rotate: false - xy: 251, 1 + xy: 863, 293 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 mech-icon-javelin-ship rotate: false - xy: 251, 1 + xy: 863, 293 size: 12, 12 orig: 12, 12 offset: 0, 0 @@ -4998,7 +5138,7 @@ border index: -1 button rotate: false - xy: 99, 15 + xy: 97, 15 size: 24, 40 split: 10, 10, 6, 10 orig: 24, 40 @@ -5006,7 +5146,7 @@ button index: -1 textarea rotate: false - xy: 99, 15 + xy: 97, 15 size: 24, 40 split: 10, 10, 9, 11 orig: 24, 40 @@ -5030,7 +5170,7 @@ button-over index: -1 button-map rotate: false - xy: 73, 15 + xy: 71, 15 size: 24, 40 split: 10, 10, 5, 10 orig: 24, 40 @@ -5054,7 +5194,7 @@ button-map-over index: -1 button-select rotate: false - xy: 333, 135 + xy: 609, 230 size: 24, 24 split: 4, 4, 4, 4 orig: 24, 24 @@ -5062,35 +5202,35 @@ button-select index: -1 check-off rotate: false - xy: 557, 209 + xy: 685, 303 size: 28, 32 orig: 28, 32 offset: 0, 0 index: -1 check-on rotate: false - xy: 703, 412 + xy: 853, 411 size: 28, 32 orig: 28, 32 offset: 0, 0 index: -1 check-on-over rotate: false - xy: 733, 412 + xy: 883, 411 size: 28, 32 orig: 28, 32 offset: 0, 0 index: -1 check-over rotate: false - xy: 763, 412 + xy: 913, 411 size: 28, 32 orig: 28, 32 offset: 0, 0 index: -1 clear rotate: false - xy: 921, 345 + xy: 931, 381 size: 10, 10 orig: 10, 10 offset: 0, 0 @@ -5118,273 +5258,273 @@ discord-banner-over index: -1 controller-cursor rotate: false - xy: 339, 117 + xy: 901, 339 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-about rotate: false - xy: 292, 65 + xy: 319, 83 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-add rotate: false - xy: 308, 65 + xy: 355, 101 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-admin rotate: false - xy: 324, 65 + xy: 335, 83 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-admin-small rotate: false - xy: 731, 311 + xy: 833, 394 size: 6, 6 orig: 6, 6 offset: 0, 0 index: -1 icon-areaDelete rotate: false - xy: 945, 357 + xy: 937, 351 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-arrow rotate: false - xy: 429, 104 + xy: 741, 254 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-arrow-16 rotate: false - xy: 429, 104 + xy: 741, 254 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-arrow-down rotate: false - xy: 945, 345 + xy: 213, 21 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-arrow-left rotate: false - xy: 879, 327 + xy: 225, 21 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-arrow-right rotate: false - xy: 877, 315 + xy: 237, 21 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-arrow-up rotate: false - xy: 416, 94 + xy: 249, 21 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-back rotate: false - xy: 447, 104 + xy: 723, 218 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-ban rotate: false - xy: 340, 65 + xy: 371, 101 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-break rotate: false - xy: 465, 104 + xy: 741, 236 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-cancel rotate: false - xy: 483, 104 + xy: 759, 254 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-chat rotate: false - xy: 428, 92 + xy: 261, 21 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-check rotate: false - xy: 867, 399 + xy: 741, 218 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-crafting rotate: false - xy: 440, 92 + xy: 273, 21 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-cursor rotate: false - xy: 452, 92 + xy: 285, 21 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-defense rotate: false - xy: 464, 92 + xy: 297, 21 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-dev-builds rotate: false - xy: 356, 65 + xy: 387, 101 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-discord rotate: false - xy: 372, 65 + xy: 403, 101 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-distribution rotate: false - xy: 476, 92 + xy: 1003, 381 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-donate rotate: false - xy: 388, 65 + xy: 419, 108 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-dots rotate: false - xy: 177, 47 + xy: 435, 108 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-editor rotate: false - xy: 177, 31 + xy: 451, 108 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-egg rotate: false - xy: 193, 47 + xy: 180, 65 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-elevation rotate: false - xy: 867, 381 + xy: 759, 236 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-eraser rotate: false - xy: 885, 401 + xy: 759, 218 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-exit rotate: false - xy: 193, 31 + xy: 196, 65 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-file rotate: false - xy: 885, 383 + xy: 777, 254 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-file-image rotate: false - xy: 903, 401 + xy: 777, 236 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-file-text rotate: false - xy: 209, 47 + xy: 212, 65 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-fill rotate: false - xy: 903, 383 + xy: 777, 218 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-floppy rotate: false - xy: 209, 31 + xy: 228, 65 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-floppy-16 rotate: false - xy: 921, 401 + xy: 795, 260 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-folder rotate: false - xy: 225, 47 + xy: 244, 65 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-folder-parent rotate: false - xy: 225, 31 + xy: 260, 65 size: 14, 14 orig: 14, 14 offset: 0, 0 @@ -5398,441 +5538,441 @@ icon-generated index: -1 icon-github rotate: false - xy: 241, 47 + xy: 276, 65 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-google-play rotate: false - xy: 241, 31 + xy: 292, 65 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-grid rotate: false - xy: 921, 383 + xy: 795, 242 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-hold rotate: false - xy: 488, 92 + xy: 1003, 369 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-holdDelete rotate: false - xy: 416, 82 + xy: 1003, 357 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-home rotate: false - xy: 257, 47 + xy: 175, 49 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-host rotate: false - xy: 257, 31 + xy: 191, 49 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-info rotate: false - xy: 404, 78 + xy: 1003, 305 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-itch.io rotate: false - xy: 273, 47 + xy: 175, 33 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-item rotate: false - xy: 404, 66 + xy: 1003, 293 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-items-none rotate: false - xy: 527, 121 + xy: 913, 243 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 icon-line rotate: false - xy: 939, 401 + xy: 795, 224 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-link rotate: false - xy: 273, 31 + xy: 207, 49 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-liquid rotate: false - xy: 416, 70 + xy: 309, 21 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-load rotate: false - xy: 181, 15 + xy: 191, 33 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-load-image rotate: false - xy: 939, 383 + xy: 687, 195 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-load-map rotate: false - xy: 957, 401 + xy: 705, 195 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-loading rotate: false - xy: 957, 383 + xy: 723, 200 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-locked rotate: false - xy: 975, 395 + xy: 741, 200 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-logic rotate: false - xy: 428, 80 + xy: 467, 112 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-map rotate: false - xy: 197, 15 + xy: 223, 49 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-menu rotate: false - xy: 440, 80 + xy: 1003, 281 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-menu-large rotate: false - xy: 975, 377 + xy: 759, 200 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-missing rotate: false - xy: 452, 80 + xy: 723, 188 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-none rotate: false - xy: 464, 80 + xy: 735, 188 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-nullitem rotate: false - xy: 537, 131 + xy: 923, 253 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 icon-pause rotate: false - xy: 476, 80 + xy: 747, 188 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-pencil rotate: false - xy: 993, 383 + xy: 777, 200 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-pencil-small rotate: false - xy: 213, 15 + xy: 207, 33 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-pick rotate: false - xy: 993, 365 + xy: 795, 206 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-play rotate: false - xy: 488, 80 + xy: 759, 188 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-play-2 rotate: false - xy: 229, 15 + xy: 239, 49 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-players rotate: false - xy: 500, 81 + xy: 771, 188 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-power rotate: false - xy: 428, 68 + xy: 783, 188 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-production rotate: false - xy: 440, 68 + xy: 425, 96 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-quit rotate: false - xy: 245, 15 + xy: 223, 33 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-redo rotate: false - xy: 665, 169 + xy: 456, 142 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-refresh rotate: false - xy: 261, 15 + xy: 255, 49 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-rename rotate: false - xy: 277, 15 + xy: 239, 33 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-resize rotate: false - xy: 683, 169 + xy: 456, 124 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-rotate rotate: false - xy: 400, 90 + xy: 271, 49 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-rotate-arrow rotate: false - xy: 492, 155 + xy: 255, 33 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-rotate-left rotate: false - xy: 501, 125 + xy: 287, 49 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-rotate-right rotate: false - xy: 501, 109 + xy: 271, 33 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-save rotate: false - xy: 501, 93 + xy: 287, 33 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-save-image rotate: false - xy: 701, 171 + xy: 951, 335 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-save-map rotate: false - xy: 719, 171 + xy: 969, 335 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-settings rotate: false - xy: 452, 68 + xy: 437, 96 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-terrain rotate: false - xy: 811, 325 + xy: 987, 335 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-tools rotate: false - xy: 846, 364 + xy: 308, 65 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-touch rotate: false - xy: 464, 68 + xy: 449, 96 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-touchDelete rotate: false - xy: 476, 68 + xy: 426, 75 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-trash rotate: false - xy: 862, 365 + xy: 303, 49 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-trash-16 rotate: false - xy: 829, 326 + xy: 951, 317 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-trello rotate: false - xy: 847, 348 + xy: 303, 33 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-tutorial rotate: false - xy: 847, 332 + xy: 324, 67 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-undo rotate: false - xy: 811, 307 + xy: 969, 317 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-units rotate: false - xy: 488, 68 + xy: 461, 96 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-unlocks rotate: false - xy: 847, 316 + xy: 340, 67 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-weapon rotate: false - xy: 500, 69 + xy: 319, 53 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-wiki rotate: false - xy: 863, 349 + xy: 351, 83 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-zoom rotate: false - xy: 829, 308 + xy: 987, 317 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-zoom-small rotate: false - xy: 863, 333 + xy: 367, 85 size: 14, 14 orig: 14, 14 offset: 0, 0 @@ -5846,7 +5986,7 @@ info-banner index: -1 inventory rotate: false - xy: 125, 19 + xy: 123, 19 size: 24, 40 split: 10, 10, 10, 14 orig: 24, 40 @@ -5861,7 +6001,7 @@ logotext index: -1 pane rotate: false - xy: 819, 416 + xy: 969, 407 size: 24, 36 split: 10, 10, 5, 5 orig: 24, 36 @@ -5869,7 +6009,7 @@ pane index: -1 pane-button rotate: false - xy: 793, 408 + xy: 943, 407 size: 24, 36 split: 10, 10, 5, 5 orig: 24, 36 @@ -5877,7 +6017,7 @@ pane-button index: -1 scroll rotate: false - xy: 711, 345 + xy: 557, 206 size: 24, 35 split: 10, 10, 6, 5 orig: 24, 35 @@ -5902,7 +6042,7 @@ scroll-knob-horizontal index: -1 scroll-knob-vertical rotate: false - xy: 151, 23 + xy: 149, 23 size: 24, 40 split: 10, 10, 6, 10 orig: 24, 40 @@ -5918,14 +6058,14 @@ scroll-knob-vertical-black index: -1 selection rotate: false - xy: 703, 379 + xy: 177, 166 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 slider rotate: false - xy: 181, 107 + xy: 486, 212 size: 1, 8 orig: 1, 8 offset: 0, 0 @@ -5981,7 +6121,7 @@ text-sides-over index: -1 textfield rotate: false - xy: 733, 382 + xy: 995, 411 size: 28, 28 split: 6, 6, 6, 6 orig: 28, 28 @@ -5989,7 +6129,7 @@ textfield index: -1 textfield-over rotate: false - xy: 703, 382 + xy: 995, 441 size: 28, 28 split: 2, 2, 2, 2 orig: 28, 28 @@ -5997,7 +6137,7 @@ textfield-over index: -1 white rotate: false - xy: 855, 485 + xy: 66, 52 size: 3, 3 orig: 3, 3 offset: 0, 0 @@ -6018,121 +6158,128 @@ window-empty orig: 27, 61 offset: 0, 0 index: -1 +dagger + rotate: false + xy: 397, 87 + size: 12, 12 + orig: 12, 12 + offset: 0, 0 + index: -1 drone rotate: false - xy: 651, 178 + xy: 849, 310 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 unit-icon-drone rotate: false - xy: 651, 178 + xy: 849, 310 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 fabricator rotate: false - xy: 701, 189 + xy: 935, 321 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 unit-icon-fabricator rotate: false - xy: 701, 189 + xy: 935, 321 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 +interceptor + rotate: false + xy: 933, 307 + size: 12, 12 + orig: 12, 12 + offset: 0, 0 + index: -1 +unit-icon-interceptor + rotate: false + xy: 933, 307 + size: 12, 12 + orig: 12, 12 + offset: 0, 0 + index: -1 monsoon rotate: false - xy: 427, 176 + xy: 692, 426 size: 18, 18 orig: 18, 18 offset: 0, 0 index: -1 unit-icon-monsoon rotate: false - xy: 427, 176 + xy: 692, 426 size: 18, 18 orig: 18, 18 offset: 0, 0 index: -1 -scout - rotate: false - xy: 934, 369 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 titan rotate: false - xy: 364, 99 + xy: 247, 99 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 titan-base rotate: false - xy: 346, 81 + xy: 229, 81 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 titan-leg rotate: false - xy: 382, 99 + xy: 265, 99 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -vtol-flame - rotate: false - xy: 512, 71 - size: 9, 9 - orig: 9, 9 - offset: 0, 0 - index: -1 blaster-equip rotate: false - xy: 572, 244 + xy: 166, 66 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 chain-blaster-equip rotate: false - xy: 651, 192 + xy: 383, 87 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 flakgun-equip rotate: false - xy: 181, 1 + xy: 863, 307 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 flamethrower-equip rotate: false - xy: 195, 1 + xy: 877, 307 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 missiles-equip rotate: false - xy: 878, 367 + xy: 975, 303 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 shockgun-equip rotate: false - xy: 948, 369 + xy: 975, 289 size: 12, 12 orig: 12, 12 offset: 0, 0 diff --git a/core/assets/sprites/sprites.png b/core/assets/sprites/sprites.png index 5a3103c7a1..b057b476c4 100644 Binary files a/core/assets/sprites/sprites.png and b/core/assets/sprites/sprites.png differ diff --git a/core/assets/ui/uiskin.json b/core/assets/ui/uiskin.json index ea7082cef6..4f43942747 100644 --- a/core/assets/ui/uiskin.json +++ b/core/assets/ui/uiskin.json @@ -1,5 +1,5 @@ { -com.badlogic.gdx.graphics.g2d.BitmapFont: { +Font: { default-font: { file: square.fnt, markupEnabled: true, @@ -26,22 +26,16 @@ com.badlogic.gdx.graphics.g2d.BitmapFont: { scale: 2 } }, -com.badlogic.gdx.graphics.Color: { +Color: { black: {a: 1, b: 0, g: 0, r: 0 }, white: {a: 1, b: 1, g: 1, r: 1 }, - green: {a: 1, b: 0, g: 1, r: 0 }, - red: {a: 1, b: 0, g: 0, r: 1 }, - blue: {a: 1, b: 1, g: 0, r: 0 }, - grey: {a: 1, b: 0.32, g: 0.32, r: 0.32 }, - lightgray: {a: 1, b: 0.3, g: 0.3, r: 0.3 }, - orange: {hex: "#FFA500"}, + gray: {a: 1, b: 0.32, g: 0.32, r: 0.32 }, + lightgray: {a: 1, b: 0.65, g: 0.65, r: 0.65 } + orange: {hex: "FFA500"}, accent: {hex: "f4ba6e"}, - vis-blue: {a: 1, b: 0.886, g: 0.631, r: 0.105 }, - vis-red: {a: 1, b: 0.047, g: 0, r: 0.862 }, - menuitem: {a: 1, b: 0.65, g: 0.65, r: 0.65 }, - link-label: {a: 1, b: 0.886, g: 0.631, r: 0.105 } + accentDark: {hex: "f4ba6e"}, }, -io.anuke.ucore.scene.Skin$TintedDrawable: { +TintedDrawable: { dialogDim: {name: white, color: {r: 0, g: 0, b: 0, a: 0.9} }, invis: {name: white, color: {r: 0, g: 0, b: 0, a: 0} } loadDim: {name: white, color: {r: 0, g: 0, b: 0, a: 0.8} }, @@ -50,61 +44,58 @@ io.anuke.ucore.scene.Skin$TintedDrawable: { clear-over: {name: white, color: {r: 1, g: 1, b: 1, a: 0.2} }, clear-down: {name: white, color: {r: 1, g: 1, b: 1, a: 0.4} } }, -io.anuke.ucore.scene.ui.Button$ButtonStyle: { +ButtonStyle: { default: {down: button-down, up: button }, menu: {up: text-sides, over: text-sides-over, down: text-sides-down}, toggle: {checked: button-down, down: button-down, up: button } }, -io.anuke.ucore.scene.ui.TextButton$TextButtonStyle: { - default: {over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey, down: button-down, up: button, transition: 0 }, +TextButtonStyle: { + default: {over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: gray, down: button-down, up: button, transition: 0 }, discord: {over: discord-banner-over, font: default-font, fontColor: white, up: discord-banner}, info: {font: default-font, fontColor: white, up: info-banner}, - clear: {down: clear-down, up: clear, over: clear-over, font: default-font, fontColor: white, disabledFontColor: grey }, + clear: {down: clear-down, up: clear, over: clear-over, font: default-font, fontColor: white, disabledFontColor: gray }, empty: {font: default-font}, - toggle: {font: default-font, fontColor: white, checked: button-down, down: button-down, up: button, over: button-over, disabled: button, disabledFontColor: grey } + toggle: {font: default-font, fontColor: white, checked: button-down, down: button-down, up: button, over: button-over, disabled: button, disabledFontColor: gray } }, -io.anuke.ucore.scene.ui.ImageButton$ImageButtonStyle: { - default: {down: button-down, up: button, over: button-over, imageDisabledColor: lightgray, imageUpColor: white }, +ImageButtonStyle: { + default: {down: button-down, up: button, over: button-over, imageDisabledColor: gray, imageUpColor: white }, empty: { imageDownColor: accent, imageUpColor: white}, - emptytoggle: {imageCheckedColor: white, imageDownColor: white, imageUpColor: lightgray}, + emptytoggle: {imageCheckedColor: white, imageDownColor: white, imageUpColor: gray}, static: {up: button }, static-down: {up: button-down }, - toggle: {checked: button-down, down: button-down, up: button, imageDisabledColor: lightgray, imageUpColor: white }, - togglemap: {down: button-map-down, up: button-map }, + toggle: {checked: button-down, down: button-down, up: button, imageDisabledColor: gray, imageUpColor: white }, select: {checked: button-select, up: clear }, clear: {down: clear-down, up: clear, over: clear-over}, }, -io.anuke.ucore.scene.ui.ScrollPane$ScrollPaneStyle: { +ScrollPaneStyle: { default: {background: border, vScroll: scroll, vScrollKnob: scroll-knob-vertical-black}, horizontal: {background: border, vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal}, volume: {background: button-map, vScroll: scroll, vScrollKnob: scroll-knob-vertical-black}, clear: {vScroll: scroll, vScrollKnob: scroll-knob-vertical-black}, clear-black: {vScroll: scroll, vScrollKnob: scroll-knob-vertical-black} }, -io.anuke.ucore.scene.ui.Window$WindowStyle: { +WindowStyle: { default: {titleFont: default-font, background: window, titleFontColor: accent }, dialog: {stageBackground: dialogDim, titleFont: default-font, background: window-empty, titleFontColor: accent } }, -io.anuke.ucore.scene.ui.KeybindDialog$KeybindDialogStyle: { - default: {keyColor: accent, keyNameColor: white, controllerColor: menuitem, paneStyle: clear}, +KeybindDialogStyle: { + default: {keyColor: accent, keyNameColor: white, controllerColor: lightgray, paneStyle: clear}, }, -io.anuke.ucore.scene.ui.Slider$SliderStyle: { +SliderStyle: { default-horizontal: {background: slider, knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down}, default-vertical: {background: slider-vertical, knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down} }, -io.anuke.ucore.scene.ui.Label$LabelStyle: { +LabelStyle: { default: {font: default-font, fontColor: white }, title: {font: title, fontColor: white }, - link-label: {fontColor: link-label, font: default-font }, - small: {font: default-font, fontColor: white }, - menuitem-shortcut: {font: default-font, fontColor: menuitem } + small: {font: default-font, fontColor: white } }, -io.anuke.ucore.scene.ui.TextField$TextFieldStyle: { - default: {font: default-font-chat, fontColor: white, disabledFontColor: grey, selection: selection, background: button, cursor: cursor, messageFont: default-font, messageFontColor: grey } - textarea: {font: default-font-chat, fontColor: white, disabledFontColor: grey, selection: selection, background: textarea, cursor: cursor, messageFont: default-font, messageFontColor: grey } +TextFieldStyle: { + default: {font: default-font-chat, fontColor: white, disabledFontColor: gray, selection: selection, background: button, cursor: cursor, messageFont: default-font, messageFontColor: gray } + textarea: {font: default-font-chat, fontColor: white, disabledFontColor: gray, selection: selection, background: textarea, cursor: cursor, messageFont: default-font, messageFontColor: gray } } -io.anuke.ucore.scene.ui.CheckBox$CheckBoxStyle: { - default: {checkboxOn: check-on, checkboxOff: check-off, checkboxOnOver: check-on-over, checkboxOver: check-over, font: default-font, fontColor: white, disabledFontColor: grey } +CheckBoxStyle: { + default: {checkboxOn: check-on, checkboxOff: check-off, checkboxOnOver: check-on-over, checkboxOver: check-over, font: default-font, fontColor: white, disabledFontColor: gray } } } diff --git a/core/src/Mindustry.gwt.xml b/core/src/Mindustry.gwt.xml index 5e6f994b46..7b014a3888 100644 --- a/core/src/Mindustry.gwt.xml +++ b/core/src/Mindustry.gwt.xml @@ -19,4 +19,6 @@ + + \ No newline at end of file diff --git a/core/src/io/anuke/mindustry/Mindustry.java b/core/src/io/anuke/mindustry/Mindustry.java index 804baca4e4..6b4e754d58 100644 --- a/core/src/io/anuke/mindustry/Mindustry.java +++ b/core/src/io/anuke/mindustry/Mindustry.java @@ -29,14 +29,18 @@ public class Mindustry extends ModuleCore{ module(ui = new UI()); module(netServer = new NetServer()); module(netClient = new NetClient()); + } + @Override + public void postInit(){ Log.info("Time to load [total]: {0}", Timers.elapsed()); } @Override public void render(){ + threads.handleBeginRender(); super.render(); - threads.handleRender(); + threads.handleEndRender(); } } diff --git a/core/src/io/anuke/mindustry/Vars.java b/core/src/io/anuke/mindustry/Vars.java index dc493e8f45..b1759ce794 100644 --- a/core/src/io/anuke/mindustry/Vars.java +++ b/core/src/io/anuke/mindustry/Vars.java @@ -32,8 +32,6 @@ public class Vars{ public static final float respawnduration = 60 * 4; //time between waves in frames (on normal mode) public static final float wavespace = 60 * 60 * 2f; - //waves can last no longer than 3 minutes, otherwise the next one spawns - public static final float maxwavespace = 60 * 60 * 4f; //set ridiculously high for now public static final float coreBuildRange = 800999f; //discord group URL @@ -41,11 +39,9 @@ public class Vars{ public static final String releasesURL = "https://api.github.com/repos/Anuken/Mindustry/releases"; public static final int maxTextLength = 150; public static final int maxNameLength = 40; - //public static final int maxCharNameLength = 20; - // public static final int saveSlots = 64; public static final float itemSize = 5f; public static final int tilesize = 8; - public static final int sectorSize = 256; + public static final int sectorSize = 300; public static final int mapPadding = 3; public static final int invalidSector = Integer.MAX_VALUE; public static Locale[] locales; @@ -69,7 +65,6 @@ public class Vars{ }; //server port public static final int port = 6567; - public static final int webPort = 6568; public static boolean testMobile; //shorthand for whether or not this is running on android or ios public static boolean mobile; @@ -143,8 +138,6 @@ public class Vars{ String code = stra[i]; if(code.contains("_")){ locales[i] = new Locale(code.split("_")[0], code.split("_")[1]); - }else if(code.contains("-")){ - locales[i] = new Locale(code.split("-")[0], code.split("-")[1]); }else{ locales[i] = new Locale(code); } diff --git a/core/src/io/anuke/mindustry/ai/Pathfinder.java b/core/src/io/anuke/mindustry/ai/Pathfinder.java index 4bd910b3b3..855980a864 100644 --- a/core/src/io/anuke/mindustry/ai/Pathfinder.java +++ b/core/src/io/anuke/mindustry/ai/Pathfinder.java @@ -89,7 +89,7 @@ public class Pathfinder{ } private boolean passable(Tile tile, Team team){ - return (tile.block() == Blocks.air && !tile.floor().isLiquid && tile.cliffs == 0 && !tile.floor().solid && !(tile.floor().isLiquid && (tile.floor().damageTaken > 0 || tile.floor().drownTime > 0))) + return (tile.block() == Blocks.air && !tile.floor().isLiquid && !tile.hasCliffs() && !tile.floor().solid && !(tile.floor().isLiquid && (tile.floor().damageTaken > 0 || tile.floor().drownTime > 0))) || (tile.breakable() && (tile.getTeam() != team)) || !tile.solid(); } diff --git a/core/src/io/anuke/mindustry/content/Items.java b/core/src/io/anuke/mindustry/content/Items.java index d9de2c5513..85f8e07024 100644 --- a/core/src/io/anuke/mindustry/content/Items.java +++ b/core/src/io/anuke/mindustry/content/Items.java @@ -71,9 +71,16 @@ public class Items implements ContentList{ cost = 1.5f; }}; - surgealloy = new Item("surge-alloy", Color.valueOf("b4d5c7")){{ - type = ItemType.material; - }}; + surgealloy = new Item("surge-alloy", Color.valueOf("b4d5c7")){ + { + type = ItemType.material; + } + + @Override + public boolean isHidden(){ + return true; + } + }; biomatter = new Item("biomatter", Color.valueOf("648b55")){{ flammability = 0.4f; diff --git a/core/src/io/anuke/mindustry/content/Mechs.java b/core/src/io/anuke/mindustry/content/Mechs.java index c946060560..f3a8d36652 100644 --- a/core/src/io/anuke/mindustry/content/Mechs.java +++ b/core/src/io/anuke/mindustry/content/Mechs.java @@ -24,11 +24,12 @@ public class Mechs implements ContentList{ speed = 0.5f; weapon = Weapons.blaster; trailColor = Palette.lightTrail; + maxSpeed = 4f; }}; delta = new Mech("delta-mech", false){{ drillPower = -1; - speed = 0.63f; + speed = 0.75f; boostSpeed = 0.86f; itemCapacity = 15; armor = 30f; @@ -37,16 +38,19 @@ public class Mechs implements ContentList{ weapon = Weapons.shockgun; ammoCapacity = 50; trailColor = Color.valueOf("d3ddff"); + maxSpeed = 5f; }}; tau = new Mech("tau-mech", false){{ drillPower = 2; speed = 0.5f; + maxSpeed = 5f; }}; omega = new Mech("omega-mech", false){{ drillPower = 1; speed = 0.4f; + maxSpeed = 3f; }}; dart = new Mech("dart-ship", true){{ diff --git a/core/src/io/anuke/mindustry/content/Recipes.java b/core/src/io/anuke/mindustry/content/Recipes.java index c8faa59ad6..a34b84588d 100644 --- a/core/src/io/anuke/mindustry/content/Recipes.java +++ b/core/src/io/anuke/mindustry/content/Recipes.java @@ -51,6 +51,7 @@ public class Recipes implements ContentList{ new Recipe(distribution, DistributionBlocks.sorter, new ItemStack(Items.carbide, 4), new ItemStack(Items.tungsten, 4)); new Recipe(distribution, DistributionBlocks.overflowGate, new ItemStack(Items.carbide, 4), new ItemStack(Items.tungsten, 8)); new Recipe(distribution, DistributionBlocks.bridgeConveyor, new ItemStack(Items.carbide, 8), new ItemStack(Items.tungsten, 8)); + new Recipe(distribution, DistributionBlocks.massDriver, new ItemStack(Items.carbide, 400), new ItemStack(Items.silicon, 300), new ItemStack(Items.lead, 400), new ItemStack(Items.thorium, 250)); //CRAFTING @@ -74,7 +75,6 @@ public class Recipes implements ContentList{ new Recipe(crafting, CraftingBlocks.solidifier, new ItemStack(Items.carbide, 30), new ItemStack(Items.tungsten, 20)); new Recipe(crafting, CraftingBlocks.melter, new ItemStack(Items.tungsten, 60), new ItemStack(Items.lead, 70), new ItemStack(Items.carbide, 90)); - new Recipe(crafting, CraftingBlocks.incinerator, new ItemStack(Items.carbide, 10), new ItemStack(Items.lead, 30)); //processing @@ -95,6 +95,7 @@ public class Recipes implements ContentList{ //generators - combustion new Recipe(power, PowerBlocks.combustionGenerator, new ItemStack(Items.tungsten, 50), new ItemStack(Items.lead, 30)); new Recipe(power, PowerBlocks.turbineGenerator, new ItemStack(Items.tungsten, 70), new ItemStack(Items.carbide, 50), new ItemStack(Items.lead, 80), new ItemStack(Items.silicon, 60)); + new Recipe(power, PowerBlocks.thermalGenerator, new ItemStack(Items.tungsten, 80), new ItemStack(Items.carbide, 70), new ItemStack(Items.lead, 100), new ItemStack(Items.silicon, 70), new ItemStack(Items.thorium, 70)); //generators - solar new Recipe(power, PowerBlocks.solarPanel, new ItemStack(Items.lead, 20), new ItemStack(Items.silicon, 30)); @@ -104,14 +105,14 @@ public class Recipes implements ContentList{ new Recipe(power, PowerBlocks.nuclearReactor, new ItemStack(Items.lead, 600), new ItemStack(Items.silicon, 400), new ItemStack(Items.carbide, 300), new ItemStack(Items.thorium, 300)); //new Recipe(distribution, StorageBlocks.core, new ItemStack(Items.carbide, 50)); - //new Recipe(distribution, StorageBlocks.unloader, new ItemStack(Items.carbide, 40), new ItemStack(Items.silicon, 50)); - new Recipe(distribution, StorageBlocks.unloader, new ItemStack(Items.carbide, 40), new ItemStack(Items.silicon, 70)); + new Recipe(distribution, StorageBlocks.unloader, new ItemStack(Items.carbide, 40), new ItemStack(Items.silicon, 50)); new Recipe(distribution, StorageBlocks.vault, new ItemStack(Items.carbide, 500), new ItemStack(Items.thorium, 350)); //DRILLS, PRODUCERS new Recipe(production, ProductionBlocks.tungstenDrill, new ItemStack(Items.tungsten, 25)); new Recipe(production, ProductionBlocks.carbideDrill, new ItemStack(Items.tungsten, 50), new ItemStack(Items.carbide, 60)); new Recipe(production, ProductionBlocks.laserdrill, new ItemStack(Items.tungsten, 90), new ItemStack(Items.carbide, 110), new ItemStack(Items.silicon, 70), new ItemStack(Items.titanium, 80)); + new Recipe(production, ProductionBlocks.blastdrill, new ItemStack(Items.tungsten, 140), new ItemStack(Items.carbide, 180), new ItemStack(Items.silicon, 120), new ItemStack(Items.titanium, 130), new ItemStack(Items.thorium, 130)); new Recipe(production, ProductionBlocks.waterextractor, new ItemStack(Items.tungsten, 50), new ItemStack(Items.carbide, 50), new ItemStack(Items.lead, 40)); new Recipe(production, ProductionBlocks.cultivator, new ItemStack(Items.tungsten, 20), new ItemStack(Items.lead, 50), new ItemStack(Items.silicon, 20)); @@ -120,7 +121,6 @@ public class Recipes implements ContentList{ //UNITS //bodies - new Recipe(units, UpgradeBlocks.dartFactory, new ItemStack(Items.lead, 150), new ItemStack(Items.silicon, 200), new ItemStack(Items.titanium, 240)) .setDesktop(); //dart is desktop only, because it's the starter mobile ship @@ -132,11 +132,18 @@ public class Recipes implements ContentList{ //new Recipe(units, UpgradeBlocks.deltaFactory, new ItemStack(Items.tungsten, 30), new ItemStack(Items.lead, 50), new ItemStack(Items.silicon, 30)); //actual unit related stuff - new Recipe(units, UnitBlocks.droneFactory, new ItemStack(Items.tungsten, 50), new ItemStack(Items.lead, 90), new ItemStack(Items.silicon, 130)); - new Recipe(units, UnitBlocks.fabricatorFactory, new ItemStack(Items.carbide, 70), new ItemStack(Items.thorium, 100), new ItemStack(Items.lead, 150), new ItemStack(Items.silicon, 300)); + new Recipe(units, UnitBlocks.dronePad, new ItemStack(Items.tungsten, 50), new ItemStack(Items.lead, 90), new ItemStack(Items.silicon, 130)); + new Recipe(units, UnitBlocks.fabricatorPad, new ItemStack(Items.carbide, 70), new ItemStack(Items.thorium, 60), new ItemStack(Items.lead, 130), new ItemStack(Items.silicon, 200)); + + new Recipe(units, UnitBlocks.daggerPad, new ItemStack(Items.lead, 80), new ItemStack(Items.silicon, 70)); + new Recipe(units, UnitBlocks.titanPad, new ItemStack(Items.thorium, 90), new ItemStack(Items.lead, 140), new ItemStack(Items.silicon, 180)); + + new Recipe(units, UnitBlocks.interceptorPad, new ItemStack(Items.titanium, 40), new ItemStack(Items.lead, 80), new ItemStack(Items.silicon, 90)); + new Recipe(units, UnitBlocks.monsoonPad, new ItemStack(Items.plastanium, 70), new ItemStack(Items.titanium, 100), new ItemStack(Items.lead, 130), new ItemStack(Items.silicon, 220)); new Recipe(units, UnitBlocks.repairPoint, new ItemStack(Items.lead, 30), new ItemStack(Items.tungsten, 30), new ItemStack(Items.silicon, 30)); new Recipe(units, UnitBlocks.resupplyPoint, new ItemStack(Items.lead, 30), new ItemStack(Items.tungsten, 30), new ItemStack(Items.silicon, 30)); + new Recipe(units, UnitBlocks.commandCenter, new ItemStack(Items.lead, 100), new ItemStack(Items.carbide, 140), new ItemStack(Items.silicon, 250)); //LIQUIDS new Recipe(liquid, LiquidBlocks.conduit, new ItemStack(Items.lead, 1)) @@ -144,7 +151,6 @@ public class Recipes implements ContentList{ new Recipe(liquid, LiquidBlocks.pulseConduit, new ItemStack(Items.titanium, 1), new ItemStack(Items.lead, 1)); new Recipe(liquid, LiquidBlocks.phaseConduit, new ItemStack(Items.phasematter, 10), new ItemStack(Items.silicon, 15), new ItemStack(Items.lead, 20), new ItemStack(Items.titanium, 20)); - new Recipe(liquid, LiquidBlocks.liquidRouter, new ItemStack(Items.carbide, 4), new ItemStack(Items.lead, 4)); new Recipe(liquid, LiquidBlocks.liquidtank, new ItemStack(Items.titanium, 50), new ItemStack(Items.lead, 50), new ItemStack(Items.carbide, 20)); new Recipe(liquid, LiquidBlocks.liquidJunction, new ItemStack(Items.carbide, 4), new ItemStack(Items.lead, 4)); @@ -153,6 +159,7 @@ public class Recipes implements ContentList{ new Recipe(liquid, LiquidBlocks.mechanicalPump, new ItemStack(Items.tungsten, 30), new ItemStack(Items.lead, 20)) .setDependencies(CraftingBlocks.smelter); new Recipe(liquid, LiquidBlocks.rotaryPump, new ItemStack(Items.tungsten, 140), new ItemStack(Items.lead, 100), new ItemStack(Items.silicon, 40), new ItemStack(Items.titanium, 70)); + new Recipe(liquid, LiquidBlocks.thermalPump, new ItemStack(Items.tungsten, 160), new ItemStack(Items.lead, 130), new ItemStack(Items.silicon, 60), new ItemStack(Items.titanium, 80), new ItemStack(Items.thorium, 70)); //DEBUG new Recipe(units, DebugBlocks.itemSource, new ItemStack(Items.carbide, 10)).setDebug(); @@ -170,8 +177,6 @@ public class Recipes implements ContentList{ new Recipe(production, ProductionBlocks.oilextractor, new ItemStack(Items.titanium, 40), new ItemStack(Items.surgealloy, 40));*/ - //new Recipe(distribution, DistributionBlocks.massDriver, new ItemStack(Items.carbide, 1)); - /* @@ -258,7 +263,7 @@ public class Recipes implements ContentList{ new Recipe(units, UnitBlocks.dropPoint, new ItemStack(Items.carbide, 10)); new Recipe(units, UnitBlocks.resupplyPoint, new ItemStack(Items.carbide, 10)); - new Recipe(units, UnitBlocks.droneFactory, new ItemStack(Items.tungsten, 50)); + new Recipe(units, UnitBlocks.dronePad, new ItemStack(Items.tungsten, 50)); new Recipe(units, UnitBlocks.reconstructor, new ItemStack(Items.tungsten, 1)); new Recipe(units, UnitBlocks.overdriveProjector, new ItemStack(Items.tungsten, 1)); diff --git a/core/src/io/anuke/mindustry/content/UnitTypes.java b/core/src/io/anuke/mindustry/content/UnitTypes.java index e17da55df6..c53c66468c 100644 --- a/core/src/io/anuke/mindustry/content/UnitTypes.java +++ b/core/src/io/anuke/mindustry/content/UnitTypes.java @@ -1,13 +1,14 @@ package io.anuke.mindustry.content; import com.badlogic.gdx.utils.Array; +import com.badlogic.gdx.utils.ObjectSet; import io.anuke.mindustry.entities.units.UnitType; import io.anuke.mindustry.entities.units.types.*; import io.anuke.mindustry.game.Content; import io.anuke.mindustry.type.ContentList; public class UnitTypes implements ContentList{ - public static UnitType drone, scout, vtol, monsoon, titan, fabricator; + public static UnitType drone, dagger, interceptor, monsoon, titan, fabricator; @Override public void load(){ @@ -22,7 +23,7 @@ public class UnitTypes implements ContentList{ health = 45; }}; - scout = new UnitType("scout", Scout.class, Scout::new){{ + dagger = new UnitType("dagger", Dagger.class, Dagger::new){{ maxVelocity = 1.1f; speed = 0.2f; drag = 0.4f; @@ -40,7 +41,7 @@ public class UnitTypes implements ContentList{ health = 260; }}; - vtol = new UnitType("vtol", Vtol.class, Vtol::new){{ + interceptor = new UnitType("interceptor", Interceptor.class, Interceptor::new){{ speed = 0.3f; maxVelocity = 1.9f; drag = 0.01f; @@ -54,13 +55,14 @@ public class UnitTypes implements ContentList{ drag = 0.01f; isFlying = true; weapon = Weapons.bomber; + ammoCapacity = 50; }}; fabricator = new UnitType("fabricator", Fabricator.class, Fabricator::new){{ isFlying = true; drag = 0.01f; speed = 0.2f; - maxVelocity = 0.6f; + maxVelocity = 0.9f; ammoCapacity = 0; range = 70f; itemCapacity = 70; @@ -69,6 +71,7 @@ public class UnitTypes implements ContentList{ buildPower = 0.9f; minePower = 1.1f; healSpeed = 0.09f; + toMine = ObjectSet.with(Items.lead, Items.tungsten, Items.titanium); }}; } diff --git a/core/src/io/anuke/mindustry/content/Weapons.java b/core/src/io/anuke/mindustry/content/Weapons.java index 5ccc7456fc..77cf2c3b48 100644 --- a/core/src/io/anuke/mindustry/content/Weapons.java +++ b/core/src/io/anuke/mindustry/content/Weapons.java @@ -46,7 +46,7 @@ public class Weapons implements ContentList{ reload = 50f; roundrobin = true; shots = 6; - inaccuracy = 15f; + inaccuracy = 10f; recoil = 2f; velocityRnd = 0.7f; ejectEffect = ShootFx.shellEjectSmall; @@ -93,7 +93,7 @@ public class Weapons implements ContentList{ bomber = new Weapon("bomber"){{ length = 0f; width = 2f; - reload = 5f; + reload = 7f; roundrobin = true; ejectEffect = Fx.none; velocityRnd = 1f; diff --git a/core/src/io/anuke/mindustry/content/blocks/Blocks.java b/core/src/io/anuke/mindustry/content/blocks/Blocks.java index 4e4bfb9d05..1e5a793f91 100644 --- a/core/src/io/anuke/mindustry/content/blocks/Blocks.java +++ b/core/src/io/anuke/mindustry/content/blocks/Blocks.java @@ -12,7 +12,7 @@ import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.*; public class Blocks extends BlockList implements ContentList{ - public static Block air, spawn, blockpart, space, metalfloor, deepwater, water, lava, oil, stone, blackstone, dirt, sand, ice, snow, grass, shrub, rock, icerock, blackrock; + public static Block air, blockpart, space, metalfloor, deepwater, water, lava, oil, stone, blackstone, dirt, sand, ice, snow, grass, shrub, rock, icerock, blackrock; @Override @@ -20,6 +20,7 @@ public class Blocks extends BlockList implements ContentList{ air = new Floor("air"){ { blend = false; + alwaysReplace = true; } //don't draw diff --git a/core/src/io/anuke/mindustry/content/blocks/DebugBlocks.java b/core/src/io/anuke/mindustry/content/blocks/DebugBlocks.java index b23a545823..4a47ff9e07 100644 --- a/core/src/io/anuke/mindustry/content/blocks/DebugBlocks.java +++ b/core/src/io/anuke/mindustry/content/blocks/DebugBlocks.java @@ -6,8 +6,7 @@ import io.anuke.annotations.Annotations.Remote; import io.anuke.mindustry.content.Liquids; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.gen.CallBlocks; -import io.anuke.mindustry.net.In; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.type.ContentList; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Liquid; @@ -28,7 +27,7 @@ import java.io.IOException; public class DebugBlocks extends BlockList implements ContentList{ public static Block powerVoid, powerInfinite, itemSource, liquidSource, itemVoid; - @Remote(targets = Loc.both, called = Loc.both, in = In.blocks, forward = true) + @Remote(targets = Loc.both, called = Loc.both, forward = true) public static void setLiquidSourceLiquid(Player player, Tile tile, Liquid liquid){ LiquidSourceEntity entity = tile.entity(); entity.source = liquid; @@ -114,7 +113,7 @@ public class DebugBlocks extends BlockList implements ContentList{ if(i == 0) continue; final int f = i; ImageButton button = cont.addImageButton("white", "toggle", 24, () -> { - CallBlocks.setLiquidSourceLiquid(null, tile, items.get(f)); + Call.setLiquidSourceLiquid(null, tile, items.get(f)); }).size(38, 42).padBottom(-5.1f).group(group).get(); button.getStyle().imageUpColor = items.get(i).color; button.setChecked(entity.source.id == f); diff --git a/core/src/io/anuke/mindustry/content/blocks/DistributionBlocks.java b/core/src/io/anuke/mindustry/content/blocks/DistributionBlocks.java index a0adfe48b5..f55abaccc3 100644 --- a/core/src/io/anuke/mindustry/content/blocks/DistributionBlocks.java +++ b/core/src/io/anuke/mindustry/content/blocks/DistributionBlocks.java @@ -50,7 +50,7 @@ public class DistributionBlocks extends BlockList implements ContentList{ massDriver = new MassDriver("mass-driver"){{ size = 3; itemCapacity = 80; - range = 300f; + range = 340f; }}; } } diff --git a/core/src/io/anuke/mindustry/content/blocks/LiquidBlocks.java b/core/src/io/anuke/mindustry/content/blocks/LiquidBlocks.java index e824005518..e5e5d97480 100644 --- a/core/src/io/anuke/mindustry/content/blocks/LiquidBlocks.java +++ b/core/src/io/anuke/mindustry/content/blocks/LiquidBlocks.java @@ -22,15 +22,19 @@ public class LiquidBlocks extends BlockList implements ContentList{ pumpAmount = 0.25f; consumes.power(0.015f); liquidCapacity = 30f; + powerCapacity = 20f; hasPower = true; size = 2; tier = 1; }}; thermalPump = new Pump("thermal-pump"){{ - pumpAmount = 0.3f; - consumes.power(0.05f); + shadow = "shadow-rounded-2"; + pumpAmount = 0.55f; + consumes.power(0.03f); liquidCapacity = 40f; + hasPower = true; + powerCapacity = 20f; size = 2; tier = 2; }}; diff --git a/core/src/io/anuke/mindustry/content/blocks/PowerBlocks.java b/core/src/io/anuke/mindustry/content/blocks/PowerBlocks.java index df8ead1a55..5acbcb02fa 100644 --- a/core/src/io/anuke/mindustry/content/blocks/PowerBlocks.java +++ b/core/src/io/anuke/mindustry/content/blocks/PowerBlocks.java @@ -21,9 +21,8 @@ public class PowerBlocks extends BlockList implements ContentList{ thermalGenerator = new LiquidHeatGenerator("thermal-generator"){{ maxLiquidGenerate = 0.5f; - powerPerLiquid = 0.08f; powerCapacity = 40f; - powerPerLiquid = 0.25f; + powerPerLiquid = 0.55f; generateEffect = BlockFx.redgeneratespark; size = 2; }}; @@ -74,12 +73,13 @@ public class PowerBlocks extends BlockList implements ContentList{ powerNode = new PowerNode("power-node"){{ shadow = "shadow-round-1"; + maxNodes = 4; }}; powerNodeLarge = new PowerNode("power-node-large"){{ size = 2; powerSpeed = 1f; - maxNodes = 5; + maxNodes = 6; laserRange = 7.5f; shadow = "shadow-round-2"; }}; diff --git a/core/src/io/anuke/mindustry/content/blocks/UnitBlocks.java b/core/src/io/anuke/mindustry/content/blocks/UnitBlocks.java index dc98341364..46e099cba7 100644 --- a/core/src/io/anuke/mindustry/content/blocks/UnitBlocks.java +++ b/core/src/io/anuke/mindustry/content/blocks/UnitBlocks.java @@ -8,11 +8,13 @@ import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.blocks.units.*; public class UnitBlocks extends BlockList implements ContentList{ - public static Block resupplyPoint, repairPoint, droneFactory, fabricatorFactory, dropPoint, reconstructor, overdriveProjector, shieldProjector; + public static Block resupplyPoint, repairPoint, dronePad, + fabricatorPad, interceptorPad, monsoonPad, daggerPad, titanPad, + dropPoint, reconstructor, overdriveProjector, shieldProjector, commandCenter; @Override public void load(){ - droneFactory = new UnitFactory("drone-factory"){{ + dronePad = new UnitPad("drone-pad"){{ type = UnitTypes.drone; produceTime = 800; size = 2; @@ -20,14 +22,48 @@ public class UnitBlocks extends BlockList implements ContentList{ consumes.items(new ItemStack[]{new ItemStack(Items.silicon, 30), new ItemStack(Items.lead, 30)}); }}; - fabricatorFactory = new UnitFactory("fabricator-factory"){{ + fabricatorPad = new UnitPad("fabricator-pad"){{ type = UnitTypes.fabricator; - produceTime = 1600; + produceTime = 1400; size = 2; consumes.power(0.2f); consumes.items(new ItemStack[]{new ItemStack(Items.silicon, 70), new ItemStack(Items.lead, 80), new ItemStack(Items.titanium, 80)}); }}; + interceptorPad = new UnitPad("interceptor-pad"){{ + type = UnitTypes.interceptor; + produceTime = 900; + size = 2; + consumes.power(0.08f); + consumes.items(new ItemStack[]{new ItemStack(Items.silicon, 20), new ItemStack(Items.titanium, 10)}); + }}; + + monsoonPad = new UnitPad("monsoon-pad"){{ + type = UnitTypes.monsoon; + produceTime = 1500; + size = 3; + consumes.power(0.14f); + shadow = "shadow-round-3"; + consumes.items(new ItemStack[]{new ItemStack(Items.silicon, 30), new ItemStack(Items.titanium, 30), new ItemStack(Items.plastanium, 20)}); + }}; + + daggerPad = new UnitPad("dagger-pad"){{ + type = UnitTypes.dagger; + produceTime = 500; + size = 2; + consumes.power(0.06f); + consumes.items(new ItemStack[]{new ItemStack(Items.silicon, 10), new ItemStack(Items.tungsten, 20)}); + }}; + + titanPad = new UnitPad("titan-pad"){{ + type = UnitTypes.titan; + produceTime = 1300; + size = 3; + consumes.power(0.15f); + shadow = "shadow-round-3"; + consumes.items(new ItemStack[]{new ItemStack(Items.silicon, 20), new ItemStack(Items.tungsten, 30), new ItemStack(Items.thorium, 30)}); + }}; + resupplyPoint = new ResupplyPoint("resupply-point"){{ shadow = "shadow-round-1"; itemCapacity = 30; @@ -51,7 +87,11 @@ public class UnitBlocks extends BlockList implements ContentList{ size = 2; }}; - shieldProjector = new ShieldProjector("shieldprojector"){{ + shieldProjector = new ShieldProjector("shield-projector"){{ + size = 2; + }}; + + commandCenter = new CommandCenter("command-center"){{ size = 2; }}; } diff --git a/core/src/io/anuke/mindustry/content/bullets/TurretBullets.java b/core/src/io/anuke/mindustry/content/bullets/TurretBullets.java index 177acacb35..d0090d44a4 100644 --- a/core/src/io/anuke/mindustry/content/bullets/TurretBullets.java +++ b/core/src/io/anuke/mindustry/content/bullets/TurretBullets.java @@ -76,12 +76,12 @@ public class TurretBullets extends BulletList implements ContentList{ } }; - basicFlame = new BulletType(2f, 5){ + basicFlame = new BulletType(2.3f, 5){ { hitsize = 7f; - lifetime = 30f; + lifetime = 35f; pierce = true; - drag = 0.07f; + drag = 0.05f; hiteffect = BulletFx.hitFlameSmall; despawneffect = Fx.none; status = StatusEffects.burning; @@ -179,7 +179,7 @@ public class TurretBullets extends BulletList implements ContentList{ } }; - driverBolt = new BulletType(5f, 20){ + driverBolt = new BulletType(5f, 50){ { collidesTiles = false; lifetime = 200f; @@ -190,11 +190,14 @@ public class TurretBullets extends BulletList implements ContentList{ @Override public void draw(Bullet b){ - Draw.color(Color.LIGHT_GRAY); - Fill.square(b.x, b.y, 3f, b.angle()); + float w = 11f, h = 13f; + + Draw.color(Palette.bulletYellowBack); + Draw.rect("shell-back", b.x, b.y, w, h, b.angle() + 90); + + Draw.color(Palette.bulletYellow); + Draw.rect("shell", b.x, b.y, w, h, b.angle() + 90); - Draw.color(Palette.lighterOrange); - Fill.square(b.x, b.y, 2f, b.angle()); Draw.reset(); } diff --git a/core/src/io/anuke/mindustry/content/bullets/WeaponBullets.java b/core/src/io/anuke/mindustry/content/bullets/WeaponBullets.java index 04997b8c68..514b6e5a12 100644 --- a/core/src/io/anuke/mindustry/content/bullets/WeaponBullets.java +++ b/core/src/io/anuke/mindustry/content/bullets/WeaponBullets.java @@ -25,13 +25,13 @@ public class WeaponBullets extends BulletList{ { bulletWidth = 8f; bulletHeight = 9f; - bulletShrink = 0.6f; - lifetime = 30f; + bulletShrink = 0.5f; + lifetime = 50f; drag = 0.04f; } }; - bombExplosive = new BombBulletType(20f, 20f, "shell"){ + bombExplosive = new BombBulletType(10f, 20f, "shell"){ { bulletWidth = 9f; bulletHeight = 13f; @@ -39,7 +39,7 @@ public class WeaponBullets extends BulletList{ } }; - bombIncendiary = new BombBulletType(15f, 10f, "shell"){ + bombIncendiary = new BombBulletType(7f, 10f, "shell"){ { bulletWidth = 8f; bulletHeight = 12f; @@ -63,7 +63,7 @@ public class WeaponBullets extends BulletList{ } }; - bombOil = new BombBulletType(3f, 3f, "shell"){ + bombOil = new BombBulletType(2f, 3f, "shell"){ { bulletWidth = 8f; bulletHeight = 12f; diff --git a/core/src/io/anuke/mindustry/content/fx/BlockFx.java b/core/src/io/anuke/mindustry/content/fx/BlockFx.java index 9260c76b0f..626e40520a 100644 --- a/core/src/io/anuke/mindustry/content/fx/BlockFx.java +++ b/core/src/io/anuke/mindustry/content/fx/BlockFx.java @@ -16,7 +16,10 @@ import io.anuke.ucore.util.Tmp; import static io.anuke.mindustry.Vars.tilesize; public class BlockFx extends FxList implements ContentList{ - public static Effect reactorsmoke, nuclearsmoke, nuclearcloud, redgeneratespark, generatespark, fuelburn, plasticburn, pulverize, pulverizeRed, pulverizeRedder, pulverizeSmall, pulverizeMedium, producesmoke, smeltsmoke, formsmoke, blastsmoke, lava, dooropen, doorclose, dooropenlarge, doorcloselarge, purify, purifyoil, purifystone, generate, mine, mineBig, mineHuge, smelt, teleportActivate, teleport, teleportOut, ripple, bubble; + public static Effect reactorsmoke, nuclearsmoke, nuclearcloud, redgeneratespark, generatespark, fuelburn, plasticburn, + pulverize, pulverizeRed, pulverizeRedder, pulverizeSmall, pulverizeMedium, producesmoke, smeltsmoke, formsmoke, blastsmoke, + lava, dooropen, doorclose, dooropenlarge, doorcloselarge, purify, purifyoil, purifystone, generate, mine, mineBig, mineHuge, + smelt, teleportActivate, teleport, teleportOut, ripple, bubble, commandSend; @Override public void load(){ @@ -274,5 +277,12 @@ public class BlockFx extends FxList implements ContentList{ }); Draw.reset(); }); + + commandSend = new Effect(28, e -> { + Draw.color(Palette.command); + Lines.stroke(e.fout() * 2f); + Lines.poly(e.x, e.y, 40, 4f + e.finpow() * 120f); + Draw.color(); + }); } } diff --git a/core/src/io/anuke/mindustry/content/fx/ShootFx.java b/core/src/io/anuke/mindustry/content/fx/ShootFx.java index 2e55246cc8..3ad4de8e71 100644 --- a/core/src/io/anuke/mindustry/content/fx/ShootFx.java +++ b/core/src/io/anuke/mindustry/content/fx/ShootFx.java @@ -75,7 +75,7 @@ public class ShootFx extends FxList implements ContentList{ shootSmallFlame = new Effect(30f, e -> { Draw.color(Palette.lightFlame, Palette.darkFlame, Color.GRAY, e.fin()); - Angles.randLenVectors(e.id, 8, e.finpow() * 26f, e.rotation, 10f, (x, y) -> { + Angles.randLenVectors(e.id, 8, e.finpow() * 36f, e.rotation, 10f, (x, y) -> { Fill.circle(e.x + x, e.y + y, 0.65f + e.fout() * 1.5f); }); diff --git a/core/src/io/anuke/mindustry/core/ContentLoader.java b/core/src/io/anuke/mindustry/core/ContentLoader.java index db6a5ed7a2..ba117646e5 100644 --- a/core/src/io/anuke/mindustry/core/ContentLoader.java +++ b/core/src/io/anuke/mindustry/core/ContentLoader.java @@ -35,65 +35,65 @@ public class ContentLoader{ private static OrderedMap> contentMap = new OrderedMap<>(); private static ObjectSet> initialization = new ObjectSet<>(); private static ContentList[] content = { - //effects - new BlockFx(), - new BulletFx(), - new EnvironmentFx(), - new ExplosionFx(), - new Fx(), - new ShootFx(), - new UnitFx(), + //effects + new BlockFx(), + new BulletFx(), + new EnvironmentFx(), + new ExplosionFx(), + new Fx(), + new ShootFx(), + new UnitFx(), - //items - new Items(), + //items + new Items(), - //status effects - new StatusEffects(), + //status effects + new StatusEffects(), - //liquids - new Liquids(), + //liquids + new Liquids(), - //bullets - new ArtilleryBullets(), - new FlakBullets(), - new MissileBullets(), - new StandardBullets(), - new TurretBullets(), - new WeaponBullets(), + //bullets + new ArtilleryBullets(), + new FlakBullets(), + new MissileBullets(), + new StandardBullets(), + new TurretBullets(), + new WeaponBullets(), - //ammotypes - new AmmoTypes(), + //ammotypes + new AmmoTypes(), - //weapons - new Weapons(), + //weapons + new Weapons(), - //mechs - new Mechs(), + //mechs + new Mechs(), - //units - new UnitTypes(), + //units + new UnitTypes(), - //blocks - new Blocks(), - new DefenseBlocks(), - new DistributionBlocks(), - new ProductionBlocks(), - new TurretBlocks(), - new DebugBlocks(), - new LiquidBlocks(), - new StorageBlocks(), - new UnitBlocks(), - new PowerBlocks(), - new CraftingBlocks(), - new UpgradeBlocks(), - new OreBlocks(), + //blocks + new Blocks(), + new DefenseBlocks(), + new DistributionBlocks(), + new ProductionBlocks(), + new TurretBlocks(), + new DebugBlocks(), + new LiquidBlocks(), + new StorageBlocks(), + new UnitBlocks(), + new PowerBlocks(), + new CraftingBlocks(), + new UpgradeBlocks(), + new OreBlocks(), - //not really a content class, but this makes initialization easier - new ColorMapper(), + //not really a content class, but this makes initialization easier + new ColorMapper(), - //recipes - new Recipes(), + //recipes + new Recipes(), }; /** diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index 0a07a4c477..6111ed6fc4 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -13,6 +13,7 @@ import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.game.Content; import io.anuke.mindustry.game.ContentDatabase; import io.anuke.mindustry.game.EventType.*; +import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.game.Saves; import io.anuke.mindustry.input.DefaultKeybinds; import io.anuke.mindustry.input.DesktopInput; @@ -48,7 +49,6 @@ public class Control extends Module{ private ObjectMap soundMap = new ObjectMap<>(); private Throwable error; - //private Input gdxInput; public Control(){ @@ -68,8 +68,6 @@ public class Control extends Module{ db.load(); - //gdxInput = Gdx.input; - Sounds.setFalloff(9000f); Sounds.setPlayer((sound, volume) -> { long time = TimeUtils.millis(); @@ -84,14 +82,14 @@ public class Control extends Module{ DefaultKeybinds.load(); Settings.defaultList( - "ip", "localhost", - "port", port + "", - "color-0", Color.rgba8888(playerColors[8]), - "color-1", Color.rgba8888(playerColors[11]), - "color-2", Color.rgba8888(playerColors[13]), - "color-3", Color.rgba8888(playerColors[9]), - "name", "player", - "lastBuild", 0 + "ip", "localhost", + "port", port + "", + "color-0", Color.rgba8888(playerColors[8]), + "color-1", Color.rgba8888(playerColors[11]), + "color-2", Color.rgba8888(playerColors[13]), + "color-3", Color.rgba8888(playerColors[9]), + "name", "player", + "lastBuild", 0 ); KeyBinds.load(); @@ -112,6 +110,12 @@ public class Control extends Module{ } state.set(State.playing); + + if(state.mode == GameMode.sandbox && !Settings.getBool("sandbox-warning", false)){ + threads.runGraphics(() -> ui.showInfo("$mode.sandbox.warning")); + Settings.putBool("sandbox-warning", true); + Settings.save(); + } }); Events.on(WorldLoadGraphicsEvent.class, () -> { @@ -144,12 +148,16 @@ public class Control extends Module{ }); Events.on(GameOverEvent.class, () -> { - Effects.shake(5, 6, Core.camera.position.x, Core.camera.position.y); + //delete saves for game-over sectors + if(world.getSector() != null && world.getSector().hasSave()){ + world.getSector().getSave().delete(); + } - //TODO game over effect - ui.restart.show(); - - Timers.runTask(30f, () -> state.set(State.menu)); + threads.runGraphics(() -> { + Effects.shake(5, 6, Core.camera.position.x, Core.camera.position.y); + ui.restart.show(); + state.set(State.menu); + }); }); Events.on(WorldLoadEvent.class, () -> threads.runGraphics(() -> Events.fire(WorldLoadGraphicsEvent.class))); @@ -362,11 +370,16 @@ public class Control extends Module{ } //check unlocked sectors - if(world.getSector() != null && world.getSector().goal.isComplete() && !world.getSector().complete){ - world.sectors().completeSector(world.getSector().x, world.getSector().y); - world.sectors().save(); - if(!headless){ - ui.showInfoFade("$text.sector.unlocked"); + if(world.getSector() != null && !world.getSector().complete){ + //all assigned missions are complete + if(world.getSector().completedMissions >= world.getSector().missions.size){ + + world.sectors().completeSector(world.getSector().x, world.getSector().y); + world.sectors().save(); + ui.missions.show(world.getSector()); + }else if(world.getSector().currentMission().isComplete()){ + //increment completed missions, check next index next frame + world.getSector().completedMissions ++; } } @@ -374,7 +387,7 @@ public class Control extends Module{ if(!state.mode.infiniteResources && Timers.get("timerCheckUnlock", 120)){ checkUnlockableBlocks(); - //save if the db changed, but don't save unlocks + //save if the db changed, but don't save in debug if(db.isDirty() && !debug){ db.save(); } diff --git a/core/src/io/anuke/mindustry/core/Logic.java b/core/src/io/anuke/mindustry/core/Logic.java index a29cb316bf..89eeb2d4a0 100644 --- a/core/src/io/anuke/mindustry/core/Logic.java +++ b/core/src/io/anuke/mindustry/core/Logic.java @@ -49,9 +49,7 @@ public class Logic extends Module{ state.set(State.playing); state.wavetime = wavespace * state.difficulty.timeScaling * 2; - //fill inventory with items for debugging - - for(TeamData team : state.teams.getTeams()){ + for(TeamData team : state.teams.getTeams(true)){ for(Tile tile : team.cores){ if(debug){ for(Item item : Item.all()){ @@ -59,13 +57,20 @@ public class Logic extends Module{ tile.entity.items.set(item, 1000); } } - }else{ + }else if(!state.mode.infiniteResources){ tile.entity.items.add(Items.tungsten, 50); tile.entity.items.add(Items.lead, 20); } } } + for(TeamData team : state.teams.getTeams(false)){ + for(Tile tile : team.cores){ + tile.entity.items.add(Items.tungsten, 2000); + tile.entity.items.add(Items.blastCompound, 2000); + } + } + Events.fire(PlayEvent.class); } @@ -131,11 +136,11 @@ public class Logic extends Module{ if(!state.is(State.paused) || Net.active()){ - if(!state.mode.disableWaveTimer){ + if(!state.mode.disableWaveTimer && !state.mode.disableWaves){ state.wavetime -= Timers.delta(); } - if(!Net.client() && state.wavetime <= 0){ + if(!Net.client() && state.wavetime <= 0 && !state.mode.disableWaves){ runWave(); } diff --git a/core/src/io/anuke/mindustry/core/NetServer.java b/core/src/io/anuke/mindustry/core/NetServer.java index ee4a833465..e318a013fc 100644 --- a/core/src/io/anuke/mindustry/core/NetServer.java +++ b/core/src/io/anuke/mindustry/core/NetServer.java @@ -12,9 +12,9 @@ import io.anuke.mindustry.content.Mechs; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.traits.SyncTrait; +import io.anuke.mindustry.game.Version; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.gen.RemoteReadServer; -import io.anuke.mindustry.game.Version; import io.anuke.mindustry.net.*; import io.anuke.mindustry.net.Administration.PlayerInfo; import io.anuke.mindustry.net.Packets.*; @@ -80,12 +80,22 @@ public class NetServer extends Module{ Net.handleServer(ConnectPacket.class, (id, packet) -> { String uuid = packet.uuid; - if(Net.getConnection(id) == null || - admins.isIPBanned(Net.getConnection(id).address)) return; + NetConnection connection = Net.getConnection(id); + + if(connection == null || + admins.isIPBanned(connection.address)) return; + + if(connection.hasBegunConnecting){ + kick(id, KickReason.idInUse); + return; + } + + connection.hasBegunConnecting = true; TraceInfo trace = admins.getTraceByID(uuid); PlayerInfo info = admins.getInfo(uuid); trace.uuid = uuid; + trace.ip = connection.address; trace.android = packet.mobile; if(admins.isIDBanned(uuid)){ @@ -112,7 +122,7 @@ public class NetServer extends Module{ return; } - if(player.uuid.equals(packet.uuid)){ + if(player.uuid.equals(packet.uuid) || player.usid.equals(packet.usid)){ kick(id, KickReason.idInUse); return; } @@ -175,16 +185,14 @@ public class NetServer extends Module{ NetConnection connection = Net.getConnection(id); if(player == null || connection == null || packet.snapid < connection.lastRecievedClientSnapshot) return; - boolean verifyPosition = !player.isDead() && !debug && headless && !player.mech.flying && player.getCarrier() == null; + boolean verifyPosition = !player.isDead() && !debug && headless && player.getCarrier() == null; if(connection.lastRecievedClientTime == 0) connection.lastRecievedClientTime = TimeUtils.millis() - 16; long elapsed = TimeUtils.timeSinceMillis(connection.lastRecievedClientTime); - float maxSpeed = (packet.boosting && !player.mech.flying ? player.mech.boostSpeed : player.mech.speed) * 2.5f; - - //extra 1.1x multiplicaton is added just in case - float maxMove = elapsed / 1000f * 60f * maxSpeed * 1.1f; + float maxSpeed = packet.boosting && !player.mech.flying ? player.mech.boostSpeed : player.mech.speed; + float maxMove = elapsed / 1000f * 60f * Math.min(compound(maxSpeed, player.mech.drag) * 1.2f, player.mech.maxSpeed * 1.05f); player.pointerX = packet.pointerX; player.pointerY = packet.pointerY; @@ -197,12 +205,16 @@ public class NetServer extends Module{ } vector.set(packet.x - player.getInterpolator().target.x, packet.y - player.getInterpolator().target.y); - vector.limit(maxMove); float prevx = player.x, prevy = player.y; player.set(player.getInterpolator().target.x, player.getInterpolator().target.y); - player.move(vector.x, vector.y); + if(!player.mech.flying){ + player.move(vector.x, vector.y); + }else{ + player.x += vector.x; + player.y += vector.y; + } float newx = player.x, newy = player.y; if(!verifyPosition){ @@ -213,6 +225,7 @@ public class NetServer extends Module{ }else if(Vector2.dst(packet.x, packet.y, newx, newy) > correctDist){ Call.onPositionSet(id, newx, newy); //teleport and correct position when necessary } + //reset player to previous synced position so it gets interpolated player.x = prevx; player.y = prevy; @@ -238,9 +251,16 @@ public class NetServer extends Module{ }); } - /** - * Sends a raw byte[] snapshot to a client, splitting up into chunks when needed. - */ + private float compound(float speed, float drag){ + float total = 0f; + for(int i = 0; i < 20; i++){ + total *= (1f - drag); + total += speed; + } + return total; + } + + /** Sends a raw byte[] snapshot to a client, splitting up into chunks when needed.*/ private static void sendSplitSnapshot(int userid, byte[] bytes, int snapshotID, int base){ if(bytes.length < maxSnapshotSize){ Call.onSnapshot(userid, bytes, snapshotID, (short) 0, bytes.length, base); @@ -314,6 +334,8 @@ public class NetServer extends Module{ @Remote(targets = Loc.client) public static void connectConfirm(Player player){ + if(player.con == null || player.con.hasConnected) return; + player.add(); player.con.hasConnected = true; Call.sendMessage("[accent]" + player.name + " [accent]has connected."); @@ -352,8 +374,8 @@ public class NetServer extends Module{ Player player = connections.get(con.id); - if(player != null && (reason == KickReason.kick || reason == KickReason.banned) && admins.getTraceByID(getUUID(con.id)).uuid != null){ - PlayerInfo info = admins.getInfo(admins.getTraceByID(getUUID(con.id)).uuid); + if(player != null && (reason == KickReason.kick || reason == KickReason.banned) && player.uuid != null){ + PlayerInfo info = admins.getInfo(player.uuid); info.timesKicked++; info.lastKicked = TimeUtils.millis(); } diff --git a/core/src/io/anuke/mindustry/core/Platform.java b/core/src/io/anuke/mindustry/core/Platform.java index 95fe6316f8..94a1bf9008 100644 --- a/core/src/io/anuke/mindustry/core/Platform.java +++ b/core/src/io/anuke/mindustry/core/Platform.java @@ -43,10 +43,6 @@ public abstract class Platform { public String getLocaleName(Locale locale){ return locale.toString(); } - /**Whether joining games is supported.*/ - public boolean canJoinGame(){ - return true; - } /**Whether debug mode is enabled.*/ public boolean isDebug(){return false;} /**Must be a base64 string 8 bytes in length.*/ diff --git a/core/src/io/anuke/mindustry/core/Renderer.java b/core/src/io/anuke/mindustry/core/Renderer.java index 18278c0dc7..0a7b92b93f 100644 --- a/core/src/io/anuke/mindustry/core/Renderer.java +++ b/core/src/io/anuke/mindustry/core/Renderer.java @@ -66,7 +66,6 @@ public class Renderer extends RendererModule{ public Renderer(){ Core.batch = new SpriteBatch(4096); - pixelate = true; Lines.setCircleVertices(14); Shaders.init(); @@ -215,7 +214,24 @@ public class Renderer extends RendererModule{ blocks.processBlocks(); blocks.drawShadows(); - blocks.drawBlocks(Layer.block); + for(Team team : Team.all){ + if(blocks.isTeamShown(team)){ + boolean outline = team != players[0].getTeam() && team != Team.none; + + if(outline){ + Shaders.outline.color.set(team.color); + Shaders.outline.color.a = 0.8f; + Graphics.beginShaders(Shaders.outline); + } + + blocks.drawTeamBlocks(Layer.block, team); + + if(outline){ + Graphics.endShaders(); + } + } + } + blocks.skipLayer(Layer.block); Graphics.shader(Shaders.blockbuild, false); blocks.drawBlocks(Layer.placement); diff --git a/core/src/io/anuke/mindustry/core/ThreadHandler.java b/core/src/io/anuke/mindustry/core/ThreadHandler.java index 22bc5ff2fe..a08c2a6185 100644 --- a/core/src/io/anuke/mindustry/core/ThreadHandler.java +++ b/core/src/io/anuke/mindustry/core/ThreadHandler.java @@ -3,6 +3,7 @@ package io.anuke.mindustry.core; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.utils.Queue; import com.badlogic.gdx.utils.TimeUtils; +import io.anuke.ucore.core.Settings; import io.anuke.ucore.core.Timers; import io.anuke.ucore.util.Log; @@ -19,6 +20,7 @@ public class ThreadHandler{ private float framesSinceUpdate; private boolean enabled; private boolean rendered = true; + private long lastFrameTime; public ThreadHandler(ThreadProvider impl){ this.impl = impl; @@ -69,7 +71,24 @@ public class ThreadHandler{ return framesSinceUpdate; } - public void handleRender(){ + public void handleBeginRender(){ + lastFrameTime = TimeUtils.millis(); + } + + public void handleEndRender(){ + int fpsCap = Settings.getInt("fpscap", 125); + + if(fpsCap <= 120){ + long target = 1000/fpsCap; + long elapsed = TimeUtils.timeSinceMillis(lastFrameTime); + if(elapsed < target){ + try{ + impl.sleep(target - elapsed); + }catch(InterruptedException e){ + e.printStackTrace(); + } + } + } if(!enabled) return; diff --git a/core/src/io/anuke/mindustry/core/UI.java b/core/src/io/anuke/mindustry/core/UI.java index fc6d38fd0e..13c7870f0b 100644 --- a/core/src/io/anuke/mindustry/core/UI.java +++ b/core/src/io/anuke/mindustry/core/UI.java @@ -43,7 +43,7 @@ public class UI extends SceneModule{ public AboutDialog about; public RestartDialog restart; - public LevelDialog levels; + public CustomGameDialog levels; public MapsDialog maps; public LoadDialog load; public DiscordDialog discord; @@ -62,26 +62,27 @@ public class UI extends SceneModule{ public UnlocksDialog unlocks; public ContentInfoDialog content; public SectorsDialog sectors; + public MissionDialog missions; private Locale lastLocale; public UI(){ Dialog.setShowAction(() -> sequence( - alpha(0f), - originCenter(), - moveToAligned(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2, Align.center), - scaleTo(0.0f, 1f), - parallel( - scaleTo(1f, 1f, 0.1f, Interpolation.fade), - fadeIn(0.1f, Interpolation.fade) - ) + alpha(0f), + originCenter(), + moveToAligned(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2, 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; @@ -154,7 +155,7 @@ public class UI extends SceneModule{ join = new JoinDialog(); discord = new DiscordDialog(); load = new LoadDialog(); - levels = new LevelDialog(); + levels = new CustomGameDialog(); language = new LanguageDialog(); settings = new SettingsMenuDialog(); host = new HostDialog(); @@ -169,6 +170,7 @@ public class UI extends SceneModule{ unlocks = new UnlocksDialog(); content = new ContentInfoDialog(); sectors = new SectorsDialog(); + missions = new MissionDialog(); Group group = Core.scene.getRoot(); @@ -179,6 +181,7 @@ public class UI extends SceneModule{ listfrag.build(group); debugfrag.build(group); loadfrag.build(group); + } @Override diff --git a/core/src/io/anuke/mindustry/core/World.java b/core/src/io/anuke/mindustry/core/World.java index 30c211761c..d436f01771 100644 --- a/core/src/io/anuke/mindustry/core/World.java +++ b/core/src/io/anuke/mindustry/core/World.java @@ -219,6 +219,7 @@ public class World extends Module{ /**Loads up a sector map. This does not call play(), but calls reset().*/ public void loadSector(Sector sector){ currentSector = sector; + state.mode = sector.missions.peek().getMode(); Timers.mark(); Timers.mark(); @@ -230,16 +231,13 @@ public class World extends Module{ Tile[][] tiles = createTiles(width, height); - Map map = new Map("Sector [" + sector.x + ", " + sector.y + "]", new MapMeta(0, new ObjectMap<>(), width, height, null), true, () -> null); + Map map = new Map("Sector " + sector.x + ", " + sector.y, new MapMeta(0, new ObjectMap<>(), width, height, null), true, () -> null); setMap(map); EntityPhysics.resizeTree(0, 0, width * tilesize, height * tilesize); Timers.mark(); - generator.generateMap(tiles, sector.x, sector.y); - Log.info("Time to generate base map: {0}", Timers.elapsed()); - - Log.info("Time to generate fully without additional events: {0}", Timers.elapsed()); + generator.generateMap(tiles, sector); endMapLoad(); diff --git a/core/src/io/anuke/mindustry/editor/MapEditor.java b/core/src/io/anuke/mindustry/editor/MapEditor.java index 640ad78520..7709c783d3 100644 --- a/core/src/io/anuke/mindustry/editor/MapEditor.java +++ b/core/src/io/anuke/mindustry/editor/MapEditor.java @@ -25,7 +25,7 @@ public class MapEditor{ private byte elevation; private int rotation; private Block drawBlock = Blocks.stone; - private Team drawTeam = Team.none; + private Team drawTeam = Team.blue; public MapEditor(){ diff --git a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java index d08b868d77..e7e2e8b53b 100644 --- a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java @@ -495,7 +495,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ .size(size).get().setAlignment(Align.center, Align.center); t.addImageButton("icon-arrow-right", 16 * 2f, () -> editor.setDrawElevation(editor.getDrawElevation() + 1)) - .disabled(b -> editor.getDrawElevation() >= 127).size(size); + .disabled(b -> editor.getDrawElevation() >= 63).size(size); }).colspan(3).height(size).padTop(-5).width(size * 3f); }).margin(0).left().growY(); @@ -566,7 +566,8 @@ public class MapEditorDialog extends Dialog implements Disposable{ for(Block block : Block.all()){ TextureRegion[] regions = block.getCompactIcon(); - if((block.synthetic() && (Recipe.getByResult(block) == null || !control.database().isUnlocked(Recipe.getByResult(block)))) && !debug && block != StorageBlocks.core){ + if((block.synthetic() && (Recipe.getByResult(block) == null || !control.database().isUnlocked(Recipe.getByResult(block)))) + && !debug && block != StorageBlocks.core){ continue; } @@ -574,6 +575,10 @@ public class MapEditorDialog extends Dialog implements Disposable{ continue; } + if(Recipe.getByResult(block) != null && Recipe.getByResult(block).desktopOnly && mobile && !debug){ + continue; + } + if(regions.length == 0 || regions[0] == Draw.region("jjfgj")) continue; Stack stack = new Stack(); diff --git a/core/src/io/anuke/mindustry/entities/Damage.java b/core/src/io/anuke/mindustry/entities/Damage.java index 0c7ac56454..1d7a86ff08 100644 --- a/core/src/io/anuke/mindustry/entities/Damage.java +++ b/core/src/io/anuke/mindustry/entities/Damage.java @@ -9,7 +9,7 @@ import io.anuke.mindustry.content.fx.Fx; import io.anuke.mindustry.entities.effect.Fire; import io.anuke.mindustry.entities.effect.Lightning; import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.gen.CallEntity; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.core.Effects; @@ -43,7 +43,7 @@ public class Damage{ } for(int i = 0; i < Mathf.clamp(flammability / 4, 0, 30); i++){ - Timers.run(i / 2, () -> CallEntity.createBullet(TurretBullets.fireball, x, y, Mathf.random(360f))); + Timers.run(i / 2, () -> Call.createBullet(TurretBullets.fireball, x, y, Mathf.random(360f))); } int waves = Mathf.clamp((int) (explosiveness / 4), 0, 30); diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/Player.java index 39161a9a8d..c87220c501 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/Player.java @@ -14,10 +14,9 @@ import io.anuke.mindustry.entities.effect.ItemDrop; import io.anuke.mindustry.entities.effect.ScorchDecal; import io.anuke.mindustry.entities.traits.*; import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.gen.CallEntity; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.graphics.Trail; -import io.anuke.mindustry.net.In; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.NetConnection; import io.anuke.mindustry.type.*; @@ -83,7 +82,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra //region unit and event overrides, utility methods - @Remote(in = In.entities, targets = Loc.server, called = Loc.server) + @Remote(targets = Loc.server, called = Loc.server) public static void onPlayerDamage(Player player, float amount){ if(player == null) return; @@ -91,7 +90,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra player.health -= amount; } - @Remote(in = In.entities, targets = Loc.server, called = Loc.server) + @Remote(targets = Loc.server, called = Loc.server) public static void onPlayerDeath(Player player){ if(player == null) return; @@ -228,10 +227,10 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra @Override public void damage(float amount){ - CallEntity.onPlayerDamage(this, calculateDamage(amount)); + Call.onPlayerDamage(this, calculateDamage(amount)); if(health <= 0 && !dead){ - CallEntity.onPlayerDeath(this); + Call.onPlayerDeath(this); } } @@ -511,7 +510,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra if(!ui.chatfrag.chatOpen() && Inputs.keyTap("drop_unit")){ if(!mech.flying){ if(getCarrier() != null){ - CallEntity.dropSelf(this); + Call.dropSelf(this); } }else if(getCarry() != null){ dropCarry(); @@ -548,7 +547,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra velocity.add(movement); } float prex = x, prey = y; - updateVelocityStatus(mech.drag, 10f); + updateVelocityStatus(mech.drag, debug ? 10f : mech.maxSpeed); moved = distanceTo(prex, prey) > 0.01f; }else{ velocity.setZero(); diff --git a/core/src/io/anuke/mindustry/entities/TileEntity.java b/core/src/io/anuke/mindustry/entities/TileEntity.java index 59b05c68df..51787ba060 100644 --- a/core/src/io/anuke/mindustry/entities/TileEntity.java +++ b/core/src/io/anuke/mindustry/entities/TileEntity.java @@ -10,8 +10,7 @@ import io.anuke.mindustry.content.fx.Fx; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.traits.TargetTrait; import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.gen.CallBlocks; -import io.anuke.mindustry.net.In; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Edges; import io.anuke.mindustry.world.Tile; @@ -55,14 +54,14 @@ public class TileEntity extends BaseEntity implements TargetTrait{ private boolean sleeping; private float sleepTime; - @Remote(called = Loc.server, in = In.blocks) + @Remote(called = Loc.server) public static void onTileDamage(Tile tile, float health){ if(tile.entity != null){ tile.entity.health = health; } } - @Remote(called = Loc.server, in = In.blocks) + @Remote(called = Loc.server) public static void onTileDestroyed(Tile tile){ if(tile.entity == null) return; tile.entity.onDeath(); @@ -85,10 +84,7 @@ public class TileEntity extends BaseEntity implements TargetTrait{ return this; } - /** - * 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 += Timers.delta(); if(!sleeping && sleepTime >= timeToSleep){ @@ -98,20 +94,6 @@ public class TileEntity extends BaseEntity implements TargetTrait{ } } - /** - * Call when something just happened to the entity. - * If the entity was sleeping, this enables it. This also resets the sleep timer. - */ - public void wakeUp(){ - noSleep(); - - for(Tile tile : proximity){ - if(tile.entity.isSleeping()){ - tile.entity.wakeUp(); - } - } - } - /**Call when this entity is updating. This wakes it up.*/ public void noSleep(){ sleepTime = 0f; @@ -159,10 +141,10 @@ public class TileEntity extends BaseEntity implements TargetTrait{ public void damage(float damage){ if(dead) return; - CallBlocks.onTileDamage(tile, health - tile.block().handleDamage(tile, damage)); + Call.onTileDamage(tile, health - tile.block().handleDamage(tile, damage)); if(health <= 0){ - CallBlocks.onTileDestroyed(tile); + Call.onTileDestroyed(tile); } } diff --git a/core/src/io/anuke/mindustry/entities/Unit.java b/core/src/io/anuke/mindustry/entities/Unit.java index 02c56c633c..e234c4936a 100644 --- a/core/src/io/anuke/mindustry/entities/Unit.java +++ b/core/src/io/anuke/mindustry/entities/Unit.java @@ -214,9 +214,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ }); } - /** - * Updates velocity and status effects. - */ + /**Updates velocity and status effects.*/ public void updateVelocityStatus(float drag, float maxVelocity){ if(isCarried()){ //carried units do not take into account velocity normally set(carrier.getX(), carrier.getY()); @@ -280,7 +278,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ if(Math.abs(py - y) <= 0.0001f) velocity.y = 0f; } - velocity.scl(Mathf.clamp(1f - drag * floor.dragMultiplier * Timers.delta())); + velocity.scl(Mathf.clamp(1f - drag * (isFlying() ? 1f : floor.dragMultiplier) * Timers.delta())); } public void applyEffect(StatusEffect effect, float intensity){ diff --git a/core/src/io/anuke/mindustry/entities/UnitInventory.java b/core/src/io/anuke/mindustry/entities/UnitInventory.java index 53fd627f88..0ebfcb27f9 100644 --- a/core/src/io/anuke/mindustry/entities/UnitInventory.java +++ b/core/src/io/anuke/mindustry/entities/UnitInventory.java @@ -110,6 +110,12 @@ public class UnitInventory implements Saveable{ ammos.add(entry); } + public void fillAmmo(AmmoType type){ + totalAmmo = ammoCapacity(); + ammos.clear(); + ammos.add(new AmmoEntry(type, ammoCapacity())); + } + public int capacity(){ return unit.getItemCapacity(); } diff --git a/core/src/io/anuke/mindustry/entities/bullet/Bullet.java b/core/src/io/anuke/mindustry/entities/bullet/Bullet.java index 0e9322928f..4aea115a35 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/Bullet.java +++ b/core/src/io/anuke/mindustry/entities/bullet/Bullet.java @@ -8,7 +8,6 @@ import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.entities.traits.SyncTrait; import io.anuke.mindustry.entities.traits.TeamTrait; import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.net.In; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.core.Timers; import io.anuke.ucore.entities.EntityGroup; @@ -33,9 +32,7 @@ public class Bullet extends BulletEntity implements TeamTrait, SyncT private Object data; private boolean supressCollision; - /** - * Internal use only! - */ + /**Internal use only!*/ public Bullet(){ } @@ -85,7 +82,7 @@ public class Bullet extends BulletEntity implements TeamTrait, SyncT create(type, parent.owner, parent.team, x, y, angle, velocityScl); } - @Remote(called = Loc.server, in = In.entities) + @Remote(called = Loc.server) public static void createBullet(BulletType type, float x, float y, float angle){ create(type, null, Team.none, x, y, angle); } diff --git a/core/src/io/anuke/mindustry/entities/effect/Fire.java b/core/src/io/anuke/mindustry/entities/effect/Fire.java index e933e5dfbf..b2f2051f6f 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Fire.java +++ b/core/src/io/anuke/mindustry/entities/effect/Fire.java @@ -12,8 +12,7 @@ import io.anuke.mindustry.entities.Damage; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.traits.SaveTrait; import io.anuke.mindustry.entities.traits.SyncTrait; -import io.anuke.mindustry.gen.CallEntity; -import io.anuke.mindustry.net.In; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -77,7 +76,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{ } } - @Remote(called = Loc.server, in = In.entities) + @Remote(called = Loc.server) public static void onFireRemoved(int fireid){ fireGroup.removeByID(fireid); } @@ -104,7 +103,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{ time = Mathf.clamp(time + Timers.delta(), 0, lifetime()); if(time >= lifetime() || tile == null){ - CallEntity.onFireRemoved(getID()); + Call.onFireRemoved(getID()); remove(); return; } @@ -133,7 +132,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{ create(other); if(Mathf.chance(0.05 * Timers.delta() * Mathf.clamp(flammability / 10.0))){ - CallEntity.createBullet(TurretBullets.fireball, x, y, Mathf.random(360f)); + Call.createBullet(TurretBullets.fireball, x, y, Mathf.random(360f)); } } diff --git a/core/src/io/anuke/mindustry/entities/effect/ItemDrop.java b/core/src/io/anuke/mindustry/entities/effect/ItemDrop.java index 3ee9a9d8ef..87430d7978 100644 --- a/core/src/io/anuke/mindustry/entities/effect/ItemDrop.java +++ b/core/src/io/anuke/mindustry/entities/effect/ItemDrop.java @@ -12,8 +12,7 @@ import io.anuke.mindustry.entities.traits.SaveTrait; import io.anuke.mindustry.entities.traits.SyncTrait; import io.anuke.mindustry.entities.traits.TargetTrait; import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.gen.CallEntity; -import io.anuke.mindustry.net.In; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.net.Interpolator; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.type.Item; @@ -69,7 +68,7 @@ public class ItemDrop extends SolidEntity implements SaveTrait, SyncTrait, DrawT create(item, amount, x, y, 0).getVelocity().set(velocityX, velocityY); } - @Remote(called = Loc.server, in = In.entities) + @Remote(called = Loc.server) public static void onPickup(int itemid){ ItemDrop drop = itemGroup.getByID(itemid); if(drop != null){ @@ -133,7 +132,7 @@ public class ItemDrop extends SolidEntity implements SaveTrait, SyncTrait, DrawT amount -= used; if(amount <= 0){ - CallEntity.onPickup(getID()); + Call.onPickup(getID()); } } } @@ -166,14 +165,14 @@ public class ItemDrop extends SolidEntity implements SaveTrait, SyncTrait, DrawT updateVelocity(0.2f); updateTime(); if(time >= lifetime()){ - CallEntity.onPickup(getID()); + Call.onPickup(getID()); } } Tile tile = world.tileWorld(x, y); if(tile != null && tile.solid()){ - CallEntity.onPickup(getID()); + Call.onPickup(getID()); } if(tile != null && tile.floor().isLiquid){ diff --git a/core/src/io/anuke/mindustry/entities/effect/ItemTransfer.java b/core/src/io/anuke/mindustry/entities/effect/ItemTransfer.java index b27b8abbd5..27ef69d948 100644 --- a/core/src/io/anuke/mindustry/entities/effect/ItemTransfer.java +++ b/core/src/io/anuke/mindustry/entities/effect/ItemTransfer.java @@ -6,7 +6,6 @@ import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.net.In; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.core.Timers; @@ -35,7 +34,7 @@ public class ItemTransfer extends TimedEntity implements DrawTrait{ public ItemTransfer(){ } - @Remote(in = In.entities, called = Loc.server, unreliable = true) + @Remote(called = Loc.server, unreliable = true) public static void transferAmmo(Item item, float x, float y, Unit to){ if(to == null) return; to.addAmmo(item); @@ -43,20 +42,20 @@ public class ItemTransfer extends TimedEntity implements DrawTrait{ }); } - @Remote(in = In.entities, called = Loc.server, unreliable = true) + @Remote(called = Loc.server, unreliable = true) public static void transferItemEffect(Item item, float x, float y, Unit to){ if(to == null) return; create(item, x, y, to, () -> { }); } - @Remote(in = In.entities, called = Loc.server, unreliable = true) + @Remote(called = Loc.server, unreliable = true) public static void transferItemToUnit(Item item, float x, float y, Unit to){ if(to == null) return; create(item, x, y, to, () -> to.inventory.addItem(item, 1)); } - @Remote(in = In.entities, called = Loc.server) + @Remote(called = Loc.server) public static void transferItemTo(Item item, int amount, float x, float y, Tile tile){ if(tile == null) return; for(int i = 0; i < Mathf.clamp(amount / 3, 1, 8); i++){ diff --git a/core/src/io/anuke/mindustry/entities/effect/Lightning.java b/core/src/io/anuke/mindustry/entities/effect/Lightning.java index 2ab599b003..6642238948 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Lightning.java +++ b/core/src/io/anuke/mindustry/entities/effect/Lightning.java @@ -11,9 +11,8 @@ import io.anuke.mindustry.content.StatusEffects; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.traits.SyncTrait; import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.gen.CallEntity; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.net.In; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Effects.Effect; import io.anuke.ucore.entities.EntityGroup; @@ -56,10 +55,10 @@ public class Lightning extends TimedEntity implements Poolable, DrawTrait, SyncT * Create a lighting branch at a location. Use Team.none to damage everyone. */ public static void create(Team team, Effect effect, Color color, float damage, float x, float y, float targetAngle, int length){ - CallEntity.createLighting(lastSeed++, team, effect, color, damage, x, y, targetAngle, length); + Call.createLighting(lastSeed++, team, effect, color, damage, x, y, targetAngle, length); } - @Remote(called = Loc.server, in = In.entities) + @Remote(called = Loc.server) public static void createLighting(int seed, Team team, Effect effect, Color color, float damage, float x, float y, float targetAngle, int length){ Lightning l = Pooling.obtain(Lightning.class); diff --git a/core/src/io/anuke/mindustry/entities/effect/Puddle.java b/core/src/io/anuke/mindustry/entities/effect/Puddle.java index 1fa0cd8a0b..214e003777 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Puddle.java +++ b/core/src/io/anuke/mindustry/entities/effect/Puddle.java @@ -15,8 +15,7 @@ import io.anuke.mindustry.content.fx.EnvironmentFx; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.traits.SaveTrait; import io.anuke.mindustry.entities.traits.SyncTrait; -import io.anuke.mindustry.gen.CallEntity; -import io.anuke.mindustry.net.In; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Tile; @@ -136,7 +135,7 @@ public class Puddle extends BaseEntity implements SaveTrait, Poolable, DrawTrait (liquid.flammability > 0.3f && dest.temperature > 0.7f)){ //flammable liquid + hot liquid Fire.create(tile); if(Mathf.chance(0.006 * amount)){ - CallEntity.createBullet(TurretBullets.fireball, x, y, Mathf.random(360f)); + Call.createBullet(TurretBullets.fireball, x, y, Mathf.random(360f)); } }else if(dest.temperature > 0.7f && liquid.temperature < 0.55f){ //cold liquid poured onto hot puddle if(Mathf.chance(0.5f * amount)){ @@ -152,7 +151,7 @@ public class Puddle extends BaseEntity implements SaveTrait, Poolable, DrawTrait return 0f; } - @Remote(called = Loc.server, in = In.entities) + @Remote(called = Loc.server) public static void onPuddleRemoved(int puddleid){ puddleGroup.removeByID(puddleid); } @@ -180,7 +179,7 @@ public class Puddle extends BaseEntity implements SaveTrait, Poolable, DrawTrait float deposited = Math.min((amount - maxLiquid / 1.5f) / 4f, 0.3f) * Timers.delta(); for(GridPoint2 point : Geometry.d4){ Tile other = world.tile(tile.x + point.x, tile.y + point.y); - if(other.block() == Blocks.air && other.cliffs == 0){ + if(other.block() == Blocks.air && !other.hasCliffs()){ deposit(other, tile, liquid, deposited, generation + 1); amount -= deposited / 2f; //tweak to speed up/slow down puddle propagation } @@ -190,7 +189,7 @@ public class Puddle extends BaseEntity implements SaveTrait, Poolable, DrawTrait amount = Mathf.clamp(amount, 0, maxLiquid); if(amount <= 0f){ - CallEntity.onPuddleRemoved(getID()); + Call.onPuddleRemoved(getID()); } } diff --git a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java index bbf7df9f9d..675d3533fb 100644 --- a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java @@ -8,7 +8,7 @@ import io.anuke.mindustry.content.fx.BlockFx; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.Unit; -import io.anuke.mindustry.gen.CallEntity; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Recipe; @@ -42,37 +42,25 @@ import static io.anuke.mindustry.Vars.world; */ public interface BuilderTrait extends Entity{ //these are not instance variables! - float placeDistance = 140f; + float placeDistance = 150f; float mineDistance = 70f; - /** - * Returns the queue for storing build requests. - */ + /**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); - /** - * 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; } @@ -120,9 +108,7 @@ public interface BuilderTrait extends Entity{ } } - /** - * 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; } @@ -145,16 +131,12 @@ public interface BuilderTrait extends Entity{ addBuildRequest(new BuildRequest(x, y, rotation, recipe)); } - /** - * 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){ synchronized(getPlaceQueue()){ for(BuildRequest request : getPlaceQueue()){ @@ -202,7 +184,11 @@ public interface BuilderTrait extends Entity{ Tile tile = world.tile(current.x, current.y); - if(!(tile.block() instanceof BuildBlock)){ + if(unit.distanceTo(tile) > placeDistance){ + return; + } + + if(!(tile.block() instanceof BuildBlock) ){ if(canCreateBlocks() && !current.remove && Build.validPlace(unit.getTeam(), current.x, current.y, current.recipe.result, current.rotation)){ Build.beginPlace(unit.getTeam(), current.x, current.y, current.recipe, current.rotation); }else if(canCreateBlocks() && current.remove && Build.validBreak(unit.getTeam(), current.x, current.y)){ @@ -229,9 +215,7 @@ public interface BuilderTrait extends Entity{ current.progress = entity.progress(); } - /** - * Do not call directly. - */ + /**Do not call directly.*/ default void updateMining(Unit unit){ Tile tile = getMineTile(); @@ -243,7 +227,7 @@ public interface BuilderTrait extends Entity{ if(unit.inventory.canAcceptItem(item) && Mathf.chance(Timers.delta() * (0.06 - item.hardness * 0.01) * getMinePower())){ - CallEntity.transferItemToUnit(item, + Call.transferItemToUnit(item, tile.worldx() + Mathf.range(tilesize / 2f), tile.worldy() + Mathf.range(tilesize / 2f), unit); @@ -257,9 +241,7 @@ public interface BuilderTrait extends Entity{ } } - /** - * Draw placement effects for an entity. This includes mining - */ + /**Draw placement effects for an entity. This includes mining*/ default void drawBuilding(Unit unit){ BuildRequest request; @@ -316,9 +298,7 @@ public interface BuilderTrait extends Entity{ Draw.color(); } - /** - * Internal use only. - */ + /**Internal use only.*/ default void drawMining(Unit unit){ Tile tile = getMineTile(); @@ -345,9 +325,7 @@ public interface BuilderTrait extends Entity{ 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 Recipe recipe; @@ -355,9 +333,7 @@ public interface BuilderTrait extends Entity{ public float progress; - /** - * This creates a build request. - */ + /**This creates a build request.*/ public BuildRequest(int x, int y, int rotation, Recipe recipe){ this.x = x; this.y = y; @@ -366,9 +342,7 @@ public interface BuilderTrait extends Entity{ this.remove = 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/CarryTrait.java b/core/src/io/anuke/mindustry/entities/traits/CarryTrait.java index 63c10a4578..bbf89e58e6 100644 --- a/core/src/io/anuke/mindustry/entities/traits/CarryTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/CarryTrait.java @@ -4,20 +4,19 @@ import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.mindustry.content.fx.UnitFx; import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.gen.CallEntity; -import io.anuke.mindustry.net.In; +import io.anuke.mindustry.gen.Call; import io.anuke.ucore.core.Effects; import io.anuke.ucore.entities.trait.SolidTrait; public interface CarryTrait extends TeamTrait, SolidTrait, TargetTrait{ - @Remote(called = Loc.both, targets = Loc.both, forward = true, in = In.entities) + @Remote(called = Loc.both, targets = Loc.both, forward = true) static void dropSelf(Player player){ if(player.getCarrier() != null){ player.getCarrier().dropCarry(); } } - @Remote(called = Loc.both, targets = Loc.both, forward = true, in = In.entities) + @Remote(called = Loc.both, targets = Loc.both, forward = true) static void setCarryOf(Player player, CarryTrait trait, CarriableTrait unit){ if(trait == null) return; if(player != null){ //when a server recieves this called from a player, set the carrier to the player. @@ -72,6 +71,6 @@ public interface CarryTrait extends TeamTrait, SolidTrait, TargetTrait{ * Carries a unit. To drop a unit, call with {@code null}. */ default void carry(CarriableTrait unit){ - CallEntity.setCarryOf(this instanceof Player ? (Player) this : null, this, unit); + Call.setCarryOf(this instanceof Player ? (Player) this : null, this, unit); } } diff --git a/core/src/io/anuke/mindustry/entities/units/BaseUnit.java b/core/src/io/anuke/mindustry/entities/units/BaseUnit.java index 51a2e11c9a..7f82b277b9 100644 --- a/core/src/io/anuke/mindustry/entities/units/BaseUnit.java +++ b/core/src/io/anuke/mindustry/entities/units/BaseUnit.java @@ -16,15 +16,15 @@ import io.anuke.mindustry.entities.traits.SpawnerTrait; import io.anuke.mindustry.entities.traits.TargetTrait; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.TeamInfo.TeamData; -import io.anuke.mindustry.gen.CallEntity; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.net.In; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.Weapon; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.units.UnitFactory.UnitFactoryEntity; +import io.anuke.mindustry.world.blocks.units.CommandCenter.CommandCenterEntity; +import io.anuke.mindustry.world.blocks.units.UnitPad.UnitFactoryEntity; import io.anuke.mindustry.world.meta.BlockFlag; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Timers; @@ -41,6 +41,7 @@ import java.io.IOException; import static io.anuke.mindustry.Vars.*; +/**Base class for AI units.*/ public abstract class BaseUnit extends Unit implements ShooterTrait{ protected static int timerIndex = 0; @@ -56,15 +57,13 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ protected boolean isWave; protected Squad squad; - protected int spawner; + protected int spawner = -1; - /** - * internal constructor used for deserialization, DO NOT USE - */ + /**internal constructor used for deserialization, DO NOT USE*/ public BaseUnit(){ } - @Remote(called = Loc.server, in = In.entities) + @Remote(called = Loc.server) public static void onUnitDeath(BaseUnit unit){ if(unit == null) return; @@ -86,9 +85,10 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ threads.runDelay(unit::remove); } - /** - * Initialize the type and team of this unit. Only call once! - */ + /**Called when a command is recieved from the command center.*/ + public abstract void onCommand(UnitCommand command); + + /**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!"); @@ -96,6 +96,17 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ this.team = team; } + public boolean isCommanded(){ + return !isWave && world.indexer().getAllied(team, BlockFlag.comandCenter).size != 0; + } + + public UnitCommand getCommand(){ + if(isCommanded()){ + return world.indexer().getAllied(team, BlockFlag.comandCenter).first().entity().command; + } + return null; + } + public UnitType getType(){ return type; } @@ -108,9 +119,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ this.spawner = tile.packedPosition(); } - /** - * Sets this to a 'wave' unit, which means it has slightly different AI and will not run out of ammo. - */ + /**Sets this to a 'wave' unit, which means it has slightly different AI and will not run out of ammo.*/ public void setWave(){ isWave = true; } @@ -320,6 +329,10 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ if(!Net.client()){ avoidOthers(8f); + + if(spawner != -1 && (world.tile(spawner) == null || world.tile(spawner).entity == null)){ + damage(health); + } } if(squad != null){ @@ -373,7 +386,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ @Override public void onDeath(){ - CallEntity.onUnitDeath(this); + Call.onUnitDeath(this); } @Override @@ -383,6 +396,10 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ state.set(getStartState()); health(maxHealth()); + + if(isCommanded()){ + onCommand(getCommand()); + } } @Override diff --git a/core/src/io/anuke/mindustry/entities/units/FlyingUnit.java b/core/src/io/anuke/mindustry/entities/units/FlyingUnit.java index 02fae5f6fc..d7ffd67c44 100644 --- a/core/src/io/anuke/mindustry/entities/units/FlyingUnit.java +++ b/core/src/io/anuke/mindustry/entities/units/FlyingUnit.java @@ -23,6 +23,9 @@ import static io.anuke.mindustry.Vars.world; public abstract class FlyingUnit extends BaseUnit implements CarryTrait{ protected static Translator vec = new Translator(); protected static float wobblyness = 0.6f; + + protected Trail trail = new Trail(8); + protected CarriableTrait carrying; protected final UnitState resupply = new UnitState(){ @@ -43,14 +46,16 @@ public abstract class FlyingUnit extends BaseUnit implements CarryTrait{ idle = new UnitState(){ public void update(){ - retarget(() -> { - targetClosest(); - targetClosestEnemyFlag(BlockFlag.target); + if(!isCommanded()){ + retarget(() -> { + targetClosest(); + targetClosestEnemyFlag(BlockFlag.target); - if(target != null){ - setState(attack); - } - }); + if(target != null){ + setState(attack); + } + }); + } target = getClosestCore(); if(target != null){ @@ -103,7 +108,7 @@ public abstract class FlyingUnit extends BaseUnit implements CarryTrait{ } public void update(){ - if(health >= maxHealth()){ + if(health >= maxHealth() && !isCommanded()){ state.set(attack); }else if(!targetHasFlag(BlockFlag.repair)){ retarget(() -> { @@ -115,14 +120,20 @@ public abstract class FlyingUnit extends BaseUnit implements CarryTrait{ } } }; - protected Trail trail = new Trail(8); - protected CarriableTrait carrying; //instantiation only public FlyingUnit(){ } + @Override + public void onCommand(UnitCommand command){ + state.set(command == UnitCommand.retreat ? retreat : + (command == UnitCommand.attack ? attack : + (command == UnitCommand.idle ? idle : + (null)))); + } + @Override public CarriableTrait getCarry(){ return carrying; @@ -167,8 +178,8 @@ public abstract class FlyingUnit extends BaseUnit implements CarryTrait{ @Override public void behavior(){ - if(health <= health * type.retreatPercent && !isWave && - Geometry.findClosest(x, y, world.indexer().getAllied(team, BlockFlag.repair)) != null){ + if(health <= health * type.retreatPercent && !isCommanded() && + Geometry.findClosest(x, y, world.indexer().getAllied(team, BlockFlag.repair)) != null){ setState(retreat); } diff --git a/core/src/io/anuke/mindustry/entities/units/GroundUnit.java b/core/src/io/anuke/mindustry/entities/units/GroundUnit.java index 5dba19a82d..638b69123e 100644 --- a/core/src/io/anuke/mindustry/entities/units/GroundUnit.java +++ b/core/src/io/anuke/mindustry/entities/units/GroundUnit.java @@ -31,9 +31,11 @@ public abstract class GroundUnit extends BaseUnit{ protected float walkTime; protected float baseRotation; + protected Weapon weapon; + public final UnitState - resupply = new UnitState(){ + resupply = new UnitState(){ public void entered(){ target = null; } @@ -51,64 +53,71 @@ public abstract class GroundUnit extends BaseUnit{ } } }, - attack = new UnitState(){ - public void entered(){ - target = null; - } + attack = new UnitState(){ + public void entered(){ + target = null; + } - public void update(){ - TileEntity core = getClosestEnemyCore(); - float dst = core == null ? 0 : distanceTo(core); + public void update(){ + TileEntity core = getClosestEnemyCore(); + float dst = core == null ? 0 : distanceTo(core); - if(core != null && inventory.hasAmmo() && dst < inventory.getAmmo().getRange() / 1.1f){ - target = core; - }else{ - retarget(() -> targetClosest()); - } + if(core != null && inventory.hasAmmo() && dst < inventory.getAmmo().getRange() / 1.1f){ + target = core; + }else{ + retarget(() -> targetClosest()); + } - if(!inventory.hasAmmo()){ - state.set(resupply); - }else if(target != null){ - if(core != null){ - if(dst > inventory.getAmmo().getRange() * 0.5f){ - moveToCore(); - } - - }else{ - moveToCore(); - } - - if(distanceTo(target) < inventory.getAmmo().getRange()){ - rotate(angleTo(target)); - - if(Mathf.angNear(angleTo(target), rotation, 13f)){ - AmmoType ammo = inventory.getAmmo(); - - Vector2 to = Predict.intercept(GroundUnit.this, target, ammo.bullet.speed); - - getWeapon().update(GroundUnit.this, to.x, to.y); - } - } - - }else{ + if(!inventory.hasAmmo()){ + state.set(resupply); + }else if(target != null){ + if(core != null){ + if(dst > inventory.getAmmo().getRange() * 0.5f){ moveToCore(); } - } - }, - retreat = new UnitState(){ - public void entered(){ - target = null; + + }else{ + moveToCore(); } - public void update(){ - if(health >= health){ - state.set(attack); + if(distanceTo(target) < inventory.getAmmo().getRange()){ + rotate(angleTo(target)); + + if(Mathf.angNear(angleTo(target), rotation, 13f)){ + AmmoType ammo = inventory.getAmmo(); + + Vector2 to = Predict.intercept(GroundUnit.this, target, ammo.bullet.speed); + + getWeapon().update(GroundUnit.this, to.x, to.y); } - - moveAwayFromCore(); } - }; - protected Weapon weapon; + + }else{ + moveToCore(); + } + } + }, + retreat = new UnitState(){ + public void entered(){ + target = null; + } + + public void update(){ + if(health >= health && !isCommanded()){ + state.set(attack); + } + + moveAwayFromCore(); + } + }; + + @Override + public void onCommand(UnitCommand command){ + state.set(command == UnitCommand.retreat ? retreat : + (command == UnitCommand.attack ? attack : + (command == UnitCommand.idle ? resupply : + (null)))); + } @Override public void init(UnitType type, Team team){ @@ -202,7 +211,7 @@ public abstract class GroundUnit extends BaseUnit{ @Override public void behavior(){ - if(health <= health * type.retreatPercent && !isWave){ + if(health <= health * type.retreatPercent && !isCommanded()){ setState(retreat); } } diff --git a/core/src/io/anuke/mindustry/entities/units/UnitCommand.java b/core/src/io/anuke/mindustry/entities/units/UnitCommand.java new file mode 100644 index 0000000000..71d77e3f73 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/units/UnitCommand.java @@ -0,0 +1,5 @@ +package io.anuke.mindustry.entities.units; + +public enum UnitCommand{ + attack, retreat, idle +} diff --git a/core/src/io/anuke/mindustry/entities/units/UnitType.java b/core/src/io/anuke/mindustry/entities/units/UnitType.java index 848ef6d372..608712e366 100644 --- a/core/src/io/anuke/mindustry/entities/units/UnitType.java +++ b/core/src/io/anuke/mindustry/entities/units/UnitType.java @@ -2,25 +2,33 @@ package io.anuke.mindustry.entities.units; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.utils.Array; +import com.badlogic.gdx.utils.ObjectSet; +import io.anuke.mindustry.content.Items; import io.anuke.mindustry.content.Weapons; import io.anuke.mindustry.entities.traits.TypeTrait; import io.anuke.mindustry.game.Content; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.UnlockableContent; +import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Weapon; import io.anuke.mindustry.ui.ContentDisplay; import io.anuke.ucore.function.Supplier; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.util.Bundles; +import io.anuke.ucore.util.Log; +import io.anuke.ucore.util.Strings; //TODO merge unit type with mech public class UnitType implements UnlockableContent{ private static byte lastid = 0; private static Array types = new Array<>(); - public final String name; - public final byte id; + protected final Supplier constructor; + + public final String name; + public final String description; + public final byte id; public float health = 60; public float hitsize = 5f; public float hitsizeTile = 4f; @@ -35,9 +43,9 @@ public class UnitType implements UnlockableContent{ public float retreatPercent = 0.2f; public float armor = 0f; public float carryWeight = 1f; - public int ammoCapacity = 100; + public int ammoCapacity = 220; public int itemCapacity = 30; - public int mineLevel = 2; + public ObjectSet toMine = ObjectSet.with(Items.lead, Items.tungsten); public float buildPower = 0.3f, minePower = 0.7f, healSpeed = 0.1f; public Weapon weapon = Weapons.blaster; public float weaponOffsetX, weaponOffsetY; @@ -48,10 +56,16 @@ public class UnitType implements UnlockableContent{ this.id = lastid++; this.name = name; this.constructor = mainConstructor; + this.description = Bundles.getOrNull("unit." + name + ".description"); types.add(this); TypeTrait.registerType(type, mainConstructor); + + if(!Bundles.has("unit." + this.name + ".name")){ + Log.err("Warning: unit '" + name + "' is missing a localized name. Add the follow to bundle.properties:"); + Log.err("unit." + this.name + ".name=" + Strings.capitalize(name.replace('-', '_'))); + } } public static UnitType getByID(byte id){ diff --git a/core/src/io/anuke/mindustry/entities/units/types/Scout.java b/core/src/io/anuke/mindustry/entities/units/types/Dagger.java similarity index 72% rename from core/src/io/anuke/mindustry/entities/units/types/Scout.java rename to core/src/io/anuke/mindustry/entities/units/types/Dagger.java index bdfdbe4f89..aab1b4161b 100644 --- a/core/src/io/anuke/mindustry/entities/units/types/Scout.java +++ b/core/src/io/anuke/mindustry/entities/units/types/Dagger.java @@ -2,6 +2,6 @@ package io.anuke.mindustry.entities.units.types; import io.anuke.mindustry.entities.units.GroundUnit; -public class Scout extends GroundUnit{ +public class Dagger extends GroundUnit{ } diff --git a/core/src/io/anuke/mindustry/entities/units/types/Drone.java b/core/src/io/anuke/mindustry/entities/units/types/Drone.java index f51229f6cf..bddd870569 100644 --- a/core/src/io/anuke/mindustry/entities/units/types/Drone.java +++ b/core/src/io/anuke/mindustry/entities/units/types/Drone.java @@ -1,9 +1,7 @@ package io.anuke.mindustry.entities.units.types; import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.utils.ObjectSet; import com.badlogic.gdx.utils.Queue; -import io.anuke.mindustry.content.Items; import io.anuke.mindustry.content.blocks.Blocks; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.Units; @@ -14,7 +12,7 @@ import io.anuke.mindustry.entities.units.BaseUnit; import io.anuke.mindustry.entities.units.FlyingUnit; import io.anuke.mindustry.entities.units.UnitState; import io.anuke.mindustry.game.EventType.BlockBuildEvent; -import io.anuke.mindustry.gen.CallEntity; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.type.Item; @@ -41,7 +39,6 @@ import java.io.IOException; import static io.anuke.mindustry.Vars.*; public class Drone extends FlyingUnit implements BuilderTrait{ - protected static ObjectSet toMine; protected static float discoverRange = 120f; protected static boolean initialized; @@ -77,7 +74,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{ //if it's missing requirements, try and mine them for(ItemStack stack : entity.recipe.requirements){ - if(!core.items.has(stack.item, stack.amount) && toMine.contains(stack.item)){ + if(!core.items.has(stack.item, stack.amount) && type.toMine.contains(stack.item)){ targetItem = stack.item; getPlaceQueue().clear(); setState(mine); @@ -230,7 +227,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{ if(distanceTo(target) < type.range){ if(tile.tile.block().acceptStack(inventory.getItem().item, inventory.getItem().amount, tile.tile, Drone.this) == inventory.getItem().amount){ - CallEntity.transferItemTo(inventory.getItem().item, inventory.getItem().amount, x, y, tile.tile); + Call.transferItemTo(inventory.getItem().item, inventory.getItem().amount, x, y, tile.tile); inventory.clearItem(); } @@ -270,8 +267,6 @@ public class Drone extends FlyingUnit implements BuilderTrait{ private static void initEvents(){ if(initialized) return; - toMine = ObjectSet.with(Items.lead, Items.tungsten); - Events.on(BlockBuildEvent.class, (team, tile) -> { EntityGroup group = unitGroups[team.ordinal()]; @@ -293,7 +288,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{ float dist = Math.min(entity.distanceTo(x, y) - placeDistance, 0); if(dist / type.maxVelocity < timeToBuild * 0.9f){ - //CallEntity.onDroneBeginBuild(this, entity.tile, entity.recipe); + //Call.onDroneBeginBuild(this, entity.tile, entity.recipe); target = entity; setState(build); } @@ -400,7 +395,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{ if(entity == null){ return; } - targetItem = Mathf.findMin(toMine, (a, b) -> -Integer.compare(entity.items.get(a), entity.items.get(b))); + targetItem = Mathf.findMin(type.toMine, (a, b) -> -Integer.compare(entity.items.get(a), entity.items.get(b))); } protected boolean findItemDrop(){ diff --git a/core/src/io/anuke/mindustry/entities/units/types/Vtol.java b/core/src/io/anuke/mindustry/entities/units/types/Interceptor.java similarity index 70% rename from core/src/io/anuke/mindustry/entities/units/types/Vtol.java rename to core/src/io/anuke/mindustry/entities/units/types/Interceptor.java index cf02014794..e37188a99d 100644 --- a/core/src/io/anuke/mindustry/entities/units/types/Vtol.java +++ b/core/src/io/anuke/mindustry/entities/units/types/Interceptor.java @@ -2,6 +2,6 @@ package io.anuke.mindustry.entities.units.types; import io.anuke.mindustry.entities.units.FlyingUnit; -public class Vtol extends FlyingUnit{ +public class Interceptor extends FlyingUnit{ } diff --git a/core/src/io/anuke/mindustry/game/GameMode.java b/core/src/io/anuke/mindustry/game/GameMode.java index fcf9e8c09a..ffadb03d8b 100644 --- a/core/src/io/anuke/mindustry/game/GameMode.java +++ b/core/src/io/anuke/mindustry/game/GameMode.java @@ -4,20 +4,21 @@ import io.anuke.ucore.util.Bundles; public enum GameMode{ waves, - //disabled for technical reasons - /*sandbox{ - { - infiniteResources = true; - disableWaveTimer = true; - } - },*/ - freebuild{ - { - disableWaveTimer = true; - } - }; + sandbox{{ + infiniteResources = true; + disableWaveTimer = true; + }}, + freebuild{{ + disableWaveTimer = true; + }}, + noWaves{{ + disableWaves = true; + hidden = true; + }}; public boolean infiniteResources; public boolean disableWaveTimer; + public boolean disableWaves; + public boolean hidden; public String description(){ return Bundles.get("mode." + name() + ".description"); diff --git a/core/src/io/anuke/mindustry/game/Saves.java b/core/src/io/anuke/mindustry/game/Saves.java index 0330037911..fd5da35bc0 100644 --- a/core/src/io/anuke/mindustry/game/Saves.java +++ b/core/src/io/anuke/mindustry/game/Saves.java @@ -75,8 +75,7 @@ public class Saves{ Timers.run(2f, () -> { try{ - SaveIO.saveToSlot(current.index); - current.meta = SaveIO.getData(current.index); + current.save(); }catch(Exception e){ e.printStackTrace(); } @@ -108,10 +107,7 @@ public class Saves{ slot.setName(name); saves.add(slot); saveMap.put(slot.index, slot); - SaveIO.saveToSlot(slot.index); - slot.meta = SaveIO.getData(slot.index); - current = slot; - + slot.save(); saveSlots(); return slot; } @@ -162,9 +158,18 @@ public class Saves{ } public void save(){ - SaveIO.saveToSlot(index); - meta = SaveIO.getData(index); - current = this; + threads.runGraphics(() -> { + //Renderer fog needs to be written on graphics thread, but save() can run on logic thread + //thus, runGraphics is required here + renderer.fog().writeFog(); + + //save on the logic thread + threads.run(() -> { + SaveIO.saveToSlot(index); + meta = SaveIO.getData(index); + current = this; + }); + }); } public boolean isHidden(){ @@ -209,7 +214,7 @@ public class Saves{ } public boolean isAutosave(){ - return Settings.getBool("save-" + index + "-autosave", !gwt); + return Settings.getBool("save-" + index + "-autosave", true); } public void setAutosave(boolean save){ diff --git a/core/src/io/anuke/mindustry/game/TeamInfo.java b/core/src/io/anuke/mindustry/game/TeamInfo.java index 8559fde11d..8ddb84624d 100644 --- a/core/src/io/anuke/mindustry/game/TeamInfo.java +++ b/core/src/io/anuke/mindustry/game/TeamInfo.java @@ -1,5 +1,6 @@ package io.anuke.mindustry.game; +import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.ObjectMap; import com.badlogic.gdx.utils.ObjectSet; import io.anuke.mindustry.world.Tile; @@ -130,7 +131,7 @@ public class TeamInfo{ } public class TeamData{ - public final ThreadArray cores = new ThreadArray<>(); + public final Array cores = new ThreadArray<>(); public final Team team; public final boolean ally; diff --git a/core/src/io/anuke/mindustry/game/Waves.java b/core/src/io/anuke/mindustry/game/Waves.java index 1d07b89bd5..7267e88d6d 100644 --- a/core/src/io/anuke/mindustry/game/Waves.java +++ b/core/src/io/anuke/mindustry/game/Waves.java @@ -11,17 +11,17 @@ public class Waves{ public static Array getSpawns(){ return Array.with( - new SpawnGroup(UnitTypes.scout){{ + new SpawnGroup(UnitTypes.dagger){{ end = 8; unitScaling = 2; }}, - new SpawnGroup(UnitTypes.vtol){{ + new SpawnGroup(UnitTypes.interceptor){{ begin = 12; end = 14; }}, - new SpawnGroup(UnitTypes.scout){{ + new SpawnGroup(UnitTypes.dagger){{ begin = 11; unitScaling = 2; spacing = 2; @@ -36,7 +36,7 @@ public class Waves{ end = 30; }}, - new SpawnGroup(UnitTypes.scout){{ + new SpawnGroup(UnitTypes.dagger){{ begin = 10; unitScaling = 2; unitAmount = 1; @@ -70,7 +70,7 @@ public class Waves{ effect = StatusEffects.overdrive; }}, - new SpawnGroup(UnitTypes.vtol){{ + new SpawnGroup(UnitTypes.interceptor){{ begin = 16; unitScaling = 2; spacing = 2; @@ -79,7 +79,7 @@ public class Waves{ max = 7; }}, - new SpawnGroup(UnitTypes.scout){{ + new SpawnGroup(UnitTypes.dagger){{ begin = 82; spacing = 3; unitAmount = 4; @@ -89,7 +89,7 @@ public class Waves{ ammoItem = Items.silicon; }}, - new SpawnGroup(UnitTypes.scout){{ + new SpawnGroup(UnitTypes.dagger){{ begin = 41; spacing = 5; unitAmount = 1; @@ -99,7 +99,7 @@ public class Waves{ max = 10; }}, - new SpawnGroup(UnitTypes.scout){{ + new SpawnGroup(UnitTypes.dagger){{ begin = 35; spacing = 3; unitAmount = 4; @@ -109,7 +109,7 @@ public class Waves{ end = 60; }}, - new SpawnGroup(UnitTypes.scout){{ + new SpawnGroup(UnitTypes.dagger){{ begin = 42; spacing = 3; unitAmount = 4; @@ -128,7 +128,7 @@ public class Waves{ max = 8; }}, - new SpawnGroup(UnitTypes.vtol){{ + new SpawnGroup(UnitTypes.interceptor){{ begin = 50; unitAmount = 4; unitScaling = 3; diff --git a/core/src/io/anuke/mindustry/graphics/BlockRenderer.java b/core/src/io/anuke/mindustry/graphics/BlockRenderer.java index 0d491b41e3..89630c4a8e 100644 --- a/core/src/io/anuke/mindustry/graphics/BlockRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/BlockRenderer.java @@ -1,6 +1,7 @@ package io.anuke.mindustry.graphics; import com.badlogic.gdx.utils.Array; +import com.badlogic.gdx.utils.IntSet; import com.badlogic.gdx.utils.Sort; import io.anuke.mindustry.content.blocks.Blocks; import io.anuke.mindustry.game.EventType.TileChangeEvent; @@ -25,6 +26,7 @@ public class BlockRenderer{ private FloorRenderer floorRenderer; private Array requests = new Array<>(initialRequests); + private IntSet teamChecks = new IntSet(); private int lastCamX, lastCamY, lastRangeX, lastRangeY; private Layer lastLayer; private int requestidx = 0; @@ -65,7 +67,11 @@ public class BlockRenderer{ Draw.color(); } - /**Process all blocks to draw, simultaneously drawing block shadows.*/ + public boolean isTeamShown(Team team){ + return teamChecks.contains(team.ordinal()); + } + + /**Process all blocks to draw, simultaneously updating the block shadow framebuffer.*/ public void processBlocks(){ iterateidx = 0; lastLayer = null; @@ -86,6 +92,7 @@ public class BlockRenderer{ shadows.setSize(shadowW, shadowH); } + teamChecks.clear(); requestidx = 0; Graphics.end(); @@ -106,6 +113,7 @@ public class BlockRenderer{ if(tile != null){ Block block = tile.block(); + Team team = tile.getTeam(); if(!expanded && block != Blocks.air && world.isAccessible(x, y)){ tile.block().drawShadow(tile); @@ -114,6 +122,7 @@ public class BlockRenderer{ if(block != Blocks.air){ if(!expanded){ addRequest(tile, Layer.block); + teamChecks.add(team.ordinal()); } if(block.expanded || !expanded){ @@ -194,7 +203,9 @@ public class BlockRenderer{ synchronized(Tile.tileSetLock){ Block block = req.tile.block(); - if(req.layer == block.layer){ + if(req.layer == Layer.block){ + block.draw(req.tile); + }else if(req.layer == block.layer){ block.drawLayer(req.tile); }else if(req.layer == block.layer2){ block.drawLayer2(req.tile); diff --git a/core/src/io/anuke/mindustry/graphics/FogRenderer.java b/core/src/io/anuke/mindustry/graphics/FogRenderer.java index b6746eecb4..42e819b63f 100644 --- a/core/src/io/anuke/mindustry/graphics/FogRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/FogRenderer.java @@ -2,6 +2,7 @@ package io.anuke.mindustry.graphics; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.Pixmap.Format; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.TextureRegion; @@ -25,19 +26,18 @@ import java.nio.ByteBuffer; import static io.anuke.mindustry.Vars.*; -/** - * Used for rendering fog of war. A framebuffer is used for this. - */ +/**Used for rendering fog of war. A framebuffer is used for this.*/ public class FogRenderer implements Disposable{ private static final int extraPadding = 3; private static final int shadowPadding = 1; private TextureRegion region = new TextureRegion(); private FrameBuffer buffer; - private ByteBuffer pixelBuffer = ByteBuffer.allocateDirect(4); + private ByteBuffer pixelBuffer; private Array changeQueue = new Array<>(); private int padding; private Rectangle rect = new Rectangle(); + private boolean dirty; public FogRenderer(){ Events.on(WorldLoadGraphicsEvent.class, () -> { @@ -56,12 +56,14 @@ public class FogRenderer implements Disposable{ for(int x = 0; x < world.width(); x++){ for(int y = 0; y < world.height(); y++){ Tile tile = world.tile(x, y); - if(tile.getTeam() == players[0].getTeam() && tile.block().synthetic() && tile.block().viewRange > 0){ changeQueue.add(tile); } } } + + pixelBuffer = ByteBuffer.allocateDirect(world.width() * world.height() * 4); + dirty = true; }); Events.on(TileChangeEvent.class, tile -> threads.runGraphics(() -> { @@ -71,6 +73,25 @@ public class FogRenderer implements Disposable{ })); } + public void writeFog(){ + if(buffer == null) return; + + buffer.begin(); + pixelBuffer.position(0); + Gdx.gl.glPixelStorei(GL20.GL_PACK_ALIGNMENT, 1); + Gdx.gl.glReadPixels(padding, padding, world.width(), world.height(), GL20.GL_RGBA, GL20.GL_UNSIGNED_BYTE, pixelBuffer); + + pixelBuffer.position(0); + for(int i = 0; i < world.width() * world.height(); i++){ + byte r = pixelBuffer.get(); + if(r != 0){ + world.tile(i).setVisibility((byte)1); + } + pixelBuffer.position(pixelBuffer.position() + 3); + } + buffer.end(); + } + public int getPadding(){ return padding; } @@ -96,12 +117,6 @@ public class FogRenderer implements Disposable{ buffer.begin(); - //TODO use this for per-tile visibility to show/hide units - //pixelBuffer.position(0); - //Gdx.gl.glPixelStorei(GL20.GL_PACK_ALIGNMENT, 1); - //Gdx.gl.glReadPixels(world.width()/2, world.height()/2 + 20, 1, 1, GL20.GL_RGB, GL20.GL_UNSIGNED_BYTE, pixelBuffer); - //Log.info(pixelBuffer.get(0)); - boolean pop = ScissorStack.pushScissors(rect.set((padding-shadowPadding), (padding-shadowPadding), (world.width() + shadowPadding*2) , (world.height() + shadowPadding*2))); @@ -120,6 +135,16 @@ public class FogRenderer implements Disposable{ changeQueue.clear(); + if(dirty){ + for(int i = 0; i < world.width() * world.height(); i++){ + Tile tile = world.tile(i); + if(tile.discovered()){ + Fill.rect(tile.worldx(), tile.worldy(), tilesize, tilesize); + } + } + dirty = false; + } + EntityDraw.setClip(true); Graphics.end(); buffer.end(); diff --git a/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java b/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java index 10c87ea51b..2b8d7afd71 100644 --- a/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java @@ -65,7 +65,7 @@ public class OverlayRenderer{ Vector2 vec = Graphics.world(input.getMouseX(), input.getMouseY()); Tile tile = world.tileWorld(vec.x, vec.y); - if(tile != null && tile.block() != Blocks.air){ + if(tile != null && tile.block() != Blocks.air && tile.target().getTeam() == players[0].getTeam()){ Tile target = tile.target(); if(showBlockDebug && target.entity != null){ diff --git a/core/src/io/anuke/mindustry/graphics/Palette.java b/core/src/io/anuke/mindustry/graphics/Palette.java index 1f369df6f2..d62d980823 100644 --- a/core/src/io/anuke/mindustry/graphics/Palette.java +++ b/core/src/io/anuke/mindustry/graphics/Palette.java @@ -3,6 +3,8 @@ package io.anuke.mindustry.graphics; import com.badlogic.gdx.graphics.Color; public class Palette{ + public static final Color command = Color.valueOf("eab678"); + public static final Color bulletYellow = Color.valueOf("ffeec9"); public static final Color bulletYellowBack = Color.valueOf("f9c87a"); diff --git a/core/src/io/anuke/mindustry/input/DesktopInput.java b/core/src/io/anuke/mindustry/input/DesktopInput.java index 80a5c9ef35..ec6d5dd58d 100644 --- a/core/src/io/anuke/mindustry/input/DesktopInput.java +++ b/core/src/io/anuke/mindustry/input/DesktopInput.java @@ -9,6 +9,8 @@ import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.input.PlaceUtils.NormalizeDrawResult; import io.anuke.mindustry.input.PlaceUtils.NormalizeResult; +import io.anuke.mindustry.maps.generation.StructureFormat; +import io.anuke.mindustry.maps.generation.StructureFormat.StructBlock; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -19,7 +21,9 @@ import io.anuke.ucore.core.KeyBinds; import io.anuke.ucore.core.Settings; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Lines; +import io.anuke.ucore.input.Input; import io.anuke.ucore.scene.ui.layout.Unit; +import io.anuke.ucore.util.Log; import io.anuke.ucore.util.Mathf; import static io.anuke.mindustry.Vars.*; @@ -63,6 +67,23 @@ public class DesktopInput extends InputHandler{ } } + void printArea(NormalizeResult result){ + StructBlock[][] blocks = new StructBlock[Math.abs(result.x2 - result.x) + 1][Math.abs(result.y2 - result.y) + 1]; + + for(int x = 0; x <= Math.abs(result.x2 - result.x); x++){ + for(int y = 0; y <= Math.abs(result.y2 - result.y); y++){ + int wx = result.x + x; + int wy = result.y + y; + + Block block = world.tile(wx, wy).block(); + + blocks[x][y] = new StructBlock(block == Blocks.blockpart ? Blocks.air : block, world.tile(wx, wy).getRotation()); + } + } + + Log.info(StructureFormat.writeBase64(blocks)); + } + @Override public boolean isDrawing(){ return mode != none || recipe != null; @@ -259,12 +280,16 @@ public class DesktopInput extends InputHandler{ }else if(mode == breaking){ //touch up while breaking, break everything in selection NormalizeResult result = PlaceUtils.normalizeArea(selectX, selectY, cursor.x, cursor.y, rotation, false, maxLength); - for(int x = 0; x <= Math.abs(result.x2 - result.x); x++){ - for(int y = 0; y <= Math.abs(result.y2 - result.y); y++){ - int wx = selectX + x * Mathf.sign(cursor.x - selectX); - int wy = selectY + y * Mathf.sign(cursor.y - selectY); + if(debug && Inputs.keyDown(Input.CONTROL_LEFT)){ + printArea(result); + }else{ + for(int x = 0; x <= Math.abs(result.x2 - result.x); x++){ + for(int y = 0; y <= Math.abs(result.y2 - result.y); y++){ + int wx = selectX + x * Mathf.sign(cursor.x - selectX); + int wy = selectY + y * Mathf.sign(cursor.y - selectY); - tryBreakBlock(wx, wy); + tryBreakBlock(wx, wy); + } } } } diff --git a/core/src/io/anuke/mindustry/input/InputHandler.java b/core/src/io/anuke/mindustry/input/InputHandler.java index d82020a712..9fd32cde63 100644 --- a/core/src/io/anuke/mindustry/input/InputHandler.java +++ b/core/src/io/anuke/mindustry/input/InputHandler.java @@ -10,9 +10,7 @@ import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.effect.ItemDrop; import io.anuke.mindustry.entities.effect.ItemTransfer; import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest; -import io.anuke.mindustry.gen.CallBlocks; -import io.anuke.mindustry.gen.CallEntity; -import io.anuke.mindustry.net.In; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.ValidateException; import io.anuke.mindustry.type.ItemStack; @@ -57,7 +55,7 @@ public abstract class InputHandler extends InputAdapter{ //methods to override - @Remote(targets = Loc.client, called = Loc.server, in = In.entities) + @Remote(targets = Loc.client, called = Loc.server) public static void dropItem(Player player, float angle){ if(Net.server() && !player.inventory.hasItem()){ throw new ValidateException(player, "Player cannot drop an item."); @@ -67,7 +65,7 @@ public abstract class InputHandler extends InputAdapter{ player.inventory.clearItem(); } - @Remote(targets = Loc.both, forward = true, called = Loc.server, in = In.blocks) + @Remote(targets = Loc.both, forward = true, called = Loc.server) public static void transferInventory(Player player, Tile tile){ if(Net.server() && (!player.inventory.hasItem() || player.isTransferring)){ throw new ValidateException(player, "Player cannot transfer an item."); @@ -118,7 +116,7 @@ public abstract class InputHandler extends InputAdapter{ }); } - @Remote(targets = Loc.both, called = Loc.server, forward = true, in = In.blocks) + @Remote(targets = Loc.both, called = Loc.server, forward = true) public static void onTileTapped(Player player, Tile tile){ if(tile == null || player == null) return; tile.block().tapped(tile, player); @@ -189,7 +187,7 @@ public abstract class InputHandler extends InputAdapter{ //call tapped event if(tile.getTeam() == player.getTeam()){ - CallBlocks.onTileTapped(player, tile); + Call.onTileTapped(player, tile); } //consume tap event if necessary @@ -303,9 +301,9 @@ public abstract class InputHandler extends InputAdapter{ ItemStack stack = player.inventory.getItem(); if(tile.block().acceptStack(stack.item, stack.amount, tile, player) > 0 && tile.block().hasItems){ - CallBlocks.transferInventory(player, tile); + Call.transferInventory(player, tile); }else{ - CallEntity.dropItem(player.angleTo(x, y)); + Call.dropItem(player.angleTo(x, y)); } } @@ -337,7 +335,7 @@ public abstract class InputHandler extends InputAdapter{ } public boolean validBreak(int x, int y){ - return Build.validBreak(player.getTeam(), x, y); + return Build.validBreak(player.getTeam(), x, y) && Vector2.dst(player.x, player.y, x * tilesize, y * tilesize) < Player.placeDistance; } public void placeBlock(int x, int y, Recipe recipe, int rotation){ @@ -346,7 +344,6 @@ public abstract class InputHandler extends InputAdapter{ } public void breakBlock(int x, int y){ - //todo multiplayer support Tile tile = world.tile(x, y).target(); player.addBuildRequest(new BuildRequest(tile.x, tile.y)); diff --git a/core/src/io/anuke/mindustry/io/SaveIO.java b/core/src/io/anuke/mindustry/io/SaveIO.java index 98ed4b251c..69a5645382 100644 --- a/core/src/io/anuke/mindustry/io/SaveIO.java +++ b/core/src/io/anuke/mindustry/io/SaveIO.java @@ -49,9 +49,7 @@ public class SaveIO{ public static void loadFromSlot(int slot){ if(gwt){ - String string = Settings.getString("save-" + slot + "-data", ""); - ByteArrayInputStream stream = new ByteArrayInputStream(Base64Coder.decode(string)); - load(stream); + load(getSlotStream(slot)); }else{ load(fileFor(slot)); } @@ -113,14 +111,14 @@ public class SaveIO{ } public static void write(FileHandle file){ - write(file.write(false)); + write(new DeflaterOutputStream(file.write(false))); } public static void write(OutputStream os){ DataOutputStream stream; try{ - stream = new DataOutputStream(new DeflaterOutputStream(os)); + stream = new DataOutputStream(os); getVersion().write(stream); stream.close(); }catch(Exception e){ diff --git a/core/src/io/anuke/mindustry/io/TypeIO.java b/core/src/io/anuke/mindustry/io/TypeIO.java index fe5e57cf8f..c4c60d145c 100644 --- a/core/src/io/anuke/mindustry/io/TypeIO.java +++ b/core/src/io/anuke/mindustry/io/TypeIO.java @@ -12,6 +12,7 @@ import io.anuke.mindustry.entities.traits.CarriableTrait; import io.anuke.mindustry.entities.traits.CarryTrait; import io.anuke.mindustry.entities.traits.ShooterTrait; import io.anuke.mindustry.entities.units.BaseUnit; +import io.anuke.mindustry.entities.units.UnitCommand; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.net.Packets.AdminAction; import io.anuke.mindustry.net.Packets.KickReason; @@ -185,6 +186,16 @@ public class TypeIO{ return AdminAction.values()[buffer.get()]; } + @WriteClass(UnitCommand.class) + public static void writeCommand(ByteBuffer buffer, UnitCommand reason){ + buffer.put((byte) reason.ordinal()); + } + + @ReadClass(UnitCommand.class) + public static UnitCommand readCommand(ByteBuffer buffer){ + return UnitCommand.values()[buffer.get()]; + } + @WriteClass(Effect.class) public static void writeEffect(ByteBuffer buffer, Effect effect){ buffer.putShort((short) effect.id); diff --git a/core/src/io/anuke/mindustry/io/versions/Save16.java b/core/src/io/anuke/mindustry/io/versions/Save16.java index 80a7b8284e..498c77b44c 100644 --- a/core/src/io/anuke/mindustry/io/versions/Save16.java +++ b/core/src/io/anuke/mindustry/io/versions/Save16.java @@ -1,6 +1,5 @@ package io.anuke.mindustry.io.versions; -import com.badlogic.gdx.utils.IntMap; import com.badlogic.gdx.utils.TimeUtils; import io.anuke.mindustry.content.blocks.Blocks; import io.anuke.mindustry.content.blocks.StorageBlocks; @@ -12,7 +11,6 @@ import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Version; import io.anuke.mindustry.io.SaveFileVersion; import io.anuke.mindustry.maps.Map; -import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.BlockPart; import io.anuke.ucore.core.Timers; @@ -41,6 +39,7 @@ public class Save16 extends SaveFileVersion{ int sector = stream.readInt(); //sector ID //general state + byte mode = stream.readByte(); String mapname = stream.readUTF(); Map map = world.maps().getByName(mapname); @@ -59,19 +58,6 @@ public class Save16 extends SaveFileVersion{ state.spawner.read(stream); - //block header - - int blocksize = stream.readInt(); - - IntMap blockMap = new IntMap<>(); - - for(int i = 0; i < blocksize; i++){ - String name = stream.readUTF(); - int id = stream.readShort(); - - blockMap.put(id, Block.getByName(name)); - } - //entities byte groups = stream.readByte(); @@ -149,6 +135,18 @@ public class Save16 extends SaveFileVersion{ tiles[x][y] = tile; } + for(int i = 0; i < width * height; i++){ + boolean discovered = stream.readBoolean(); + int consecutives = stream.readUnsignedShort(); + if(discovered){ + for(int j = i + 1; j < i + 1 + consecutives; j++){ + int newx = j % width, newy = j / width; + tiles[newx][newy].setVisibility((byte) 1); + } + } + i += consecutives; + } + world.endMapLoad(); } @@ -171,16 +169,6 @@ public class Save16 extends SaveFileVersion{ state.spawner.write(stream); - //--BLOCK HEADER-- - - stream.writeInt(Block.all().size); - - for(int i = 0; i < Block.all().size; i++){ - Block block = Block.all().get(i); - stream.writeUTF(block.name); - stream.writeShort(block.id); - } - //--ENTITIES-- int groups = 0; @@ -247,5 +235,27 @@ public class Save16 extends SaveFileVersion{ i += consecutives; } } + + //write visibility, length-run encoded + for(int i = 0; i < world.width() * world.height(); i++){ + Tile tile = world.tile(i); + boolean discovered = tile.discovered(); + + int consecutives = 0; + + for(int j = i + 1; j < world.width() * world.height() && consecutives < 32767*2-1; j++){ + Tile nextTile = world.tile(j); + + if(nextTile.discovered() != discovered){ + break; + } + + consecutives++; + } + + stream.writeBoolean(discovered); + stream.writeShort(consecutives); + i += consecutives; + } } } diff --git a/core/src/io/anuke/mindustry/maps/Maps.java b/core/src/io/anuke/mindustry/maps/Maps.java index f30447fe9a..5b0ce56937 100644 --- a/core/src/io/anuke/mindustry/maps/Maps.java +++ b/core/src/io/anuke/mindustry/maps/Maps.java @@ -19,7 +19,7 @@ import static io.anuke.mindustry.Vars.*; public class Maps implements Disposable{ /**List of all built-in maps.*/ - private static final String[] defaultMapNames = {}; + private static final String[] defaultMapNames = {"sandbox"}; /**Tile format version.*/ private static final int version = 0; diff --git a/core/src/io/anuke/mindustry/maps/Sector.java b/core/src/io/anuke/mindustry/maps/Sector.java index 126fd84016..1618b0c694 100644 --- a/core/src/io/anuke/mindustry/maps/Sector.java +++ b/core/src/io/anuke/mindustry/maps/Sector.java @@ -4,8 +4,8 @@ import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.utils.Array; import io.anuke.mindustry.game.Saves.SaveSlot; import io.anuke.mindustry.game.SpawnGroup; -import io.anuke.mindustry.maps.goals.Goal; -import io.anuke.mindustry.maps.goals.WaveGoal; +import io.anuke.mindustry.maps.missions.Mission; +import io.anuke.mindustry.type.Item; import io.anuke.ucore.util.Bits; import static io.anuke.mindustry.Vars.control; @@ -19,12 +19,26 @@ public class Sector{ public int saveID = -1; /**Sector size; if more than 1, the coordinates are the bottom left corner.*/ public int size = 1; + /**Num of missions in this sector that have been completed so far.*/ + public int completedMissions; /**Display texture. Needs to be disposed.*/ public transient Texture texture; - /**Goal of this sector-- what needs to be accomplished to unlock it.*/ - public transient Goal goal = new WaveGoal(30); + /**Missions of this sector-- what needs to be accomplished to unlock it.*/ + public transient Array missions = new Array<>(); /**Enemies spawned at this sector.*/ - public transient Array spawns = new Array<>(); + public transient Array spawns; + /**Ores that appear in this sector.*/ + public transient Array ores = new Array<>(); + /**Difficulty of the sector, measured by calculating distance from origin and applying scaling.*/ + public transient int difficulty; + + public Mission currentMission(){ + return missions.get(Math.min(completedMissions, missions.size - 1)); + } + + public int getSeed(){ + return Bits.packInt(x, y); + } public SaveSlot getSave(){ return control.getSaves().getByID(saveID); diff --git a/core/src/io/anuke/mindustry/maps/Sectors.java b/core/src/io/anuke/mindustry/maps/Sectors.java index 1584e3f165..7202057ee1 100644 --- a/core/src/io/anuke/mindustry/maps/Sectors.java +++ b/core/src/io/anuke/mindustry/maps/Sectors.java @@ -5,13 +5,18 @@ import com.badlogic.gdx.graphics.Pixmap.Format; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.math.GridPoint2; import com.badlogic.gdx.utils.Array; +import io.anuke.mindustry.content.Items; +import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.maps.generation.WorldGenerator.GenResult; +import io.anuke.mindustry.maps.missions.BattleMission; +import io.anuke.mindustry.maps.missions.WaveMission; import io.anuke.mindustry.world.ColorMapper; import io.anuke.mindustry.world.Edges; import io.anuke.ucore.core.Settings; import io.anuke.ucore.util.Bits; import io.anuke.ucore.util.GridMap; +import io.anuke.ucore.util.Log; import io.anuke.ucore.util.Mathf; import static io.anuke.mindustry.Vars.*; @@ -26,6 +31,31 @@ public class Sectors{ Settings.json().addClassTag("Sector", Sector.class); } + public void playSector(Sector sector){ + if(!sector.hasSave()){ + world.loadSector(sector); + logic.play(); + sector.saveID = control.getSaves().addSave("sector-" + sector.packedPosition()).index; + world.sectors().save(); + world.setSector(sector); + }else{ + try{ + sector.getSave().load(); + world.setSector(sector); + state.set(State.playing); + }catch(Exception e){ + Log.err(e); + sector.getSave().delete(); + + playSector(sector); + + if(!headless){ + threads.runGraphics(() -> ui.showError("$text.sector.corrupted")); + } + } + } + } + /**If a sector is not yet unlocked, returns null.*/ public Sector get(int x, int y){ return grid.get(x, y); @@ -62,6 +92,7 @@ public class Sectors{ sector.y = (short)y; sector.complete = false; sector.size = isLarge ? 2 : 1; + initSector(sector); for(int cx = 0; cx < sector.size; cx++){ for(int cy = 0; cy < sector.size; cy++){ @@ -77,6 +108,7 @@ public class Sectors{ for(Sector sector : out){ createTexture(sector); + initSector(sector); for(int cx = 0; cx < sector.size; cx++){ for(int cy = 0; cy < sector.size; cy++){ grid.put(sector.x + cx, sector.y + cy, sector); @@ -100,10 +132,26 @@ public class Sectors{ Settings.save(); } - private int round2(int i){ - if(i < 0){ - i --; + private void initSector(Sector sector){ + double waveChance = 0.3; + + sector.difficulty = (int)(Mathf.dst(sector.x, sector.y)); + + if(sector.difficulty == 0){ + sector.missions.add(new WaveMission(10)); + }else{ + sector.missions.add(Mathf.randomSeed(sector.getSeed() + 1) < waveChance ? new WaveMission(Math.min(sector.difficulty*5 + Mathf.randomSeed(sector.getSeed(), 0, 3)*5, 100)) + : new BattleMission()); } + + sector.spawns = sector.missions.first().getWaves(sector); + + //add all ores for now since material differences aren't well handled yet + sector.ores.addAll(Items.tungsten, Items.coal, Items.lead, Items.thorium, Items.titanium); + } + + private int round2(int i){ + if(i < 0) i --; return i/2*2; } diff --git a/core/src/io/anuke/mindustry/maps/generation/FortressGenerator.java b/core/src/io/anuke/mindustry/maps/generation/FortressGenerator.java new file mode 100644 index 0000000000..77c92d86b3 --- /dev/null +++ b/core/src/io/anuke/mindustry/maps/generation/FortressGenerator.java @@ -0,0 +1,231 @@ +package io.anuke.mindustry.maps.generation; + +import com.badlogic.gdx.math.Rectangle; +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.utils.Array; +import io.anuke.mindustry.content.Items; +import io.anuke.mindustry.content.blocks.Blocks; +import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.maps.generation.StructureFormat.StructBlock; +import io.anuke.mindustry.type.AmmoType; +import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.blocks.defense.turrets.ItemTurret; +import io.anuke.mindustry.world.blocks.defense.turrets.PowerTurret; +import io.anuke.mindustry.world.blocks.units.ResupplyPoint; +import io.anuke.ucore.util.Mathf; + +import static io.anuke.mindustry.Vars.world; + +public class FortressGenerator{ + private final static int minCoreDst = 60; + + private static Structure[] structures; + private static Structure[] bases; + + private int enemyX, enemyY, coreX, coreY; + private Team team; + private Generation gen; + + private static void init(){ + if(structures != null) return; + + String vaults = "BQMADWNhcmJpZGUtZHJpbGwCAA10dW5nc3Rlbi13YWxsAQATdHVuZ3N0ZW4td2FsbC1sYXJnZQAAA2FpcgQABXZhdWx0CQUAAgABAAEAAQABAAIAAAABAAAAAAACAAAAAQAAAAABAQABAgEBAQAAAAIAAgMBAAEAAAICAAAAAAAAAgACAgAABAIAAAIAAgIAAAAAAAACAAICAgMCAwIDAgM="; + + structures = new Structure[]{ + //tiny duo outpost + new Structure(0.03f, Items.tungsten, "BAMADnR1bmdzdGVuLWRyaWxsAgADZHVvAQANdHVuZ3N0ZW4td2FsbAAAA2FpcgMFAQABAwEDAQMBAAEAAgMDAwIDAQABAAEBAQEBAQEA"), + + //basic outposts with duos + new Structure(0.03f, Items.tungsten, "BAIAA2R1bwMADWNhcmJpZGUtZHJpbGwBAA10dW5nc3Rlbi13YWxsAAADYWlyBQUAAAEAAQABAAAAAQABAAIAAQABAAEAAgADAwIAAQABAAEAAgABAAEAAAABAAEAAQAAAA=="), + + //more advanced duo outpost + new Structure(0.04f, Items.lead, "BwYADnR1bmdzdGVuLWRyaWxsAwADZHVvBAAIc3BsaXR0ZXIBAA10dW5nc3Rlbi13YWxsAgATdHVuZ3N0ZW4td2FsbC1sYXJnZQAAA2FpcgUACGNvbnZleW9yCQkAAAAAAQEBAQEBAQEBAgAAAAAAAAICAAEDAAQDAwACAgAAAAABAgACAAABAgUCAQEAAAAAAQABAgMAAQIBAgUCAQEBAQMAAQABAgQCBQMFAwYCBQEFAQQDAQABAgMAAQEBAQUAAQMBAwMAAQABAwICAAMBAQUAAQMCAgADAQMAAAAAAAIDAAQDAwAAAwADAAAAAAAAAQIBAwEDAQMBAwAAAAA="), + + //tungsten duo and drone outpost + new Structure(0.02f, Items.tungsten, "BgEADXR1bmdzdGVuLXdhbGwEAA1jYXJiaWRlLWRyaWxsAwADZHVvAgATdHVuZ3N0ZW4td2FsbC1sYXJnZQAAA2FpcgUACWRyb25lLXBhZAUHAAAAAAEDAQMCAgAAAAAAAAAAAQADAAADAAMBAgAAAAABAAQBBQAAAAECAAAAAAEAAwAAAAAAAQIAAAAAAQABAQEBAQEBAg=="), + + //resupply point + new Structure(0.03f, Items.lead, "BgEADXR1bmdzdGVuLXdhbGwCAAtzb2xhci1wYW5lbAUAA2R1bwMADnJlc3VwcGx5LXBvaW50AAADYWlyBAANY2FyYmlkZS1kcmlsbAUFAQABAAEAAAAAAAEAAgMBAQEBAQABAAMDBAEFAQEAAQACAwEBAQEBAAEBAQEBAQAAAAA="), + + //lead storage + new Structure(0.02f, Items.lead, vaults), + + //mini dagger outpost + new Structure(0.02f, Items.lead, "CwIADXR1bmdzdGVuLXdhbGwGAAhjb252ZXlvcgUAA2R1bwgACmRhZ2dlci1wYWQBABN0dW5nc3Rlbi13YWxsLWxhcmdlBwAIc3BsaXR0ZXIDAA5yZXN1cHBseS1wb2ludAoADHJlcGFpci1wb2ludAkADnR1bmdzdGVuLWRyaWxsAAADYWlyBAALc29sYXItcGFuZWwHCQAAAAABAAABAgECAQIBAAAAAAEAAAMAAwADAwEEAAIBAgICAgAAAAAFAwYDBwMCAQIBBQECAgAAAAAIAAAACQMGAQYBBwMCAgAAAAAAAAAAAQMAAAIDBQECAgEAAAAKAQQBAAAAAAIBAgECAgAAAAACAQIBAgEAAAAAAAAAAA=="), + + //salvo outpost + new Structure(0.02f, Items.tungsten, "BAIABXNhbHZvAwANY2FyYmlkZS1kcmlsbAAAA2FpcgEADGNhcmJpZGUtd2FsbAcHAAAAAAEDAQMBAwEDAAABAwEDAQMCAAAAAQMAAAEAAgAAAAAAAAABAwEDAQAAAAAAAwACAAAAAQIBAAEBAgAAAAAAAAABAgAAAQEAAAAAAQEBAQEBAAABAQEBAQEBAQAAAAA="), + + //advanced laser outpost + new Structure(0.03f, null, "BQIABmxhbmNlcgEAEmNhcmJpZGUtd2FsbC1sYXJnZQQAEXNvbGFyLXBhbmVsLWxhcmdlAAADYWlyAwALc29sYXItcGFuZWwLCwAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAMAAwAAAAAAAwABAAAAAAABAAAAAgAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAQAAAACAAAAAQAAAAAAAQAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAIAAAADAAMAAQAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), + + //titanium storage + new Structure(0.02f, Items.titanium, vaults), + + //2x interceptor outpost + new Structure(0.02f, Items.lead, "CgMAEXNvbGFyLXBhbmVsLWxhcmdlBgADZHVvAgAPaW50ZXJjZXB0b3ItcGFkBAASY2FyYmlkZS13YWxsLWxhcmdlBwAOcmVzdXBwbHktcG9pbnQAAANhaXIFAAtzb2xhci1wYW5lbAEADGNhcmJpZGUtd2FsbAkAC2Rpc3RyaWJ1dG9yCAALbGFzZXItZHJpbGwKCAEAAQMBAwEDAQMBAwECAAABAAIDAAAAAAAAAAABAgAAAQAAAAAAAAADAQAAAQIBAgQDAAAFAAAAAAAAAAYCAQMAAAAABwAIAAAACQAAAAECBAMAAAEAAAAAAAABAAABAgAAAAAFAAAAAAAAAAYCAQIBAAIDAAAAAAMBAAABAgECAQAAAAAAAAAAAAAAAQIAAAEAAQEBAQEBAQEBAQEBAAA="), + + //resupply point (again) + new Structure(0.02f, Items.lead, "BgEADXR1bmdzdGVuLXdhbGwCAAtzb2xhci1wYW5lbAUAA2R1bwMADnJlc3VwcGx5LXBvaW50AAADYWlyBAANY2FyYmlkZS1kcmlsbAUFAQABAAEAAAAAAAEAAgMBAQEBAQABAAMDBAEFAQEAAQACAwEBAQEBAAEBAQEBAQAAAAA="), + + //coal laser outpost + new Structure(0.03f, null, "BgEADHRob3JpdW0td2FsbAMABmxhbmNlcgUAFGNvbWJ1c3Rpb24tZ2VuZXJhdG9yBAANY2FyYmlkZS1kcmlsbAAAA2FpcgIAC3NvbGFyLXBhbmVsBwcAAAEAAQABAQEBAQEBAAAAAQACAgMAAAACAAEAAAABAAICAAAAAAIAAQAAAAEAAQAEAQUAAQABAAAAAQACAAMBAAMCAAEAAAABAAIAAAMAAwIAAQAAAAEAAQABAwEDAQABAA=="), + + //ultimate laser outpost + new Structure(0.02f, null, "BgMABmxhbmNlcgIAEmNhcmJpZGUtd2FsbC1sYXJnZQUAEXNvbGFyLXBhbmVsLWxhcmdlAAADYWlyBAALc29sYXItcGFuZWwBAAxjYXJiaWRlLXdhbGwPDwAAAAAAAAAAAAABAwIDAAABAwAAAAAAAAAAAAAAAAAAAAACAwAAAgMAAAAAAAACAwAAAgMAAAAAAAAAAAAAAQMAAAAAAAAAAAMDAAAAAAAAAAAAAAIDAAAAAAAAAgMAAAMDAAAEAwAAAAADAwAAAwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIDAAAAAAAAAgMAAAMDAAAAAAUDAAAAAAAAAAAEAwAAAAABAwEDAAAAAAAAAAAAAAAAAAAAAAUDAAADAwAAAgMAAAIDAAADAwAAAAAAAAAABAMAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAFAwAAAAAAAAAAAwMAAAIDAAABAwEDAgMAAAQDAAAAAAAAAAAFAwAAAAAAAAAAAAAAAAAAAAAAAAMDAAADAwAAAAAAAAAAAwMAAAIDAAAAAAAAAgMAAAAAAAAAAAAAAwMAAAQDAAAAAAAAAAAAAAAAAAAAAAIDAAACAwAAAAAAAAIDAAACAwAAAQMAAAAAAAABAwAAAAAAAAAAAgMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDAAAAAAEDAAAAAAAAAAAAAA=="), + + //fabricator outpost + new Structure(0.02f, Items.tungsten, "BgUADWNhcmJpZGUtZHJpbGwBABJ0aG9yaXVtLXdhbGwtbGFyZ2UCAAx0aG9yaXVtLXdhbGwEAANkdW8AAANhaXIDAA5mYWJyaWNhdG9yLXBhZAkJAAAAAAEDAAACAwEDAAAAAAAAAAACAwADAAMCAwADAAMCAgAAAQMAAAMCAAACAAMCAAABAwAAAAAAAAAAAAAEAgAAAAAAAgAAAgMCAAIBBAIFAAQCAgMCAgIDAQMAAAMCAAAEAgMCAAABAwAAAAAAAAAAAAACAQAAAAAAAgAAAAACAAEDAAECAQEDAAECAQAAAAAAAAAAAAACAwACAAAAAAAA"), + + //coal storage + new Structure(0.02f, Items.coal, vaults), + }; + + bases = new Structure[]{ + //primitive 4-spawner base + new Structure("CAQADXR1bmdzdGVuLXdhbGwFAANkdW8HAARjb3JlAQAKZGFnZ2VyLXBhZAYACHVubG9hZGVyAgAMcmVwYWlyLXBvaW50AAADYWlyAwALc29sYXItcGFuZWwJBwAAAQMAAAIDAQMAAAAAAAAAAAAAAwIAAAAAAAAEAAQBBAEEAQQBBAEEAgQABQIAAAAAAAAFAgQCBAAGAwAABwAAAAYDBAAEAAUCAAAAAAAABQIEAAQABAMEAwQDBAMEAAQAAAABAwAAAwIBAwAAAAAAAAAAAAACAwAAAAAAAA=="), + + //more advanced base, 8 spawners + new Structure("CQIADXR1bmdzdGVuLXdhbGwGAANkdW8IAARjb3JlAQAKZGFnZ2VyLXBhZAcACHVubG9hZGVyBAATdHVuZ3N0ZW4td2FsbC1sYXJnZQUADHJlcGFpci1wb2ludAAAA2FpcgMAC3NvbGFyLXBhbmVsCwsAAAAAAQEAAAAAAAAAAAEBAAAAAAAAAAAAAAAAAAACAwMAAgMAAAAAAAAAAAEBAAAEAAAAAgMFAAIDBAAAAAEBAAAAAAAAAAAAAAYABwIGAAAAAAAAAAAAAAACAAIABgAAAAAAAAAGAAICAgAAAAAAAwAFAAcCAAAIAAAABwIFAAMAAAAAAAIAAgAGAAAAAAAAAAYAAgICAAAAAQEAAAQAAAAGAAcCBgAEAAAAAQEAAAAAAAAAAAAAAgEFAAIBAAAAAAAAAAAAAAAAAQEAAAIDAwACAwEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), + + //rather advanced flyer base, no ground units, drones + new Structure("DQIADXR1bmdzdGVuLXdhbGwHAAhjb252ZXlvcgMAA2R1bwwABGNvcmULAAh1bmxvYWRlcgEAE3R1bmdzdGVuLXdhbGwtbGFyZ2UGAA9pbnRlcmNlcHRvci1wYWQFAAhzcGxpdHRlcgoADHJlcGFpci1wb2ludAQABXNhbHZvAAADYWlyCAAJZHJvbmUtcGFkCQALc29sYXItcGFuZWwREQAAAAAAAAAAAAAAAAEAAAACAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAAAAwAAAAAAAgABAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAADAAUAAwAEAAAAAAAAAAAAAAAAAAAAAQAAAAYAAAAAAAAAAgMHAgIDAAAAAAYAAAABAAAAAAAAAAAAAAAAAAAAAgMHAgcDBQEHAQcCAgMAAAAAAAAAAAAAAAACAAQAAAACAwgAAAAJAAcCCQAIAAAAAgMEAAAAAgAAAAEAAAAAAAAABwMAAAAACgMLAgoDAAAAAAcBAAAAAAEAAAAAAAAAAwACAwcCCQAKAwAAAAAAAAoDCQAHAgIDAwAAAAAAAgADAAUABwMFAAcDCwIAAAwAAAALAwcBBQIHAQUAAwACAAEAAAADAAIDBwAJAAoDAAAAAAAACgMJAAcAAgMDAAEAAAAAAAAABAAAAAcDCAAAAAoDCwMKAwgAAAAHAQQAAAAAAAAAAAACAAAAAAACAwAAAAAJAAcACQAAAAAAAgMAAAAAAgAAAAAAAQAAAAYAAAACAwcABwMFAgcBBwACAwYAAAABAAAAAAAAAAAAAAAAAAAABAAAAAIDBwACAwQAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAADAAUDAwAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAEAAAADAAEAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAA"), + + //advanced carbide base with fabricators, drones + new Structure("Ew4ADXR1bmdzdGVuLXdhbGwHABFzb2xhci1wYW5lbC1sYXJnZRAACGNvbnZleW9yDAADZHVvEgAEY29yZQMACmRhZ2dlci1wYWQRAAh1bmxvYWRlcgkAD2ludGVyY2VwdG9yLXBhZA8ACHNwbGl0dGVyBgAGbGFuY2VyDQARdGl0YW5pdW0tY29udmV5b3IBABJjYXJiaWRlLXdhbGwtbGFyZ2ULAAxyZXBhaXItcG9pbnQIAAVzYWx2bwAAA2FpcgUACXRpdGFuLXBhZAoAC3NvbGFyLXBhbmVsAgAMY2FyYmlkZS13YWxsBAAOZmFicmljYXRvci1wYWQTFQAAAAAAAAAAAAAAAAAAAQMAAwAAAAAAAAEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAAAAAAIBAAEAAQAAAAAAAAABAAECAQAAAAACAgAAAAAAAAAAAAAAAAICAwAAAAICBAAAAAAABQAAAAQAAAACAAMAAAACAgAAAAAAAAAAAAAAAAICAAAAAAICAAAAAAAAAAAAAAAAAAACAAAAAAACAgAAAAAAAAAAAAAAAAEAAAABAAAABgAAAAAAAAAAAAYAAAABAAAAAQAAAAAAAAAAAAIAAQIAAAAAAAAAAAAAAAMAAwAABwAAAAAAAAAAAAAAAAAAAAECAAACAAIAAAAAAAEAAAAIAAAACQAAAAAAAAAAAAkAAAAIAAAAAQAAAAAAAAACAAIACAMAAAAAAAAAAAAAAAAAAAoACwAKAAAAAAAAAAAAAAAAAAgDAAACAAIAAAAAAAIADAMMAw0CDgAMAAAAAAAAAAwADgANAgwBDAECAAAAAAACAAIAAgMPAw0DDwAPAw8AEAMRAgAAEgAAABECEAEPAA8DDwANAQ8DAgMCAAIACAMAAAIADAMMAw0ADgAMAAAAAAAAAAwADgANAAwBDAECAAgDAAACAAIAAAAAAAEAAAAIAAAACQAAAAoACwAKAAkAAAAIAAAAAQAAAAAAAAACAAIAAQIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAAACAAIAAAIAAAEAAAABAAAABgAAAAAABwAAAAYAAAABAAAAAQAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAwAAAAICBAAAAAAAAAAAAAQAAAACAAMAAAACAAAAAAAAAAAAAAAAAAIAAAAAAAICAAAAAAAABQAAAAAAAAACAAAAAAACAAAAAAAAAAAAAAAAAAIAAAAAAAICAQMAAwAAAAAAAAEDAAMCAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAA=="), + + //lots of titans and daggers + new Structure("DAcACHNwbGl0dGVyBgADZHVvCwAEY29yZQMACmRhZ2dlci1wYWQKAAh1bmxvYWRlcggAEXRpdGFuaXVtLWNvbnZleW9yAgASY2FyYmlkZS13YWxsLWxhcmdlBQAFc2Fsdm8AAANhaXIEAAl0aXRhbi1wYWQBAAxjYXJiaWRlLXdhbGwJAAtkaXN0cmlidXRvchMTAAAAAAECAAAAAAAAAAAAAAECAAABAgAAAAAAAAAAAAABAgAAAAAAAAIDAAAAAAAAAAAAAAAAAQIBAAECAAAAAAAAAAAAAAIDAAAAAAECAAAAAAAAAAAAAAMAAAABAgEAAQIDAAAAAAAAAAAAAAAAAAECAAAAAAAAAAAAAAAAAAMAAAECAQABAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAFAwAABgAHAAYABQMAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAgCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAFAwAACQAAAAYDCAIGAwkAAAAFAwAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCgMKAAoDAAAAAAAAAAAAAAAAAAAAAAECAQMBAwEDBgABAAYDCgMAAAAAAAAKAwYDAQAGAAEBAQEBAQECAAABAwEDAQMHAAgDCAMKAAAACwAAAAoACAEIAQcAAQEBAQEBAAABAgEDAQMBAwYAAQAGAwoDAAAAAAAACgMGAwEABgABAQEBAQEBAgAAAAADAAAABQMAAAkAAAAKAwoACgMJAAAABQMAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYDCAAGAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAwAAAQMIAAEDBQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAGAAcABgAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAECAQABAAMAAAAAAAAAAAAAAAAAAAABAgIDAAAAAAAAAAAAAAAAAQIBAAEAAAAAAAADAAMAAwIDAAABAgAAAAAAAAAAAAAAAAAAAAABAgEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAAAAAAAAAAAAAAECAAABAgAAAAAAAAAAAAABAgAAAAA="), + + //superfortress + new Structure("EwwAEXNvbGFyLXBhbmVsLWxhcmdlDgADZHVvEgAEY29yZQMACmRhZ2dlci1wYWQQAAttb25zb29uLXBhZBEACHVubG9hZGVyCgAPaW50ZXJjZXB0b3ItcGFkCQAGbGFuY2VyDwARdGl0YW5pdW0tY29udmV5b3ICABJjYXJiaWRlLXdhbGwtbGFyZ2UGAA5yZXN1cHBseS1wb2ludAQADHJlcGFpci1wb2ludAsABXNhbHZvAAADYWlyCAAJZHJvbmUtcGFkBwAJdGl0YW4tcGFkBQALc29sYXItcGFuZWwBAAxjYXJiaWRlLXdhbGwNAAtkaXN0cmlidXRvch8fAAAAAAAAAAAAAAAAAAABAwAAAAAAAAAAAAACAgAAAQICAgAAAAAAAAAAAAAAAAECAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDAAAAAAAAAAAAAAAAAAABAgAAAAAAAAAAAAAAAAAAAQIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAAAAAAAAAAADAgAABAEFAQYBBQEEAQMCAAAAAAAAAAACAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAAAAAAAABwIAAAAAAAAIAgAABQEIAgAAAAAAAAAABwIAAAAAAAABAgAAAAAAAAAAAAAAAAAAAAAAAAICAAAJAgAAAAAAAAAACgMAAAAAAAABAAAAAAAKAwAAAAAAAAAACQIAAAICAAAAAAAAAAAAAAAAAAAAAAECAAAAAAAAAAAAAAAAAAAAAAAACwAAAAEACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAAAAAAAAAAAAAAICAAAJAgAACQIAAAAADAAAAAsAAAAAAAAAAQAAAAAACwAAAAAADAAAAAkCAAAJAgAAAgIAAAAAAAABAwEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0AAAAOAg0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAAAA4CAAAAAAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwIAAAAADAAAAAAADAAAAAAAAAABAQ8CDwIPAgEAAAAAAAAADAAAAAAADAAAAAAABwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBDwIPAg8CAQABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAgAACgMAAAsAAAALAAAAAQIAAAAAAAAPAg8CDwIAAAAAAAABAQsAAAALAAAACgMAAAMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgAAEAIAAA8CDwIPAgAAEAIAAAEAAAIAAAAAAAAAAAAAAAAAAAAAAAACAgAABAEIAgAACwEAAA0AAAABAQEBAAAAAAAAEQARABEAAAAAAAAAAQABAA0AAAALAQAACAIAAAQBAgIAAAAAAAAFAQAAAAAAAAAAAAAAAA8DDwMPAw8DEQMAAAAAAAARAw8BDwEPAQ8BAAAAAAAAAAAAAAAABQEAAAAAAQMBAwYBBQEBAQEBAQEOAg4CDwMPAw8DDwMRAAAAEgAAABEADwEPAQ8BDwEOAQ4BAQEBAQEBBQEGAQEBAQECAgAABQEIAgAACwEAAA0AAAAPAw8DDwMPAxEDAAAAAAAAEQMPAQ8BDwEPAQ0AAAALAQAACAIAAAUBAgIAAAAAAAAEAQAAAAAAAAAAAAAAAAECAQIAAAAAAAARAxEAEQMAAAAAAAABAwEDAAAAAAAAAAAAAAAABAEAAAAAAAAAAAMCAAAKAwAACwAAAAsAAAABAgAAEAIAAA8ADwAPAAAAEAIAAAEACwAAAAsAAAAKAwAAAwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAAAAAAAADwAPAA8AAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEPAA8ADwABAwEDAQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwIAAAAADAAAAAAADAAAAAsAAAABAQ8ADwAPAAEDCwAAAAAADAAAAAAADAIAAAAABwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0AAAAOAA0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDAQMCAgAACQIAAAkCAAAAAAAAAAALAAAAAAAAAA4AAAAAAAsAAAAAAAAAAAAJAgAACQIAAAICAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAALAQAAAQILAQAAAAAAAAAADAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgICAAAJAgAAAAAAAAAACgMAAAAAAAABAgAAAAAKAwAAAAAAAAAACQIAAAICAAABAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAIAAAECCAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAgIAAAAABwIAAAMCAAAAAAAABQEAAAAAAwIAAAAABwIAAAICAAABAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBBQEGAQUBBAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAgIAAAEAAgIAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAA="), + + //welcome to drone hell + new Structure("CwcAEXNvbGFyLXBhbmVsLWxhcmdlCQAMdGhvcml1bS13YWxsCgAEY29yZQUACmRhZ2dlci1wYWQDAAZsYW5jZXIBABJjYXJiaWRlLXdhbGwtbGFyZ2UGAAxyZXBhaXItcG9pbnQAAANhaXIIAAlkcm9uZS1wYWQEAAtzb2xhci1wYW5lbAIADGNhcmJpZGUtd2FsbBERAQMAAAEAAAACAwIDAAAAAAICAAAAAAIBAgEBAwAAAQMAAAAAAAAAAAAAAwAAAAAAAAACAgADAAMDAAAAAAAAAAAAAAABAAAABAEEAwAAAAAFAwAABgEFAwAAAAAAAAQBBAEBAwAAAAAAAAQDAAAAAAAAAAAAAAQCAAAAAAAAAAAAAAQBAAAAAAIAAwAAAAAABwMAAAgBAAAJAAgBAAAAAAcDAAADAAAAAgACAAAAAAAAAAAAAAAAAAAACQAAAAAAAAAAAAAAAAAAAAIAAAAAAAUDAAAIAQAACQMJAwkDCQMJAwgBAAAFAwAAAAAAAAAAAAAAAAAAAAAAAAkAAAAAAAAACQIAAAAAAAAAAAAAAAACAwIDBgEEAgkBCQEJAAAACgAAAAkCCQEJAQQCBgECAQIBAAAAAAUDAAAIAQAACQAAAAAAAAAJAggBAAAFAwAAAAAAAAAAAAAAAAAAAAEAAAkACQEJAQkBCQEAAAAAAAAAAAAAAAACAAMAAAAAAAAAAAAIAQAACQIIAQAAAAAAAAAAAwAAAAIAAgAAAAAAAAAHAwAAAAAAAAkCAAAAAAAABwMAAAAAAAACAAEDAAAEAAAAAAAAAAUDAAAEAgUDAAAAAAAAAAAEAAEDAAAAAAAABAAEAAMAAAAAAAAABgEAAAAAAwAAAAQABAAAAAAAAQMAAAEDAAAAAAAAAAAAAAIAAAAAAAAAAAABAwAAAQMAAAAAAAAAAAAAAgMCAwAAAAACAAAAAAACAQIBAAAAAAAAAAA="), + + //welcome to bomber/interceptor hell + new Structure("DgUACHNwbGl0dGVyBgAEaGFpbAIAEnRob3JpdW0td2FsbC1sYXJnZQEADHRob3JpdW0td2FsbAQAA2R1bw0ABGNvcmULAAttb25zb29uLXBhZAwACHVubG9hZGVyCgAPaW50ZXJjZXB0b3ItcGFkCAARdGl0YW5pdW0tY29udmV5b3IDAAVzYWx2bwkABnJpcHBsZQAAA2FpcgcAC2Rpc3RyaWJ1dG9yGRkAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAgIAAAEAAgMAAAIDAAACAwAAAwIAAAQBAwIAAAIDAAACAwAAAgMAAAEAAgIAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAEBAQEAAAAAAAAGAQYBAwIAAAcAAAAIAgcAAAADAgAABgEGAQAAAAAAAAEBAQEAAAAAAgIAAAAACQEAAAoCAAAAAAAAAAAAAAgCAAAAAAAAAAAKAgAAAAAJAQAAAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgCCAIIAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAAAGAAoCAAAKAwAAAAALAwAACAIIAggCAAALAwAACgMAAAoCAAAGAAICAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAIAggCCAIAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAACAgAAAwIAAAAAAAAAAAAAAAAAAAgCCAIIAgAAAAAAAAAAAAAAAAMCAAACAgAAAAABAAAAAAAAAAAAAAALAwAAAAALAwAACAIIAggCAAALAwAAAAALAwAAAAAAAAAAAAABAAEAAwIAAAcAAAAAAAAAAAAAAAAAAAAMAwwBDAIAAAAAAAAAAAAAAAAHBQAAAwIAAAEAAQAAAAAAAAAAAAgDCAMIAwgDCAMMAQAAAAAAAAwCCAEIAQgBCAEIAQAAAAAAAAAAAQABAAQBBQAIAwgDCAMIAwgDCAMIAwwDAAANAAAADAMIAQgBCAEIAQgBCAEIAQUABAEBAAEAAwIAAAcAAAAIAwgDCAMIAwgDDAIAAAAAAAAMAwgBCAEIAQgBCAEHAAAAAwIAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAwCDAMMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAAIAAAADAgAAAAALAwAAAAALAwAACAAIAAgAAAALAwAAAAALAwAAAwIAAAIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAABgAKAgAACgMAAAAAAAAAAAgACAAIAAAAAAAAAAoDAAAKAgAABgACAAAAAAAAAAAAAAEGAAAAAAAAAAAAAAALAwAACAAIAAgAAAALAwAAAAAAAAAAAAAGAAAAAAAAAAAAAgAAAAAAAAAAAAoCAAAAAAAAAAAIAAgACAAAAAAAAAAKAgAAAAAAAAAAAgAAAAAAAAAAAAAAAAAJAQAAAAAAAAMCAAAHBQAACAAHAAAAAwIAAAAAAAAAAAkBAAAAAAAAAAAAAAEBAQEAAAAAAAAGAQYBAAAAAAAAAAAIAAAAAAAAAAAABgMGAwAAAAAAAAEBAQEAAAAAAgMAAAEAAgMAAwIDAAACAwAAAwIAAAUAAwIAAAIBAAACAQAAAgEAAAEDAgMAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAABAEAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAA=="), + + //welcome to unit hell + new Structure("DQoACHNwbGl0dGVyBAAMdGhvcml1bS13YWxsDAAEY29yZQEACmRhZ2dlci1wYWQHAAttb25zb29uLXBhZAsACHVubG9hZGVyCAAPaW50ZXJjZXB0b3ItcGFkBQARdGl0YW5pdW0tY29udmV5b3IJAAxyZXBhaXItcG9pbnQDAAVzYWx2bwAAA2FpcgIACXRpdGFuLXBhZAYAC3NvbGFyLXBhbmVsFRUAAAAAAAAAAAAAAAABAQAAAQEAAAAAAQEAAAEBAAAAAAAAAAAAAAAAAAAAAAIBAAAAAAIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAAAAAAIBAAAAAAAAAAAAAAAAAAADAQAABAAEAAAABAAEAAMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQMGAAAABgAFAQAAAAAAAAAAAAAAAAAAAAAAAAIBAAAAAAcDAAAIAwAABQIJAAAACQAFAggDAAAAAAcDAAAAAAIBAAAAAAAAAAAAAAAAAAAAAAAABQIKAAACCgAFAgAAAAAAAAAAAAAAAAAAAAABAQAAAwEAAAgDAAAAAAAAAAAFAgACBQIAAAAAAAAIAwAAAwEAAAEBAAAAAAAAAAAAAAAAAAAAAAcDAAAFAgACBQIAAAcDAAAAAAAAAAAAAAAAAAABAQAABAMFAgUDBQMAAAAAAAALAQACCwEAAAAAAAAFAQUBBQIEAQEBAAAAAAAABAMGAAkACgAFAwUDCwIAAAAAAAALAQUBBQEKAAkABgAEAQAAAAAAAAAAAAAAAAAAAAMAAwADAAIAAAwAAAAAAgABAAEAAQAAAAAAAAAAAAABAQAABAMGAAkACgAFAwUDCwAAAAAAAAALAgUBBQEKAAkABgAEAQEBAAAAAAAABAMFAAUDBQMAAAAAAAALAQABCwAAAAAAAAAFAQUBBQAEAQAAAAABAQAAAwEAAAgDAAAAAAcDAAAFAAAABQAAAAcDAAAIAwAAAwEAAAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAwAABQAKAAAACgAFAAgDAAAAAAAAAAAAAAAAAAAAAAIBAAAAAAcDAAAAAAAABQAJAAAACQAFAAAAAAAAAAcDAAAAAAIBAAAAAAAAAAAAAAAAAAADAQAABQMGAAAABgAFAQMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAIBAAAAAAIBAAEBAQAAAQEAAAAAAQEAAAEBAAAAAAIBAAAAAAIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAA=") + }; + } + + public void generate(Generation gen, Team team, int coreX, int coreY, int enemyX, int enemyY){ + init(); + + this.enemyX = enemyX; + this.enemyY = enemyY; + this.coreX = coreX; + this.coreY = coreY; + this.gen = gen; + this.team = team; + + genOutposts(); + } + + void genOutposts(){ + int padding = 10; + int maxDifficulty = 13; + Array selected = new Array<>(); + Array used = new Array<>(); + Rectangle rect = new Rectangle(); + Structure base = bases[Mathf.clamp((int)(bases.length * (float)gen.sector.difficulty / maxDifficulty) + gen.random.range(2), 0, bases.length-1)]; + + int maxIndex = (int)(1 + ((float)gen.sector.difficulty / maxDifficulty * (structures.length-2))); + + for(int i = maxIndex/2; i < maxIndex; i++){ + selected.add(structures[i]); + } + + float baseChance = 0.8f / selected.size; + + used.add(new Rectangle(enemyX - base.width()/2, enemyY - base.height()/2, base.width(), base.height())); + int elev = gen.tiles[enemyX][enemyY].getElevation(); + for(int x = 0; x < base.width(); x++){ + for(int y = 0; y < base.height(); y++){ + Tile tile = gen.tiles[enemyX - base.width()/2 + x][enemyY - base.height()/2 + y]; + StructBlock block = base.layout[x][y]; + tile.setElevation(elev); + tile.setRotation(block.rotation); + tile.setBlock(block.block, team); + } + } + + for(Structure struct : selected){ + for(int x = padding; x < gen.width - padding; x++){ + loop: + for(int y = padding; y < gen.height - padding; y++){ + rect.set(x - struct.layout.length, y - struct.layout[0].length, struct.layout.length, struct.layout[0].length); + if(Vector2.dst(x, y, coreX, coreY) > minCoreDst && Vector2.dst(x, y, enemyX, enemyY) > 30 && world.tile(x, y).floor().liquidDrop == null && + (struct.ore == null || gen.tiles[x][y].floor().dropsItem(struct.ore)) && gen.random.chance(struct.chance * baseChance)){ + for(Rectangle other : used){ + if(other.overlaps(rect)){ + continue loop; + } + } + used.add(new Rectangle(rect.x - 1, rect.y - 1, rect.width + 2, rect.height + 2)); + int elevation = world.tile(x, y).getElevation(); + for(int cx = 0; cx < struct.layout.length; cx++){ + for(int cy = 0; cy < struct.layout[0].length; cy++){ + int wx = x + cx - struct.layout.length/2; + int wy = y + cy - struct.layout[0].length/2; + StructBlock block = struct.layout[cx][cy]; + Tile tile = world.tile(wx, wy); + if(block.block != Blocks.air && tile.block().alwaysReplace){ + tile.setElevation(elevation); + tile.setRotation(block.rotation); + tile.setBlock(block.block, team); + + fill(tile); + } + } + } + } + } + } + } + } + + void fill(Tile tile){ + Block block = tile.block(); + + if(block instanceof PowerTurret){ + tile.entity.power.amount = block.powerCapacity; + }else if(block instanceof ItemTurret){ + ItemTurret turret = (ItemTurret)block; + AmmoType[] type = turret.getAmmoTypes(); + block.handleStack(type[0].item, block.acceptStack(type[0].item, 1000, tile, null), tile, null); + }else if(block instanceof ResupplyPoint){ + tile.entity.items.add(Items.lead, tile.block().itemCapacity); + } + } + + static class Structure{ + public final StructBlock[][] layout; + public final Item ore; + public final float chance; + + public Structure(float chance, Item ore, String encoding){ + this.ore = ore; + this.layout = StructureFormat.read(encoding); + this.chance = chance; + } + + public Structure(String encoding){ + this.ore = null; + this.layout = StructureFormat.read(encoding); + this.chance = 0; + } + + int width(){ + return layout.length; + } + + int height(){ + return layout[0].length; + } + } +} diff --git a/core/src/io/anuke/mindustry/maps/generation/GenProperties.java b/core/src/io/anuke/mindustry/maps/generation/GenProperties.java deleted file mode 100644 index 9c94ec3e94..0000000000 --- a/core/src/io/anuke/mindustry/maps/generation/GenProperties.java +++ /dev/null @@ -1,115 +0,0 @@ -package io.anuke.mindustry.maps.generation; - -public class GenProperties{ - public long seed; - public MapStyle maps; - public OreStyle ores; - public RiverType riverType; - public RiverStyle rivers; - public TerrainStyle terrains; - public FoliageStyle foliage; - public EnvironmentStyle environment; - - enum MapStyle{ - /** - * 256x512 - */ - longY, - /** - * 128x256 - */ - smallY, - /** - * 128x128 - */ - small, - /** - * 256x256 - */ - normal - } - - enum OreStyle{ - /** - * 'vanilla' noise-distributed ores - */ - normal, - /** - * ores hug the walls - */ - nearWalls, - /** - * ores hug all liquid rivers - */ - nearRivers, - /** - * large veins - */ - largeVeins - } - - enum RiverType{ - lava, - water, - oil, - none - } - - enum RiverStyle{ - /** - * long thin river spanning entire map - */ - longThin, - /** - * long river branching into many others - */ - longBranch, - /** - * one long, thick river - */ - longThick, - /** - * short, thick river that ends in a lake - */ - shortLake - } - - enum TerrainStyle{ - /** - * bordered around by the normal material - */ - normal, - /** - * everything is islands - */ - waterIslands, - /** - * everything is islands: lava edition - */ - lavaIslands - } - - enum FoliageStyle{ - patches, - veins, - blobs, - ridges - } - - enum FoilageType{ - grass, - sand, - darkStone, - ice, - } - - enum EnvironmentStyle{ - desert, - stoneDesert, - grassy, - dark, - darkStone, - stone, - icy, - } -} diff --git a/core/src/io/anuke/mindustry/maps/generation/Generation.java b/core/src/io/anuke/mindustry/maps/generation/Generation.java new file mode 100644 index 0000000000..c8329b4c23 --- /dev/null +++ b/core/src/io/anuke/mindustry/maps/generation/Generation.java @@ -0,0 +1,20 @@ +package io.anuke.mindustry.maps.generation; + +import io.anuke.mindustry.maps.Sector; +import io.anuke.mindustry.world.Tile; +import io.anuke.ucore.util.SeedRandom; + +public class Generation{ + public final Sector sector; + public final Tile[][] tiles; + public final int width, height; + public final SeedRandom random; + + public Generation(Sector sector, Tile[][] tiles, int width, int height, SeedRandom random){ + this.sector = sector; + this.tiles = tiles; + this.width = width; + this.height = height; + this.random = random; + } +} diff --git a/core/src/io/anuke/mindustry/maps/generation/StructureFormat.java b/core/src/io/anuke/mindustry/maps/generation/StructureFormat.java new file mode 100644 index 0000000000..f84d4cd061 --- /dev/null +++ b/core/src/io/anuke/mindustry/maps/generation/StructureFormat.java @@ -0,0 +1,97 @@ +package io.anuke.mindustry.maps.generation; + +import com.badlogic.gdx.utils.Base64Coder; +import com.badlogic.gdx.utils.IntMap; +import com.badlogic.gdx.utils.ObjectIntMap; +import com.badlogic.gdx.utils.ObjectIntMap.Entry; +import io.anuke.mindustry.content.blocks.Blocks; +import io.anuke.mindustry.world.Block; + +import java.io.*; + +public class StructureFormat{ + + public static byte[] write(StructBlock[][] blocks){ + try{ + ByteArrayOutputStream out = new ByteArrayOutputStream(); + DataOutputStream stream = new DataOutputStream(out); + + ObjectIntMap mapping = new ObjectIntMap<>(); + int lastid = 1; + mapping.put(Blocks.air, 0); + + for(int x = 0; x < blocks.length; x++){ + for(int y = 0; y < blocks[0].length; y++){ + Block block = blocks[x][y].block; + if(!mapping.containsKey(block)){ + mapping.put(block, lastid++); + } + } + } + + stream.writeByte(mapping.size); + for(Entry entry : mapping){ + stream.writeByte(entry.value); + stream.writeUTF(entry.key.name); + } + + stream.writeByte(blocks.length); + stream.writeByte(blocks[0].length); + + for(int x = 0; x < blocks.length; x++){ + for(int y = 0; y < blocks[0].length; y++){ + StructBlock block = blocks[x][y]; + stream.writeByte(mapping.get(block.block, 0)); + stream.writeByte(block.rotation); + } + } + + return out.toByteArray(); + + }catch(IOException e){ + throw new RuntimeException(e); + } + } + + public static String writeBase64(StructBlock[][] blocks){ + return new String(Base64Coder.encode(write(blocks))); + } + + public static StructBlock[][] read(byte[] bytes){ + try{ + + DataInputStream stream = new DataInputStream(new ByteArrayInputStream(bytes)); + byte size = stream.readByte(); + IntMap map = new IntMap<>(); + for(int i = 0; i < size; i++){ + map.put(stream.readByte(), Block.getByName(stream.readUTF())); + } + + byte width = stream.readByte(), height = stream.readByte(); + StructBlock[][] blocks = new StructBlock[width][height]; + for(int x = 0; x < width; x++){ + for(int y = 0; y < height; y++){ + blocks[x][y] = new StructBlock(map.get(stream.readByte()), stream.readByte()); + } + } + + return blocks; + }catch(IOException e){ + throw new RuntimeException(e); + } + } + + public static StructBlock[][] read(String base64){ + return read(Base64Coder.decode(base64)); + } + + public static class StructBlock{ + public final Block block; + public final byte rotation; + + public StructBlock(Block block, byte rotation){ + this.block = block; + this.rotation = rotation; + } + } +} diff --git a/core/src/io/anuke/mindustry/maps/generation/WorldGenerator.java b/core/src/io/anuke/mindustry/maps/generation/WorldGenerator.java index fba0e5d89b..bdd6ee375c 100644 --- a/core/src/io/anuke/mindustry/maps/generation/WorldGenerator.java +++ b/core/src/io/anuke/mindustry/maps/generation/WorldGenerator.java @@ -1,6 +1,7 @@ package io.anuke.mindustry.maps.generation; import com.badlogic.gdx.math.GridPoint2; +import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.IntArray; import com.badlogic.gdx.utils.ObjectMap; @@ -11,14 +12,16 @@ import io.anuke.mindustry.content.blocks.StorageBlocks; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.maps.MapTileData; import io.anuke.mindustry.maps.MapTileData.TileDataMarker; +import io.anuke.mindustry.maps.Sector; +import io.anuke.mindustry.maps.missions.Mission; import io.anuke.mindustry.type.Item; 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.ucore.noise.RidgedPerlin; import io.anuke.ucore.noise.Simplex; import io.anuke.ucore.noise.VoronoiNoise; -import io.anuke.ucore.util.Bits; import io.anuke.ucore.util.Geometry; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.SeedRandom; @@ -27,16 +30,15 @@ import static io.anuke.mindustry.Vars.*; public class WorldGenerator{ - private final int seed = 0; + private static final int baseSeed = 0; private int oreIndex = 0; - private Simplex sim = new Simplex(seed); - private Simplex sim2 = new Simplex(seed + 1); - private Simplex sim3 = new Simplex(seed + 2); - private RidgedPerlin rid = new RidgedPerlin(seed + 4, 1); - private VoronoiNoise vn = new VoronoiNoise(seed + 2, (short)0); - - private SeedRandom random = new SeedRandom(seed + 3); + private Simplex sim = new Simplex(baseSeed); + private Simplex sim2 = new Simplex(baseSeed + 1); + private Simplex sim3 = new Simplex(baseSeed + 2); + private RidgedPerlin rid = new RidgedPerlin(baseSeed + 4, 1); + private VoronoiNoise vn = new VoronoiNoise(baseSeed + 2, (short)0); + private SeedRandom random = new SeedRandom(baseSeed + 3); private GenResult result = new GenResult(); private ObjectMap decoration; @@ -66,10 +68,12 @@ public class WorldGenerator{ } } - prepareTiles(tiles, seed, genOres); + prepareTiles(tiles); + + generateOres(tiles, seed, genOres, null); } - public void prepareTiles(Tile[][] tiles, int seed, boolean genOres){ + public void prepareTiles(Tile[][] tiles){ //find multiblocks IntArray multiblocks = new IntArray(); @@ -127,37 +131,52 @@ public class WorldGenerator{ tile.updateOcclusion(); //fix things on cliffs that shouldn't be - if(tile.block() != Blocks.air && tile.cliffs != 0){ + if(tile.block() != Blocks.air && tile.hasCliffs() && !tile.block().isMultiblock() && tile.block() != Blocks.blockpart){ tile.setBlock(Blocks.air); } + + if(tile.floor() instanceof OreBlock && tile.hasCliffs()){ + tile.setFloor(((OreBlock)tile.floor()).base); + } } } + } + public void generateOres(Tile[][] tiles, long seed, boolean genOres, Array usedOres){ oreIndex = 0; if(genOres){ - Array ores = Array.with( - new OreEntry(Items.tungsten, 0.3f, seed), - new OreEntry(Items.coal, 0.284f, seed), - new OreEntry(Items.lead, 0.28f, seed), - new OreEntry(Items.titanium, 0.27f, seed), - new OreEntry(Items.thorium, 0.26f, seed) + Array baseOres = Array.with( + new OreEntry(Items.tungsten, 0.3f, seed), + new OreEntry(Items.coal, 0.284f, seed), + new OreEntry(Items.lead, 0.28f, seed), + new OreEntry(Items.titanium, 0.27f, seed), + new OreEntry(Items.thorium, 0.26f, seed) ); + Array ores = new Array<>(); + if(usedOres == null){ + ores.addAll(baseOres); + }else{ + for(Item item : usedOres){ + ores.add(baseOres.select(entry -> entry.item == item).iterator().next()); + } + } + for(int x = 0; x < tiles.length; x++){ for(int y = 0; y < tiles[0].length; y++){ Tile tile = tiles[x][y]; - if(!tile.floor().hasOres || tile.cliffs != 0 || tile.block() != Blocks.air){ + if(!tile.floor().hasOres || tile.hasCliffs() || tile.block() != Blocks.air){ continue; } for(int i = ores.size - 1; i >= 0; i--){ OreEntry entry = ores.get(i); if(entry.noise.octaveNoise2D(1, 0.7, 1f / (4 + i * 2), x, y) / 4f + - Math.abs(0.5f - entry.noise.octaveNoise2D(2, 0.7, 1f / (50 + i * 2), x, y)) > 0.48f && - Math.abs(0.5f - entry.noise.octaveNoise2D(1, 1, 1f / (55 + i * 4), x, y)) > 0.22f){ + Math.abs(0.5f - entry.noise.octaveNoise2D(2, 0.7, 1f / (50 + i * 2), x, y)) > 0.48f && + Math.abs(0.5f - entry.noise.octaveNoise2D(1, 1, 1f / (55 + i * 4), x, y)) > 0.22f){ tile.setFloor((Floor) OreBlocks.get(tile.floor(), entry.item)); break; } @@ -167,12 +186,15 @@ public class WorldGenerator{ } } - public void generateMap(Tile[][] tiles, int sectorX, int sectorY){ + public void generateMap(Tile[][] tiles, Sector sector){ int width = tiles.length, height = tiles[0].length; + SeedRandom rnd = new SeedRandom(sector.getSeed()); + Generation gena = new Generation(sector, tiles, tiles.length, tiles[0].length, rnd); + Array spawnpoints = sector.currentMission().getSpawnPoints(gena); for(int x = 0; x < width; x++){ for(int y = 0; y < height; y++){ - GenResult result = generateTile(sectorX, sectorY, x, y); + GenResult result = generateTile(this.result, sector.x, sector.y, x, y, true, spawnpoints); Tile tile = new Tile(x, y, (byte)result.floor.id, (byte)result.wall.id, (byte)0, (byte)0, result.elevation); tiles[x][y] = tile; } @@ -188,7 +210,7 @@ public class WorldGenerator{ if(!Mathf.inBounds(x + point.x, y + point.y, width, height)) continue; if(tiles[x + point.x][y + point.y].getElevation() < elevation){ - if(Mathf.chance(0.06)){ + if(sim2.octaveNoise2D(1, 1, 1.0 / 8, x, y) > 0.8){ tile.setElevation(-1); } break; @@ -197,16 +219,15 @@ public class WorldGenerator{ } } - int coreX = width/2, coreY = height/3; + generateOres(tiles, sector.getSeed(), true, sector.ores); - tiles[coreX][coreY].setBlock(StorageBlocks.core); - tiles[coreX][coreY].setTeam(Team.blue); + Generation gen = new Generation(sector, tiles, tiles.length, tiles[0].length, random); - prepareTiles(tiles, seed, true); - } + for(Mission mission : sector.missions){ + mission.generate(gen); + } - public void setSector(int sectorX, int sectorY){ - random.setSeed(Bits.packLong(sectorX, sectorY)); + prepareTiles(tiles); } public GenResult generateTile(int sectorX, int sectorY, int localX, int localY){ @@ -214,10 +235,10 @@ public class WorldGenerator{ } public GenResult generateTile(int sectorX, int sectorY, int localX, int localY, boolean detailed){ - return generateTile(result, sectorX, sectorY, localX, localY, detailed); + return generateTile(result, sectorX, sectorY, localX, localY, detailed, null); } - public GenResult generateTile(GenResult result, int sectorX, int sectorY, int localX, int localY, boolean detailed){ + public GenResult generateTile(GenResult result, int sectorX, int sectorY, int localX, int localY, boolean detailed, Array spawnpoints){ int x = sectorX * sectorSize + localX + Short.MAX_VALUE; int y = sectorY * sectorSize + localY + Short.MAX_VALUE; @@ -226,9 +247,25 @@ public class WorldGenerator{ double ridge = rid.getValue(x, y, 1f / 400f); double iceridge = rid.getValue(x+99999, y, 1f / 300f) + sim3.octaveNoise2D(2, 1f, 1f/14f, x, y)/11f; - double elevation = sim.octaveNoise2D(detailed ? 7 : 2, 0.5, 1f / 500, x, y) * 6.1 - 1 - ridge; + double elevation = elevationOf(x, y, detailed); double temp = vn.noise(x, y, 1f / 300f) * sim3.octaveNoise2D(detailed ? 2 : 1, 1, 1f / 13f, x, y)/13f - + sim3.octaveNoise2D(detailed ? 12 : 6, 0.6, 1f / 920f, x, y); + + sim3.octaveNoise2D(detailed ? 12 : 6, 0.6, 1f / 920f, x, y); + + int lerpDst = 20; + lerpDst *= lerpDst; + float minDst = Float.MAX_VALUE; + + if(detailed && spawnpoints != null){ + for(GridPoint2 p : spawnpoints){ + float dst = Vector2.dst2(p.x, p.y, localX, localY); + minDst = Math.min(minDst, dst); + + if(dst < lerpDst){ + float targetElevation = Math.max(0.86f, (float)elevationOf(sectorX * sectorSize + p.x + Short.MAX_VALUE, sectorY * sectorSize + p.y + Short.MAX_VALUE, true)); + elevation = Mathf.lerp((float)elevation, targetElevation, Mathf.clamp(1.5f*(1f-(dst / lerpDst)))); + } + } + } if(elevation < 0.7){ floor = Blocks.deepwater; @@ -238,21 +275,27 @@ public class WorldGenerator{ floor = Blocks.sand; }else if(temp < 0.55){ floor = Blocks.grass; - }else if(temp < 0.65){ + }else if(temp < 0.6){ floor = Blocks.sand; }else if(temp + ridge/2f < 0.8 || elevation < 1.3){ floor = Blocks.blackstone; + + if(iceridge > 0.25 && minDst > lerpDst/1.5f){ + elevation ++; + } }else{ floor = Blocks.lava; } - if(elevation > 3.5){ - floor = Blocks.snow; - }else if(elevation > 3){ - floor = Blocks.stone; + if(temp < 0.6f){ + if(elevation > 3){ + floor = Blocks.snow; + }else if(elevation > 2.5){ + floor = Blocks.stone; + } } - if(elevation > 3.3 && iceridge > 0.25){ + if(elevation > 3.3 && iceridge > 0.25 && temp < 0.6f){ elevation ++; floor = Blocks.ice; } @@ -271,6 +314,11 @@ public class WorldGenerator{ return result; } + double elevationOf(int x, int y, boolean detailed){ + double ridge = rid.getValue(x, y, 1f / 400f); + return sim.octaveNoise2D(detailed ? 7 : 2, 0.62, 1f / 640, x, y) * 6.1 - 1 - ridge; + } + public static class GenResult{ public Block floor, wall; public byte elevation; @@ -283,11 +331,11 @@ public class WorldGenerator{ final RidgedPerlin ridge; final int index; - OreEntry(Item item, float frequency, int seed){ + OreEntry(Item item, float frequency, long seed){ this.frequency = frequency; this.item = item; this.noise = new Simplex(seed + oreIndex); - this.ridge = new RidgedPerlin(seed + oreIndex, 2); + this.ridge = new RidgedPerlin((int)(seed + oreIndex), 2); this.index = oreIndex++; } } diff --git a/core/src/io/anuke/mindustry/maps/goals/Goal.java b/core/src/io/anuke/mindustry/maps/goals/Goal.java deleted file mode 100644 index c0ad1bd509..0000000000 --- a/core/src/io/anuke/mindustry/maps/goals/Goal.java +++ /dev/null @@ -1,5 +0,0 @@ -package io.anuke.mindustry.maps.goals; - -public interface Goal{ - boolean isComplete(); -} diff --git a/core/src/io/anuke/mindustry/maps/goals/WaveGoal.java b/core/src/io/anuke/mindustry/maps/goals/WaveGoal.java deleted file mode 100644 index e87ded082e..0000000000 --- a/core/src/io/anuke/mindustry/maps/goals/WaveGoal.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.anuke.mindustry.maps.goals; - -import static io.anuke.mindustry.Vars.*; - -public class WaveGoal implements Goal{ - private final int target; - - public WaveGoal(int target){ - this.target = target; - } - - @Override - public boolean isComplete(){ - return state.wave >= target; - } -} diff --git a/core/src/io/anuke/mindustry/maps/missions/BattleMission.java b/core/src/io/anuke/mindustry/maps/missions/BattleMission.java new file mode 100644 index 0000000000..68a7218351 --- /dev/null +++ b/core/src/io/anuke/mindustry/maps/missions/BattleMission.java @@ -0,0 +1,51 @@ +package io.anuke.mindustry.maps.missions; + +import com.badlogic.gdx.math.GridPoint2; +import com.badlogic.gdx.utils.Array; +import io.anuke.mindustry.Vars; +import io.anuke.mindustry.game.GameMode; +import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.maps.generation.FortressGenerator; +import io.anuke.mindustry.maps.generation.Generation; +import io.anuke.ucore.scene.ui.layout.Table; +import io.anuke.ucore.util.Bundles; + +public class BattleMission implements Mission{ + private final static int coreX = 60, coreY = 60; + + @Override + public void display(Table table){ + table.add("$text.mission.battle"); + } + + @Override + public GameMode getMode(){ + return GameMode.noWaves; + } + + @Override + public String displayString(){ + return Bundles.get("text.mission.battle"); + } + + @Override + public void generate(Generation gen){ + int enemyX = gen.width-1-coreX, enemyY = gen.height-1-coreX; + + generateCoreAt(gen, coreX, coreY, Team.blue); + generateCoreAt(gen, enemyX, enemyY, Team.red); + + new FortressGenerator().generate(gen, Team.red, coreX, coreY, enemyX, enemyY); + } + + @Override + public boolean isComplete(){ + //TODO check all enemy teams, not just the first + return Vars.state.teams.getTeams(false).first().cores.size == 0; + } + + @Override + public Array getSpawnPoints(Generation gen){ + return Array.with(new GridPoint2(coreX, coreY), new GridPoint2(gen.width - 1 - coreX, gen.height - 1 - coreY)); + } +} diff --git a/core/src/io/anuke/mindustry/maps/missions/Mission.java b/core/src/io/anuke/mindustry/maps/missions/Mission.java new file mode 100644 index 0000000000..5c20056d27 --- /dev/null +++ b/core/src/io/anuke/mindustry/maps/missions/Mission.java @@ -0,0 +1,33 @@ +package io.anuke.mindustry.maps.missions; + +import com.badlogic.gdx.math.GridPoint2; +import com.badlogic.gdx.utils.Array; +import io.anuke.mindustry.content.blocks.StorageBlocks; +import io.anuke.mindustry.game.GameMode; +import io.anuke.mindustry.game.SpawnGroup; +import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.maps.Sector; +import io.anuke.mindustry.maps.generation.Generation; +import io.anuke.ucore.scene.ui.layout.Table; + +public interface Mission{ + boolean isComplete(); + String displayString(); + GameMode getMode(); + void display(Table table); + + default Array getWaves(Sector sector){ + return new Array<>(); + } + + default Array getSpawnPoints(Generation gen){ + return Array.with(); + } + + default void generate(Generation gen){} + + default void generateCoreAt(Generation gen, int coreX, int coreY, Team team){ + gen.tiles[coreX][coreY].setBlock(StorageBlocks.core); + gen.tiles[coreX][coreY].setTeam(team); + } +} diff --git a/core/src/io/anuke/mindustry/maps/missions/ResourceMission.java b/core/src/io/anuke/mindustry/maps/missions/ResourceMission.java new file mode 100644 index 0000000000..b8f6ff7ca8 --- /dev/null +++ b/core/src/io/anuke/mindustry/maps/missions/ResourceMission.java @@ -0,0 +1,37 @@ +package io.anuke.mindustry.maps.missions; + +import io.anuke.mindustry.Vars; +import io.anuke.mindustry.game.GameMode; +import io.anuke.mindustry.type.Item; +import io.anuke.ucore.scene.ui.layout.Table; +import io.anuke.ucore.util.Bundles; + +public class ResourceMission implements Mission{ + private final Item item; + private final int amount; + + public ResourceMission(Item item, int amount){ + this.item = item; + this.amount = amount; + } + + @Override + public void display(Table table){ + + } + + @Override + public GameMode getMode(){ + return GameMode.waves; + } + + @Override + public boolean isComplete(){ + return Vars.state.teams.getTeams(true).first().cores.first().entity.items.has(item, amount); + } + + @Override + public String displayString(){ + return Bundles.format("text.mission.resource", item.localizedName(), amount); + } +} diff --git a/core/src/io/anuke/mindustry/maps/missions/WaveMission.java b/core/src/io/anuke/mindustry/maps/missions/WaveMission.java new file mode 100644 index 0000000000..f31bbc49af --- /dev/null +++ b/core/src/io/anuke/mindustry/maps/missions/WaveMission.java @@ -0,0 +1,59 @@ +package io.anuke.mindustry.maps.missions; + +import com.badlogic.gdx.math.GridPoint2; +import com.badlogic.gdx.utils.Array; +import io.anuke.mindustry.game.GameMode; +import io.anuke.mindustry.game.SpawnGroup; +import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.game.Waves; +import io.anuke.mindustry.maps.Sector; +import io.anuke.mindustry.maps.generation.Generation; +import io.anuke.ucore.scene.ui.layout.Table; +import io.anuke.ucore.util.Bundles; + +import static io.anuke.mindustry.Vars.state; + +public class WaveMission implements Mission{ + private final int target; + + public WaveMission(int target){ + this.target = target; + } + + @Override + public Array getWaves(Sector sector){ + Array spawns = new Array<>(); + return Waves.getSpawns(); + } + + @Override + public void generate(Generation gen){ + int coreX = gen.width/2, coreY = gen.height/2; + generateCoreAt(gen, coreX, coreY, Team.blue); + } + + @Override + public void display(Table table){ + table.add(Bundles.format("text.mission.wave", target)); + } + + @Override + public GameMode getMode(){ + return GameMode.waves; + } + + @Override + public String displayString(){ + return Bundles.format("text.mission.wave", target); + } + + @Override + public boolean isComplete(){ + return state.wave >= target; + } + + @Override + public Array getSpawnPoints(Generation gen){ + return Array.with(new GridPoint2(gen.width/2, gen.height/2)); + } +} diff --git a/core/src/io/anuke/mindustry/net/In.java b/core/src/io/anuke/mindustry/net/In.java deleted file mode 100644 index d00e0aba41..0000000000 --- a/core/src/io/anuke/mindustry/net/In.java +++ /dev/null @@ -1,10 +0,0 @@ -package io.anuke.mindustry.net; - -/** - * Stores class nameas for remote method invocation for consistency's sake. - */ -public class In{ - public static final String normal = "Call"; - public static final String entities = "CallEntity"; - public static final String blocks = "CallBlocks"; -} diff --git a/core/src/io/anuke/mindustry/net/Net.java b/core/src/io/anuke/mindustry/net/Net.java index bd15fc6614..3a38764218 100644 --- a/core/src/io/anuke/mindustry/net/Net.java +++ b/core/src/io/anuke/mindustry/net/Net.java @@ -38,6 +38,14 @@ public class Net{ private static IntMap streams = new IntMap<>(); + public static boolean hasClient(){ + return clientProvider != null; + } + + public static boolean hasServer(){ + return serverProvider != null; + } + /** * Display a network error. */ diff --git a/core/src/io/anuke/mindustry/net/NetConnection.java b/core/src/io/anuke/mindustry/net/NetConnection.java index 9c66726434..e8e3c7697b 100644 --- a/core/src/io/anuke/mindustry/net/NetConnection.java +++ b/core/src/io/anuke/mindustry/net/NetConnection.java @@ -31,6 +31,7 @@ public abstract class NetConnection{ public long lastRecievedClientTime; public boolean hasConnected = false; + public boolean hasBegunConnecting = false; public NetConnection(int id, String address){ this.id = id; diff --git a/core/src/io/anuke/mindustry/net/NetworkIO.java b/core/src/io/anuke/mindustry/net/NetworkIO.java index d8c8adee15..dcf8ccbf21 100644 --- a/core/src/io/anuke/mindustry/net/NetworkIO.java +++ b/core/src/io/anuke/mindustry/net/NetworkIO.java @@ -96,6 +96,28 @@ public class NetworkIO{ } } + //write visibility, length-run encoded + for(int i = 0; i < world.width() * world.height(); i++){ + Tile tile = world.tile(i); + boolean discovered = tile.discovered(); + + int consecutives = 0; + + for(int j = i + 1; j < world.width() * world.height() && consecutives < 32767*2-1; j++){ + Tile nextTile = world.tile(j); + + if(nextTile.discovered() != discovered){ + break; + } + + consecutives++; + } + + stream.writeBoolean(discovered); + stream.writeShort(consecutives); + i += consecutives; + } + //write team data stream.writeByte(state.teams.getTeams().size); for(TeamData data : state.teams.getTeams()){ @@ -215,6 +237,18 @@ public class NetworkIO{ tiles[x][y] = tile; } + for(int i = 0; i < width * height; i++){ + boolean discovered = stream.readBoolean(); + int consecutives = stream.readUnsignedShort(); + if(discovered){ + for(int j = i + 1; j < i + 1 + consecutives; j++){ + int newx = j % width, newy = j / width; + tiles[newx][newy].setVisibility((byte) 1); + } + } + i += consecutives; + } + player.reset(); state.teams = new TeamInfo(); diff --git a/core/src/io/anuke/mindustry/net/TraceInfo.java b/core/src/io/anuke/mindustry/net/TraceInfo.java index 512c8e85ff..0b62ec54d2 100644 --- a/core/src/io/anuke/mindustry/net/TraceInfo.java +++ b/core/src/io/anuke/mindustry/net/TraceInfo.java @@ -21,7 +21,7 @@ public class TraceInfo{ public String uuid; - public TraceInfo(String ip){ - this.ip = ip; + public TraceInfo(String uuid){ + this.uuid = uuid; } } diff --git a/core/src/io/anuke/mindustry/type/Item.java b/core/src/io/anuke/mindustry/type/Item.java index 18653372c6..2e29a94973 100644 --- a/core/src/io/anuke/mindustry/type/Item.java +++ b/core/src/io/anuke/mindustry/type/Item.java @@ -23,33 +23,19 @@ public class Item implements Comparable, UnlockableContent{ public final Color color; public TextureRegion region; - /** - * 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; - /** - * how effective this item is as flux for smelting. 0 = not a flux, 0.5 = normal flux, 1 = very good - */ + /**how effective this item is as flux for smelting. 0 = not a flux, 0.5 = normal flux, 1 = very good*/ public float fluxiness = 0f; - /** - * drill hardness of the item - */ + /**drill hardness of the item*/ public int hardness = 0; - /** - * the burning color of this item - */ + /**the burning color of this item*/ public Color flameColor = Palette.darkFlame.cpy(); /** * base material cost of this item, used for calculating place times diff --git a/core/src/io/anuke/mindustry/type/Recipe.java b/core/src/io/anuke/mindustry/type/Recipe.java index 36b5e4bca6..b8040acabe 100644 --- a/core/src/io/anuke/mindustry/type/Recipe.java +++ b/core/src/io/anuke/mindustry/type/Recipe.java @@ -113,7 +113,7 @@ public class Recipe implements UnlockableContent{ @Override public boolean isHidden(){ - return debugOnly; + return debugOnly || (desktopOnly && mobile); } @Override diff --git a/core/src/io/anuke/mindustry/type/Weapon.java b/core/src/io/anuke/mindustry/type/Weapon.java index a5d3610048..623be27e86 100644 --- a/core/src/io/anuke/mindustry/type/Weapon.java +++ b/core/src/io/anuke/mindustry/type/Weapon.java @@ -9,8 +9,7 @@ import io.anuke.mindustry.content.fx.Fx; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.traits.ShooterTrait; -import io.anuke.mindustry.gen.CallEntity; -import io.anuke.mindustry.net.In; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.net.Net; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Effects.Effect; @@ -82,7 +81,7 @@ public class Weapon extends Upgrade{ super(name); } - @Remote(targets = Loc.server, called = Loc.both, in = In.entities, unreliable = true) + @Remote(targets = Loc.server, called = Loc.both, unreliable = true) public static void onPlayerShootWeapon(Player player, float x, float y, float rotation, boolean left){ if(player == null) return; //clients do not see their own shoot events: they are simulated completely clientside to prevent laggy visuals @@ -94,7 +93,7 @@ public class Weapon extends Upgrade{ shootDirect(player, x, y, rotation, left); } - @Remote(targets = Loc.server, called = Loc.both, in = In.entities, unreliable = true) + @Remote(targets = Loc.server, called = Loc.both, unreliable = true) public static void onGenericShootWeapon(ShooterTrait shooter, float x, float y, float rotation, boolean left){ if(shooter == null) return; shootDirect(shooter, x, y, rotation, left); @@ -176,9 +175,9 @@ public class Weapon extends Upgrade{ shootDirect(p, x, y, angle, left); }else{ if(p instanceof Player){ //players need special weapon handling logic - CallEntity.onPlayerShootWeapon((Player) p, x, y, angle, left); + Call.onPlayerShootWeapon((Player) p, x, y, angle, left); }else{ - CallEntity.onGenericShootWeapon(p, x, y, angle, left); + Call.onGenericShootWeapon(p, x, y, angle, left); } } diff --git a/core/src/io/anuke/mindustry/ui/ContentDisplay.java b/core/src/io/anuke/mindustry/ui/ContentDisplay.java index 181e5704f1..fcaba75760 100644 --- a/core/src/io/anuke/mindustry/ui/ContentDisplay.java +++ b/core/src/io/anuke/mindustry/ui/ContentDisplay.java @@ -9,7 +9,6 @@ import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.type.Mech; import io.anuke.mindustry.type.Recipe; import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.blocks.defense.turrets.Turret; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.BlockStats; import io.anuke.mindustry.world.meta.StatCategory; @@ -17,6 +16,7 @@ import io.anuke.mindustry.world.meta.StatValue; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.util.Bundles; +import io.anuke.ucore.util.Strings; public class ContentDisplay{ @@ -26,10 +26,6 @@ public class ContentDisplay{ table.table(title -> { int size = 8 * 6; - if(block instanceof Turret){ - size = (8 * block.size + 2) * (7 - block.size * 2); - } - title.addImage(Draw.region("block-icon-" + block.name)).size(size); title.add("[accent]" + block.formalName).padLeft(5); }); @@ -144,6 +140,31 @@ public class ContentDisplay{ } public static void displayUnit(Table table, UnitType unit){ + table.table(title -> { + title.addImage(unit.getContentIcon()).size(8 * 6); + title.add("[accent]" + unit.localizedName()).padLeft(5); + }); + table.row(); + + table.addImage("white").height(3).color(Color.LIGHT_GRAY).pad(15).padLeft(0).padRight(0).fillX(); + + table.row(); + + if(unit.description != null){ + table.add(unit.description).padLeft(5).padRight(5).width(400f).wrap().fillX(); + table.row(); + + table.addImage("white").height(3).color(Color.LIGHT_GRAY).pad(15).padLeft(0).padRight(0).fillX(); + table.row(); + } + + table.left().defaults().fillX(); + + table.add(Bundles.format("text.unit.health", unit.health)); + table.row(); + table.add(Bundles.format("text.unit.speed", Strings.toFixed(unit.speed, 1))); + table.row(); + table.row(); } } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/AboutDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/AboutDialog.java index ed489a0630..afcf8abfd3 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/AboutDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/AboutDialog.java @@ -93,7 +93,7 @@ public class AboutDialog extends FloatingDialog{ public void showCredits(){ FloatingDialog dialog = new FloatingDialog("$text.credits"); dialog.addCloseButton(); - dialog.content().add("$text.about"); + dialog.content().add("$text.credits.text"); dialog.show(); } } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/LevelDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java similarity index 75% rename from core/src/io/anuke/mindustry/ui/dialogs/LevelDialog.java rename to core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java index e8bbfdd562..920f2251d8 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/LevelDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java @@ -8,22 +8,20 @@ import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.ui.BorderImage; import io.anuke.ucore.core.Settings; -import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.scene.event.Touchable; import io.anuke.ucore.scene.ui.ButtonGroup; import io.anuke.ucore.scene.ui.ImageButton; import io.anuke.ucore.scene.ui.ScrollPane; import io.anuke.ucore.scene.ui.TextButton; import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.scene.utils.Elements; import io.anuke.ucore.util.Bundles; import io.anuke.ucore.util.Mathf; import static io.anuke.mindustry.Vars.*; -public class LevelDialog extends FloatingDialog{ +public class CustomGameDialog extends FloatingDialog{ - public LevelDialog(){ + public CustomGameDialog(){ super("$text.level.select"); addCloseButton(); shown(this::setup); @@ -46,11 +44,10 @@ public class LevelDialog extends FloatingDialog{ selmode.add("$text.level.mode").padRight(15f); for(GameMode mode : GameMode.values()){ - TextButton[] b = {null}; - b[0] = Elements.newButton("$mode." + mode.name() + ".name", "toggle", () -> state.mode = mode); - b[0].update(() -> b[0].setChecked(state.mode == mode)); - group.add(b[0]); - selmode.add(b[0]).size(130f, 54f); + if(mode.hidden) continue; + + selmode.addButton("$mode." + mode.name() + ".name", "toggle", () -> state.mode = mode) + .update(b -> b.setChecked(state.mode == mode)).group(group).size(130f, 54f); } selmode.addButton("?", this::displayGameModeHelp).size(50f, 54f).padLeft(18f); @@ -115,31 +112,9 @@ public class LevelDialog extends FloatingDialog{ i++; } - ImageButton genb = maps.addImageButton("icon-editor", "clear", 16 * 3, () -> { - hide(); - //TODO - - /* - ui.loadfrag.show(); - - Timers.run(5f, () -> { - Cursors.restoreCursor(); - threads.run(() -> { - world.loadSector(0, 0); - logic.play(); - Gdx.app.postRunnable(ui.loadfrag::hide); - }); - });*/ - }).width(170).fillY().pad(4f).get(); - - genb.top(); - genb.margin(5); - genb.clearChildren(); - genb.add(new BorderImage(Draw.region("icon-generated"), 3f)).size(images); - genb.row(); - genb.add("$text.map.random").growX().wrap().pad(3f).get().setAlignment(Align.center, Align.center); - genb.row(); - genb.add("").pad(3f); + if(world.maps().all().size == 0){ + maps.add("$text.maps.none").pad(50); + } content().add(pane).uniformX(); } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/GenViewDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/GenViewDialog.java index 7080cfdcb0..830f2003b4 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/GenViewDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/GenViewDialog.java @@ -81,7 +81,7 @@ public class GenViewDialog extends FloatingDialog{ Pixmap pixmap = new Pixmap(sectorSize, sectorSize, Format.RGBA8888); for(int i = 0; i < sectorSize; i++){ for(int j = 0; j < sectorSize; j++){ - world.generator().generateTile(result, wx, wy, i, j, true); + world.generator().generateTile(result, wx, wy, i, j, true, null); pixmap.drawPixel(i, sectorSize - 1 - j, ColorMapper.colorFor(result.floor, result.wall, Team.none, result.elevation)); } } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java index 16c6e98947..3e81f0a3e9 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java @@ -14,6 +14,7 @@ import io.anuke.ucore.scene.ui.Image; import io.anuke.ucore.scene.ui.ScrollPane; import io.anuke.ucore.scene.ui.TextButton; import io.anuke.ucore.scene.ui.layout.Table; +import io.anuke.ucore.scene.utils.UIUtils; import io.anuke.ucore.util.Bundles; import io.anuke.ucore.util.Log; import io.anuke.ucore.util.Strings; @@ -23,6 +24,7 @@ import java.io.DataInputStream; import static io.anuke.mindustry.Vars.*; public class MapsDialog extends FloatingDialog{ + private FloatingDialog dialog; public MapsDialog(){ super("$text.maps"); @@ -58,6 +60,11 @@ public class MapsDialog extends FloatingDialog{ }).size(230f, 64f); shown(this::setup); + onResize(() -> { + if(dialog != null){ + dialog.hide(); + } + }); } void setup(){ @@ -101,10 +108,10 @@ public class MapsDialog extends FloatingDialog{ } void showMapInfo(Map map){ - FloatingDialog dialog = new FloatingDialog("$text.editor.mapinfo"); + dialog = new FloatingDialog("$text.editor.mapinfo"); dialog.addCloseButton(); - float mapsize = 300f; + float mapsize = UIUtils.portrait() ? 160f : 300f; Table table = dialog.content(); ((Image) table.stack(new Image(map.texture), new BorderImage(map.texture)).size(mapsize).get().getChildren().first()).setScaling(Scaling.fit); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/MissionDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/MissionDialog.java new file mode 100644 index 0000000000..13094c7ec5 --- /dev/null +++ b/core/src/io/anuke/mindustry/ui/dialogs/MissionDialog.java @@ -0,0 +1,24 @@ +package io.anuke.mindustry.ui.dialogs; + +import io.anuke.mindustry.Vars; +import io.anuke.mindustry.maps.Sector; +import io.anuke.ucore.util.Bundles; + +public class MissionDialog extends FloatingDialog{ + + public MissionDialog(){ + super("$text.mission.complete"); + setFillParent(false); + } + + public void show(Sector sector){ + buttons().clear(); + content().clear(); + + addCloseButton(); + + buttons().addButton("$text.quit", () -> Vars.ui.paused.runExitSave()).size(190f, 64f); + content().add(Bundles.format("text.mission.complete.body", sector.x, sector.y)).pad(10); + show(); + } +} diff --git a/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java index 01aab615e1..efa2a413e8 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java @@ -2,6 +2,7 @@ package io.anuke.mindustry.ui.dialogs; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.net.Net; +import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.util.Bundles; import static io.anuke.mindustry.Vars.*; @@ -10,10 +11,24 @@ public class PausedDialog extends FloatingDialog{ public boolean wasPaused = false; private SaveDialog save = new SaveDialog(); private LoadDialog load = new LoadDialog(); + private Table missionTable; public PausedDialog(){ super("$text.menu"); setup(); + + shown(this::rebuild); + } + + void rebuild(){ + missionTable.clear(); + if(world.getSector() != null && !world.getSector().complete){ + missionTable.add("[LIGHT_GRAY]" + Bundles.format("text.mission", "")); + missionTable.row(); + missionTable.table(t -> { + world.getSector().currentMission().display(t); + }); + } } void setup(){ @@ -28,6 +43,9 @@ public class PausedDialog extends FloatingDialog{ if(!Net.active()) state.set(State.paused); }); + content().table(t -> missionTable = t); + content().row(); + if(!mobile){ content().defaults().width(220).height(50); @@ -43,27 +61,20 @@ public class PausedDialog extends FloatingDialog{ content().row(); content().addButton("$text.savegame", () -> { save.show(); - }); + }).disabled(s -> world.getSector() != null); content().row(); content().addButton("$text.loadgame", () -> { load.show(); }).disabled(b -> Net.active()); - //Local multiplayer is currently functional, but disabled. - /* - content().row(); - content().addButton("$text.addplayers", () -> { - ui.localplayers.show(); - }).disabled(b -> Net.active());*/ - content().row(); content().addButton("$text.hostserver", () -> { if(!gwt){ ui.host.show(); }else{ - ui.showInfo("$text.host.web"); + ui.showInfo("$text.web.unsupported"); } }).disabled(b -> Net.active()); @@ -88,7 +99,7 @@ public class PausedDialog extends FloatingDialog{ state.set(State.playing); }); content().addRowImageTextButton("$text.settings", "icon-tools", isize, ui.settings::show); - content().addRowImageTextButton("$text.save", "icon-save", isize, save::show); + content().addRowImageTextButton("$text.save", "icon-save", isize, save::show).disabled(b -> world.getSector() != null); content().row(); @@ -104,7 +115,7 @@ public class PausedDialog extends FloatingDialog{ } } - private void runExitSave(){ + public void runExitSave(){ if(control.getSaves().getCurrent() == null || !control.getSaves().getCurrent().isAutosave()){ state.set(State.menu); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/RestartDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/RestartDialog.java index 38554f889f..c02bdecb5c 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/RestartDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/RestartDialog.java @@ -1,30 +1,50 @@ package io.anuke.mindustry.ui.dialogs; import io.anuke.mindustry.core.GameState.State; -import io.anuke.ucore.scene.ui.Dialog; +import io.anuke.mindustry.maps.Sector; +import io.anuke.ucore.util.Bundles; import static io.anuke.mindustry.Vars.*; -public class RestartDialog extends Dialog{ +public class RestartDialog extends FloatingDialog{ public RestartDialog(){ - super("$text.gameover", "dialog"); + super("$text.gameover"); + setFillParent(false); + shown(this::rebuild); + } - shown(() -> { - content().clearChildren(); + void rebuild(){ + buttons().clear(); + content().clear(); + + buttons().margin(10); + + if(world.getSector() == null){ if(control.isHighScore()){ content().add("$text.highscore").pad(6); content().row(); } - content().add("$text.lasted").pad(12).get(); - content().add("[accent]" + state.wave); - pack(); - }); + content().add(Bundles.format("text.wave.lasted", state.wave)).pad(12); - getButtonTable().addButton("$text.menu", () -> { - hide(); - state.set(State.menu); - logic.reset(); - }).size(130f, 60f); + buttons().addButton("$text.menu", () -> { + hide(); + state.set(State.menu); + logic.reset(); + }).size(130f, 60f); + }else{ + content().add("$text.sector.gameover"); + buttons().addButton("$text.menu", () -> { + hide(); + state.set(State.menu); + logic.reset(); + }).size(130f, 60f); + + buttons().addButton("$text.sector.retry", () -> { + Sector sector = world.getSector(); + ui.loadLogic(() -> world.sectors().playSector(sector)); + hide(); + }).size(130f, 60f); + } } } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/SaveDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/SaveDialog.java index 338eb5dc3a..26d0096ea8 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/SaveDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/SaveDialog.java @@ -27,7 +27,7 @@ public class SaveDialog extends LoadDialog{ ui.showTextInput("$text.save", "$text.save.newslot", "", text -> { ui.loadAnd("$text.saving", () -> { control.getSaves().addSave(text); - setup(); + threads.runGraphics(() -> threads.run(() -> threads.runGraphics(this::setup))); }); }) ).fillX().margin(10f).minWidth(300f).height(70f).pad(4f).padRight(-4); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/SectorsDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/SectorsDialog.java index 17ca964915..c33cdf4ab6 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/SectorsDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/SectorsDialog.java @@ -3,7 +3,6 @@ package io.anuke.mindustry.ui.dialogs; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; -import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.maps.Sector; import io.anuke.ucore.core.Graphics; @@ -13,7 +12,7 @@ import io.anuke.ucore.scene.Element; import io.anuke.ucore.scene.event.ClickListener; import io.anuke.ucore.scene.event.InputEvent; import io.anuke.ucore.scene.event.InputListener; -import io.anuke.ucore.scene.ui.TextButton; +import io.anuke.ucore.scene.ui.layout.Unit; import io.anuke.ucore.scene.utils.Cursors; import io.anuke.ucore.scene.utils.ScissorStack; import io.anuke.ucore.util.Bundles; @@ -37,28 +36,21 @@ public class SectorsDialog extends FloatingDialog{ addCloseButton(); - content().label(() -> Bundles.format("text.sector", selected == null ? "" : + content().label(() -> Bundles.format("text.sector", selected == null ? Bundles.get("text.none") : (selected.x + ", " + selected.y + (!selected.complete && selected.saveID != -1 ? " " + Bundles.get("text.sector.locked") : "")) + (selected.saveID == -1 ? " " + Bundles.get("text.sector.unexplored") : (selected.hasSave() ? " [accent]/[white] " + Bundles.format("text.sector.time", selected.getSave().getPlayTime()) : "")))); content().row(); + content().label(() -> Bundles.format("text.mission", selected == null || selected.completedMissions >= selected.missions.size ? Bundles.get("text.none") : selected.missions.get(selected.completedMissions).displayString())); + content().row(); content().add(new SectorView()).grow(); content().row(); buttons().addImageTextButton("$text.sector.deploy", "icon-play", 10*3, () -> { hide(); - ui.loadLogic(() -> { - if(!selected.hasSave()){ - world.loadSector(selected); - logic.play(); - selected.saveID = control.getSaves().addSave("sector-" + selected.packedPosition()).index; - world.sectors().save(); - }else{ - control.getSaves().getByID(selected.saveID).load(); - state.set(State.playing); - } - }); - }).size(230f, 64f).name("deploy-button").disabled(b -> selected == null); + ui.loadLogic(() -> world.sectors().playSector(selected)); + }).size(230f, 64f).disabled(b -> selected == null) + .update(t -> t.setText(selected != null && selected.hasSave() ? "$text.sector.resume" : "$text.sector.deploy")); if(debug){ buttons().addButton("unlock", () -> world.sectors().completeSector(selected.x, selected.y)).size(230f, 64f).disabled(b -> selected == null); @@ -66,14 +58,13 @@ public class SectorsDialog extends FloatingDialog{ } void selectSector(Sector sector){ - buttons().find("deploy-button").setText(sector.hasSave() ? "$text.sector.resume" : "$text.sector.deploy"); selected = sector; } class SectorView extends Element{ float lastX, lastY; - float sectorSize = 100f; - float sectorPadding = 14f; + float sectorSize = Unit.dp.scl(100f); + float sectorPadding = Unit.dp.scl(14f); boolean clicked = false; float panX = -sectorPadding/2f, panY = -sectorSize/2f; @@ -170,13 +161,13 @@ public class SectorsDialog extends FloatingDialog{ Draw.color(Color.LIGHT_GRAY); } - Lines.stroke(stroke); + Lines.stroke(Unit.dp.scl(stroke)); Lines.crect(drawX, drawY, sectorSize * size + padding, sectorSize * size + padding, (int)stroke); } } Draw.color(Palette.accent); - Lines.stroke(4f); + Lines.stroke(Unit.dp.scl(4f)); Lines.crect(x + width/2f, y + height/2f, clipSize, clipSize); Draw.reset(); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java index a1fc7bbc3f..10fe0a70dd 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java @@ -132,7 +132,11 @@ public class SettingsMenuDialog extends SettingsDialog{ //game.checkPref("smoothcam", true); game.checkPref("effects", true); //game.sliderPref("sensitivity", 100, 10, 300, i -> i + "%"); - game.sliderPref("saveinterval", 90, 10, 5 * 120, i -> Bundles.format("setting.seconds", i)); + game.sliderPref("saveinterval", 60, 10, 5 * 120, i -> Bundles.format("setting.seconds", i)); + + if(!gwt){ + graphics.sliderPref("fpscap", 125, 5, 125, 5, s -> (s > 120 ? Bundles.get("setting.fpscap.none") : Bundles.format("setting.fpscap.text", s))); + } if(!gwt){ graphics.checkPref("multithread", true, threads::setEnabled); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/UnlocksDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/UnlocksDialog.java index 7bc8d5e445..0b765eafba 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/UnlocksDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/UnlocksDialog.java @@ -7,6 +7,7 @@ import io.anuke.mindustry.core.ContentLoader; import io.anuke.mindustry.game.Content; import io.anuke.mindustry.game.UnlockableContent; import io.anuke.mindustry.graphics.Palette; +import io.anuke.ucore.scene.event.HandCursorListener; import io.anuke.ucore.scene.ui.Image; import io.anuke.ucore.scene.ui.ScrollPane; import io.anuke.ucore.scene.ui.Tooltip; @@ -56,6 +57,7 @@ public class UnlocksDialog extends FloatingDialog{ if(unlock.isHidden()) continue; Image image = control.database().isUnlocked(unlock) ? new Image(unlock.getContentIcon()) : new Image("icon-locked"); + image.addListener(new HandCursorListener()); list.add(image).size(size).pad(3); if(control.database().isUnlocked(unlock)){ diff --git a/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java b/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java index 75f83b032e..a933e1b579 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java @@ -8,10 +8,8 @@ import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.gen.CallBlocks; -import io.anuke.mindustry.gen.CallEntity; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.input.InputHandler; -import io.anuke.mindustry.net.In; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.ui.ItemImage; import io.anuke.mindustry.world.Tile; @@ -44,7 +42,7 @@ public class BlockInventoryFragment extends Fragment{ this.input = input; } - @Remote(called = Loc.server, targets = Loc.both, in = In.blocks, forward = true) + @Remote(called = Loc.server, targets = Loc.both, forward = true) public static void requestItem(Player player, Tile tile, Item item, int amount){ if(player == null) return; @@ -52,7 +50,7 @@ public class BlockInventoryFragment extends Fragment{ player.inventory.addItem(item, removed); for(int j = 0; j < Mathf.clamp(removed / 3, 1, 8); j++){ - Timers.run(j * 3f, () -> CallEntity.transferItemEffect(item, tile.drawx(), tile.drawy(), player)); + Timers.run(j * 3f, () -> Call.transferItemEffect(item, tile.drawx(), tile.drawy(), player)); } } @@ -99,7 +97,7 @@ public class BlockInventoryFragment extends Fragment{ if(holdTime >= holdWithdraw){ int amount = Math.min(tile.entity.items.get(lastItem), player.inventory.itemCapacityUsed(lastItem)); - CallBlocks.requestItem(player, tile, lastItem, amount); + Call.requestItem(player, tile, lastItem, amount); holding = false; holdTime = 0f; } @@ -149,7 +147,7 @@ public class BlockInventoryFragment extends Fragment{ public boolean touchDown(InputEvent event, float x, float y, int pointer, int button){ if(!canPick.get() || !tile.entity.items.has(item)) return false; int amount = Math.min(1, player.inventory.itemCapacityUsed(item)); - CallBlocks.requestItem(player, tile, item, amount); + Call.requestItem(player, tile, item, amount); lastItem = item; holding = true; holdTime = 0f; diff --git a/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java b/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java index 5e1a5c9884..79e18ea09e 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java @@ -227,10 +227,12 @@ public class BlocksFragment extends Fragment{ if(entity == null) return; - for(ItemStack s : r.requirements){ - if(!entity.items.has(s.item, Mathf.ceil(s.amount))){ - istack.setColor(Color.GRAY); - return; + if(!state.mode.infiniteResources){ + for(ItemStack s : r.requirements){ + if(!entity.items.has(s.item, Mathf.ceil(s.amount))){ + istack.setColor(Color.GRAY); + return; + } } } istack.setColor(Color.WHITE); @@ -310,7 +312,7 @@ public class BlocksFragment extends Fragment{ requirements.addImage(stack.item.region).size(8 * 3); Label reqlabel = new Label(() -> { TileEntity core = players[0].getClosestCore(); - if(core == null) return "*/*"; + if(core == null || state.mode.infiniteResources) return "*/*"; int amount = core.items.get(stack.item); String color = (amount < stack.amount / 2f ? "[red]" : amount < stack.amount ? "[orange]" : "[white]"); diff --git a/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java b/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java index c9860c6fb0..10aa2d8460 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java @@ -4,12 +4,10 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.files.FileHandle; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.entities.effect.ItemDrop; import io.anuke.mindustry.entities.units.BaseUnit; import io.anuke.mindustry.entities.units.UnitType; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.net.Net; -import io.anuke.mindustry.type.Item; import io.anuke.mindustry.ui.dialogs.FloatingDialog; import io.anuke.mindustry.ui.dialogs.GenViewDialog; import io.anuke.ucore.core.Timers; @@ -20,7 +18,6 @@ import io.anuke.ucore.scene.ui.Label; import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.util.Log; import io.anuke.ucore.util.Log.LogHandler; -import io.anuke.ucore.util.Mathf; import static io.anuke.mindustry.Vars.*; @@ -128,12 +125,6 @@ public class DebugFragment extends Fragment{ t.row(); t.addButton("noclip", "toggle", () -> noclip = !noclip); t.row(); - t.addButton("items", () -> { - for(int i = 0; i < 10; i++){ - ItemDrop.create(Item.all().random(), 5, player.x, player.y, Mathf.random(360f)); - } - }); - t.row(); t.addButton("team", "toggle", player::toggleTeam); t.row(); t.addButton("blocks", "toggle", () -> showBlockDebug = !showBlockDebug); diff --git a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java index 85b3c3d25b..b935623087 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java @@ -97,7 +97,7 @@ public class HudFragment extends Fragment{ cont.row(); - cont.table(this::addWaveTable).touchable(Touchable.enabled).fillX().height(66f); + Table waves = cont.table(this::addWaveTable).touchable(Touchable.enabled).fillX().height(66f).get(); cont.row(); @@ -109,8 +109,10 @@ public class HudFragment extends Fragment{ t.label(() -> fps.get(Gdx.graphics.getFramesPerSecond())).padRight(10); t.label(() -> tps.get(threads.getTPS())).visible(() -> threads.isEnabled()); t.row(); - t.label(() -> ping.get(Net.getPing())).visible(() -> Net.client() && !gwt).colspan(2); - }).size(-1).visible(() -> Settings.getBool("fps")).get(); + if(Net.hasClient()){ + t.label(() -> ping.get(Net.getPing())).visible(() -> Net.client() && !gwt).colspan(2); + } + }).size(-1).visible(() -> Settings.getBool("fps")).update(t -> t.setTranslation(0, state.mode.disableWaves ? waves.getHeight() : 0)).get(); //make wave box appear below rest of menu cont.swapActor(wavetable, menu.getParent()); @@ -283,6 +285,7 @@ public class HudFragment extends Fragment{ }); table.add().growX(); + table.visible(() -> !state.mode.disableWaves); playButton(uheight); } diff --git a/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java b/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java index b08d2adbb8..74ca174ba9 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java @@ -153,11 +153,11 @@ public class MenuFragment extends Fragment{ dialog.content().row(); dialog.content().add(new MenuButton("icon-add", "$text.joingame", () -> { - if(Platform.instance.canJoinGame()){ + if(!gwt){ ui.join.show(); dialog.hide(); }else{ - ui.showInfo("$text.multiplayer.web"); + ui.showInfo("$text.web.unsupported"); } })); diff --git a/core/src/io/anuke/mindustry/world/BaseBlock.java b/core/src/io/anuke/mindustry/world/BaseBlock.java index 9b97c1940e..e6408b4fb4 100644 --- a/core/src/io/anuke/mindustry/world/BaseBlock.java +++ b/core/src/io/anuke/mindustry/world/BaseBlock.java @@ -10,6 +10,7 @@ import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.consumers.ConsumeItem; import io.anuke.mindustry.world.consumers.ConsumeLiquid; import io.anuke.mindustry.world.consumers.Consumers; +import io.anuke.mindustry.world.meta.Producers; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Timers; import io.anuke.ucore.util.Mathf; @@ -23,14 +24,13 @@ public abstract class BaseBlock{ public boolean outputsLiquid = false; public boolean singleLiquid = true; - public boolean outputsItems = false; - public int itemCapacity; public float liquidCapacity = 10f; public float liquidFlowFactor = 4.9f; public float powerCapacity = 10f; public Consumers consumes = new Consumers(); + public Producers produces = new Producers(); public boolean shouldConsume(Tile tile){ return true; @@ -55,17 +55,21 @@ public abstract class BaseBlock{ * Remove a stack from this inventory, and return the amount removed. */ public int removeStack(Tile tile, Item item, int amount){ - tile.entity.wakeUp(); + tile.entity.noSleep(); tile.entity.items.remove(item, amount); return amount; } /**Handle a stack input.*/ public void handleStack(Item item, int amount, Tile tile, Unit source){ - tile.entity.wakeUp(); + tile.entity.noSleep(); tile.entity.items.add(item, amount); } + public boolean outputsItems(){ + return hasItems; + } + /**Returns offset for stack placement.*/ public void getStackOffset(Item item, Tile tile, Translator trns){ @@ -85,8 +89,8 @@ public abstract class BaseBlock{ 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.01f)) - && (!consumes.has(ConsumeLiquid.class) || consumes.liquid() == liquid); + (!singleLiquid || (tile.entity.liquids.current() == liquid || tile.entity.liquids.get(tile.entity.liquids.current()) < 0.01f)) && + (!consumes.has(ConsumeLiquid.class) || consumes.liquid() == liquid); } public void handleLiquid(Tile tile, Tile source, Liquid liquid, float amount){ @@ -117,7 +121,7 @@ public abstract class BaseBlock{ Tile other = proximity.get((i + dump) % proximity.size); Tile in = Edges.getFacingEdge(tile, other); - if(other.block().hasLiquids){ + if(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; @@ -127,6 +131,10 @@ public abstract class BaseBlock{ } + public boolean canDumpLiquid(Tile tile, Tile to, Liquid liquid){ + return true; + } + public void tryMoveLiquid(Tile tile, Tile tileSource, Tile next, float amount, Liquid liquid){ float flow = Math.min(next.block().liquidCapacity - next.entity.liquids.get(liquid) - 0.001f, amount); diff --git a/core/src/io/anuke/mindustry/world/Block.java b/core/src/io/anuke/mindustry/world/Block.java index 4b78de36a7..013b0f8882 100644 --- a/core/src/io/anuke/mindustry/world/Block.java +++ b/core/src/io/anuke/mindustry/world/Block.java @@ -13,6 +13,7 @@ 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.game.Content; +import io.anuke.mindustry.game.UnlockableContent; import io.anuke.mindustry.graphics.CacheLayer; import io.anuke.mindustry.graphics.Layer; import io.anuke.mindustry.graphics.Palette; @@ -29,13 +30,13 @@ import io.anuke.ucore.util.Bundles; import io.anuke.ucore.util.EnumSet; import io.anuke.ucore.util.Mathf; -import static io.anuke.mindustry.Vars.tilesize; -import static io.anuke.mindustry.Vars.world; +import static io.anuke.mindustry.Vars.*; public class Block extends BaseBlock implements Content{ private static int lastid; private static Array blocks = new Array<>(140); private static ObjectMap map = new ObjectMap<>(); + /** internal name */ public final String name; /** internal ID */ @@ -104,12 +105,16 @@ public class Block extends BaseBlock implements Content{ public Color minimapColor = Color.CLEAR; /** View range of this block type. Use a value < 0 to disable. */ public float viewRange = 10; + /**Whether the top icon is outlined, like a turret.*/ + public boolean turretIcon = false; + protected Array tempTiles = new Array<>(); protected Color tempColor = new Color(); protected TextureRegion[] blockIcon; protected TextureRegion[] icon; protected TextureRegion[] compactIcon; protected TextureRegion editorIcon; + public TextureRegion shadowRegion; public TextureRegion region; @@ -146,6 +151,20 @@ public class Block extends BaseBlock implements Content{ return blocks.get(id); } + /**Populates the array with all blocks that produce this content.*/ + public static void getByProduction(Array arr, Content content){ + arr.clear(); + for(Block block : Block.all()){ + if(block.produces.get() == content){ + arr.add(block); + } + } + } + + public boolean dropsItem(Item item){ + return drops != null && drops.item == item; + } + public boolean isLayer(Tile tile){ return true; } @@ -181,6 +200,13 @@ public class Block extends BaseBlock implements Content{ return true; } + /**Call when some content is produced. This unlocks the content if it is applicable.*/ + public void useContent(UnlockableContent content){ + if(!headless){ + control.database().unlockContent(content); + } + } + /** Called after all blocks are created. */ @Override public void init(){ diff --git a/core/src/io/anuke/mindustry/world/Build.java b/core/src/io/anuke/mindustry/world/Build.java index 34726fec7f..6b0f226cac 100644 --- a/core/src/io/anuke/mindustry/world/Build.java +++ b/core/src/io/anuke/mindustry/world/Build.java @@ -154,7 +154,7 @@ 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.cliffs != 0 || !other.floor().placeableOn || + || other.hasCliffs() || !other.floor().placeableOn || (tile.floor().liquidDrop != null && !type.floating)){ return false; } @@ -164,7 +164,7 @@ public class Build{ }else{ return (tile.getTeam() == Team.none || tile.getTeam() == team) && (tile.floor().liquidDrop == null || type.floating) - && tile.floor().placeableOn && tile.cliffs == 0 + && tile.floor().placeableOn && !tile.hasCliffs() && ((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); diff --git a/core/src/io/anuke/mindustry/world/ColorMapper.java b/core/src/io/anuke/mindustry/world/ColorMapper.java index 9bddff9665..20d0067f58 100644 --- a/core/src/io/anuke/mindustry/world/ColorMapper.java +++ b/core/src/io/anuke/mindustry/world/ColorMapper.java @@ -22,7 +22,10 @@ public class ColorMapper implements ContentList{ } public static int colorFor(Block floor, Block wall, Team team, int elevation){ - int color = wall.breakable ? team.intColor : getBlockColor(wall); + if(wall.synthetic()){ + return team.intColor; + } + int color = getBlockColor(wall); if(color == 0) color = ColorMapper.getBlockColor(floor); if(elevation > 0){ if(tmpColors.get() == null) tmpColors.set(new Color()); diff --git a/core/src/io/anuke/mindustry/world/Tile.java b/core/src/io/anuke/mindustry/world/Tile.java index a8ba24f7df..24a1c1bb46 100644 --- a/core/src/io/anuke/mindustry/world/Tile.java +++ b/core/src/io/anuke/mindustry/world/Tile.java @@ -29,22 +29,23 @@ public class Tile implements PosTrait, TargetTrait{ * This is relative to the block it is linked to; negate coords to find the link. */ public byte link = 0; - public short x, y; /** Tile traversal cost. */ public byte cost = 1; - /** Position of cliffs around the tile, packed into bits 0-8. */ - public byte cliffs; /** Tile entity, usually null. */ public TileEntity entity; - /** Block ID data. */ + public short x, y; + /** Position of cliffs around the tile, packed into bits 0-8. */ + private byte cliffs; private Block wall; private Floor floor; - /** Rotation, 0-3. Also used to store offload location for routers, in which case it can be any number. */ + /** 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; /** Tile elevation. -1 means slope.*/ private byte elevation; + /** Visibility status: 3 states, but saved as a single bit. 0 = unexplored, 1 = visited, 2 = currently visible (saved as 1)*/ + private byte visibility; public Tile(int x, int y){ this.x = (short) x; @@ -68,6 +69,10 @@ public class Tile implements PosTrait, TargetTrait{ this.team = team; } + public boolean discovered(){ + return visibility > 0; + } + public int packedPosition(){ return x + y * world.width(); } @@ -160,6 +165,11 @@ public class Tile implements PosTrait, TargetTrait{ } } + public void setBlock(Block type, Team team){ + setBlock(type); + setTeam(team); + } + public void setBlock(Block type){ synchronized(tileSetLock){ preChanged(); @@ -173,6 +183,14 @@ public class Tile implements PosTrait, TargetTrait{ this.floor = type; } + public byte getVisibility(){ + return visibility; + } + + public void setVisibility(byte visibility){ + this.visibility = visibility; + } + public byte getRotation(){ return rotation; } @@ -197,6 +215,18 @@ public class Tile implements PosTrait, TargetTrait{ this.elevation = (byte)elevation; } + public byte getCliffs(){ + return cliffs; + } + + public void setCliffs(byte cliffs){ + this.cliffs = cliffs; + } + + public boolean hasCliffs(){ + return getCliffs() != 0; + } + public boolean passable(){ Block block = block(); Block floor = floor(); @@ -212,7 +242,7 @@ public class Tile implements PosTrait, TargetTrait{ public boolean solid(){ Block block = block(); Block floor = floor(); - return block.solid || cliffs != 0 || (floor.solid && (block == Blocks.air || block.solidifes)) || block.isSolidFor(this) + return block.solid || getCliffs() != 0 || (floor.solid && (block == Blocks.air || block.solidifes)) || block.isSolidFor(this) || (isLinked() && getLinked().block().isSolidFor(getLinked())); } diff --git a/core/src/io/anuke/mindustry/world/blocks/BlockPart.java b/core/src/io/anuke/mindustry/world/blocks/BlockPart.java index dd90451dec..fdb3e34561 100644 --- a/core/src/io/anuke/mindustry/world/blocks/BlockPart.java +++ b/core/src/io/anuke/mindustry/world/blocks/BlockPart.java @@ -16,6 +16,7 @@ public class BlockPart extends Block{ super("blockpart"); solid = false; hasPower = hasItems = hasLiquids = true; + viewRange = -1; } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java b/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java index bdbb6abd93..c110d9dbeb 100644 --- a/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java @@ -11,12 +11,11 @@ import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.entities.effect.RubbleDecal; import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest; import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.gen.CallBlocks; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Layer; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.graphics.Shaders; import io.anuke.mindustry.input.CursorType; -import io.anuke.mindustry.net.In; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.Recipe; import io.anuke.mindustry.world.BarType; @@ -46,13 +45,13 @@ public class BuildBlock extends Block{ solidifes = true; } - @Remote(called = Loc.server, in = In.blocks) + @Remote(called = Loc.server) public static void onDeconstructFinish(Tile tile, Block block){ Effects.effect(Fx.breakBlock, tile.drawx(), tile.drawy(), block.size); world.removeBlock(tile); } - @Remote(called = Loc.server, in = In.blocks) + @Remote(called = Loc.server) public static void onConstructFinish(Tile tile, Block block, int builderID, byte rotation, Team team){ world.setBlock(tile, block, team); tile.setRotation(rotation); @@ -209,8 +208,8 @@ public class BuildBlock extends Block{ builderID = builder.getID(); } - if(progress >= 1f || debug){ - CallBlocks.onConstructFinish(tile, recipe.result, builderID, tile.getRotation(), tile.getTeam()); + if(progress >= 1f || debug || state.mode.infiniteResources){ + Call.onConstructFinish(tile, recipe.result, builderID, tile.getRotation(), builder.getTeam()); } } @@ -237,8 +236,8 @@ public class BuildBlock extends Block{ progress = Mathf.clamp(progress - amount); - if(progress <= 0 || debug){ - CallBlocks.onDeconstructFinish(tile, this.recipe == null ? previous : this.recipe.result); + if(progress <= 0 || debug || state.mode.infiniteResources){ + Call.onDeconstructFinish(tile, this.recipe == null ? previous : this.recipe.result); } } diff --git a/core/src/io/anuke/mindustry/world/blocks/Floor.java b/core/src/io/anuke/mindustry/world/blocks/Floor.java index 72b8fbdec1..04106ac14b 100644 --- a/core/src/io/anuke/mindustry/world/blocks/Floor.java +++ b/core/src/io/anuke/mindustry/world/blocks/Floor.java @@ -12,6 +12,7 @@ import io.anuke.mindustry.type.StatusEffect; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.core.Effects.Effect; +import io.anuke.ucore.function.BiPredicate; import io.anuke.ucore.function.Predicate; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Geometry; @@ -60,6 +61,7 @@ public class Floor extends Block{ protected TextureRegion[] variantRegions; protected Vector2[] offsets; protected Predicate blends = block -> block != this && !block.blendOverride(this); + protected BiPredicate tileBlends = (tile, other) -> false; protected boolean blend = true; public Floor(String name){ @@ -138,12 +140,12 @@ public class Floor extends Block{ Draw.rect(variantRegions[Mathf.randomSeed(tile.id(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy()); - if(tile.cliffs != 0 && cliffRegions != null){ + if(tile.hasCliffs() && cliffRegions != null){ for(int i = 0; i < 4; i++){ - if((tile.cliffs & (1 << i * 2)) != 0){ + if((tile.getCliffs() & (1 << i * 2)) != 0){ Draw.colorl(i > 1 ? 0.6f : 1f); - boolean above = (tile.cliffs & (1 << ((i + 1) % 4) * 2)) != 0, below = (tile.cliffs & (1 << (Mathf.mod(i - 1, 4)) * 2)) != 0; + boolean above = (tile.getCliffs() & (1 << ((i + 1) % 4) * 2)) != 0, below = (tile.getCliffs() & (1 << (Mathf.mod(i - 1, 4)) * 2)) != 0; if(above && below){ Draw.rect(cliffRegions[0], tile.worldx(), tile.worldy(), i * 90); @@ -167,7 +169,7 @@ public class Floor extends Block{ } protected void drawEdges(Tile tile, boolean sameLayer){ - if(!blend || tile.cliffs > 0) return; + if(!blend || tile.getCliffs() > 0) return; for(int i = 0; i < 8; i++){ int dx = Geometry.d8[i].x, dy = Geometry.d8[i].y; @@ -178,7 +180,7 @@ public class Floor extends Block{ Floor floor = other.floor(); - if((floor.id <= this.id && !(tile.getElevation() != -1 && other.getElevation() > tile.getElevation())) || !blends.test(floor) || (floor.cacheLayer.ordinal() > this.cacheLayer.ordinal() && !sameLayer) || + if((floor.id <= this.id && !(tile.getElevation() != -1 && other.getElevation() > tile.getElevation())) || (!blends.test(floor) && !tileBlends.test(tile, other)) || (floor.cacheLayer.ordinal() > this.cacheLayer.ordinal() && !sameLayer) || (sameLayer && floor.cacheLayer == this.cacheLayer)) continue; TextureRegion region = floor.edgeRegions[i]; diff --git a/core/src/io/anuke/mindustry/world/blocks/OreBlock.java b/core/src/io/anuke/mindustry/world/blocks/OreBlock.java index 57c7f67aa2..1f33c90895 100644 --- a/core/src/io/anuke/mindustry/world/blocks/OreBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/OreBlock.java @@ -19,6 +19,7 @@ public class OreBlock extends Floor{ this.variants = 3; this.minimapColor = ore.color; this.blends = block -> block instanceof OreBlock && ((OreBlock) block).base != base; + this.tileBlends = (tile, other) -> tile.getElevation() < other.getElevation(); this.edge = base.name; } 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 b982ff5a0b..2972248ac2 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 @@ -21,6 +21,10 @@ public class ItemTurret extends CooledTurret{ hasItems = true; } + public AmmoType[] getAmmoTypes(){ + return ammoTypes; + } + @Override public void setStats(){ super.setStats(); 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 e053be47e1..74f7c26c71 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 @@ -40,8 +40,8 @@ public abstract class LiquidTurret extends Turret{ TurretEntity entity = tile.entity(); - Effects.effect(shootEffect, type.liquid.color, tile.drawx() + tr.x, tile.drawy() + tr.y, entity.rotation); - Effects.effect(smokeEffect, type.liquid.color, tile.drawx() + tr.x, tile.drawy() + tr.y, entity.rotation); + Effects.effect(type.shootEffect, type.liquid.color, tile.drawx() + tr.x, tile.drawy() + tr.y, entity.rotation); + Effects.effect(type.smokeEffect, type.liquid.color, tile.drawx() + tr.x, tile.drawy() + tr.y, entity.rotation); if(shootShake > 0){ Effects.shake(shootShake, shootShake, tile.entity); 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 a2bd405b78..5b8b8f4825 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 @@ -85,6 +85,12 @@ public abstract class Turret extends Block{ solid = true; layer = Layer.turret; group = BlockGroup.turrets; + turretIcon = true; + } + + @Override + public boolean outputsItems(){ + return false; } @Override 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 01513da6b8..2061950eb1 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Conduit.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Conduit.java @@ -121,7 +121,7 @@ public class Conduit extends LiquidBlock{ @Override public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ - tile.entity.wakeUp(); + tile.entity.noSleep(); return super.acceptLiquid(tile, source, liquid, amount) && ((2 + source.relativeTo(tile.x, tile.y)) % 4 != tile.getRotation()); } 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 33ce205151..a8bec8c381 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Conveyor.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Conveyor.java @@ -128,7 +128,7 @@ public class Conveyor extends Block{ Tile other = tile.getNearby(Mathf.mod(tile.getRotation() - direction, 4)); if(other != null) other = other.target(); - if(other == null || (!other.block().outputsItems && !other.block().hasItems)) return false; + if(other == null || !other.block().outputsItems()) return false; return (tile.getNearby(tile.getRotation()) == other) || (!other.block().rotate || other.getNearby(other.getRotation()) == tile); } @@ -141,11 +141,6 @@ public class Conveyor extends Block{ return super.getIcon(); } - @Override - public boolean isLayer(Tile tile){ - return tile.entity().convey.size > 0; - } - @Override public void drawLayer(Tile tile){ ConveyorEntity entity = tile.entity(); @@ -214,7 +209,6 @@ public class Conveyor extends Block{ int minremove = Integer.MAX_VALUE; float speed = Math.max(this.speed - (1f - (carryCapacity - entity.carrying) / carryCapacity), 0f); - float totalMoved = 0f; for(int i = entity.convey.size - 1; i >= 0; i--){ long value = entity.convey.get(i); @@ -226,7 +220,6 @@ public class Conveyor extends Block{ break; } - float prev = pos.y; float nextpos = (i == entity.convey.size - 1 ? 100f : pos2.set(entity.convey.get(i + 1), ItemPos.updateShorts).y) - itemSpace; if(entity.minCarry >= pos.y && entity.minCarry <= nextpos){ nextpos = entity.minCarry; @@ -241,11 +234,9 @@ public class Conveyor extends Block{ } pos.y = Mathf.clamp(pos.y); - totalMoved += (pos.y - prev); if(pos.y >= 0.9999f && offloadDir(tile, pos.item)){ minremove = Math.min(i, minremove); - totalMoved = 1f; tile.entity.items.remove(pos.item, 1); }else{ value = pos.pack(); @@ -265,7 +256,7 @@ public class Conveyor extends Block{ entity.carrying = 0f; entity.minCarry = 2f; - if(totalMoved/Timers.delta() <= 0.0001f){ + if(entity.items.total() == 0){ entity.sleep(); }else{ entity.noSleep(); @@ -282,7 +273,7 @@ public class Conveyor extends Block{ @Override public synchronized int removeStack(Tile tile, Item item, int amount){ ConveyorEntity entity = tile.entity(); - entity.wakeUp(); + entity.noSleep(); int removed = 0; for(int j = 0; j < amount; j++){ @@ -308,17 +299,20 @@ public class Conveyor extends Block{ @Override public synchronized int acceptStack(Item item, int amount, Tile tile, Unit source){ ConveyorEntity entity = tile.entity(); - return entity.minitem > itemSpace ? 1 : 0; + return (int)(entity.minitem / itemSpace); } @Override public synchronized void handleStack(Item item, int amount, Tile tile, Unit source){ ConveyorEntity entity = tile.entity(); - long result = ItemPos.packItem(item, 0f, 0f, (byte) Mathf.random(255)); - entity.convey.insert(0, result); - entity.items.add(item, 1); - entity.wakeUp(); + for(int i = amount - 1; i >= 0; i--){ + long result = ItemPos.packItem(item, 0f, i * itemSpace, (byte) Mathf.random(255)); + entity.convey.insert(0, result); + entity.items.add(item, 1); + } + + entity.noSleep(); } @Override @@ -340,7 +334,7 @@ public class Conveyor extends Block{ float y = (ang == -1 || ang == 3) ? 1 : (ang == 1 || ang == -3) ? -1 : 0; ConveyorEntity entity = tile.entity(); - entity.wakeUp(); + entity.noSleep(); long result = ItemPos.packItem(item, y * 0.9f, pos, (byte) Mathf.random(255)); boolean inserted = false; 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 d54992df5f..1d7f7f197b 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/ItemBridge.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/ItemBridge.java @@ -9,10 +9,9 @@ import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.gen.CallBlocks; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Layer; import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.net.In; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -52,7 +51,7 @@ public class ItemBridge extends Block{ hasItems = true; } - @Remote(targets = Loc.both, called = Loc.both, in = In.blocks, forward = true) + @Remote(targets = Loc.both, called = Loc.both, forward = true) public static void linkItemBridge(Player player, Tile tile, Tile other){ ItemBridgeEntity entity = tile.entity(); ItemBridgeEntity oe = other.entity(); @@ -60,7 +59,7 @@ public class ItemBridge extends Block{ oe.incoming.add(tile.packedPosition()); } - @Remote(targets = Loc.both, called = Loc.server, in = In.blocks, forward = true) + @Remote(targets = Loc.both, called = Loc.server, forward = true) public static void unlinkItemBridge(Player player, Tile tile, Tile other){ ItemBridgeEntity entity = tile.entity(); entity.link = -1; @@ -85,7 +84,7 @@ public class ItemBridge extends Block{ if(linkValid(tile, last)){ ItemBridgeEntity entity = last.entity(); if(!linkValid(last, world.tile(entity.link))){ - CallBlocks.linkItemBridge(null, last, tile); + Call.linkItemBridge(null, last, tile); } } lastPlaced = tile.packedPosition(); @@ -138,9 +137,9 @@ public class ItemBridge extends Block{ if(linkValid(tile, other)){ if(entity.link == other.packedPosition()){ - CallBlocks.unlinkItemBridge(null, tile, other); + Call.unlinkItemBridge(null, tile, other); }else{ - CallBlocks.linkItemBridge(null, tile, other); + Call.linkItemBridge(null, tile, other); } return false; } 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 f5e795d5be..a339ce3f41 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Junction.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Junction.java @@ -20,10 +20,14 @@ public class Junction extends Block{ update = true; solid = true; instantTransfer = true; - outputsItems = true; group = BlockGroup.transportation; } + @Override + public boolean outputsItems(){ + return true; + } + @Override public void update(Tile tile){ JunctionEntity entity = tile.entity(); 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 55444ca2b0..7f9d9cb2a9 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidBridge.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidBridge.java @@ -1,6 +1,8 @@ package io.anuke.mindustry.world.blocks.distribution; +import com.badlogic.gdx.utils.IntSet.IntSetIterator; import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.core.Timers; import io.anuke.ucore.util.Mathf; @@ -48,4 +50,31 @@ public class LiquidBridge extends ItemBridge{ public boolean acceptItem(Item item, Tile tile, Tile source){ return false; } + + @Override + public boolean canDumpLiquid(Tile tile, Tile to, Liquid liquid){ + ItemBridgeEntity entity = tile.entity(); + + Tile other = world.tile(entity.link); + if(!linkValid(tile, other)){ + int i = tile.absoluteRelativeTo(to.x, to.y); + + IntSetIterator it = entity.incoming.iterator(); + + while(it.hasNext){ + int v = it.next(); + int x = v % world.width(); + int y = v / world.width(); + if(tile.absoluteRelativeTo(x, y) == i){ + return false; + } + } + return true; + } + + int rel = tile.absoluteRelativeTo(other.x, other.y); + int rel2 = tile.relativeTo(to.x, to.y); + + return rel != rel2; + } } 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 7be3b85cc5..0ad3cd3f5f 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidExtendingBridge.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidExtendingBridge.java @@ -1,6 +1,8 @@ package io.anuke.mindustry.world.blocks.distribution; +import com.badlogic.gdx.utils.IntSet.IntSetIterator; import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.core.Timers; import io.anuke.ucore.util.Mathf; @@ -48,4 +50,31 @@ public class LiquidExtendingBridge extends ExtendingItemBridge{ public boolean acceptItem(Item item, Tile tile, Tile source){ return false; } + + @Override + public boolean canDumpLiquid(Tile tile, Tile to, Liquid liquid){ + ItemBridgeEntity entity = tile.entity(); + + Tile other = world.tile(entity.link); + if(!linkValid(tile, other)){ + int i = tile.absoluteRelativeTo(to.x, to.y); + + IntSetIterator it = entity.incoming.iterator(); + + while(it.hasNext){ + int v = it.next(); + int x = v % world.width(); + int y = v / world.width(); + if(tile.absoluteRelativeTo(x, y) == i){ + return false; + } + } + return true; + } + + int rel = tile.absoluteRelativeTo(other.x, other.y); + int rel2 = tile.relativeTo(to.x, to.y); + + return rel != rel2; + } } 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 ac20aefb83..33f9111fad 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/MassDriver.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/MassDriver.java @@ -1,5 +1,6 @@ package io.anuke.mindustry.world.blocks.distribution; +import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.utils.ObjectSet; import com.badlogic.gdx.utils.Pool.Poolable; import io.anuke.annotations.Annotations.Loc; @@ -11,13 +12,14 @@ import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.effect.ItemDrop; -import io.anuke.mindustry.gen.CallBlocks; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Layer; import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.net.In; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.meta.BlockStat; +import io.anuke.mindustry.world.meta.StatUnit; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Effects.Effect; import io.anuke.ucore.core.Timers; @@ -39,11 +41,12 @@ public class MassDriver extends Block{ protected float translation = 7f; protected int minDistribute = 10; protected float knockback = 4f; - protected float reloadTime = 80f; + protected float reloadTime = 100f; protected Effect shootEffect = ShootFx.shootBig2; protected Effect smokeEffect = ShootFx.shootBigSmoke2; - protected Effect recieveEffect = BlockFx.smeltsmoke; + protected Effect recieveEffect = BlockFx.mineBig; protected float shake = 3f; + protected TextureRegion turretRegion; public MassDriver(String name){ super(name); @@ -51,12 +54,11 @@ public class MassDriver extends Block{ solid = true; configurable = true; hasItems = true; - itemCapacity = 50; layer = Layer.turret; hasPower = true; } - @Remote(targets = Loc.both, called = Loc.server, in = In.blocks, forward = true) + @Remote(targets = Loc.both, called = Loc.server, forward = true) public static void linkMassDriver(Player player, Tile tile, int position){ MassDriverEntity entity = tile.entity(); @@ -64,7 +66,7 @@ public class MassDriver extends Block{ threads.run(() -> entity.link = position); } - @Remote(called = Loc.server, in = In.blocks) + @Remote(called = Loc.server) public static void onMassDriverFire(Tile tile, Tile target){ //just in case the client has invalid data if(!(tile.entity instanceof MassDriverEntity) || !(target.entity instanceof MassDriverEntity)) return; @@ -100,6 +102,35 @@ public class MassDriver extends Block{ Effects.shake(driver.shake, driver.shake, entity); } + @Override + public TextureRegion[] getBlockIcon(){ + if(blockIcon == null){ + blockIcon = new TextureRegion[]{region, turretRegion}; + } + return super.getBlockIcon(); + } + + @Override + public void load(){ + super.load(); + + turretRegion = Draw.region(name + "-turret"); + } + + @Override + public void setStats(){ + super.setStats(); + + stats.add(BlockStat.powerShot, powerCapacity, StatUnit.powerUnits); + } + + @Override + public void init(){ + super.init(); + + viewRange = range; + } + @Override public void update(Tile tile){ MassDriverEntity entity = tile.entity(); @@ -137,7 +168,7 @@ public class MassDriver extends Block{ if(Mathf.angNear(entity.rotation, target, 1f) && Mathf.angNear(other.rotation, target + 180f, 1f)){ - CallBlocks.onMassDriverFire(tile, link); + Call.onMassDriverFire(tile, link); } } } @@ -149,7 +180,7 @@ public class MassDriver extends Block{ public void drawLayer(Tile tile){ MassDriverEntity entity = tile.entity(); - Draw.rect(name + "-turret", + Draw.rect(turretRegion, tile.drawx() + Angles.trnsx(entity.rotation + 180f, entity.reload * knockback), tile.drawy() + Angles.trnsy(entity.rotation + 180f, entity.reload * knockback), entity.rotation - 90); @@ -157,7 +188,11 @@ public class MassDriver extends Block{ @Override public void drawConfigure(Tile tile){ - super.drawConfigure(tile); + float sin = Mathf.absin(Timers.time(), 6f, 1f); + + Draw.color(Palette.accent); + Lines.stroke(1f); + Lines.circle(tile.drawx(), tile.drawy(), (tile.block().size/2f+1) * tilesize + sin); MassDriverEntity entity = tile.entity(); @@ -165,8 +200,7 @@ public class MassDriver extends Block{ Tile target = world.tile(entity.link); Draw.color(Palette.place); - Lines.square(target.drawx(), target.drawy(), - target.block().size * tilesize / 2f + 1f); + Lines.circle(target.drawx(), target.drawy(), (target.block().size/2f+1) * tilesize + sin); Draw.reset(); } @@ -182,10 +216,10 @@ public class MassDriver extends Block{ MassDriverEntity entity = tile.entity(); if(entity.link == other.packedPosition()){ - CallBlocks.linkMassDriver(null, tile, -1); + Call.linkMassDriver(null, tile, -1); return false; }else if(other.block() instanceof MassDriver && other.distanceTo(tile) <= range){ - CallBlocks.linkMassDriver(null, tile, other.packedPosition()); + Call.linkMassDriver(null, tile, other.packedPosition()); return false; } @@ -218,7 +252,6 @@ public class MassDriver extends Block{ public void reset(){ from = null; to = null; - ; } } 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 d45bb84078..eb556afef1 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Sorter.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Sorter.java @@ -5,8 +5,7 @@ import io.anuke.annotations.Annotations.Remote; import io.anuke.mindustry.content.Items; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.gen.CallBlocks; -import io.anuke.mindustry.net.In; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -27,12 +26,16 @@ public class Sorter extends Block implements SelectionTrait{ update = true; solid = true; instantTransfer = true; - outputsItems = true; group = BlockGroup.transportation; configurable = true; } - @Remote(targets = Loc.both, called = Loc.both, in = In.blocks, forward = true) + @Override + public boolean outputsItems(){ + return true; + } + + @Remote(targets = Loc.both, called = Loc.both, forward = true) public static void setSorterItem(Player player, Tile tile, Item item){ SorterEntity entity = tile.entity(); entity.sortItem = item; @@ -107,7 +110,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 -> CallBlocks.setSorterItem(null, tile, item)); + buildItemTable(table, () -> entity.sortItem, item -> Call.setSorterItem(null, tile, item)); } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/Splitter.java b/core/src/io/anuke/mindustry/world/blocks/distribution/Splitter.java index 4b405c7f78..964bf3ca53 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Splitter.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Splitter.java @@ -11,7 +11,7 @@ import io.anuke.mindustry.world.meta.BlockGroup; import io.anuke.ucore.core.Timers; public class Splitter extends Block{ - protected float speed = 7f; + protected float speed = 8f; public Splitter(String name){ super(name); @@ -36,7 +36,7 @@ public class Splitter extends Block{ entity.time += 1f/speed * Timers.delta(); Tile target = getTileTarget(tile, entity.lastItem, entity.lastInput, false); - if(target != null && (entity.time >= 1f)){ + if(target != null && (entity.time >= 1f || !(target.block() instanceof Splitter))){ getTileTarget(tile, entity.lastItem, entity.lastInput, true); target.block().handleItem(entity.lastItem, target, Edges.getFacingEdge(tile, target)); entity.items.remove(entity.lastItem, 1); diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/WarpGate.java b/core/src/io/anuke/mindustry/world/blocks/distribution/WarpGate.java index 0ed512555b..921ed20126 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/WarpGate.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/WarpGate.java @@ -9,8 +9,7 @@ import io.anuke.mindustry.content.Liquids; import io.anuke.mindustry.content.fx.BlockFx; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.gen.CallBlocks; -import io.anuke.mindustry.net.In; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Tile; @@ -75,7 +74,7 @@ public class WarpGate extends PowerBlock{ configurable = true; } - @Remote(targets = Loc.both, called = Loc.both, in = In.blocks, forward = true) + @Remote(targets = Loc.both, called = Loc.both, forward = true) public static void setTeleporterColor(Player player, Tile tile, byte color){ TeleporterEntity entity = tile.entity(); entity.color = color; @@ -88,7 +87,7 @@ public class WarpGate extends PowerBlock{ @Override public void placed(Tile tile){ - CallBlocks.setTeleporterColor(null, tile, lastColor); + Call.setTeleporterColor(null, tile, lastColor); } @Override @@ -254,7 +253,7 @@ public class WarpGate extends PowerBlock{ final int f = i; ImageButton button = cont.addImageButton("white", "toggle", 24, () -> { lastColor = (byte) f; - CallBlocks.setTeleporterColor(null, tile, (byte) f); + Call.setTeleporterColor(null, tile, (byte) f); }).size(34, 38).padBottom(-5.1f).group(group).get(); button.getStyle().imageUpColor = colorArray[f]; button.setChecked(entity.color == f); 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 5fac88bc26..7fca52eb2f 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/PowerGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/PowerGenerator.java @@ -12,6 +12,11 @@ public class PowerGenerator extends PowerDistributor{ flags = EnumSet.of(BlockFlag.producer); } + @Override + public boolean outputsItems(){ + return false; + } + @Override public TileEntity getEntity(){ return new GeneratorEntity(); @@ -19,6 +24,5 @@ public class PowerGenerator extends PowerDistributor{ public static class GeneratorEntity extends TileEntity{ public float generateTime; - public float uptime; } } 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 13c92a5b54..f031a9636b 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/PowerNode.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/PowerNode.java @@ -6,10 +6,9 @@ import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.gen.CallBlocks; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Layer; import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.net.In; import io.anuke.mindustry.world.Edges; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.PowerBlock; @@ -52,7 +51,7 @@ public class PowerNode extends PowerBlock{ configurable = true; } - @Remote(targets = Loc.both, called = Loc.server, in = In.blocks, forward = true) + @Remote(targets = Loc.both, called = Loc.server, forward = true) public static void linkPowerDistributors(Player player, Tile tile, Tile other){ DistributorEntity entity = tile.entity(); @@ -70,7 +69,7 @@ public class PowerNode extends PowerBlock{ } } - @Remote(targets = Loc.both, called = Loc.server, in = In.blocks, forward = true) + @Remote(targets = Loc.both, called = Loc.server, forward = true) public static void unlinkPowerDistributors(Player player, Tile tile, Tile other){ DistributorEntity entity = tile.entity(); @@ -91,7 +90,7 @@ public class PowerNode extends PowerBlock{ public void placed(Tile tile){ Tile before = world.tile(lastPlaced); if(linkValid(tile, before) && before.block() instanceof PowerNode){ - CallBlocks.linkPowerDistributors(null, tile, before); + Call.linkPowerDistributors(null, tile, before); } lastPlaced = tile.packedPosition(); @@ -119,9 +118,9 @@ public class PowerNode extends PowerBlock{ if(linkValid(tile, other)){ if(linked(tile, other)){ - threads.run(() -> CallBlocks.unlinkPowerDistributors(null, tile, result)); + threads.run(() -> Call.unlinkPowerDistributors(null, tile, result)); }else if(entity.links.size < maxNodes){ - threads.run(() -> CallBlocks.linkPowerDistributors(null, tile, result)); + threads.run(() -> Call.linkPowerDistributors(null, tile, result)); } return false; } 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 d4a1d33368..8a5235da6e 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Drill.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Drill.java @@ -21,9 +21,6 @@ import io.anuke.ucore.core.Timers; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Mathf; -import static io.anuke.mindustry.Vars.control; -import static io.anuke.mindustry.Vars.headless; - public class Drill extends Block{ protected final static float hardnessDrillMultiplier = 50f; protected final int timerDump = timers++; @@ -187,10 +184,7 @@ public class Drill extends Block{ int index = entity.index % toAdd.size; offloadNear(tile, toAdd.get(index)); - //unlock item content - if(!headless){ - control.database().unlockContent(toAdd.get(index)); - } + useContent(toAdd.get(index)); entity.index++; entity.progress = 0f; 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 9c0f60ba75..f6c796174a 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/GenericCrafter.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/GenericCrafter.java @@ -22,9 +22,6 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; -import static io.anuke.mindustry.Vars.control; -import static io.anuke.mindustry.Vars.headless; - public class GenericCrafter extends Block{ protected final int timerDump = timers++; @@ -49,6 +46,13 @@ public class GenericCrafter extends Block{ tile -> (float) tile.entity.items.get(consumes.item()) / itemCapacity)); } + @Override + public void init(){ + super.init(); + + produces.set(output); + } + @Override public void setStats(){ super.setStats(); @@ -93,10 +97,7 @@ public class GenericCrafter extends Block{ if(consumes.has(ConsumeItem.class)) tile.entity.items.remove(consumes.item(), consumes.itemAmount()); - //unlock output item - if(!headless){ - control.database().unlockContent(output); - } + useContent(output); offloadNear(tile, output); Effects.effect(craftEffect, tile.drawx(), tile.drawy()); diff --git a/core/src/io/anuke/mindustry/world/blocks/production/LiquidMixer.java b/core/src/io/anuke/mindustry/world/blocks/production/LiquidMixer.java index 11733cf392..6f92f062b4 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/LiquidMixer.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/LiquidMixer.java @@ -24,6 +24,13 @@ public class LiquidMixer extends LiquidBlock{ outputsLiquid = true; } + @Override + public void init(){ + super.init(); + + produces.set(outputLiquid); + } + @Override public void setStats(){ super.setStats(); diff --git a/core/src/io/anuke/mindustry/world/blocks/production/PowerCrafter.java b/core/src/io/anuke/mindustry/world/blocks/production/PowerCrafter.java index c43860227f..351e674938 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/PowerCrafter.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/PowerCrafter.java @@ -12,13 +12,9 @@ import io.anuke.ucore.core.Timers; public class PowerCrafter extends Block{ protected final int timerDump = timers++; - /** - * Optional. - */ + /**Optional.*/ protected Item outputItem; - /** - * Optional. Set hasLiquids to true when using. - */ + /**Optional. Set hasLiquids to true when using.*/ protected Liquid outputLiquid; protected float outputLiquidAmount; protected float craftTime; @@ -31,6 +27,11 @@ public class PowerCrafter extends Block{ hasItems = true; } + @Override + public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ + return false; + } + @Override public void init(){ super.init(); @@ -38,6 +39,12 @@ public class PowerCrafter extends Block{ if(outputLiquid != null){ outputsLiquid = true; } + + if(outputLiquid != null){ + produces.set(outputLiquid); + }else if(outputItem != null){ + produces.set(outputItem); + } } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/production/PowerSmelter.java b/core/src/io/anuke/mindustry/world/blocks/production/PowerSmelter.java index ebb561aa12..7fbf99a4c4 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/PowerSmelter.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/PowerSmelter.java @@ -31,7 +31,7 @@ public class PowerSmelter extends PowerBlock{ protected float minFlux = 0.2f; protected int fluxNeeded = 1; - protected float baseFluxChance = 0.15f; + protected float baseFluxChance = 0.25f; protected boolean useFlux = false; protected float heatUpTime = 80f; @@ -53,6 +53,13 @@ public class PowerSmelter extends PowerBlock{ itemCapacity = 20; } + @Override + public void init(){ + super.init(); + + produces.set(result); + } + @Override public void load(){ super.load(); diff --git a/core/src/io/anuke/mindustry/world/blocks/production/Smelter.java b/core/src/io/anuke/mindustry/world/blocks/production/Smelter.java index 1f347070d9..d6a396f905 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Smelter.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Smelter.java @@ -27,7 +27,7 @@ public class Smelter extends Block{ protected Item result; protected float minFlux = 0.2f; - protected float baseFluxChance = 0.15f; + protected float baseFluxChance = 0.25f; protected boolean useFlux = false; protected float craftTime = 20f; @@ -75,6 +75,8 @@ public class Smelter extends Block{ throw new IllegalArgumentException("'" + name + "' has input item '" + item.item.name + "', which is a flux, when useFlux is enabled. To prevent ambiguous item use, either remove this flux item from the inputs, or set useFlux to false."); } } + + produces.set(result); } @Override 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 028d0651ce..d6d90797e6 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java @@ -14,11 +14,9 @@ import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.traits.SpawnerTrait; import io.anuke.mindustry.entities.units.BaseUnit; import io.anuke.mindustry.entities.units.UnitType; -import io.anuke.mindustry.gen.CallBlocks; -import io.anuke.mindustry.gen.CallEntity; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.graphics.Shaders; -import io.anuke.mindustry.net.In; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemType; @@ -66,7 +64,7 @@ public class CoreBlock extends StorageBlock{ flags = EnumSet.of(BlockFlag.resupplyPoint, BlockFlag.target); } - @Remote(called = Loc.server, in = In.blocks) + @Remote(called = Loc.server) public static void onUnitRespawn(Tile tile, Unit player){ if(player == null) return; @@ -82,7 +80,7 @@ public class CoreBlock extends StorageBlock{ entity.currentUnit = null; } - @Remote(called = Loc.server, in = In.blocks) + @Remote(called = Loc.server) public static void setCoreSolid(Tile tile, boolean solid){ CoreEntity entity = tile.entity(); entity.solid = solid; @@ -193,7 +191,7 @@ public class CoreBlock extends StorageBlock{ CoreEntity entity = tile.entity(); if(!entity.solid && !Units.anyEntities(tile)){ - CallBlocks.setCoreSolid(tile, true); + Call.setCoreSolid(tile, true); } if(entity.currentUnit != null){ @@ -207,7 +205,7 @@ public class CoreBlock extends StorageBlock{ } if(entity.progress >= 1f){ - CallBlocks.onUnitRespawn(tile, entity.currentUnit); + Call.onUnitRespawn(tile, entity.currentUnit); } }else{ entity.warmup += Timers.delta(); @@ -229,6 +227,8 @@ public class CoreBlock extends StorageBlock{ unit.setDead(true); unit.add(); + useContent(droneType); + entity.droneID = unit.id; } } @@ -248,7 +248,7 @@ public class CoreBlock extends StorageBlock{ if(tile.entity.items.get(item) > 0 && unit.acceptsAmmo(item)){ tile.entity.items.remove(item, 1); unit.addAmmo(item); - CallEntity.transferAmmo(item, tile.drawx(), tile.drawy(), unit); + Call.transferAmmo(item, tile.drawx(), tile.drawy(), unit); return; } } @@ -262,7 +262,7 @@ public class CoreBlock extends StorageBlock{ } /* - @Remote(called = Loc.server, in = In.blocks) + @Remote(called = Loc.server) public static void onCoreUnitSet(Tile tile, Unit player){ CoreEntity entity = tile.entity(); entity.currentUnit = player; diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/SortedUnloader.java b/core/src/io/anuke/mindustry/world/blocks/storage/SortedUnloader.java index 20363f7f31..36b249ff71 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/SortedUnloader.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/SortedUnloader.java @@ -3,11 +3,9 @@ package io.anuke.mindustry.world.blocks.storage; import com.badlogic.gdx.graphics.Color; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; -import io.anuke.mindustry.content.Items; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.gen.CallBlocks; -import io.anuke.mindustry.net.In; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.SelectionTrait; @@ -25,9 +23,10 @@ public class SortedUnloader extends Unloader implements SelectionTrait{ configurable = true; } - @Remote(targets = Loc.both, called = Loc.both, in = In.blocks, forward = true) + @Remote(targets = Loc.both, called = Loc.both, forward = true) public static void setSortedUnloaderItem(Player player, Tile tile, Item item){ SortedUnloaderEntity entity = tile.entity(); + entity.items.clear(); entity.sortItem = item; } @@ -37,7 +36,7 @@ public class SortedUnloader extends Unloader implements SelectionTrait{ if(entity.items.total() == 0 && entity.timer.get(timerUnload, speed)){ tile.allNearby(other -> { - if(other.block() instanceof StorageBlock && entity.items.total() == 0 && + if(other.getTeam() == 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)); } @@ -63,7 +62,7 @@ public class SortedUnloader extends Unloader implements SelectionTrait{ @Override public void buildTable(Tile tile, Table table){ SortedUnloaderEntity entity = tile.entity(); - buildItemTable(table, true, () -> entity.sortItem, item -> CallBlocks.setSortedUnloaderItem(null, tile, item)); + buildItemTable(table, true, () -> entity.sortItem, item -> Call.setSortedUnloaderItem(null, tile, item)); } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java b/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java index b5e4c83a8c..25f3d4a220 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java @@ -12,6 +12,11 @@ public abstract class StorageBlock extends Block{ hasItems = true; } + @Override + public boolean outputsItems(){ + return false; + } + /** * Removes an item and returns it. If item is not null, it should return the item. * Returns null if no items are there. 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 6e7d32403c..ab7c951836 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/Unloader.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/Unloader.java @@ -22,7 +22,7 @@ public class Unloader extends Block{ public void update(Tile tile){ if(tile.entity.items.total() == 0 && tile.entity.timer.get(timerUnload, speed)){ tile.allNearby(other -> { - if(other.block() instanceof StorageBlock && tile.entity.items.total() == 0 && + if(other.getTeam() == tile.getTeam() && other.block() instanceof StorageBlock && tile.entity.items.total() == 0 && ((StorageBlock) other.block()).hasItem(other, null)){ offloadNear(tile, ((StorageBlock) other.block()).removeItem(other, null)); } diff --git a/core/src/io/anuke/mindustry/world/blocks/units/CommandCenter.java b/core/src/io/anuke/mindustry/world/blocks/units/CommandCenter.java index c4a5ca3859..39d1b31486 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/CommandCenter.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/CommandCenter.java @@ -1,9 +1,110 @@ package io.anuke.mindustry.world.blocks.units; +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.utils.ObjectSet; +import io.anuke.annotations.Annotations.Loc; +import io.anuke.annotations.Annotations.Remote; +import io.anuke.mindustry.content.fx.BlockFx; +import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.units.BaseUnit; +import io.anuke.mindustry.entities.units.UnitCommand; +import io.anuke.mindustry.gen.Call; +import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.meta.BlockFlag; +import io.anuke.ucore.core.Effects; +import io.anuke.ucore.core.Effects.Effect; +import io.anuke.ucore.graphics.Draw; +import io.anuke.ucore.scene.ui.ButtonGroup; +import io.anuke.ucore.scene.ui.ImageButton; +import io.anuke.ucore.scene.ui.layout.Table; +import io.anuke.ucore.util.EnumSet; + +import static io.anuke.mindustry.Vars.*; public class CommandCenter extends Block{ + protected TextureRegion[] commandRegions = new TextureRegion[UnitCommand.values().length]; + protected Color topColor = Palette.command; + protected Color bottomColor = Color.valueOf("5e5e5e"); + protected Effect effect = BlockFx.commandSend; + public CommandCenter(String name){ super(name); + + flags = EnumSet.of(BlockFlag.comandCenter); + destructible = true; + solid = true; + configurable = true; + } + + @Override + public void placed(Tile tile){ + ObjectSet set = world.indexer().getAllied(tile.getTeam(), BlockFlag.comandCenter); + + if(set.size > 0){ + CommandCenterEntity entity = tile.entity(); + CommandCenterEntity oe = set.first().entity(); + entity.command = oe.command; + } + } + + @Override + public void load(){ + super.load(); + + for(UnitCommand cmd : UnitCommand.values()){ + commandRegions[cmd.ordinal()] = Draw.region("command-" + cmd.name()); + } + } + + @Override + public void draw(Tile tile){ + CommandCenterEntity entity = tile.entity(); + super.draw(tile); + + Draw.color(bottomColor); + Draw.rect(commandRegions[entity.command.ordinal()], tile.drawx(), tile.drawy() - 1); + Draw.color(topColor); + Draw.rect(commandRegions[entity.command.ordinal()], tile.drawx(), tile.drawy()); + Draw.color(); + } + + @Override + public void buildTable(Tile tile, Table table){ + CommandCenterEntity entity = tile.entity(); + ButtonGroup group = new ButtonGroup<>(); + + for(UnitCommand cmd : UnitCommand.values()){ + table.addImageButton("command-" + cmd.name(), "toggle", 8*3, () -> threads.run(() -> Call.onCommandCenterSet(players[0], tile, cmd))).size(40f, 44f) + .checked(entity.command == cmd).group(group); + } + } + + @Remote(called = Loc.server, forward = true, targets = Loc.both) + public static void onCommandCenterSet(Player player, Tile tile, UnitCommand command){ + Effects.effect(((CommandCenter)tile.block()).effect, tile); + + for(Tile center : world.indexer().getAllied(tile.getTeam(), BlockFlag.comandCenter)){ + if(center.block() instanceof CommandCenter){ + CommandCenterEntity entity = center.entity(); + entity.command = command; + } + } + + for(BaseUnit unit : unitGroups[player.getTeam().ordinal()].all()){ + unit.onCommand(command); + } + } + + @Override + public TileEntity getEntity(){ + return new CommandCenterEntity(); + } + + public class CommandCenterEntity extends TileEntity{ + public UnitCommand command = UnitCommand.idle; } } diff --git a/core/src/io/anuke/mindustry/world/blocks/units/MechFactory.java b/core/src/io/anuke/mindustry/world/blocks/units/MechFactory.java index df2c2db165..35f7f3dfce 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/MechFactory.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/MechFactory.java @@ -11,10 +11,9 @@ import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.traits.SpawnerTrait; -import io.anuke.mindustry.gen.CallBlocks; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.graphics.Shaders; -import io.anuke.mindustry.net.In; import io.anuke.mindustry.type.Mech; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -44,7 +43,7 @@ public class MechFactory extends Block{ solidifes = true; } - @Remote(targets = Loc.both, called = Loc.server, in = In.blocks) + @Remote(targets = Loc.both, called = Loc.server) public static void onMechFactoryTap(Player player, Tile tile){ if(!checkValidTap(tile, player)) return; @@ -52,7 +51,7 @@ public class MechFactory extends Block{ player.beginRespawning(entity); } - @Remote(called = Loc.server, in = In.blocks) + @Remote(called = Loc.server) public static void onMechFactoryDone(Tile tile){ MechFactoryEntity entity = tile.entity(); @@ -93,7 +92,7 @@ public class MechFactory extends Block{ if(mobile && !mech.flying) return; if(checkValidTap(tile, player)){ - CallBlocks.onMechFactoryTap(player, tile); + Call.onMechFactoryTap(player, tile); }else if(player.isLocal && mobile){ player.moveTarget = tile.entity; } @@ -159,7 +158,7 @@ public class MechFactory extends Block{ entity.time += 0.5f; if(entity.progress >= 1f){ - CallBlocks.onMechFactoryDone(tile); + Call.onMechFactoryDone(tile); } }else{ if(Units.anyEntities(tile, 4f, unit -> unit.getTeam() == entity.getTeam() && unit instanceof Player)){ diff --git a/core/src/io/anuke/mindustry/world/blocks/units/Reconstructor.java b/core/src/io/anuke/mindustry/world/blocks/units/Reconstructor.java index 02e74a5f1e..7865b4a65c 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/Reconstructor.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/Reconstructor.java @@ -10,10 +10,9 @@ import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.traits.SpawnerTrait; -import io.anuke.mindustry.gen.CallBlocks; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.graphics.Shaders; -import io.anuke.mindustry.net.In; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.core.Effects; @@ -71,7 +70,7 @@ public class Reconstructor extends Block{ entity.link = -1; } - @Remote(targets = Loc.both, called = Loc.server, in = In.blocks, forward = true) + @Remote(targets = Loc.both, called = Loc.server, forward = true) public static void reconstructPlayer(Player player, Tile tile){ ReconstructorEntity entity = tile.entity(); @@ -91,7 +90,7 @@ public class Reconstructor extends Block{ //player.setRespawning(); } - @Remote(targets = Loc.both, called = Loc.server, in = In.blocks, forward = true) + @Remote(targets = Loc.both, called = Loc.server, forward = true) public static void linkReconstructor(Player player, Tile tile, Tile other){ //just in case the client has invalid data if(!(tile.entity instanceof ReconstructorEntity) || !(other.entity instanceof ReconstructorEntity)) return; @@ -109,7 +108,7 @@ public class Reconstructor extends Block{ }); } - @Remote(targets = Loc.both, called = Loc.server, in = In.blocks, forward = true) + @Remote(targets = Loc.both, called = Loc.server, forward = true) public static void unlinkReconstructor(Player player, Tile tile, Tile other){ //just in case the client has invalid data if(!(tile.entity instanceof ReconstructorEntity) || !(other.entity instanceof ReconstructorEntity)) return; @@ -163,10 +162,10 @@ public class Reconstructor extends Block{ ReconstructorEntity entity = tile.entity(); if(entity.link == other.packedPosition()){ - CallBlocks.unlinkReconstructor(null, tile, other); + Call.unlinkReconstructor(null, tile, other); return false; }else if(other.block() instanceof Reconstructor){ - CallBlocks.linkReconstructor(null, tile, other); + Call.linkReconstructor(null, tile, other); return false; } @@ -296,7 +295,7 @@ public class Reconstructor extends Block{ if(!checkValidTap(tile, entity, player)) return; - CallBlocks.reconstructPlayer(player, tile); + Call.reconstructPlayer(player, tile); } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java b/core/src/io/anuke/mindustry/world/blocks/units/UnitPad.java similarity index 72% rename from core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java rename to core/src/io/anuke/mindustry/world/blocks/units/UnitPad.java index 98142a6972..844f6cce05 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/UnitPad.java @@ -9,11 +9,12 @@ import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.units.BaseUnit; import io.anuke.mindustry.entities.units.UnitType; -import io.anuke.mindustry.gen.CallBlocks; +import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.graphics.Shaders; -import io.anuke.mindustry.net.In; import io.anuke.mindustry.net.Net; +import io.anuke.mindustry.type.AmmoType; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.world.BarType; @@ -35,27 +36,28 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; -public class UnitFactory extends Block{ +public class UnitPad extends Block{ + protected float gracePeriodMultiplier = 8f; protected UnitType type; protected float produceTime = 1000f; protected float openDuration = 50f; protected float launchVelocity = 0f; - protected String unitRegion; - public UnitFactory(String name){ + public UnitPad(String name){ super(name); update = true; hasPower = true; hasItems = true; solidifes = true; + itemCapacity = 10; consumes.require(ConsumeItems.class); } - @Remote(called = Loc.server, in = In.blocks) + @Remote(called = Loc.server) public static void onUnitFactorySpawn(Tile tile){ UnitFactoryEntity entity = tile.entity(); - UnitFactory factory = (UnitFactory) tile.block(); + UnitPad factory = (UnitPad) tile.block(); entity.buildTime = 0f; entity.hasSpawned = true; @@ -69,9 +71,20 @@ public class UnitFactory extends Block{ unit.set(tile.drawx(), tile.drawy()); unit.add(); unit.getVelocity().y = factory.launchVelocity; + + //fill inventory with 1st ammo + if(tile.getTeam() == Team.red){ + AmmoType type = unit.getWeapon().getAmmoType(unit.getWeapon().getAcceptedItems().iterator().next()); + unit.inventory.fillAmmo(type); + } } } + @Override + public boolean outputsItems(){ + return false; + } + @Override public void setStats(){ super.setStats(); @@ -96,15 +109,15 @@ public class UnitFactory extends Block{ @Override public TextureRegion[] getIcon(){ return new TextureRegion[]{ - Draw.region(name), - Draw.region(name + "-top") + Draw.region(name), + Draw.region(name + "-top") }; } @Override public void draw(Tile tile){ UnitFactoryEntity entity = tile.entity(); - TextureRegion region = Draw.region(unitRegion == null ? type.name : unitRegion); + TextureRegion region = type.iconRegion; Draw.rect(name(), tile.drawx(), tile.drawy()); @@ -130,7 +143,7 @@ public class UnitFactory extends Block{ Draw.reset(); - Draw.rect(name + (entity.open ? "-top-open" : "-top"), tile.drawx(), tile.drawy()); + Draw.rect(name + (entity.open || entity.hasSpawned ? "-top-open" : "-top"), tile.drawx(), tile.drawy()); } @Override @@ -152,21 +165,27 @@ public class UnitFactory extends Block{ } } - /* - if(!entity.hasSpawned){ - for(BaseUnit unit : unitGroups[tile.getTeamID()].all()){ - if(unit.getType() == type && unit.getSpawner() == null){ - entity.hasSpawned = true; - unit.setSpawner(tile); - break; - } + boolean isEnemy = tile.getTeam() == Team.red; + + if(isEnemy){ + entity.warmup += Timers.delta(); + } + + if(!isEnemy){ + //player-made spawners have default behavior + + if(!entity.hasSpawned && hasRequirements(entity.items, entity.buildTime / produceTime) && + entity.cons.valid() && !entity.open){ + + entity.buildTime += Timers.delta(); + entity.speedScl = Mathf.lerpDelta(entity.speedScl, 1f, 0.05f); + }else{ + if(!entity.open) entity.speedScl = Mathf.lerpDelta(entity.speedScl, 0f, 0.05f); } - }*/ - - if(!entity.hasSpawned && hasRequirements(entity.items, entity.buildTime / produceTime) && - entity.cons.valid() && !entity.open){ - - entity.buildTime += Timers.delta(); + //check if grace period had passed + }else if(!entity.hasSpawned && entity.warmup > produceTime*gracePeriodMultiplier){ + //otherwise, it's an enemy, cheat by not requiring resources + entity.buildTime += Timers.delta() / 4f; entity.speedScl = Mathf.lerpDelta(entity.speedScl, 1f, 0.05f); }else{ if(!entity.open) entity.speedScl = Mathf.lerpDelta(entity.speedScl, 0f, 0.05f); @@ -175,7 +194,8 @@ public class UnitFactory extends Block{ if(entity.buildTime >= produceTime && !entity.open){ entity.open = true; - Timers.run(openDuration / 1.5f, () -> CallBlocks.onUnitFactorySpawn(tile)); + Timers.run(openDuration / 1.5f, () -> Call.onUnitFactorySpawn(tile)); + useContent(type); entity.openCountdown = openDuration; @@ -188,13 +208,23 @@ public class UnitFactory extends Block{ @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){ + 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; + } + @Override public TileEntity getEntity(){ return new UnitFactoryEntity(); @@ -216,16 +246,19 @@ public class UnitFactory extends Block{ public float time; public float speedScl; public boolean hasSpawned; + public float warmup; //only for enemy spawners @Override public void write(DataOutputStream stream) throws IOException{ stream.writeFloat(buildTime); + stream.writeFloat(warmup); stream.writeBoolean(hasSpawned); } @Override public void read(DataInputStream stream) throws IOException{ buildTime = stream.readFloat(); + warmup = stream.readFloat(); hasSpawned = stream.readBoolean(); } } diff --git a/core/src/io/anuke/mindustry/world/meta/BlockFlag.java b/core/src/io/anuke/mindustry/world/meta/BlockFlag.java index 44820e6646..b09645715f 100644 --- a/core/src/io/anuke/mindustry/world/meta/BlockFlag.java +++ b/core/src/io/anuke/mindustry/world/meta/BlockFlag.java @@ -1,30 +1,20 @@ 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), - /** - * Point to resupply resources. - */ + /**Point to resupply resources.*/ resupplyPoint(Float.MAX_VALUE), - /** - * Point to drop off resources. - */ + /**Point to drop off resources.*/ dropPoint(Float.MAX_VALUE), - /** - * Producer of important goods. - */ + /**Producer of important goods.*/ producer(20), - /** - * Producer or storage unit of volatile materials. - */ + /**Producer or storage unit of volatile materials.*/ explosive(10), - /** - * Repair point. - */ - repair(Float.MAX_VALUE); + /**Repair point.*/ + repair(Float.MAX_VALUE), + /**Special flag for command center blocks.*/ + comandCenter(30); public final float cost; diff --git a/core/src/io/anuke/mindustry/world/meta/Producers.java b/core/src/io/anuke/mindustry/world/meta/Producers.java new file mode 100644 index 0000000000..53ff1c85a0 --- /dev/null +++ b/core/src/io/anuke/mindustry/world/meta/Producers.java @@ -0,0 +1,15 @@ +package io.anuke.mindustry.world.meta; + +import io.anuke.mindustry.game.Content; + +public class Producers{ + private Content output; + + public void set(Content content){ + this.output = content; + } + + public Content get(){ + return output; + } +} diff --git a/core/src/io/anuke/mindustry/world/modules/InventoryModule.java b/core/src/io/anuke/mindustry/world/modules/InventoryModule.java index 85a349f334..40e8873fcc 100644 --- a/core/src/io/anuke/mindustry/world/modules/InventoryModule.java +++ b/core/src/io/anuke/mindustry/world/modules/InventoryModule.java @@ -92,6 +92,8 @@ public class InventoryModule extends BlockModule{ } public void remove(Item item, int amount){ + amount = Math.min(amount, items[item.id]); + items[item.id] -= amount; total -= amount; } diff --git a/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java b/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java index 02833bcb52..15950177d8 100644 --- a/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java +++ b/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java @@ -1,32 +1,21 @@ package io.anuke.mindustry.desktop; -import com.apple.eawt.Application; import com.badlogic.gdx.ApplicationListener; import com.badlogic.gdx.Files.FileType; -import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Preferences; import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application; import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration; import com.badlogic.gdx.backends.lwjgl3.Lwjgl3FileHandle; -import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.utils.ObjectMap; import io.anuke.kryonet.KryoClient; import io.anuke.kryonet.KryoServer; import io.anuke.mindustry.Mindustry; import io.anuke.mindustry.core.Platform; -import io.anuke.mindustry.io.SaveIO; -import io.anuke.mindustry.game.Saves.SaveSlot; import io.anuke.mindustry.net.Net; import io.anuke.ucore.io.BinaryPreferences; -import io.anuke.ucore.util.Bundles; import io.anuke.ucore.util.OS; -import io.anuke.ucore.util.Strings; import java.io.File; -import java.io.IOException; -import java.util.List; - -import static io.anuke.mindustry.Vars.*; public class DesktopLauncher extends Lwjgl3Application{ ObjectMap prefmap; @@ -43,43 +32,6 @@ public class DesktopLauncher extends Lwjgl3Application{ config.setWindowedMode(960, 540); config.setWindowIcon("sprites/icon.png"); - if(OS.isMac){ - Application.getApplication().setOpenFileHandler(e -> { - List list = e.getFiles(); - - File target = (File) list.get(0); - - Gdx.app.postRunnable(() -> { - FileHandle file = OS.getAppDataDirectory("Mindustry").child("tmp").child(target.getName()); - - Gdx.files.absolute(target.getAbsolutePath()).copyTo(file); - - if(file.extension().equalsIgnoreCase(saveExtension)){ //open save - - if(SaveIO.isSaveValid(file)){ - try{ - SaveSlot slot = control.getSaves().importSave(file); - ui.load.runLoadSave(slot); - }catch(IOException e2){ - ui.showError(Bundles.format("text.save.import.fail", Strings.parseException(e2, false))); - } - }else{ - ui.showError("$text.save.import.invalid"); - } - - }else if(file.extension().equalsIgnoreCase(mapExtension)){ //open map - Gdx.app.postRunnable(() -> { - if(!ui.editor.isShown()){ - ui.editor.show(); - } - - ui.editor.beginEditMap(file.read()); - }); - } - }); - }); - } - 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 31812f0783..5162e7f56b 100644 --- a/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java +++ b/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java @@ -108,8 +108,8 @@ public class DesktopPlatform extends Platform{ @Override public boolean isDebug(){ //honestly I'm just putting this ridiculous """anti-debug""" mess here to see if anyone bothers solving it without editing source - return args.length > 0 && args[0].equals("-debug_" + getUUID().hashCode() + "_" - + " " + System.getProperty("os.arch") + "nice" + (int)(Math.sin(System.getProperty("user.dir").hashCode()) * 100) + Thread.currentThread().getStackTrace()[1].toString()) && new File("../../desktop/build/").exists(); + return args.length > 0 && args[0].equals(("-debug_" + getUUID().hashCode() + "_" + + " " + System.getProperty("os.arch") + "nice" + (int)(Math.sin(System.getProperty("user.dir").hashCode()) * 100) + Thread.currentThread().getStackTrace()[1].toString()).hashCode() + "") && new File("../../desktop/build/").exists(); } @Override diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2d80b69a76..a95009c3b9 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.8.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/html/build.gradle b/html/build.gradle index bfc2ceac5c..ae3ae651a6 100644 --- a/html/build.gradle +++ b/html/build.gradle @@ -13,6 +13,7 @@ gwt { compiler { strict = true disableCastChecking = true + //style = Style.DETAILED } } diff --git a/html/src/io/anuke/mindustry/GdxDefinition.gwt.xml b/html/src/io/anuke/mindustry/GdxDefinition.gwt.xml index e1a5cefdca..15601ef897 100644 --- a/html/src/io/anuke/mindustry/GdxDefinition.gwt.xml +++ b/html/src/io/anuke/mindustry/GdxDefinition.gwt.xml @@ -1,11 +1,9 @@ - - diff --git a/html/src/io/anuke/mindustry/client/HtmlLauncher.java b/html/src/io/anuke/mindustry/client/HtmlLauncher.java index 208e24b976..5215771eda 100644 --- a/html/src/io/anuke/mindustry/client/HtmlLauncher.java +++ b/html/src/io/anuke/mindustry/client/HtmlLauncher.java @@ -18,7 +18,6 @@ import com.google.gwt.i18n.shared.DateTimeFormat; import com.google.gwt.user.client.ui.*; import io.anuke.mindustry.Mindustry; import io.anuke.mindustry.core.Platform; -import io.anuke.mindustry.net.Net; import io.anuke.ucore.function.Consumer; import java.io.ByteArrayInputStream; @@ -94,8 +93,6 @@ public class HtmlLauncher extends GwtApplication { setupResizeHook(); } }); - - Net.setClientProvider(new WebsocketClient()); Platform.instance = new Platform(){ DateTimeFormat format = DateTimeFormat.getFormat("EEE, dd MMM yyyy HH:mm:ss"); @@ -118,12 +115,6 @@ public class HtmlLauncher extends GwtApplication { return NumberFormat.getDecimalFormat().format(number); } - @Override - public boolean canJoinGame(){ - String ref = Document.get().getReferrer(); - return !ref.startsWith("https") && !ref.contains("itch.io"); - } - @Override public void downloadFile(String name, byte[] bytes) { downloadBytes(name, new String(Base64Coder.encode(bytes))); diff --git a/html/src/io/anuke/mindustry/client/WebsocketClient.java b/html/src/io/anuke/mindustry/client/WebsocketClient.java deleted file mode 100644 index 8b959aae1e..0000000000 --- a/html/src/io/anuke/mindustry/client/WebsocketClient.java +++ /dev/null @@ -1,150 +0,0 @@ -package io.anuke.mindustry.client; - -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.Base64Coder; -import com.badlogic.gdx.utils.reflect.ClassReflection; -import com.badlogic.gdx.utils.reflect.ReflectionException; -import com.sksamuel.gwt.websockets.Websocket; -import com.sksamuel.gwt.websockets.WebsocketListener; -import io.anuke.mindustry.core.Platform; -import io.anuke.mindustry.net.*; -import io.anuke.mindustry.net.Net.ClientProvider; -import io.anuke.mindustry.net.Net.SendMode; -import io.anuke.mindustry.net.Packets.Connect; -import io.anuke.mindustry.net.Packets.Disconnect; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.function.Consumer; - -import java.io.IOException; -import java.nio.ByteBuffer; - -import static io.anuke.mindustry.Vars.webPort; - -public class WebsocketClient implements ClientProvider { - Websocket socket; - ByteBuffer buffer = ByteBuffer.allocate(1024); - - @Override - public void connect(String ip, int port){ - socket = new Websocket("ws://" + ip + ":" + webPort); - socket.addListener(new WebsocketListener() { - public void onMessage(byte[] bytes) { - try { - ByteBuffer buffer = ByteBuffer.wrap(bytes); - byte id = buffer.get(); - if(id != -2){ //ignore framework messages - Class type = Registrator.getByID(id); - Packet packet = (Packet) ClassReflection.newInstance(type); - packet.read(buffer); - Net.handleClientReceived(packet); - } - }catch (ReflectionException e){ - throw new RuntimeException(e); - } - } - - @Override - public void onClose() { - Disconnect disconnect = new Disconnect(); - Net.handleClientReceived(disconnect); - } - - @Override - public void onMessage(String msg) { - onMessage(Base64Coder.decode(msg)); - } - - @Override - public void onOpen() { - Connect connect = new Connect(); - connect.addressTCP = ip; - Net.handleClientReceived(connect); - } - }); - socket.open(); - } - - @Override - public void send(Object object, SendMode mode) { - if(!(object instanceof Packet)) throw new RuntimeException("All sent objects must be packets!"); - Packet p = (Packet)object; - buffer.position(0); - buffer.put(Registrator.getID(object.getClass())); - p.write(buffer); - int pos = buffer.position(); - buffer.position(0); - byte[] out = new byte[pos]; - buffer.get(out); - String string = new String(Base64Coder.encode(out)); - socket.send(string); - } - - @Override - public void updatePing() { - - } - - @Override - public int getPing() { - return 0; - } - - @Override - public void disconnect() { - socket.close(); - } - - @Override - public void discover(Consumer> callback){ - callback.accept(new Array<>()); - } - - @Override - public void pingHost(String address, int port, Consumer valid, Consumer failed) { - try { - if (!Platform.instance.canJoinGame()) { - failed.accept(new IOException()); - } else { - Websocket socket = new Websocket("ws://" + address + ":" + webPort); - final boolean[] accepted = {false}; - socket.addListener(new WebsocketListener() { - @Override - public void onClose() { - if (!accepted[0]) failed.accept(new IOException("Failed to connect to host.")); - } - - @Override - public void onMessage(String msg) { - byte[] bytes = Base64Coder.decode(msg); - Host host = NetworkIO.readServerData(address, ByteBuffer.wrap(bytes)); - if(bytes.length != 128) - valid.accept(new Host("Unknown", address, "Unknown", 0, 0, 0)); - else - valid.accept(host); - accepted[0] = true; - socket.close(); - } - - @Override - public void onOpen() { - socket.send("ping"); - } - }); - socket.open(); - Timers.runTask(60f * 5, () -> { - if (!accepted[0]) { - failed.accept(new IOException("Failed to connect to host.")); - socket.close(); - } - }); - } - }catch (Exception e){ - failed.accept(new IOException("Failed to connect to host.")); - } - } - - @Override - public void dispose() { - socket.close(); - } -} diff --git a/kryonet/src/io/anuke/kryonet/KryoServer.java b/kryonet/src/io/anuke/kryonet/KryoServer.java index bd3f488fd7..b41ccd254a 100644 --- a/kryonet/src/io/anuke/kryonet/KryoServer.java +++ b/kryonet/src/io/anuke/kryonet/KryoServer.java @@ -2,48 +2,38 @@ package io.anuke.kryonet; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.Base64Coder; import com.esotericsoftware.kryonet.Connection; import com.esotericsoftware.kryonet.FrameworkMessage; import com.esotericsoftware.kryonet.Listener; import com.esotericsoftware.kryonet.Server; import com.esotericsoftware.kryonet.util.InputStreamSender; import io.anuke.kryonet.CustomListeners.UnreliableListener; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net.SendMode; import io.anuke.mindustry.net.Net.ServerProvider; import io.anuke.mindustry.net.NetConnection; import io.anuke.mindustry.net.NetworkIO; -import io.anuke.mindustry.net.Packets.*; +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.Streamable; import io.anuke.ucore.UCore; import io.anuke.ucore.core.Timers; import io.anuke.ucore.util.Log; -import org.java_websocket.WebSocket; -import org.java_websocket.exceptions.WebsocketNotConnectedException; -import org.java_websocket.handshake.ClientHandshake; -import org.java_websocket.server.WebSocketServer; import java.io.IOException; -import java.net.BindException; -import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.ClosedSelectorException; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; -import static io.anuke.mindustry.Vars.headless; - public class KryoServer implements ServerProvider { final boolean tcpOnly = System.getProperty("java.version") == null; final Server server; - final ByteSerializer serializer = new ByteSerializer(); - final ByteBuffer buffer = ByteBuffer.allocate(4096); final CopyOnWriteArrayList connections = new CopyOnWriteArrayList<>(); final CopyOnWriteArraySet missing = new CopyOnWriteArraySet<>(); final Array array = new Array<>(); - SocketServer webServer; Thread serverThread; int lastconnection = 0; @@ -147,8 +137,6 @@ public class KryoServer implements ServerProvider { }else{ server.bind(port, port); } - webServer = new SocketServer(Vars.webPort); - webServer.start(); serverThread = new Thread(() -> { try{ @@ -168,27 +156,6 @@ public class KryoServer implements ServerProvider { lastconnection = 0; async(server::close); - - //kill them all - for (Thread worker : Thread.getAllStackTraces().keySet()) { - if (worker.getName().contains("WebSocketWorker")) { - worker.interrupt(); - } - } - - try { - if (webServer != null) webServer.stop(1); - }catch (NullPointerException e){ - try { - synchronized (webServer) { - ((Thread) UCore.getPrivate(WebSocketServer.class, webServer, "selectorthread")).join(1); - } - }catch (InterruptedException j){ - handleException(j); - } - }catch (InterruptedException e){ - handleException(e); - } } @Override @@ -289,17 +256,6 @@ public class KryoServer implements ServerProvider { return null; } - KryoConnection getBySocket(WebSocket socket){ - for(int i = 0; i < connections.size(); i ++){ - KryoConnection con = connections.get(i); - if(con.socket == socket){ - return con; - } - } - - return null; - } - void async(Runnable run){ Thread thread = new Thread(run); thread.setDaemon(true); @@ -307,169 +263,41 @@ public class KryoServer implements ServerProvider { } class KryoConnection extends NetConnection{ - public final WebSocket socket; public final Connection connection; - public KryoConnection(int id, String address, WebSocket socket) { - super(id, address); - this.socket = socket; - this.connection = null; - } - public KryoConnection(int id, String address, Connection connection) { super(id, address); - this.socket = null; this.connection = connection; } @Override public boolean isConnected(){ - return connection == null ? !socket.isClosed() : connection.isConnected(); + return connection.isConnected(); } @Override public void send(Object object, SendMode mode){ - if(socket != null){ - try { - synchronized (buffer) { - buffer.position(0); - serializer.write(buffer, object); - int pos = buffer.position(); - buffer.position(0); - byte[] out = new byte[pos]; - buffer.get(out); - String string = new String(Base64Coder.encode(out)); - socket.send(string); - } - }catch (WebsocketNotConnectedException e){ - //don't log anything, it's not important - connections.remove(this); - }catch (Exception e){ - connections.remove(this); - e.printStackTrace(); + try { + if (mode == SendMode.tcp) { + connection.sendTCP(object); + } else { + connection.sendUDP(object); } - }else if (connection != null) { - try { - if (mode == SendMode.tcp) { - connection.sendTCP(object); - } else { - connection.sendUDP(object); - } - }catch (Exception e){ - Log.err(e); - Log.info("Disconnecting invalid client!"); + }catch (Exception e){ + Log.err(e); + Log.info("Disconnecting invalid client!"); + connection.close(); - try{ - //send error packet here - /* - NetErrorPacket packet = new NetErrorPacket(); - packet.message = Strings.parseException(e, true); - Timers.runTask(5f, connection::close);*/ - }catch (Exception e2){ - Log.err(e2); - connection.close(); - } - connection.close(); - - KryoConnection k = getByKryoID(connection.getID()); - if(k != null) connections.remove(k); - Log.info("Connection removed {0}", k); - } + KryoConnection k = getByKryoID(connection.getID()); + if(k != null) connections.remove(k); + Log.info("Connection removed {0}", k); } } @Override public void close(){ - if(socket != null){ - if(socket.isOpen()) socket.close(); - }else if (connection != null) { - if(connection.isConnected()) connection.close(); - } + if(connection.isConnected()) connection.close(); } - - } - - class SocketServer extends WebSocketServer { - - public SocketServer(int port) { - super(new InetSocketAddress(port)); - } - - @Override - public void onOpen(WebSocket conn, ClientHandshake handshake) {} - - @Override - public void onClose(WebSocket conn, int code, String reason, boolean remote) { - if (conn == null) return; - - KryoConnection k = getBySocket(conn); - if(k == null) return; - - Disconnect disconnect = new Disconnect(); - disconnect.id = k.id; - Log.info("&bLost web connection: {0}", k.id); - Gdx.app.postRunnable(() -> Net.handleServerReceived(k.id, disconnect)); - } - - @Override - public void onMessage(WebSocket conn, String message) { - try { - if(message.equals("ping")){ - ByteBuffer ping = NetworkIO.writeServerData(); - conn.send(new String(Base64Coder.encode(ping.array()))); - }else { - KryoConnection k = getBySocket(conn); - - if (k == null){ - Connect connect = new Connect(); - connect.addressTCP = conn.getRemoteSocketAddress().getAddress().getHostAddress(); - k = new KryoConnection(lastconnection ++, connect.addressTCP, conn); - - Log.info("&bRecieved web connection: {0} {1}", k.id, connect.addressTCP); - connections.add(k); - - int id = k.id; - - Gdx.app.postRunnable(() -> Net.handleServerReceived(id, connect)); - } - - int id = k.id; - - byte[] out = Base64Coder.decode(message); - ByteBuffer buffer = ByteBuffer.wrap(out); - Object o = serializer.read(buffer); - Gdx.app.postRunnable(() -> { - try { - Net.handleServerReceived(id, o); - }catch (Exception e){ - e.printStackTrace(); - } - }); - } - }catch (Exception e){ - Log.err(e); - } - } - - @Override - public void onError(WebSocket conn, Exception ex) { - Log.info("WS error: "); - Log.err(ex); - if(ex instanceof BindException){ - Net.closeServer(); - if(!headless) { - Net.showError("$text.server.addressinuse"); - }else{ - Log.err("Web address in use!"); - } - }else if(ex.getMessage().equals("Permission denied")){ - Net.closeServer(); - Net.showError("Permission denied."); - } - } - - @Override - public void onStart() {} } } diff --git a/packer/src/io/anuke/mindustry/Generators.java b/packer/src/io/anuke/mindustry/Generators.java index 062f7bc387..6479115ee9 100644 --- a/packer/src/io/anuke/mindustry/Generators.java +++ b/packer/src/io/anuke/mindustry/Generators.java @@ -10,7 +10,6 @@ import io.anuke.mindustry.type.Upgrade; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.blocks.Floor; import io.anuke.mindustry.world.blocks.OreBlock; -import io.anuke.mindustry.world.blocks.defense.turrets.Turret; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Hue; @@ -26,15 +25,10 @@ public class Generators { continue; } - if(block instanceof Turret){ + if(block.turretIcon){ Color color = Color.ROYAL; Image image = context.get(block.name); - if(image.width() != block.size*8 + 2){ - Image resized = context.create(block.size*8 + 2, block.size*8 + 2); - resized.draw(image, (resized.width() - image.width())/2, (resized.height() - image.height())/2); - image = resized; - } Image read = context.create(image.width(), image.height()); read.draw(image); @@ -61,11 +55,9 @@ public class Generators { } } - Image padded = context.create(base.width() + 2, base.height() + 2); - padded.draw(base, 1, 1); - padded.draw(image, 0, 0); + base.draw(image); - padded.save("block-icon-" + block.name); + base.save("block-icon-" + block.name); }else { Image image = context.get(regions[0]); diff --git a/server/src/io/anuke/mindustry/server/ServerControl.java b/server/src/io/anuke/mindustry/server/ServerControl.java index 633ed4b0ec..659e0e7dd3 100644 --- a/server/src/io/anuke/mindustry/server/ServerControl.java +++ b/server/src/io/anuke/mindustry/server/ServerControl.java @@ -39,9 +39,9 @@ public class ServerControl extends Module{ public ServerControl(String[] args){ Settings.defaultList( - "shufflemode", "normal", - "bans", "", - "admins", "" + "shufflemode", "normal", + "bans", "", + "admins", "" ); mode = ShuffleMode.valueOf(Settings.getString("shufflemode"));