diff --git a/README.md b/README.md index 1599d9962c..f6fbd91e13 100644 --- a/README.md +++ b/README.md @@ -16,22 +16,24 @@ Bleeding-edge live builds are generated automatically for every commit. You can If you'd rather compile on your own, follow these instructions. First, make sure you have Java 8 and JDK 8 installed. Open a terminal in the root directory, and run the following commands: +#### Windows -**_Windows_** +_Running:_ `gradlew desktop:run` +_Building:_ `gradlew desktop:dist` -_Running:_ `gradlew.bat desktop:run` -_Building:_ `gradlew.bat desktop:dist` - - -**_Linux_** +#### Linux _Running:_ `./gradlew desktop:run` _Building:_ `./gradlew desktop:dist` +#### For Server Builds... + +Server builds are bundled with each released build (in Releases). If you'd rather compile on your own, replace 'desktop' with 'server' i.e. `gradlew server:dist`. + --- Gradle may take up to several minutes to download files. Be patient.
-After building, the output .JAR file should be in `/desktop/build/libs/desktop-release.jar.` +After building, the output .JAR file should be in `/desktop/build/libs/desktop-release.jar` for desktop builds, and in `/server/build/libs/server-release.jar` for server builds. ### Downloads diff --git a/android/build.gradle b/android/build.gradle index 2129412ee2..c49e21aae1 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,3 +1,16 @@ +buildscript { + repositories { + mavenLocal() + mavenCentral() + google() + maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.2.1' + } +} apply plugin: "com.android.application" @@ -14,9 +27,9 @@ repositories { dependencies { implementation project(":core") implementation project(":kryonet") - implementation 'com.android.support:support-v4:25.3.1' + implementation 'com.android.support:support-v4:28.0.0' implementation 'org.sufficientlysecure:donations:2.5' - implementation 'com.google.android.gms:play-services-auth:11.8.0' + implementation 'com.google.android.gms:play-services-auth:16.0.1' implementation "com.badlogicgames.gdx:gdx-backend-android:$gdxVersion" natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi" diff --git a/android/src/io/anuke/mindustry/AndroidLauncher.java b/android/src/io/anuke/mindustry/AndroidLauncher.java index 44fa1e6363..4564fc8c08 100644 --- a/android/src/io/anuke/mindustry/AndroidLauncher.java +++ b/android/src/io/anuke/mindustry/AndroidLauncher.java @@ -19,11 +19,9 @@ import com.google.android.gms.common.GoogleApiAvailability; import com.google.android.gms.common.GooglePlayServicesNotAvailableException; import com.google.android.gms.common.GooglePlayServicesRepairableException; import com.google.android.gms.security.ProviderInstaller; -import io.anuke.kryonet.DefaultThreadImpl; 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.game.Saves.SaveSlot; import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.net.Net; @@ -43,7 +41,6 @@ import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; -import java.util.Locale; import static io.anuke.mindustry.Vars.*; @@ -75,26 +72,15 @@ public class AndroidLauncher extends PatchedAndroidApplication{ TextFieldDialogListener.add(field, 0, length); } - @Override - public String getLocaleName(Locale locale){ - return locale.getDisplayName(locale); - } - @Override public void openDonations(){ showDonations(); } - @Override - public ThreadProvider getThreadProvider(){ - return new DefaultThreadImpl(); - } - @Override public String getUUID(){ try{ - String s = Secure.getString(getContext().getContentResolver(), - Secure.ANDROID_ID); + String s = Secure.getString(getContext().getContentResolver(), Secure.ANDROID_ID); int len = s.length(); byte[] data = new byte[len / 2]; for(int i = 0; i < len; i += 2){ diff --git a/annotations/build.gradle b/annotations/build.gradle index afd5e6ab73..edc88bfb58 100644 --- a/annotations/build.gradle +++ b/annotations/build.gradle @@ -1,4 +1,6 @@ apply plugin: "java" sourceCompatibility = 1.8 -sourceSets.main.java.srcDirs = [ "src/" ] +sourceSets.main.java.srcDirs = [ "src/main/java/" ] +sourceSets.main.resources.srcDirs = [ "src/main/resources/" ] + diff --git a/annotations/src/io/anuke/annotations/Annotations.java b/annotations/src/main/java/io/anuke/annotations/Annotations.java similarity index 100% rename from annotations/src/io/anuke/annotations/Annotations.java rename to annotations/src/main/java/io/anuke/annotations/Annotations.java diff --git a/annotations/src/io/anuke/annotations/ClassEntry.java b/annotations/src/main/java/io/anuke/annotations/ClassEntry.java similarity index 90% rename from annotations/src/io/anuke/annotations/ClassEntry.java rename to annotations/src/main/java/io/anuke/annotations/ClassEntry.java index a9be2ec134..3da814be88 100644 --- a/annotations/src/io/anuke/annotations/ClassEntry.java +++ b/annotations/src/main/java/io/anuke/annotations/ClassEntry.java @@ -1,5 +1,7 @@ package io.anuke.annotations; +import io.anuke.annotations.MethodEntry; + import java.util.ArrayList; /** Represents a class witha list method entries to include in it. */ diff --git a/annotations/src/io/anuke/annotations/IOFinder.java b/annotations/src/main/java/io/anuke/annotations/IOFinder.java similarity index 100% rename from annotations/src/io/anuke/annotations/IOFinder.java rename to annotations/src/main/java/io/anuke/annotations/IOFinder.java diff --git a/annotations/src/io/anuke/annotations/MethodEntry.java b/annotations/src/main/java/io/anuke/annotations/MethodEntry.java similarity index 100% rename from annotations/src/io/anuke/annotations/MethodEntry.java rename to annotations/src/main/java/io/anuke/annotations/MethodEntry.java diff --git a/annotations/src/io/anuke/annotations/RemoteMethodAnnotationProcessor.java b/annotations/src/main/java/io/anuke/annotations/RemoteMethodAnnotationProcessor.java similarity index 100% rename from annotations/src/io/anuke/annotations/RemoteMethodAnnotationProcessor.java rename to annotations/src/main/java/io/anuke/annotations/RemoteMethodAnnotationProcessor.java diff --git a/annotations/src/io/anuke/annotations/RemoteReadGenerator.java b/annotations/src/main/java/io/anuke/annotations/RemoteReadGenerator.java similarity index 98% rename from annotations/src/io/anuke/annotations/RemoteReadGenerator.java rename to annotations/src/main/java/io/anuke/annotations/RemoteReadGenerator.java index 5898e369a1..524e590847 100644 --- a/annotations/src/io/anuke/annotations/RemoteReadGenerator.java +++ b/annotations/src/main/java/io/anuke/annotations/RemoteReadGenerator.java @@ -2,6 +2,8 @@ package io.anuke.annotations; import com.squareup.javapoet.*; import io.anuke.annotations.IOFinder.ClassSerializer; +import io.anuke.annotations.MethodEntry; +import io.anuke.annotations.Utils; import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; diff --git a/annotations/src/io/anuke/annotations/RemoteWriteGenerator.java b/annotations/src/main/java/io/anuke/annotations/RemoteWriteGenerator.java similarity index 100% rename from annotations/src/io/anuke/annotations/RemoteWriteGenerator.java rename to annotations/src/main/java/io/anuke/annotations/RemoteWriteGenerator.java diff --git a/annotations/src/io/anuke/annotations/SerializeAnnotationProcessor.java b/annotations/src/main/java/io/anuke/annotations/SerializeAnnotationProcessor.java similarity index 98% rename from annotations/src/io/anuke/annotations/SerializeAnnotationProcessor.java rename to annotations/src/main/java/io/anuke/annotations/SerializeAnnotationProcessor.java index 58aa2abd5b..3cb31a1ee3 100644 --- a/annotations/src/io/anuke/annotations/SerializeAnnotationProcessor.java +++ b/annotations/src/main/java/io/anuke/annotations/SerializeAnnotationProcessor.java @@ -52,7 +52,7 @@ public class SerializeAnnotationProcessor extends AbstractProcessor{ TypeSpec.Builder serializer = TypeSpec.anonymousClassBuilder("") .addSuperinterface(ParameterizedTypeName.get( - ClassName.get(Class.forName("io.anuke.ucore.io.TypeSerializer")), type)); + ClassName.bestGuess("io.anuke.ucore.io.TypeSerializer"), type)); MethodSpec.Builder writeMethod = MethodSpec.methodBuilder("write") .returns(void.class) diff --git a/annotations/src/io/anuke/annotations/Utils.java b/annotations/src/main/java/io/anuke/annotations/Utils.java similarity index 100% rename from annotations/src/io/anuke/annotations/Utils.java rename to annotations/src/main/java/io/anuke/annotations/Utils.java diff --git a/annotations/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/annotations/src/main/resources/META-INF/services/javax.annotation.processing.Processor new file mode 100644 index 0000000000..a83673baa6 --- /dev/null +++ b/annotations/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -0,0 +1,2 @@ +io.anuke.annotations.RemoteMethodAnnotationProcessor +io.anuke.annotations.SerializeAnnotationProcessor diff --git a/build.gradle b/build.gradle index e21d058b06..13ee44b98f 100644 --- a/build.gradle +++ b/build.gradle @@ -8,8 +8,6 @@ buildscript { } dependencies { classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.0' - classpath 'de.richsource.gradle.plugins:gwt-gradle-plugin:0.6' - classpath 'com.android.tools.build:gradle:3.2.1' classpath "com.badlogicgames.gdx:gdx-tools:1.9.8" } } @@ -27,7 +25,7 @@ allprojects { appName = 'Mindustry' gdxVersion = '1.9.8' roboVMVersion = '2.3.0' - uCoreVersion = '6080b6fb8c81f9c8e8dcb5809c2399061e15a63f' + uCoreVersion = 'dec41336067c013f04f0e17db3b06e24d3c11f6a' getVersionString = { String buildVersion = getBuildVersion() @@ -101,24 +99,6 @@ project(":desktop") { } } -project(":html") { - apply plugin: "gwt" - apply plugin: "war" - - dependencies { - compile project(":core") - compileOnly project(":annotations") - - 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-controllers:$gdxVersion:sources" - compile "com.badlogicgames.gdx:gdx-controllers-gwt:$gdxVersion" - compile "com.badlogicgames.gdx:gdx-controllers-gwt:$gdxVersion:sources" - } -} - project(":ios") { apply plugin: "java" apply plugin: "robovm" @@ -160,7 +140,6 @@ project(":core") { } dependencies { - compileOnly project(":annotations") build.finalizedBy(finish) def comp = System.properties["release"] == null || System.properties["release"] == "false" @@ -178,11 +157,10 @@ project(":core") { compile "com.badlogicgames.gdx:gdx:$gdxVersion" compile "com.badlogicgames.gdx:gdx-controllers:$gdxVersion" - } - compileJava.options.compilerArgs = [ - "-processor", "io.anuke.annotations.RemoteMethodAnnotationProcessor,io.anuke.annotations.SerializeAnnotationProcessor" - ] + compileOnly project(":annotations") + annotationProcessor project(":annotations") + } } project(":server") { @@ -195,7 +173,6 @@ project(":server") { } dependencies { - compileOnly project(":annotations") compile project(":core") compile project(":kryonet") diff --git a/core/assets-raw/sprites/blocks/environment/oil.png b/core/assets-raw/sprites/blocks/environment/tar.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/oil.png rename to core/assets-raw/sprites/blocks/environment/tar.png diff --git a/core/assets-raw/sprites/blocks/environment/oiledge.png b/core/assets-raw/sprites/blocks/environment/taredge.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/oiledge.png rename to core/assets-raw/sprites/blocks/environment/taredge.png diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/arc.png b/core/assets-raw/sprites/blocks/turrets/turrets/arc.png index c41a9b2a80..82d7b7fb6f 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/turrets/arc.png and b/core/assets-raw/sprites/blocks/turrets/turrets/arc.png differ diff --git a/core/assets-raw/sprites/items/item-phase-fabric.png b/core/assets-raw/sprites/items/item-phase-fabric.png new file mode 100644 index 0000000000..f2cb017346 Binary files /dev/null and b/core/assets-raw/sprites/items/item-phase-fabric.png differ diff --git a/core/assets-raw/sprites/items/item-phase-matter.png b/core/assets-raw/sprites/items/item-phase-matter.png deleted file mode 100644 index 8cd0e35514..0000000000 Binary files a/core/assets-raw/sprites/items/item-phase-matter.png and /dev/null differ diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index a7c2c57c8f..8aa7829c85 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -77,7 +77,6 @@ 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.serverClose = Server closed. @@ -137,7 +136,6 @@ 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\! @@ -217,7 +215,6 @@ text.editor.description = Description\: text.editor.name = Name\: text.editor.teams = Teams text.editor.elevation = Elevation -text.editor.badsize = [orange]Invalid image dimensions\![]\nValid map dimensions\: {0} text.editor.errorimageload = Error loading file\:\n[orange]{0} text.editor.errorimagesave = Error saving file\:\n[orange]{0} text.editor.generate = Generate @@ -263,6 +260,15 @@ text.tutorial = Tutorial text.editor = Editor text.mapeditor = Map Editor text.donate = Donate + +text.connectfail = [crimson]Failed to connect to server\:\n\n[accent]{0} +text.error.unreachable = Server unreachable. +text.error.invalidaddress = Invalid address. +text.error.timedout = Timed out!\nMake sure the host has port forwarding set up, and that the address is correct! +text.error.mismatch = Packet error:\npossible client/server version mismatch.\nMake sure you and the host have the latest version of Mindustry! +text.error.alreadyconnected = Already connected. +text.error.any = Unkown network error. + text.settings.language = Language text.settings.reset = Reset to Defaults text.settings.rebind = Rebind @@ -348,10 +354,8 @@ setting.difficulty.easy = easy setting.difficulty.normal = normal setting.difficulty.hard = hard setting.difficulty.insane = insane -setting.difficulty.purge = purge setting.difficulty.name = Difficulty\: setting.screenshake.name = Screen Shake -setting.indicators.name = Enemy Indicators setting.effects.name = Display Effects setting.sensitivity.name = Controller Sensitivity setting.saveinterval.name = Autosave Interval @@ -361,7 +365,6 @@ setting.multithread.name = Multithreading setting.fps.name = Show FPS setting.vsync.name = VSync setting.lasers.name = Show Power Lasers -setting.healthbars.name = Show Entity Health bars setting.minimap.name = Show Minimap setting.musicvol.name = Music Volume setting.mutemusic.name = Mute Music @@ -428,11 +431,13 @@ item.titanium.description = A rare super-light metal used extensively in liquid item.thorium.name = Thorium 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.silicon.description = An extremely useful semiconductor, with applications in solar panels and many complex electronics. item.plastanium.name = Plastanium item.plastanium.description = A light, ductile material used in advanced aircraft and fragmentation ammunition. -item.phase-matter.name = Phase Matter +item.phase-fabric.name = Phase Fabric +item.phase-fabric.description = A near-weightless substance used in advanced electronics and self-repairing technology. item.surge-alloy.name = Surge Alloy +item.surge-alloy.description = An advanced alloy with unique electrical properties. item.biomatter.name = Biomatter item.biomatter.description = A clump of organic mush; used for conversion into oil or as a basic fuel. item.sand.name = Sand @@ -495,7 +500,7 @@ block.metalfloor.name = Metal Floor block.deepwater.name = deepwater block.water.name = water block.lava.name = lava -block.oil.name = oil +block.tar.name = Tar block.blackstone.name = blackstone block.stone.name = stone block.dirt.name = dirt diff --git a/core/assets/bundles/bundle_de.properties b/core/assets/bundles/bundle_de.properties index 269ab837dc..3767dee4fe 100644 --- a/core/assets/bundles/bundle_de.properties +++ b/core/assets/bundles/bundle_de.properties @@ -428,7 +428,7 @@ item.titanium.description = Ein seltenes sehr leichtes Metal. Häufig in Flüssi item.thorium.name = Uran item.thorium.description = Ein dichtes radioaktives Metal, welches als strukturelle Unterstützung und nuklearer Kraftstoff verwendet wird. item.silicon.name = Silikon -item.silcion.description = Ein sehr nützlicher Halbleiter. Findet Anwendung in Solar Anlagen und komplexer Elektronik. +item.silicon.description = Ein sehr nützlicher Halbleiter. Findet Anwendung in Solar Anlagen und komplexer Elektronik. item.plastanium.name = Plastanium item.plastanium.description = Ein leichtes dehnbares Material welches in Flugzeugen und Splittermunition verwendet wird. item.phase-matter.name = Phase Materie diff --git a/core/assets/bundles/bundle_es.properties b/core/assets/bundles/bundle_es.properties index d35e0ce502..411478e3ef 100644 --- a/core/assets/bundles/bundle_es.properties +++ b/core/assets/bundles/bundle_es.properties @@ -12,7 +12,7 @@ text.linkfail = ¡Error al abrir el enlace\!\nLa URL ha sido copiada a su portap text.editor.web = ¡La versión web no es compatible con el editor\!\nDescargue el juego para usarlo. text.web.unsupported = ¡La versión web no soporta esta característica\! Descarga el juego para poder usarla. text.gameover = Tu núcleo ha sido destruido. -text.gameover.pvp = The[accent] {0}[] team is victorious\! +text.gameover.pvp = El equipo[accent] {0}[] ha ganado\! text.sector.gameover = Este sector ha sido perdido. ¿Re-instaurar? text.sector.retry = Reintentar text.highscore = [accent]¡Nueva mejor puntuación\! @@ -22,7 +22,7 @@ text.level.delete.title = Confirmar Eliminación text.map.delete = ¿Estás seguro que quieres borrar el mapa "[orange]{0}[]"? text.level.select = Selección de nivel text.level.mode = Modo de juego\: -text.construction.desktop = Desktop controls have been changed.\nTo deselect a block or stop building, [accent]use space[]. +text.construction.desktop = Los controles de la versión de escritorio han cambiado.\nPara deseleccionar un bloque o dejar de construir, [accent]usa la barra espaciadora[]. text.construction.title = Guía de Construcción de Bloques text.construction = Acaba de seleccionar el [accent]modo de construcción de bloques[].\n\nPara empezar a colocar, simplemente presione en una localización valida cerca de su nave.\nCuando haya terminado de seleccionar algunos bloques, presiona la casilla para confirmar, y su nave empezara a construirlos.\n\n- [accent]Remueve bloques[] de tu selección presionando en ellos.\n- [accent]Cambia tu selección de lugar[] manteniendo y arrastrando cualquier bloque en la selección.\n- [accent]Coloca bloques en línea[] presionando y manteniendo en un espacio vacío, y arrastrando hacia cualquier dirección.\n- [accent]Cancela la construcción o selección[] presionando la X abajo a la izquierda. text.deconstruction.title = Guía de Deconstrucción de Bloques @@ -39,31 +39,31 @@ text.sectors = Sectores text.sector = Sector\: [LIGHT_GRAY]{0} text.sector.time = Tiempo\: [LIGHT_GRAY]{0} text.sector.deploy = Desplegar -text.sector.abandon = Abandon -text.sector.abandon.confirm = Are you sure you want to abandon all progress at this sector?\nThis cannot be undone\! +text.sector.abandon = Abandonar +text.sector.abandon.confirm = ¿Definitivamente quieres abandonar todo el progreso hecho en este sector?\nEsto no se puede deshacer\! text.sector.resume = Resumir text.sector.locked = [scarlet][[Incompleto] text.sector.unexplored = [accent][[Inexplorado] text.missions = Missions\:[LIGHT_GRAY] {0} text.mission = Misión\:[LIGHT_GRAY] {0} -text.mission.main = Main Mission\:[LIGHT_GRAY] {0} -text.mission.info = Mission Info +text.mission.main = Misión Principal\:[LIGHT_GRAY] {0} +text.mission.info = Información de la Misión text.mission.complete = ¡Misión completada\! -text.mission.complete.body = Sector {0},{1} ha sido conquistado. +text.mission.complete.body = El Sector {0},{1} ha sido conquistado. text.mission.wave = Sobrevive [accent]{0}[] hordas. -text.mission.wave.enemies = Survive[accent] {0}/{1} []waves\n{2} Enemies -text.mission.wave.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy -text.mission.wave.menu = Survive[accent] {0} []waves +text.mission.wave.enemies = Sobrevive[accent] {0}/{1} []hordas\n{2} Enemigas +text.mission.wave.enemy = Sobrevive[accent] {0}/{1} []hordas\n{2} Enemigas +text.mission.wave.menu = Sobrevive[accent] {0} []hordas text.mission.battle = Destruye la base enemiga. -text.mission.resource.menu = Obtain {0} x{1} +text.mission.resource.menu = Obtener {0} x{1} text.mission.resource = Obtén {0} x{1} -text.mission.block = Create {0} -text.mission.unit = Create {0} Unit -text.mission.command = Send Command {0} To Units +text.mission.block = Crear {0} +text.mission.unit = Crear {0} Unit +text.mission.command = Enviar Comando {0} A Las Unidades text.mission.linknode = Link Power Node -text.mission.display = [accent]Mission\:\n[LIGHT_GRAY]{0} -text.mission.mech = Switch to mech[accent] {0}[] -text.mission.create = Create[accent] {0}[] +text.mission.display = [accent]Misión\:\n[LIGHT_GRAY]{0} +text.mission.mech = Cambiar a mech[accent] {0}[] +text.mission.create = Crear[accent] {0}[] text.none = text.close = Cerrar text.quit = Salir @@ -94,7 +94,7 @@ text.server.kicked.customClient = Este servidor no soporta versiones personaliza text.host.info = El botón [accent]hostear[] hostea un servidor en el puerto [scarlet]6567[]. \nCualquier persona en la misma [LIGHT_GRAY]wifi o red local[] debería poder ver tu servidor en la lista de servidores.\n\nSi quieres que cualquier persona se pueda conectar de cualquier lugar por IP, la [accent]asignación de puertos[] es requerida.\n\n[LIGHT_GRAY]Nota\: Si alguien experimenta problemas conectándose a tu partida LAN, asegúrate de permitir a Mindustry acceso a tu red local mediante la configuración de tu firewall. text.join.info = Acá, tu puedes escribir la [accent]IP de un servidor[] para conectarte, o para descubrir servidores de [accent]red local[] para conectarte.\nLAN y WAN es soportado para jugar en multijugador.\n\n[LIGHT_GRAY]Nota\: No hay lista automática global de servidores; si quieres conectarte por IP, tendrás que preguntarle al anfitrión por la IP. text.hostserver = Hostear Servidor -text.hostserver.mobile = Host\nGame +text.hostserver.mobile = Hostear\nJuego text.host = Hostear text.hosting = [accent]Abriendo servidor... text.hosts.refresh = Actualizar @@ -193,9 +193,9 @@ text.saving = [accent]Guardando... text.wave = [orange]Horda {0} text.wave.waiting = Horda en {0} text.waiting = Esperando... -text.waiting.players = Waiting for players... -text.wave.enemies = [LIGHT_GRAY]{0} Enemies Remaining -text.wave.enemy = [LIGHT_GRAY]{0} Enemy Remaining +text.waiting.players = Esperando por jugafores... +text.wave.enemies = [LIGHT_GRAY]{0} Enemigos Restantes +text.wave.enemy = [LIGHT_GRAY]{0} Enemigo Restante text.loadimage = Cargar Imagen text.saveimage = Guardar Imagen text.unknown = Desconocido @@ -270,12 +270,12 @@ text.settings.controls = Controles text.settings.game = Juego text.settings.sound = Sonido text.settings.graphics = Gráficos -text.settings.cleardata = Clear Game Data... -text.settings.clear.confirm = Are you sure you want to clear this data?\nWhat is done cannot be undone\! -text.settings.clearall.confirm = [scarlet]WARNING\![]\nThis will clear all data, including saves, maps, unlocks and keybinds.\nOnce you press 'ok' the game will wipe all data and automatically exit. -text.settings.clearsectors = Clear Sectors -text.settings.clearunlocks = Clear Unlocks -text.settings.clearall = Clear All +text.settings.cleardata = Limpiar Datos del Juego... +text.settings.clear.confirm = ¿Estas seguro de querer limpiar estos datos?\nEsta accion no puede deshacerse\! +text.settings.clearall.confirm = [scarlet]ADVERTENCIA\![]\nEsto va a eliminar todos tus datos, incluyendo saves, mapas, desbloqueos y keybinds.\nUna vez presiones 'ok' el juego va a borrrar todos tus datos y a salir del juego automáticamente. +text.settings.clearsectors = Limpiar Sectores +text.settings.clearunlocks = Limpiar Desbloqueos +text.settings.clearall = Limpiar Todo text.paused = Pausado text.yes = Si text.no = No @@ -308,7 +308,7 @@ text.blocks.outputitem = Objeto de Salida text.blocks.drilltier = Taladrable text.blocks.drillspeed = Velocidad de Base del Taladro text.blocks.liquidoutput = Líquido de Salida -text.blocks.liquidoutputspeed = Liquid Output Speed +text.blocks.liquidoutputspeed = Velocidad de Salida del Líquido text.blocks.liquiduse = Uso del Líquido text.blocks.coolant = Refrigerante text.blocks.coolantuse = Uso del Refrigerante @@ -343,7 +343,7 @@ setting.autotarget.name = Auto-Target setting.fpscap.name = Max FPS setting.fpscap.none = Nada setting.fpscap.text = {0} FPS -setting.difficulty.training = training +setting.difficulty.training = entrenamiento setting.difficulty.easy = fácil setting.difficulty.normal = normal setting.difficulty.hard = difícil @@ -371,17 +371,17 @@ text.keybind.title = Reasignar Teclas category.general.name = General category.view.name = View category.multiplayer.name = Multiplayer -command.attack = Attack -command.retreat = Retreat -command.patrol = Patrol -keybind.press = Press a key... +command.attack = Atacar +command.retreat = Retirada +command.patrol = Patrullar +keybind.press = Presiona una tecla... keybind.press.axis = Press an axis or key... keybind.move_x.name = Mover x keybind.move_y.name = Mover y keybind.select.name = Seleccionar keybind.break.name = Remover -keybind.deselect.name = Deselect -keybind.shoot.name = Dispar +keybind.deselect.name = Deseleccionar +keybind.shoot.name = Disparar keybind.zoom_hold.name = Mantener Zoom keybind.zoom.name = Zoom keybind.menu.name = Menu @@ -391,12 +391,12 @@ keybind.chat.name = Chat keybind.player_list.name = Lista de jugadores keybind.console.name = consola keybind.rotate.name = Rotar -keybind.toggle_menus.name = Toggle menus -keybind.chat_history_prev.name = Chat history prev -keybind.chat_history_next.name = Chat history next +keybind.toggle_menus.name = Alternar menús +keybind.chat_history_prev.name = Historial de chat anterior +keybind.chat_history_next.name = Historial de chat siguiente keybind.chat_scroll.name = Chat scroll keybind.drop_unit.name = drop unit -keybind.zoom_minimap.name = Zoom minimap +keybind.zoom_minimap.name = Zoom minimapa mode.text.help.title = Descripción de modos mode.waves.name = hordas mode.waves.description = el modo normal. con recursos limitados y entrada de hordas automática. @@ -428,7 +428,7 @@ item.titanium.description = Un metal raro super ligero usado extensivamente en t item.thorium.name = Torio item.thorium.description = Un metal radiactivo, muy denso usado en soporte de estructuras y combustible nuclear. item.silicon.name = Silicona -item.silcion.description = Un semiconductor muy útil, se usa para paneles solares y muchos electrónicos complejos. +item.silicon.description = Un semiconductor muy útil, se usa para paneles solares y muchos electrónicos complejos. item.plastanium.name = Plastanio item.plastanium.description = Un material dúctil, ligero usado en aeronaves y proyectiles de fragmentación. item.phase-matter.name = Materia de Fase @@ -666,4 +666,4 @@ tutorial.silicon = Silicon is being produced. Get some.\n\nImproving the product tutorial.daggerfactory = Construct a[accent] dagger mech factory.[]\n\nThis will be used to create attack mechs. tutorial.router = Factories need resources to function.\nCreate a router to split conveyor resources. tutorial.dagger = Link power nodes to the factory.\nOnce requirements are met, a mech will be created.\n\nCreate more drills, generators and conveyors as necessary. -tutorial.battle = The[LIGHT_GRAY] enemy[] has revealed their core.\nDestroy it with your unit and dagger mechs. \ No newline at end of file +tutorial.battle = The[LIGHT_GRAY] enemy[] has revealed their core.\nDestroy it with your unit and dagger mechs. diff --git a/core/assets/bundles/bundle_fr.properties b/core/assets/bundles/bundle_fr.properties index be631a58ca..54bcbf9ad3 100644 --- a/core/assets/bundles/bundle_fr.properties +++ b/core/assets/bundles/bundle_fr.properties @@ -428,7 +428,7 @@ item.titanium.description = Un métal rare super-léger largement utilisé dans item.thorium.name = Thorium item.thorium.description = Un métal dense, et radioactif utilisé comme support structurel et comme carburant nucléaire. item.silicon.name = Silicon -item.silcion.description = An extremely useful semiconductor, with applications in solar panels and many complex electronics. +item.silicon.description = An extremely useful semiconductor, with applications in solar panels and many complex electronics. item.plastanium.name = Plastanium item.plastanium.description = Un matériau léger et docile utilisé dans l'aviation avancée et dans les munitions à fragmentation. item.phase-matter.name = Matière phasée diff --git a/core/assets/bundles/bundle_fr_be.properties b/core/assets/bundles/bundle_fr_BE.properties similarity index 99% rename from core/assets/bundles/bundle_fr_be.properties rename to core/assets/bundles/bundle_fr_BE.properties index be3a5fc413..0c736b2329 100644 --- a/core/assets/bundles/bundle_fr_be.properties +++ b/core/assets/bundles/bundle_fr_BE.properties @@ -428,7 +428,7 @@ item.titanium.description = Un métal rare super-léger largement utilisé dans item.thorium.name = Thorium item.thorium.description = Un métal dense, et radioactif utilisé comme support structurel et comme carburant nucléaire. item.silicon.name = Silicone -item.silcion.description = Un matériau semi-conducteur extrêmement utile, avec des utilisations dans les panneaux solaires et beaucoup d'autre composants électroniques complexes. +item.silicon.description = Un matériau semi-conducteur extrêmement utile, avec des utilisations dans les panneaux solaires et beaucoup d'autre composants électroniques complexes. item.plastanium.name = Plastanium item.plastanium.description = Un matériau léger et docile utilisé dans l'aviation avancée et dans les munitions à fragmentation. item.phase-matter.name = Matière phasée diff --git a/core/assets/bundles/bundle_in_ID.properties b/core/assets/bundles/bundle_in_ID.properties index 50f42c0b08..ac89d6cc1a 100644 --- a/core/assets/bundles/bundle_in_ID.properties +++ b/core/assets/bundles/bundle_in_ID.properties @@ -428,7 +428,7 @@ item.titanium.description = A rare super-light metal used extensively in liquid item.thorium.name = thorium 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.silicon.description = An extremely useful semiconductor, with applications in solar panels and many complex electronics. item.plastanium.name = Plastanium item.plastanium.description = A light, ductile material used in advanced aircraft and fragmentation ammunition. item.phase-matter.name = Phase Matter diff --git a/core/assets/bundles/bundle_ita.properties b/core/assets/bundles/bundle_ita.properties index cd9f40507d..16c74cbf9c 100644 --- a/core/assets/bundles/bundle_ita.properties +++ b/core/assets/bundles/bundle_ita.properties @@ -428,7 +428,7 @@ item.titanium.description = Un raro metallo super leggero usato ampiamente nel t item.thorium.name = Torio item.thorium.description = Un materiale denso e radioattivo, utilizzato nella costruzione di strutture e come carburante del reattore nucleare. item.silicon.name = Silicio -item.silcion.description = Un semiconduttore molto utile che viene utilizzato nei pannelli solari e nei macchinari elettronici. +item.silicon.description = Un semiconduttore molto utile che viene utilizzato nei pannelli solari e nei macchinari elettronici. item.plastanium.name = Plastaniu item.plastanium.description = Un materiale leggero e duttile, utilizzato nelle navi avanzete e come munizione. item.phase-matter.name = Vaporizzatore di materia diff --git a/core/assets/bundles/bundle_ko.properties b/core/assets/bundles/bundle_ko.properties index 9bd3bcaacb..361df5c93e 100644 --- a/core/assets/bundles/bundle_ko.properties +++ b/core/assets/bundles/bundle_ko.properties @@ -1,6 +1,6 @@ -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 = 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.discord = Mindustry Discord 에 참여하세요! text.link.discord.description = 공식 Mindustry Discord 채팅방 text.link.github.description = 게임 소스코드 text.link.dev-builds.description = 개발중인 빌드 @@ -8,27 +8,27 @@ text.link.trello.description = 다음 출시될 기능들을 게시한 공식 Tr text.link.itch.io.description = PC 버전 다운로드와 HTML5 버전이 있는 itch.io 사이트 text.link.google-play.description = Google Play 스토어 정보 text.link.wiki.description = 공식 Mindustry 위키 (영어) -text.linkfail = 링크를 여는데 실패했습니다\! URL이 기기의 클립보드에 복사되었습니다. -text.editor.web = HTML5 버전은 에디터 기능을 지원하지 않습니다\! 게임을 다운로드 한 뒤에 사용 해 주세요. -text.web.unsupported = HTML5 버전은 이 기능을 지원하지 않습니다\! 게임을 다운로드 한 뒤에 사용 해 주세요. -text.gameover = 코어가 터졌습니다. 게임 오버\! -text.gameover.pvp = [accent]{0}[] 팀이 승리했습니다\! +text.linkfail = 링크를 여는데 실패했습니다! URL이 기기의 클립보드에 복사되었습니다. +text.editor.web = HTML5 버전은 에디터 기능을 지원하지 않습니다! 게임을 다운로드 한 뒤에 사용 해 주세요. +text.web.unsupported = HTML5 버전은 이 기능을 지원하지 않습니다! 게임을 다운로드 한 뒤에 사용 해 주세요. +text.gameover = 코어가 터졌습니다. 게임 오버! +text.gameover.pvp = [accent]{0}[] 팀이 승리했습니다! text.sector.gameover = 이 구역을 공략하는데 실패했습니다. 다시 배치하시겠습니까? -text.sector.retry = 다시할끄임 -text.highscore = [YELLOW]최고점수 달성\! +text.sector.retry = 다시할꺼임 +text.highscore = [YELLOW]최고점수 달성! text.wave.lasted = [accent]{0}[] 까지 버티셨습니다. -text.level.highscore = 최고 점수 \: [accent]{0} +text.level.highscore = 최고 점수 : [accent]{0} text.level.delete.title = 삭제 확인 text.map.delete = 정말로 "[orange]{0}[]" 맵을 삭제하시겠습니까? text.level.select = 맵 선택 -text.level.mode = 게임모드 \: +text.level.mode = 게임모드 : text.construction.desktop = PC 에서의 조작 방법이 변경되었습니다.\n블록 선택을 해제하거나 건설을 중지하려면 [accent]스페이스 바[]를 누르세요. text.construction.title = 블록 배치 안내서 -text.construction = [accent]블록 배치 모드[]를 선택하셨습니다.\n\n블록을 설치하고 싶으면, 자신의 건설 가능 범위 내에서 간단히 탭 하면 됩니다.\n일부 블록을 선택한 후에 확인 버튼을 누르면 배가 배치 작업을 진행할 것입니다.\n- [accent]블록을 삭제[]하고 싶다면 배치하고 싶은 영역을 탭 하세요. \n- [accent]블록을 넓게 배치[]하고 싶다면 배치하고 싶은 시작 영역을 길게 누르며 드래그 하면 됩니다.- [accent]블록을 한줄로 배치[]하고 싶다면 배치하고 싶은 시작 영역을 한번 탭 하고 길게 누르면서 드래그 하면 됩니다. \n- [accent]블록 배치 모드를 취소[]하고 싶다면 화면 하단 왼쪽에 있는 X 버튼을 누르면 됩니다. +text.construction = [accent]블록 배치 모드[]를 선택하셨습니다.\n\n블록을 설치하고 싶으면, 자신의 건설 가능 범위 내에서 간단히 탭 하면 됩니다.\n일부 블록을 선택한 후에 확인 버튼을 누르면 배가 배치 작업을 진행할 것입니다.\n\n- [accent]블록을 삭제[]하고 싶다면 배치하고 싶은 영역을 탭 하세요. \n- [accent]블록을 넓게 배치[]하고 싶다면 배치하고 싶은 시작 영역을 길게 누르며 드래그 하면 됩니다.\n- [accent]블록을 한줄로 배치[]하고 싶다면 배치하고 싶은 시작 영역을 한번 탭 하고 길게 누르면서 드래그 하면 됩니다. \n- [accent]블록 배치 모드를 취소[]하고 싶다면 화면 하단 왼쪽에 있는 X 버튼을 누르면 됩니다. text.deconstruction.title = 블록 삭제 안내서 -text.deconstruction = [accent]블록 삭제 모드[]를 선택하셨습니다\n블록을 삭제하고 싶다면, 자신의 건설 가능 범위 내에서 간단히 탭 하면 됩니다.\n일부 블록을 선택한 후에 확인 버튼을 누르면 배가 파괴 작업을 진행할 것입니다.\n- [accent]블록을 삭제[]하고 싶다면 배치하고 싶은 영역을 탭 하세요- [accent]블록을 넓은 범위로 삭제[]하고 싶다면 배치하고 싶은 시작 영역을 길게 누르며 드래그 하면 됩니다.- [accent]블록 삭제 모드를 취소[]하고 싶다면 화면 하단 왼쪽에 있는 X 버튼을 누르면 됩니다. +text.deconstruction = [accent]블록 삭제 모드[]를 선택하셨습니다\n\n블록을 삭제하고 싶다면, 자신의 건설 가능 범위 내에서 간단히 탭 하면 됩니다.\n일부 블록을 선택한 후에 확인 버튼을 누르면 배가 파괴 작업을 진행할 것입니다.\n\n- [accent]블록을 삭제[]하고 싶다면 배치하고 싶은 영역을 탭 하세요\n- [accent]블록을 넓은 범위로 삭제[]하고 싶다면 배치하고 싶은 시작 영역을 길게 누르며 드래그 하면 됩니다.\n- [accent]블록 삭제 모드를 취소[]하고 싶다면 화면 하단 왼쪽에 있는 X 버튼을 누르면 됩니다. text.showagain = 다음 세션에서 이 메세지를 표시하지 않습니다 -text.coreattack = < 코어가 공격받고 있습니다 \! > +text.coreattack = < 코어가 공격받고 있습니다 ! > text.unlocks = 아이템들 text.savegame = 게임 저장 text.loadgame = 게임 불러오기 @@ -36,62 +36,63 @@ text.joingame = 게임 참가 text.addplayers = 플레이어 추가/제거 text.customgame = 커스텀 게임 text.sectors = 구역 -text.sector = 선택된 구역 \: [LIGHT_GRAY]{0} -text.sector.time = 시간 \: [LIGHT_GRAY]{0} +text.sector = 구역 : [LIGHT_GRAY]{0} +text.sector.time = 시간 : [LIGHT_GRAY]{0} text.sector.deploy = 시작 text.sector.abandon = 초기화 -text.sector.abandon.confirm = 정말로 이 구역의 모든 진행상활을 초기화 하겠습니까?\n이 작업은 되돌릴 수 없습니다\! +text.sector.abandon.confirm = 정말로 이 구역의 모든 진행상활을 초기화 하겠습니까?\n이 작업은 되돌릴 수 없습니다! text.sector.resume = 계속하기 text.sector.locked = [scarlet][[완료안됨] text.sector.unexplored = [accent][[탐색안됨] -text.missions = 목표 \: [LIGHT_GRAY] {0} -text.mission = 목표 \: [LIGHT_GRAY] {0} +text.missions = 목표 : [LIGHT_GRAY] {0} +text.mission = 목표 : [LIGHT_GRAY] {0} +text.mission.main = 주요 목표 : [LIGHT_GRAY]{0} text.mission.info = 미션 정보 -text.mission.complete = 미션 성공\! -text.mission.complete.body = 구역 {0},{1} 탐색 성공. +text.mission.complete = 미션 성공! +text.mission.complete.body = 구역 {0},{1} 클리어. text.mission.wave = [accent]{0}[]단계가 될때까지 생존하세요. text.mission.wave.enemies = [accent] {0}/{1} []단계동안 생존하세요.\n{2}마리 남음 text.mission.wave.enemy = [accent] {0}/{1} []단계동안 생존하세요.\n{2}마리 남음 -text.mission.wave.menu = [accent] {0} []단계 +text.mission.wave.menu = [accent]{0} []단계 text.mission.battle = 적 본부를 파괴하세요. text.mission.resource.menu = {0} {1}개 수집 -text.mission.resource = {0} 자원을 {1}개 모으세요. -text.mission.block = {0}를 만드세요. -text.mission.unit = {0}유닛을 만드세요. -text.mission.command = 유닛에게 {0} 명령을 보내세요 +text.mission.resource = {0} 자원을 수집하세요 :\n[accent]{1}/{2}[] +text.mission.block = 이것을 만드세요 :\n{0} +text.mission.unit = 이 유닛을 만드세요 :\n{0} +text.mission.command = 유닛에게 이 명령을 보내세요 :\n{0} text.mission.linknode = 전력 노드를 연결하세요. -text.mission.display = [accent]미션 \: \n[LIGHT_GRAY]{0} -text.mission.mech = [accent] {0}[] 기체로 바꾸세요. -text.mission.create = [accent] {0}[] 를 만드세요. +text.mission.display = [accent]미션 : \n[LIGHT_GRAY]{0} +text.mission.mech = 이 기체로 바꾸세요 :\n[accent]{0} +text.mission.create = 이 자원을 만드세요 :\n[accent]{0} text.none = <없음> text.close = 닫기 text.quit = 나가기 text.maps = 맵 text.continue = 계속하기 text.nextmission = 다음 임무 -text.maps.none = [LIGHT_GRAY]맵을 찾을 수 없습니다\! +text.maps.none = [LIGHT_GRAY]맵을 찾을 수 없습니다! text.about.button = 정보 -text.name = 이름 \: -text.unlocked = 새 블록 잠금 해제 -text.unlocked.plural = 새 블록 잠금 해제 +text.name = 이름 : +text.unlocked = 새 블록 잠금 해제됨 +text.unlocked.plural = 잠금 해제 text.players = 현재 {0}명 접속중 text.players.single = 현재 {0}명만 있음. -text.server.mismatch = 클라이언트와 서버 버전이 일치하지 않습니다. 자신이 서버를 호스트하거나 최신 버전을 사용 해 주세요\! +text.server.mismatch = 클라이언트와 서버 버전이 일치하지 않습니다.\n자신이 서버를 호스트하거나 최신 버전을 사용 해 주세요! text.server.closing = [accent]서버 닫는중... -text.server.kicked.kick = 서버에서 추방되었습니다\! +text.server.kicked.kick = 서버에서 추방되었습니다! text.server.kicked.serverClose = 서버 종료됨. text.server.kicked.sectorComplete = 구역 클리어. text.server.kicked.sectorComplete.text = 임무 성공.\n서버가 다음구역 맵으로 이동되었습니다. -text.server.kicked.clientOutdated = 오래된 버전의 클라이언트 입니다\! 게임을 업데이트 하세요\! -text.server.kicked.serverOutdated = 오래된 버전의 서버입니다\! 서버 호스트 관리자에게 문의하세요\! -text.server.kicked.banned = 서버에서 영 좋지 않은 행위를 하여 영구 차단되었습니다. +text.server.kicked.clientOutdated = 오래된 버전의 클라이언트 입니다! 게임을 업데이트 하세요! +text.server.kicked.serverOutdated = 오래된 버전의 서버입니다! 서버 호스트 관리자에게 문의하세요! +text.server.kicked.banned = 뭘 하셨는지는 모르겠지만, 이제 영원히 서버에 접속할 수 없습니다. text.server.kicked.recentKick = 방금 추방처리 되었습니다. 잠시 기다린 후에 접속 해 주세요. text.server.kicked.nameInUse = 이 닉네임이 이미 서버에서 사용중입니다. text.server.kicked.nameEmpty = 닉네임에는 반드시 영어 또는 숫자가 있어야 합니다. -text.server.kicked.idInUse = 이미 서버에 접속중입니다\! 다중 계정은 허용되지 않습니다. +text.server.kicked.idInUse = 이미 서버에 접속중입니다! 다중 계정은 허용되지 않습니다. text.server.kicked.customClient = 이 서버는 직접 빌드한 버전을 지원하지 않습니다. 공식 버전을 사용하세요. -text.host.info = [accent]호스트[] 버튼은 현재 네트워크의 [scarlet]6567[] 과 [scarlet]6568[] 포트를 사용합니다.\n[LIGHY_GRAY]같은 Wi-Fi 또는 로컬 네트워크[] 에서 서버 목록을 볼 수 있습니다.\n\n만약 플레이어들이 이 IP를 통해 어디에서나 연결할 수 있게 하고 싶다면, 공유기 설정에서 [accent]포트 포워딩[]을 해야 합니다.\n\n[LIGHT_GRAY]참고 \: LAN 게임 연결에 문제가 있는 사람이 있다면, 방화벽 설정에서 Mindustry 가 로컬 네트워크에 액세스하도록 허용했는지 확인 해 주세요. -text.join.info = 여기서 [accent]서버 IP[]를 입력하여 다른 서버에 접속할 수 있습니다.\n또는 [accent]로컬 네트워크(LAN)[] 서버를 검색하여 접속할 수 있습니다.\nLAN 및 WAN 멀티 플레이어 모두 지원됩니다.\n\n[LIGHT_GRAY]참고\:여기에서는 자동으로 글로벌 서버를 추가하지 않습니다. IP로 다른 사람의 서버에 접속할려면 서버장에게 IP를 요청해야 합니다. +text.host.info = [accent]호스트[] 버튼은 현재 네트워크의 [scarlet]6567[] 과 [scarlet]6568[] 포트를 사용합니다.\n[LIGHY_GRAY]같은 Wi-Fi 또는 로컬 네트워크[] 에서 서버 목록을 볼 수 있습니다.\n\n만약 플레이어들이 이 IP를 통해 어디에서나 연결할 수 있게 하고 싶다면, 공유기 설정에서 [accent]포트 포워딩[]을 해야 합니다.\n\n[LIGHT_GRAY]참고 : LAN 게임 연결에 문제가 있는 사람이 있다면, 방화벽 설정에서 Mindustry 가 로컬 네트워크에 액세스하도록 허용했는지 확인 해 주세요. +text.join.info = 여기서 [accent]서버 IP[]를 입력하여 다른 서버에 접속할 수 있습니다.\n또는 [accent]로컬 네트워크(LAN)[] 서버를 검색하여 접속할 수 있습니다.\nLAN 및 WAN 멀티 플레이어 모두 지원됩니다.\n\n[LIGHT_GRAY]참고:여기에서는 자동으로 글로벌 서버를 추가하지 않습니다. IP로 다른 사람의 서버에 접속할려면 서버장에게 IP를 요청해야 합니다. text.hostserver = 서버 열기 text.hostserver.mobile = 게임\n호스트 text.host = 호스트 @@ -99,31 +100,31 @@ text.hosting = [accent]서버 여는중.. text.hosts.refresh = 새로고침 text.hosts.discovering = LAN 게임 찾기 text.server.refreshing = 서버 목록 새로고치는중... -text.hosts.none = [lightgray]LAN 게임을 찾을 수 없습니다\! -text.host.invalid = [scarlet]서버에 연결할 수 없습니다\! +text.hosts.none = [lightgray]LAN 게임을 찾을 수 없습니다! +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 = 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 입니다\! 공식 Mindustry Discord 으로 버그 보고서를 제출 해 주세요. +text.trace.playername = 이름 : [accent]{0} +text.trace.ip = IP : [accent]{0} +text.trace.id = 고유 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} +text.invalidid = 잘못된 클라이언트 ID 입니다! 공식 Mindustry Discord 으로 버그 보고서를 제출 해 주세요. text.server.bans = 차단된 유저 text.server.bans.none = 차단된 플레이어가 없습니다. -text.server.admins = 영자 -text.server.admins.none = 영자가 없습니다\! +text.server.admins = 관리자 +text.server.admins.none = 관리자가 없습니다! text.server.add = 서버 추가 text.server.delete = 이 서버를 삭제 하시겠습니까? -text.server.hostname = 호스트 \: {0} +text.server.hostname = 호스트 : {0} text.server.edit = 서버 수정 -text.server.outdated = [crimson]서버 버전이 낮습니다\![] -text.server.outdated.client = [Crimson]클라이언트 버전이 낮습니다\![] -text.server.version = [lightgray]서버 버전 \: {0} +text.server.outdated = [crimson]서버 버전이 낮습니다![] +text.server.outdated.client = [Crimson]클라이언트 버전이 낮습니다![] +text.server.version = [lightgray]서버 버전 : {0} text.server.custombuild = [yellow]커스텀 서버 text.confirmban = 이 플레이어를 차단하시겠습니까? text.confirmkick = 정말로 이 플레이어를 추방시키겠습니까? @@ -131,46 +132,46 @@ text.confirmunban = 이 플레이어를 차단해제 하시겠습니까? text.confirmadmin = 이 플레이어를 영자로 만들겠습니까? text.confirmunadmin = 이 플레이어를 일반 유저로 만들겠습니까? text.joingame.title = 게임 참가 -text.joingame.ip = IP \: +text.joingame.ip = IP : text.disconnect = 서버와 연결이 해제되었습니다. text.disconnect.data = 맵 데이터를 받아오는데 실패했습니다. text.connecting = [accent]연결중... text.connecting.data = [accent]맵 데이터 다운로드중... text.connectfail = [crimson]{0}[orange] 서버에 연결하지 못했습니다.[] -text.server.port = 포트 \: -text.server.addressinuse = 이 주소는 이미 사용중입니다\! +text.server.port = 포트 : +text.server.addressinuse = 이 주소는 이미 사용중입니다! text.server.invalidport = 포트 번호가 잘못되었습니다. text.server.error = [crimson]{0}[orange]서버를 여는데 오류가 발생했습니다.[] text.save.old = 이 저장파일은 이전 버전의 게임용이며, 지금은 사용할 수 없습니다. \n\n[LIGHT_GRAY]4.0 정식때 이전 게임버전에서 만든 저장파일과 호환됩니다. text.save.new = 새로 저장 text.save.overwrite = 이 저장 슬롯을 덮어씌우겠습니까? text.overwrite = 덮어쓰기 -text.save.none = 저장 파일을 찾지 못했습니다\! +text.save.none = 저장 파일을 찾지 못했습니다! text.saveload = [accent]저장중... -text.savefail = 게임을 저장하지 못했습니다\! +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.invalid = [orange]파일이 잘못되었습니다! +text.save.import.fail = [crimson]저장파일을 불러오지 못함 : [orange]{0} +text.save.export.fail = [crimson]저장파일을 내보내지 못함 : [orange]{0} text.save.import = 저장파일 불러오기 -text.save.newslot = 저장 파일이름 \: +text.save.newslot = 저장 파일이름 : text.save.rename = 이름 변경 -text.save.rename.text = 새 이름 \: +text.save.rename.text = 새 이름 : text.selectslot = 저장슬롯을 선택하십시오. text.slot = [accent]{0}번째 슬롯 -text.save.corrupted = [orange]세이브 파일이 손상되었거나 잘못된 파일입니다\! 만약 게임을 업데이트 했다면 이것은 아마 저장 형식 변경일 것이고, 이것은 버그가 [scarlet]아닙니다[]. +text.save.corrupted = [orange]세이브 파일이 손상되었거나 잘못된 파일입니다! 만약 게임을 업데이트 했다면 이것은 아마 저장 형식 변경일 것이고, 이것은 버그가 [scarlet]아닙니다[]. text.sector.corrupted = [orange]저장 파일에서 구역을 발견했으나 불러오지 못했습니다.\n새로 생성되었습니다. text.empty = <비어있음> text.on = 켜기 text.off = 끄기 -text.save.autosave = 자동저장 \: {0} -text.save.map = 맵 \: {0} +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.save.difficulty = 난이도 : {0} +text.save.date = 마지막 저장날짜 : {0} +text.save.playtime = 플레이시간 : {0} text.confirm = 확인 text.delete = 삭제 text.ok = 확인 @@ -184,7 +185,7 @@ text.changelog.title = 변경사항 text.changelog.loading = 변경사항 가져오는중... text.changelog.error.android = [orange]게임 변경사항은 가끔 Android 4.4 이하에서 작동하지 않습니다.이것은 내부 Android 버그 때문입니다. text.changelog.error.ios = [orange]현재 iOS에서는 변경 사항을 지원하지 않습니다. -text.changelog.error = [scarlet]게임 변경사항을 가져오는 중 오류가 발생했습니다\![]\n인터넷 연결을 확인하십시오. +text.changelog.error = [scarlet]게임 변경사항을 가져오는 중 오류가 발생했습니다![]\n인터넷 연결을 확인하십시오. text.changelog.current = [orange][[현재 버전] text.changelog.latest = [orange][[최신 버전] text.loading = [accent]불러오는중... @@ -199,34 +200,34 @@ text.loadimage = 사진 불러오기 text.saveimage = 사진 저장 text.unknown = 알 수 없음 text.custom = 커스텀 -text.builtin = 내장 -text.map.delete.confirm = 이 맵을 삭제하시겠습니까? 이 명령은 취소할 수 없습니다\! +text.builtin = 기본맵 +text.map.delete.confirm = 이 맵을 삭제하시겠습니까? 이 명령은 취소할 수 없습니다! text.map.random = [accent]랜덤 맵 -text.map.nospawn = 이 맵에 플레이어가 스폰 할 코어가 없습니다\! 맵 편집기에서 [ROYAL]파란색[]코어를 맵에 추가하세요. -text.map.nospawn.pvp = 이 맵에는 적팀 코어가 없습니다\! 에디터에서 [scarlet]빨간팀[] 코어를 추가하세요. +text.map.nospawn = 이 맵에 플레이어가 스폰 할 코어가 없습니다! 맵 편집기에서 [ROYAL]파란색[]코어를 맵에 추가하세요. +text.map.nospawn.pvp = 이 맵에는 적팀 코어가 없습니다! 에디터에서 [scarlet]빨간팀[] 코어를 추가하세요. text.map.invalid = 파일이 잘못되었거나 손상되어 맵을 열 수 없습니다. text.editor.brush = 브러쉬 text.editor.slope = \\ text.editor.openin = 편집기 열기 text.editor.oregen = 광물 무작위 생성 -text.editor.oregen.info = 광물 무작위 생성 \: +text.editor.oregen.info = 광물 무작위 생성 : text.editor.mapinfo = 맵 정보 -text.editor.author = 만든이 \: -text.editor.description = 설명 \: -text.editor.name = 이름 \: +text.editor.author = 만든이 : +text.editor.description = 설명 : +text.editor.name = 이름 : text.editor.teams = 팀 -text.editor.elevation = 높이 -text.editor.badsize = [orange]사진 크기가 잘못되었습니다\![] 유효한 맵 크기 \: {0} +text.editor.elevation = 지형 높이 +text.editor.badsize = [orange]사진 크기가 잘못되었습니다![] 유효한 맵 크기 : {0} text.editor.errorimageload = [orange]{0}[] 파일을 불러오는데 오류가 발생했습니다. text.editor.errorimagesave = [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.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 = 이미 존재하는 맵 가져오기 @@ -241,21 +242,21 @@ text.editor.exportimage = 지형 이미지 내보내기 text.editor.exportimage.description = 맵 이미지 파일 내보내기 text.editor.loadimage = 지형 가져오기 text.editor.saveimage = 지형 내보내기 -text.editor.unsaved = [scarlet]변경사항을 저장하지 않았습니다\![]\n정말로 나가시겠습니까? +text.editor.unsaved = [scarlet]변경사항을 저장하지 않았습니다![]\n정말로 나가시겠습니까? text.editor.resizemap = 맵 크기 조정 -text.editor.mapname = 맵 이름 \: -text.editor.overwrite = [accept]경고\!이 명령은 기존 맵을 덮어씌우게 됩니다. -text.editor.overwrite.confirm = [scarlet]경고\![] 이 이름을 가진 맵이 이미 있습니다. 덮어 쓰시겠습니까? -text.editor.selectmap = 불러올 맵 선택 \: -text.width = 넓이 \: -text.height = 높이 \: +text.editor.mapname = 맵 이름 : +text.editor.overwrite = [accept]경고!이 명령은 기존 맵을 덮어씌우게 됩니다. +text.editor.overwrite.confirm = [scarlet]경고![] 이 이름을 가진 맵이 이미 있습니다. 덮어 쓰시겠습니까? +text.editor.selectmap = 불러올 맵 선택 : +text.width = 넓이 : +text.height = 높이 : text.menu = 메뉴 text.play = 플레이 text.load = 불러오기 text.save = 저장 text.fps = {0}FPS text.tps = {0}TPS -text.ping = ping \: {0}ms +text.ping = ping : {0}ms text.language.restart = 언어를 변경하려면 게임을 다시시작 해 주세요. text.settings = 설정 text.tutorial = 게임 방법 @@ -270,8 +271,8 @@ text.settings.game = 게임 text.settings.sound = 소리 text.settings.graphics = 화면 text.settings.cleardata = 게임 데이터 초기화... -text.settings.clear.confirm = 정말로 초기화 하겠습니까?\n이 작업을 되돌릴 수 없습니다\! -text.settings.clearall.confirm = [scarlet]경고\![]\n이 작업은 저장된 맵, 맵파일, 잠금 해제된 목록과 키 매핑, 그리고 모든 데이터를 삭제합니다.\n확인 버튼을 다시 눌러 모든 데이터를 삭제하고 게임에서 나갑니다. +text.settings.clear.confirm = 정말로 초기화 하겠습니까?\n이 작업을 되돌릴 수 없습니다! +text.settings.clearall.confirm = [scarlet]경고![]\n이 작업은 저장된 맵, 맵파일, 잠금 해제된 목록과 키 매핑, 그리고 모든 데이터를 삭제합니다.\n확인 버튼을 다시 눌러 모든 데이터를 삭제하고 게임에서 나갑니다. text.settings.clearsectors = 구역 초기화 text.settings.clearunlocks = 잠금 해제 초기화 text.settings.clearall = 모두 초기화 @@ -313,7 +314,7 @@ text.blocks.coolant = 냉각제 text.blocks.coolantuse = 냉각수 사용 text.blocks.inputliquidfuel = 연료 액 text.blocks.liquidfueluse = 액체 연료 사용 -text.blocks.explosive = 이게 터지면 펑 터지면서 주변 블록에게 피해를 입힙니다\! +text.blocks.explosive = 이게 터지면 펑 터지면서 주변 블록에게 피해를 입힙니다! text.blocks.health = 체력 text.blocks.inaccuracy = 오차각 text.blocks.shots = 발포 횟수 @@ -348,7 +349,7 @@ setting.difficulty.normal = 보통 setting.difficulty.hard = 어려움 setting.difficulty.insane = 이걸 할수있을까? setting.difficulty.purge = 위이이이잉 -setting.difficulty.name = 난이도 \: +setting.difficulty.name = 난이도 : setting.screenshake.name = 화면 흔들기 setting.indicators.name = 적 위치 표시 화살표 setting.effects.name = 화면 효과 @@ -402,7 +403,7 @@ mode.waves.description = 이것은 일반 모드입니다. 제한된 자원과 mode.sandbox.name = 샌드박스 mode.sandbox.description = 무한한 자원과 다음단계 시작을 위한 타이머가 없습니다. mode.custom.warning = [scarlet]서버에서 잠금해제한 블록은 저장되지 않습니다.[]\n\n구역을 플레이 하여 잠금해제하세요. -mode.custom.warning.read = 꼭 읽어보시길 바랍니다 \:\n[scarlet]커스텀 게임에서 잠금해제한 블록은 구역 플레이나 다른 모드에서 적용되지 않습니다\!\n\n[LIGHT_GRAY](이게 필요하지 않았으면 좋겠는데) +mode.custom.warning.read = 꼭 읽어보시길 바랍니다 :\n[scarlet]커스텀 게임에서 잠금해제한 블록은 구역 플레이나 다른 모드에서 적용되지 않습니다!\n\n[LIGHT_GRAY](이게 필요하지 않았으면 좋겠는데) mode.freebuild.name = 자유 건축 mode.freebuild.description = 제한된 자원과 다음단계 시작을 위한 타이머가 없습니다. mode.pvp.name = PvP @@ -413,88 +414,90 @@ content.unit.name = 유닛 content.recipe.name = 블록 content.mech.name = 기체 item.stone.name = 돌 -item.stone.description = 흔히 찾을 수 있는 자원. 바닥에서 돌을 캐거나 용암을 사용하여 얻을 수 있습니다. +item.stone.description = 주로 용암을 사용하여 얻을 수 있습니다. item.copper.name = 구리 -item.copper.description = 기본 블록 재료입니다. 모든 유형의 블록에서 광범위하게 사용됩니다. +item.copper.description = 모든 유형의 블록에서 광범위하게 사용되는 자원입니다. item.lead.name = 납 -item.lead.description = 기본적인 시작 자원. 전자 및 액체 수송 블록에서 광범위하게 사용됩니다. +item.lead.description = 쉽게 구할 수 있는 자원.\n전자 및 액체 수송 블록에서 광범위하게 사용되는 자원입니다. item.coal.name = 석탄 -item.coal.description = 일반적이고 쉽게 이용할 수 있는 연료. +item.coal.description = 쉽게 구할 수 있으며, 주로 제련소 등에서 연료로 사용됩니다. item.dense-alloy.name = 합금 -item.dense-alloy.description = 납과 구리로 만든 튼튼한 합금. 고급 수송 블록이나 상위 티어 블록을 건설하는데 사용됩니다. +item.dense-alloy.description = 납과 구리로 만든 튼튼한 합금.\n고급 수송 블록이나 상위 티어 블록을 건설하는데 사용됩니다. item.titanium.name = 티타늄 -item.titanium.description = 물 운반이나 드릴, 비행기등에서 재료로 사용되는 자원입니다. +item.titanium.description = 파이프 재료나 고급 드릴, 비행기/기체 등에서 재료로 사용되는 자원입니다. item.thorium.name = 토륨 -item.thorium.description = 건물 탄약 또는 핵연료로 사용되는 방사성 금속. +item.thorium.description = 건물의 재료, 포탑의 탄약 또는 핵연료로 사용되는 방사성 금속입니다. item.silicon.name = 실리콘 -item.silcion.description = 매우 유용한 반도체로, 태양 전지판과 복잡한 전자 제품에 응용할 수 있습니다. -item.plastanium.name = 플라스타늄 +item.silicon.description = 매우 유용한 반도체로, 태양 전지판과 복잡한 전자 제품에 사용할 수 있습니다. +item.plastanium.name = 플라스터늄 item.plastanium.description = 고급 항공기 및 분열 탄약에 사용되는 가벼운 연성 재료. item.phase-matter.name = 메타 -item.surge-alloy.name = 설탕 +item.phase-matter.description = 최고급 자원. 최상위 기체/비행기나 방어 건물등에 사용됩니다. +item.surge-alloy.name = 설금 +item.surge-alloy.description = 주로 건물의 재료로 사용되는 자원입니다 item.biomatter.name = 바이오메터 -item.biomatter.description = 이것은 유기농 덤불입니다\! 석유로 전환하거나 기본 연료로 사용됩니다. +item.biomatter.description = 이것은 유기농 덤불입니다!\n석유로 전환하거나 연료로 사용됩니다. item.sand.name = 모래 -item.sand.description = 합금 및 플렉스 모두에서 제련시 광범위하게 사용되는 일반적인 재료. -item.blast-compound.name = 폭발 화합물 -item.blast-compound.description = 폭탄 및 폭발물에 사용되는 휘발성 화합물. 이 연료로 불을 낼 수 있지만, 별로 추천하지는 않습니다. -item.pyratite.name = 피러레이트 -item.pyratite.description = 화염 무기에 사용되는 엄청난 가연성 물질. +item.sand.description = 합금이나 플렉스 등에서 제련시 광범위하게 사용되는 일반적인 재료입니다. +item.blast-compound.name = 화합물 +item.blast-compound.description = 포탑 및 건설의 재료로 사용되는 휘발성 화합물.\n연료로도 사용할 수 있지만, 별로 추천하지는 않습니다. +item.pyratite.name = 피라테 +item.pyratite.description = 폭발성을 가진 재료로, 주로 포탑의 탄약으로 사용됩니다. liquid.water.name = 물 liquid.lava.name = 용암 liquid.oil.name = 석유 liquid.cryofluid.name = 냉각수 mech.alpha-mech.name = 알파 -mech.alpha-mech.weapon = Heavy Repeater -mech.alpha-mech.ability = Drone Swarm -mech.alpha-mech.description = 표준 기체. 적절한 속도와 공격력을 갖추고 있으며, 공격 능력을 높이기 위해 최대 3대의 드론을 만들 수 있습니다. +mech.alpha-mech.weapon = 중무장 소총 +mech.alpha-mech.ability = 드론 소환 +mech.alpha-mech.description = 표준 기체.\n적절한 속도와 공격력을 갖추고 있으며, 공격 능력을 높이기 위해 최대 3대의 드론을 만들 수 있습니다. mech.delta-mech.name = 델타 -mech.delta-mech.weapon = Arc Generator -mech.delta-mech.ability = Discharge -mech.delta-mech.description = 치고 빠지는 공격을 위해 만든 빠르고 가벼운 기체. 구조물에는 거의 피해를 주지 않지만, 번개 무기를 사용하여 많은 적군을 매우 빠르게 죽일 수 있습니다. -mech.tau-mech.name = Tau -mech.tau-mech.weapon = Restruct Laser -mech.tau-mech.ability = Repair Burst -mech.tau-mech.description = 지원형 기체. 총을 발사하여 건물을 치료하고 회복 능력 사용으로 화재를 진압하거나 반경 내 아군을 치유시킵니다. +mech.delta-mech.weapon = 전격 생산기 +mech.delta-mech.ability = 충전 +mech.delta-mech.description = 빠르게 이동하는 적을 처치하기 위한 가벼운 기체.\n구조물에는 거의 피해를 주지 않지만, 전격 무기를 사용하여 많은 적군을 매우 빠르게 죽일 수 있습니다. +mech.tau-mech.name = 타우 +mech.tau-mech.weapon = 건물 수리총 +mech.tau-mech.ability = 유닛 치료 +mech.tau-mech.description = 지원형 기체.\n총을 발사하여 건물을 치료하고 회복 능력 사용으로 화재를 진압하거나, 반경 내 아군을 치유시킵니다. mech.omega-mech.name = 오메가 -mech.omega-mech.weapon = Swarm Missiles -mech.omega-mech.ability = Armored Configuration -mech.omega-mech.description = 전방 공격용으로 만든 부피가 크고 튼튼한 기체. 방어 능력은 최대 90%의 피해를 흡수할 수 있습니다. -mech.dart-ship.name = Dart -mech.dart-ship.weapon = Repeater +mech.omega-mech.weapon = 전방 유도미사일 +mech.omega-mech.ability = 방어모드 +mech.omega-mech.description = 지상 기체 최종판이자 건물 파괴용으로 적합한 부피가 크고 튼튼한 기체. 방어 모드는 최대 90% 의 피해를 줄일 수 있습니다. +mech.dart-ship.name = 다트 +mech.dart-ship.weapon = 소총 mech.dart-ship.description = 표준 비행선. 빠르고 가볍지만 공격력이 거의 없고 채광 속도가 느립니다. -mech.javelin-ship.name = Javelin -mech.javelin-ship.description = 치고 빠지는 공격을 위한 비행선. 처음에는 느리지만, 가속도가 붙어 엄청난 속도로 미사일 피해를 입힐 수 있으며, 번개 능력을 사용할 수 있습니다. -mech.javelin-ship.weapon = Burst Missiles -mech.javelin-ship.ability = Discharge Booster -mech.trident-ship.name = Trident +mech.javelin-ship.name = 자비린 +mech.javelin-ship.description = 치고 빠지는 공격을 위한 비행선. 처음에는 느리지만, 가속도가 붙어 엄청난 속도로 미사일 피해를 입힐 수 있으며, 전격 능력을 사용할 수 있습니다. +mech.javelin-ship.weapon = 유도 미사일 +mech.javelin-ship.ability = 가속 전격 생성기 +mech.trident-ship.name = 삼지창 mech.trident-ship.description = 대형 공중 폭격기. 당연하게도 엄청 단단합니다. -mech.trident-ship.weapon = Bomb Bay -mech.glaive-ship.name = Glaive +mech.trident-ship.weapon = 폭탄 저장고 +mech.glaive-ship.name = 글레브 mech.glaive-ship.description = 크고 잘 무장된 총을 가진 비행선. 방화용 리피터가 장착되어 있으며, 가속도와 최대속도가 높습니다. -mech.glaive-ship.weapon = Flame Repeater -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.unit.health = [LIGHT_GRAY]체력 \: {0} -text.unit.speed = [LIGHT_GRAY]속도 \: {0} -text.mech.weapon = [LIGHT_GRAY]무기 \: {0} -text.mech.armor = [LIGHT_GRAY]방어 \: {0} -text.mech.itemcapacity = [LIGHT_GRAY]아이템 수용 용량 \: {0} -text.mech.minespeed = [LIGHT_GRAY]채광 속도 \: {0} -text.mech.minepower = [LIGHT_GRAY]채광 레벨 \: {0} -text.mech.ability = [LIGHT_GRAY]능력 \: {0} -text.liquid.heatcapacity = [LIGHT_GRAY]발열량 \: {0} -text.liquid.viscosity = [LIGHT_GRAY]점도 \: {0} -text.liquid.temperature = [LIGHT_GRAY]온도 \: {0} +mech.glaive-ship.weapon = 방화총 +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.unit.health = [LIGHT_GRAY]체력 : {0} +text.unit.speed = [LIGHT_GRAY]속도 : {0} +text.mech.weapon = [LIGHT_GRAY]무기 : {0} +text.mech.armor = [LIGHT_GRAY]방어력 : {0} +text.mech.itemcapacity = [LIGHT_GRAY]아이템 수용 용량 : {0} +text.mech.minespeed = [LIGHT_GRAY]채광 속도 : {0} +text.mech.minepower = [LIGHT_GRAY]채광 레벨 : {0} +text.mech.ability = [LIGHT_GRAY]능력 : {0} +text.liquid.heatcapacity = [LIGHT_GRAY]발열량 : {0} +text.liquid.viscosity = [LIGHT_GRAY]점도 : {0} +text.liquid.temperature = [LIGHT_GRAY]온도 : {0} block.spawn.name = 적 스폰지점 block.core.name = 코어 -block.metalfloor.name = Metal Floor +block.metalfloor.name = 메탈 바닥 block.deepwater.name = 깊은물 block.water.name = 물 block.lava.name = 용암 -block.oil.name = 석유 +block.tar.name = 타르 block.blackstone.name = 검은돌 block.stone.name = 돌 block.dirt.name = 흙 @@ -510,9 +513,9 @@ block.copper-wall.name = 구리벽 block.copper-wall-large.name = 큰 구리벽 block.dense-alloy-wall.name = 합금 벽 block.dense-alloy-wall-large.name = 큰 합금 벽 -block.phase-wall.name = Phase Wall -block.phase-wall-large.name = Large Phase Wall -block.thorium-wall.name = 토룸벽 +block.phase-wall.name = 메타벽 +block.phase-wall-large.name = 메타벽 +block.thorium-wall.name = 토륨벽 block.thorium-wall-large.name = 대형 토륨벽 block.door.name = 문 block.door-large.name = 대형문 @@ -532,13 +535,13 @@ block.sorter.description = 아이템을 넣어서 필터에 설정된 아이템 block.overflow-gate.name = 오버플로 게이트 block.overflow-gate.description = 정면 경로가 차단된 경우 왼쪽과 오른쪽으로만 출력하는 복합 분배기입니다. block.bridgeconveyor.name = 터널 -block.bridgeconveyor.description = 최대 2블록을 건너 뛰고 자원을 운반하게 해 주는 블록. +block.bridgeconveyor.description = 최대 4블록을 건너 뛰고 자원을 운반하게 해 주는 블록. block.smelter.name = 제련소 block.arc-smelter.name = 대형 제련소 block.silicon-smelter.name = 실리콘 제련소 block.phase-weaver.name = 메타 합성기 block.pulverizer.name = 분쇄기 -block.cryofluidmixer.name = 냉각수 혼합기 +block.cryofluidmixer.name = 냉각수 제조기 block.melter.name = 융해기 block.incinerator.name = 소각로 block.biomattercompressor.name = 바이오메터 압축기 @@ -550,26 +553,26 @@ block.battery.name = 배터리 block.battery-large.name = 대형 배터리 block.combustion-generator.name = 석탄 발전기 block.turbine-generator.name = 터빈 발전기 -block.mechanical-drill.name = Mechanical Drill -block.pneumatic-drill.name = Pneumatic Drill +block.mechanical-drill.name = 기계식 드릴 +block.pneumatic-drill.name = 강철 드릴 block.laser-drill.name = 레이저 드릴 block.water-extractor.name = 물 추출기 block.cultivator.name = 온실 block.alpha-mech-pad.name = 알파 기체 패드 block.dart-ship-pad.name = 다트 비행선 패드 block.delta-mech-pad.name = 델타 기체 패드 -block.javelin-ship-pad.name = 자바린 비행선 패드 +block.javelin-ship-pad.name = 자비린 비행선 패드 block.trident-ship-pad.name = 삼지창 비행선 패드 block.glaive-ship-pad.name = 글레브 비행선 패드 block.omega-mech-pad.name = 오메가 기체 패드 -block.tau-mech-pad.name = Tau 기체 패드 +block.tau-mech-pad.name = 타우 기체 패드 block.conduit.name = 파이프 block.mechanical-pump.name = 기계식 펌프 block.itemsource.name = 아이템 소스 -block.itemvoid.name = 아이템 무효 -block.liquidsource.name = 액체 소스 -block.powervoid.name = 무효 전력 -block.powerinfinite.name = 무한한 힘 +block.itemvoid.name = 히오스 +block.liquidsource.name = 무한 액체공급 장치 +block.powervoid.name = 방전장치 +block.powerinfinite.name = 무한 전력공급 장치 block.unloader.name = 언로더 block.sortedunloader.name = 정렬된 언로더 block.vault.name = 창고 @@ -580,20 +583,20 @@ block.ripple.name = 립플 block.phase-conveyor.name = 메타 컨베이어 block.bridge-conveyor.name = 터널 block.plastanium-compressor.name = 플라스터늄 압축기 -block.pyratite-mixer.name = 피터레이트 혼합기 -block.blast-mixer.name = 폭발 화합물 혼합기 +block.pyratite-mixer.name = 피라테 제조기 +block.blast-mixer.name = 화합물 제조기 block.solidifer.name = 고체 block.solar-panel.name = 태양 전지판 block.solar-panel-large.name = 대형 태양 전지판 block.oil-extractor.name = 석유 추출기 -block.spirit-factory.name = Spirit 드론 공장 +block.spirit-factory.name = 스피릿 드론 공장 block.phantom-factory.name = 팬텀 드론 공장 -block.wraith-factory.name = Wraith Fighter Factory -block.ghoul-factory.name = Ghoul Bomber Factory +block.wraith-factory.name = 유령 전투기 공장 +block.ghoul-factory.name = 구울 폭격기 공장 block.dagger-factory.name = 디거 기체 공장 block.titan-factory.name = 타이탄 기체 공장 -block.fortress-factory.name = Fortress Mech Factory -block.revenant-factory.name = Revenant Fighter Factory +block.fortress-factory.name = 포트리스 기체 공장 +block.revenant-factory.name = 레비던트 전투기 공장 block.repair-point.name = 정비소 block.pulse-conduit.name = 퓨즈 파이프 block.phase-conduit.name = 메타 파이프 @@ -602,33 +605,36 @@ block.liquid-tank.name = 물탱크 block.liquid-junction.name = 액체 교차기 block.bridge-conduit.name = 다리 파이프 block.rotary-pump.name = 동력 펌프 -block.thorium-reactor.name = Thorium Reactor +block.thorium-reactor.name = 핵 발전소 block.command-center.name = 명령 본부 block.mass-driver.name = 물질 이동기 block.blast-drill.name = 고속 발열 드릴 block.thermal-pump.name = 지열 펌프 block.thermal-generator.name = 지열 발전기 -block.alloy-smelter.name = Alloy Smtler -block.mend-projector.name = Mend Projector -block.surge-wall.name = Surge Wall -block.surge-wall-large.name = Large Surge Wall +block.alloy-smelter.name = 설금 제련소 +block.mend-projector.name = 치료 프로젝터 +block.surge-wall.name = 설금벽 +block.surge-wall-large.name = 큰 설금벽 block.cyclone.name = 사이클론 block.fuse.name = 퓨즈 -block.shock-mine.name = Shock Mine -block.overdrive-projector.name = Overdrive Projector -block.force-projector.name = Force Projector -block.arc.name = Arc -block.rtg-generator.name = RTG Generator -block.spectre.name = Spectre -block.meltdown.name = Meltdown +block.shock-mine.name = 전격 지뢰 +block.overdrive-projector.name = 가속 프로젝터 +block.force-projector.name = 강제 프로젝터 +block.arc.name = 아크 +block.rtg-generator.name = 토륨 발전소 +block.spectre.name = 스펙터 +block.meltdown.name = 멜트다운 block.container.name = 컨테이너 + team.blue.name = 블루팀 team.red.name = 레드팀 team.orange.name = 오렌지팀 team.none.name = 공기팀 team.green.name = 그린팀 team.purple.name = 보라색팀 -unit.alpha-drone.name = Alpha Drone + +unit.alpha-drone.name = 알파 드론 +unit.alpha-drone.description = unit.spirit.name = 스피릿 드론 unit.spirit.description = 기본 드론 유닛. 기본적으로 코어에서 1개가 스폰됩니다. 자동으로 채광하며 아이템을 수집하고, 블록을 수리합니다. unit.phantom.name = 팬텀 드론 @@ -637,14 +643,15 @@ unit.dagger.name = 디거 unit.dagger.description = 기본 지상 유닛입니다. 스웜과 같이 쓰면 유용합니다. unit.titan.name = 타이탄 unit.titan.description = 고급 지상 유닛입니다. 합금을 탄약으로 사용하며 지상과 공중 둘다 공격할 수 있습니다. -unit.ghoul.name = Ghoul Bomber -unit.ghoul.description = A heavy carpet bomber. Uses blast compound or pyratite as ammo. -unit.wraith.name = Wraith Fighter -unit.wraith.description = 빠르고, 치고 빠지는 공격방식을 사용합니다. -unit.fortress.name = Fortress -unit.fortress.description = 중포 지상 부대 유닛. -unit.revenant.name = Revenant -unit.revenant.description = A heavy laser platform. +unit.ghoul.name = 구울 폭격기 +unit.ghoul.description = 무거운 지상 폭격기 입니다. 화합물 또는 피라테를 탄약으로 사용합니다. +unit.wraith.name = 유령 전투기 +unit.wraith.description = 코어를 집중적으로 공격하는 방식을 사용하는 전투기 입니다. +unit.fortress.name = 포트리스 +unit.fortress.description = 중포 지상 유닛. 높은 공격력과 체력을 가지고 있습니다. +unit.revenant.name = 레비던트 +unit.revenant.description = 대형 레이저를 발사하는 공중 유닛입니다. + tutorial.begin = 플레이어의 임무는 [LIGHT_GRAY]적군[]을 제거하는 것입니다.\n\n[accent]구리를 채광[]하는 것으로 시작합니다. 이것을 하기 위해 플레이어의 중심부 근처에 있는 구리 광맥을 누르세요. tutorial.drill = 수동으로 채광하는 것은 비효율 적입니다.\n[accent]드릴[]은 자동으로 채광 작업을 합니다.\n구리 광맥에 표시된 영역에 드릴을 하나를 놓으세요. tutorial.conveyor = [accent]컨베이어[]를 사용하여 아이템을 코어로 운반합니다.\n드릴에서 코어까지 컨베이어 라인을 만드세요. @@ -655,14 +662,128 @@ tutorial.waves = [LIGHT_GRAY]적[]이 접근합니다.\n\n2단계 동안 코어 tutorial.lead = 더 많은 광석을 이용할 수 있습니다. [accent]납[]을 찾아 탐색하세요.\n\n아이템을 코어로 전송할려면 플레이어 기체 또는 비행기에서 코어로 드래그 하세요. tutorial.smelter = 구리와 납은 약한 금속입니다.\n[accent]합금[]은 제련소에서 만들 수 있습니다.\n\n하나 만드세요. tutorial.densealloy = 이 제련소는 이제 합금을 생산할 것입니다.\n몇개 더 생산하세요.\n필요한 경우 더 만드세요. -tutorial.siliconsmelter = The core will now create a[accent] spirit drone[] for mining and repairing blocks.\n\nFactories for other units can be created with [accent] silicon.\nMake a silicon smelter. -tutorial.silicondrill = Silicon requires[accent] coal[] and[accent] sand[].\nStart by making drills. -tutorial.generator = This technology requires power.\nCreate a[accent] combustion generator[] for it. -tutorial.generatordrill = Combustion generators need fuel.\nFuel it with coal from a drill. -tutorial.node = Power requires transport.\nCreate a[accent] power node[] next to your combustion generator to transfer its power. -tutorial.nodelink = Power can be transferred through contacting power blocks and generators, or by linked power nodes.\n\nLink power by tapping the node and selecting the generator and silicon smelter. -tutorial.silicon = Silicon is being produced. Get some.\n\nImproving the production system is advised. -tutorial.daggerfactory = Construct a[accent] dagger mech factory.[]\n\nThis will be used to create attack mechs. +tutorial.siliconsmelter = 이제 이코어는 채굴과 수리하기 위한[accent] 스피릿 드론[]을 생성 할 것 입니다.\n\n[accent]실리콘[]을 사용해 다른 유닛을 생성하기 위한 공장을 만들 수 있습니다.\n실리콘 제련기를 제작하세요! +tutorial.silicondrill = 실리콘을 제작하려면[accent] 석탄[] 과[accent] 모래[]가 필요합니다.\n드릴을 먼저 건설해보는건 어떤가요? +tutorial.generator = 이 기술은[LIGHT_YELLOW] 애너지[]가 필요합니다.\n[accent] 석탄 발전기[]를 건설하세요. +tutorial.generatordrill = [accent] 석탄 발전기[]는 연료가 필요합니다.\n[accent] 석탄[]을 드릴로 채굴해서 연료를 체워주세요. +tutorial.node = 전력은 송신해줄 송신기가 필요합니다.\n[accent] 전력 송신기[]를 석탄 등등 발전기 옆에 설치해서 생산된 전기를 다른곳으로 송신합시다. +tutorial.nodelink = 전력은 전력 블록과 발전기에 연결하거나, 연결된 전력 송신기를 통해 전송이 가능합니다. \n\n전력 송신기를 누르고 발전기와 실리콘 제련기를 선택하여 전원을 연결합시다. +tutorial.silicon = 실리콘이 생산되고 있습니다.\n\n생산 시스템의 개선을 권고 드립니다. +tutorial.daggerfactory = 이[accent] 디거 기체 공장[]은\n\n공격하는 기체를 생산하기 위해 사용됩니다. tutorial.router = 공장을 작동시키기 위해 자원이 필요합니다.\n컨베이어에 운반되고 있는 자원을 분할할 분배기를 만드세요. tutorial.dagger = 전력 노드를 공장에 연결하세요.\n일단 요구 사항이 충족되면 기체 생산을 시작합니다.\n\n필요에 따라 드릴 및 발전기, 컨베이어를 더 많이 만들 수 있습니다. -tutorial.battle = [LIGHT_GRAY]적[]의 코어가 드러났습니다.\n당신의 부대와 디거를 사용하여 파괴하세요. \ No newline at end of file +tutorial.battle = [LIGHT_GRAY]적[]의 코어가 드러났습니다.\n당신의 부대와 디거를 사용하여 파괴하세요. + +liquid.water.description = 유닛이 이 위를 지나가면 이동속도가 느려지고, 깊은 물에 빠지면 죽습니다. +liquid.lava.description = 유닛이 이 위를 지나가면 이동속도가 매우 느려지고, 지속적으로 데미지를 입습니다. +liquid.oil.description = 일부 조합 블록에서 사용되는 자원입니다. +liquid.cryofluid.description = 포탑 및 핵 발전소에서 사용되는 자원입니다. 누출시 폭발 및 방화의 위험성이 있습니다. + +block.core.description = 게임에서 가장 중요한 건물입니다.\n파괴되면 게임이 끝납니다. +block.copper-wall.description = 구리로 만든 벽. +block.copper-wall-large.description = 구리로 만든 큰 벽. +block.dense-alloy-wall.description = 합금으로 만든 벽. 구리벽보다 체력이 높습니다. +block.dense-alloy-wall-large.description = 합금으로 만든 큰 벽. +block.phase-wall.description = 날라오는 모든 총알을 튕겨내고 데미지를 입는 특수한 벽입니다. +block.phase-wall-large.description = 메타로 제작한 큰 벽. 날라오는 총알을 모두 튕겨냅니다. +block.thorium-wall.description = 토륨으로 만든 벽. +block.thorium-wall-large.description = 토륨으로 만든 큰 벽. +block.door.description = 유닛이 지나갈 수 있도록 만든 문. 클릭하면 열고 닫습니다. +block.door-large.description = 유닛이 자나갈 수 있도록 만든 큰 문. 클릭하면 열고 닫습니다. +block.duo.description = 범용성을 가진 터렛.\n지상 및 공중공격을 하며, 초중반에 유용합니다. +block.scorch.description = 근거리 화염 방사기 터렛입니다.\n이 터렛에 가까이 있는 적들을 지져버립니다. +block.hail.description = 장거리 지상 공격을 하는 터렛입니다.\n적이 오기 전에 쓸어버릴 수 있습니다. +block.lancer.description = 중거리 레이져 포탑입니다.\n적을 관통하기 때문에 뭉쳐있는 적들에게 매우 효과적입니다. +block.conveyor.description = 느린 속도로 자원을 수송할 수 있는 컨베이어. +block.titanium-conveyor.description = 빠른 속도로 자원을 수송할 수 있는 컨베이어. +block.junction.description = 컨베이어를 교차시켜 자원을 수송할 때 사용할 수 있는 블록입니다. +block.smelter.description = 합금을 제작할 수 있는 건물입니다. +block.arc-smelter.description = 합금을 제작할 수 있는 건물이지만, 이 건물은 석탄이 필요 없고 좀더 빠른 속도로 합금을 생산해낼 수 있습니다. +block.silicon-smelter.description = 실리콘을 제작할 수 있는 건물입니다. +block.phase-weaver.description = 메타를 제작할 수 있는 건물입니다. +block.pulverizer.description = 돌을 갈아서 모래로 만들 수 있는 건물입니다. +block.cryofluidmixer.description = 냉각수를 제작할 수 있는 건물입니다. +block.melter.description = 용암을 돌로 만들 수 있는 건물입니다. +block.incinerator.description = 불필요한 아이템을 소각시켜 줄 수 있는 건물입니다. +block.biomattercompressor.description = 잔디밭에서 바이오메터를 추출할 수 있는 건물입니다. +block.separator.description = 돌을 분해하여 각종 자원으로 재활용 할 수 있게 해 주는 건물입니다. +block.centrifuge.description = 돌을 분해하여 각종 자원으로 재활용 할 수 있게 해 주는 건물이지만, 이 건물은 좀 더 다양한 자원을 얻을 수 있게 해 줍니다. +block.power-node.description = 생성된 전기를 다른 건물로 전달하기 위한 전력 노드입니다. +block.power-node-large.description = 생성된 전기를 다른 건물로 전달하기 위한 건물이며, 일반 노드보다 더 많은 전력을 이동시킬 수 있습니다. +block.battery.description = 흔히 아는 충전식 배터리입니다.\n전력 생산건물에서 전력이 떨어질경우, 이 배터리를 전력 노드에 연결하면 이 배터리에 에 있는 전력을 사용하여 전기를 소모하는 건물에 전력을 지속적으로 공급할 수 있습니다. +block.battery-large.description = 일반 배터리보다 용량이 매우 커진 커진 배터리. +block.combustion-generator.description = 석탄을 연료로 전기를 생산해내는 발전소 입니다. +block.turbine-generator.description = 석탄 발전기보다 더 많은량의 전기를 생산하는 발전기입니다. +block.mechanical-drill.description = 구리로 제작할 수 있는 기본 드릴입니다. +block.pneumatic-drill.description = 돌, 티타늄을 채광할 수 있는 고급 드릴입니다. +block.laser-drill.description = 토륨을 채광할 수 있는 최고급 드릴입니다.\n전력과 물을 공급하여 빠른 속도로 채광할 수 있습니다. +block.water-extractor.description = 바닥에서 물을 추출하여 건물에 공급할 수 있는 건물입니다. +block.cultivator.description = 잔디에서 바이오메터를 추출할 수 있는 건물입니다. +block.alpha-mech-pad.description = 알파 기체로 바꿀 수 있는 패드입니다. +block.dart-ship-pad.description = 다트 비행선으로 바꿀 수 있는 패드입니다. +block.delta-mech-pad.description = 델타 기체로 바꿀 수 있는 패드입니다. +block.javelin-ship-pad.description = 자비린 비행선으로 바꿀 수 있는 패드입니다. +block.trident-ship-pad.description = 삼지창 비행선으로 바꿀 수 있는 패드입니다. +block.glaive-ship-pad.description = 글레브 비행선으로 바꿀 수 있는 패드입니다. +block.omega-mech-pad.description = 오메가 기체로 바꿀 수 있는 패드 +block.tau-mech-pad.description = 타우 기체로 바꿀 수 있는 패드 +block.conduit.description = 일반 파이프. 액체가 지나갈 수 있도록 해 줍니다. +block.liquidrouter.description = 파이프에 공급되고 있는 액체를 다른 방향으로 보낼 수 있게 해 줍니다. +block.bridge-conduit.description = 다리와 다리 사이를 연결하여 액체가 지나갈 수 있게 해 줍니다.\n주로 다리 사이에 지나갈 수 없는 장애물이 있을 때 사용합니다. +block.mechanical-pump.description = 구리로 제작할 수 있는 기계식 물펌프입니다. +block.itemsource.description = 자원을 선택하면 그 자원이 무한하게 튀어나오는 블록입니다. +block.itemvoid.description = 아이템을 시공으로 빠트려 사라지게 만듭니다. +block.liquidsource.description = 무한한 액체를 출력해냅니다. +block.powervoid.description = 무한한 아이템을 출력해냅니다. +block.powerinfinite.description = 무한한 전력을 출력해냅니다. +block.unloader.description = 해당 창고 및 코어에서 자원을 빼내는데 사용됩니다. +block.sortedunloader.description = 알 수 없음. +block.vault.description = 아이템을 임시로 저장할 수 있는 대형 창고 +block.wave.description = 적이 있는 자리에 액체를 뿌립니다.\n이 포탑을 활용하여 액체를 뿌린 곳에 불을 붙이거나 적을 느리게 할 수 있습니다. +block.swarmer.description = 4발씩 끊어 발사하고, 유도 미사일을 가진 포탑입니다. +block.salvo.description = 명중률이 높고, 3발씩 끊어 발사하는 포탑입니다. +block.ripple.description = 4개의 탄약으로 나눠 발사하여 명중률이 낮지만, 사거리가 매우 긴 포탑입니다. +block.phase-conveyor.description = 자원을 순간이동 시켜 주는 컨베이어 입니다. +block.bridge-conveyor.description = 교차기와 다르게 이 블록은 사이에 있는 블록들을 건너 띄우고 자원들을 운반할 수 있습니다. 주로 언덕간 자원 수송에서 사용됩니다. +block.plastanium-compressor.description = 플라스터늄을 제조할 수 있는 건물입니다. +block.pyratite-mixer.description = 피라테를 제조할 수 있는 건물입니다. +block.blast-mixer.description = 화합물을 제조할 수 있는 건물입니다. +block.solidifer.description = 용암을 돌로 만들 수 있는 건물입니다. +block.solar-panel.description = 태양열을 받아 자기 스스로 전력을 생산하는 블록입니다. +block.solar-panel-large.description = 태양열을 받아 자기 스스로 전력을 생산하지만, 이 블록은 더 빨리 전력을 생산할 수 있습니다. +block.oil-extractor.description = 기름을 추출 해 주는 건물. +block.spirit-factory.description = 스피릿 유닛을 생산하는 공장입니다. +block.phantom-factory.description = 유닛 팬텀을 생산하는 공장입니다. +block.wraith-factory.description = 유닛 유령 전투기를 소환하는 공장입니다. +block.fortress-factory.description = 포트리스를 생산하는 공장입니다. +block.ghoul-factory.description = 구울 유닛을 생산하는 공장입니다. +block.dagger-factory.description = 디거를 생산하는 공장입니다. +block.titan-factory.description = 타이탄 유닛을 생산할 수 있는 공장 +block.revenant-factory.description = 레비던트 유닛을 생산할 수 있는 공장 +block.repair-point.description = 근처 유닛들을 수리하는 건물입니다. +block.pulse-conduit.description = 티타늄으로 만들어 졌으며, 일반 파이프보다 액체 수용량이 높습니다. +block.phase-conduit.description = 물을 먼거리로 순간이동 시켜 주는 장치입니다. +block.liquid-router.description = 물펌프를 다른 방향으로 분배할 수 있게 하는 블럭입니다. +block.liquid-tank.description = 액체 종류를 저장할 수 있는 물탱크 입니다. +block.liquid-junction.description = 물펌프와 다른 물펌프를 서로 교차시키게 할 수 있는 블럭입니다. +block.rotary-pump.description = 일반 물 펌프보다 더 빠른 속도로 물을 끌어올릴 수 있는 펌프입니다. +block.thorium-reactor.description = 토륨을 원료로 하는 핵 발전소 입니다.\n많은 전력을 생산하지만 엄청난 열을 발생시키기 때문에, 많은 량의 물 또는 냉각수가 있어야 터지지 않고 작동합니다. +block.command-center.description = 생산된 유닛들을 제어할 수 있는 건물입니다.\n첫번째 버튼은 적 기지로 공격하며, 두번째는 대기 상태, 세번째는 기지 근처를 돌며 정찰합니다. +block.mass-driver.description = 자원을 받아서 다른 물질 이동기로 전달할 수 있는 블록입니다.\n엄청난 사거리를 가지고 있으며, 주로 컨베이어가 접근할 수 없는 곳에 유용하게 사용됩니다. +block.blast-drill.description = 최상위 드릴입니다. 엄청난 양의 전력과 물을 소모하는 대신, 매우 빠른 속도로 채광합니다. +block.thermal-pump.description = 용암 위에서 사용할 수 있는 펌프입니다. +block.thermal-generator.description = 용암을 원료로 전력을 생산할 수 있는 발전소입니다. +block.alloy-smelter.description = 설금을 제작할 수 있는 건물입니다. +block.mend-projector.description = 주위 건물을 치료하는 건물입니다. +block.surge-wall.description = 데미지를 입으면 번개를 일으켜 대상에게 피해를 입히는 특수한 벽입니다. +block.surge-wall-large.description = 설금을 재료로 한 큰 벽.\n데미지를 입으면 번개를 일으켜 대상에게 피해를 입힙니다. +block.cyclone.description = 낮은 명중률과 높은 RPM 을 가진 포탑입니다.\n탄약이 남아있는 한 멈추지 않고 계속 연사합니다. +block.fuse.description = 단거리에서 범위형 레이저를 발사하는 포탑입니다. +block.shock-mine.description = 적이 이 블록을 지나가면 전격 공격을 하는 함정형 방어 건물입니다. +block.overdrive-projector.description = 범위 내 모든 행동의 속도를 높여주는 보조형 방어 건물입니다. +block.force-projector.description = 보호막을 생성하는 건물입니다.\n기본적으로 전기만 있으면 작동하지만, 메타를 넣어 보호막의 범위를 크게 확장시킬 수 있습니다. +block.arc.description = 목표 방향으로 전격 공격을 하는 포탑입니다. +block.spectre.description = 높은 명중률과 RPM 을 가진 포탑입니다.\n탄약이 남아있는 한 멈추지 않고 계속 연사합니다. +block.meltdown.description = 목표를 따라 초대형 레이져를 발사하는 포탑입니다.\n뭉쳐있는 몹에게 매우 효과가 좋습니다. +block.container.description = 자원을 운반하기 위한 수송 블록입니다. +text.filename = 파일 이름 : diff --git a/core/assets/bundles/bundle_pl.properties b/core/assets/bundles/bundle_pl.properties index 858a8d5f08..113a06e791 100644 --- a/core/assets/bundles/bundle_pl.properties +++ b/core/assets/bundles/bundle_pl.properties @@ -428,7 +428,7 @@ item.titanium.description = Rzadki i bardzo lekki materiał. Używany w bardzo z item.thorium.name = uran item.thorium.description = Zwarty i radioaktywny materiał używany w struktucrach i paliwie nuklearnym. Nie trzymaj go w rękach\! item.silicon.name = Krzem -item.silcion.description = Niesamowicie przydatny półprzewodnk uźywany w panelach słonecznych i skomplikowanej elektronice. Nie, w Dolinie Krzemowej już nie ma krzemu. +item.silicon.description = Niesamowicie przydatny półprzewodnk uźywany w panelach słonecznych i skomplikowanej elektronice. Nie, w Dolinie Krzemowej już nie ma krzemu. item.plastanium.name = Plastan item.plastanium.description = Lekki i plastyczny materiał używany w amunicji odłamkowej i samolotach. Używany też w w klockach LEGO (Dlatego są niezniszczalne) item.phase-matter.name = Materia Fazowa diff --git a/core/assets/bundles/bundle_pt_BR.properties b/core/assets/bundles/bundle_pt_BR.properties index f889461016..444bbf090e 100644 --- a/core/assets/bundles/bundle_pt_BR.properties +++ b/core/assets/bundles/bundle_pt_BR.properties @@ -428,7 +428,7 @@ item.titanium.description = Um Material raro super leve, metal usado intensivame item.thorium.name = Urânio item.thorium.description = A dense, radioactive metal used as structural support and nuclear fuel. item.silicon.name = Sílicio -item.silcion.description = Condutor extremamente importante,Com aplicação em paneis solares e dispositivos complexos. +item.silicon.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 diff --git a/core/assets/bundles/bundle_ru.properties b/core/assets/bundles/bundle_ru.properties index 2d24c53676..de6b7880f4 100644 --- a/core/assets/bundles/bundle_ru.properties +++ b/core/assets/bundles/bundle_ru.properties @@ -428,7 +428,7 @@ item.titanium.description = Редкий сверхлёгкий металл ш item.thorium.name = Торий item.thorium.description = Плотный радиоактивный металл используется в качестве структурной поддержки и ядерного топлива. item.silicon.name = Кремень -item.silcion.description = Очень полезный полупроводник с применениями в солнечных батареях и множестве сложной электроники. +item.silicon.description = Очень полезный полупроводник с применениями в солнечных батареях и множестве сложной электроники. item.plastanium.name = Пластиний item.plastanium.description = Легкий, пластичный материал, используемый в современных самолетах и боеприпасах для фрагментации. item.phase-matter.name = Фазовая материя diff --git a/core/assets/bundles/bundle_tk.properties b/core/assets/bundles/bundle_tk.properties index e537cb87b3..39815123f4 100644 --- a/core/assets/bundles/bundle_tk.properties +++ b/core/assets/bundles/bundle_tk.properties @@ -428,7 +428,7 @@ item.titanium.description = Nadir ve hafif bir materyal. Hava araclarinda, Kazma item.thorium.name = Toryum item.thorium.description = Nukleer yakit olarak kullanilan sert ve nukleer bir materyal. item.silicon.name = Silikon -item.silcion.description = Gunes panellerinde ve gelismis materallerde kullanilan bir materyal +item.silicon.description = Gunes panellerinde ve gelismis materallerde kullanilan bir materyal item.plastanium.name = Plastanyum item.plastanium.description = hafif bir madde, hava makinelerinde ve silahlara kursun olarak kullanilir. item.phase-matter.name = Faz maddesi diff --git a/core/assets/bundles/bundle_tr.properties b/core/assets/bundles/bundle_tr.properties index 1c07feed1e..2e3345b4b4 100644 --- a/core/assets/bundles/bundle_tr.properties +++ b/core/assets/bundles/bundle_tr.properties @@ -428,7 +428,7 @@ item.titanium.description = A rare super-light metal used extensively in liquid item.thorium.name = Thorium 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.silicon.description = An extremely useful semiconductor, with applications in solar panels and many complex electronics. item.plastanium.name = Plastanium item.plastanium.description = A light, ductile material used in advanced aircraft and fragmentation ammunition. item.phase-matter.name = Phase Matter diff --git a/core/assets/bundles/bundle_uk_UA.properties b/core/assets/bundles/bundle_uk_UA.properties index b501137309..7acfec8177 100644 --- a/core/assets/bundles/bundle_uk_UA.properties +++ b/core/assets/bundles/bundle_uk_UA.properties @@ -428,7 +428,7 @@ item.titanium.description = Рідкий суперлегкий метал ши item.thorium.name = Торій item.thorium.description = Густий, радіоактивний метал, що використовується як структурна підтримка та ядерне паливо. item.silicon.name = Кремній -item.silcion.description = Надзвичайно корисний напівпровідник з застосуванням в сонячних батареях та багатьох складних електроніках. +item.silicon.description = Надзвичайно корисний напівпровідник з застосуванням в сонячних батареях та багатьох складних електроніках. item.plastanium.name = Пластиній item.plastanium.description = Легкий, пластичний матеріал, що використовується в сучасних літальних апаратах, та боєприпаси для фрагментації. item.phase-matter.name = Фазова матерія diff --git a/core/assets/bundles/bundle_zh_CN.properties b/core/assets/bundles/bundle_zh_CN.properties index 3d2c05af29..78fa984308 100644 --- a/core/assets/bundles/bundle_zh_CN.properties +++ b/core/assets/bundles/bundle_zh_CN.properties @@ -428,7 +428,7 @@ item.titanium.description = 一种罕见的超轻金属,被广泛运用于液 item.thorium.name = 钍 item.thorium.description = 一种致密的放射性金属,用作支撑结构和核燃料。 item.silicon.name = 硅 -item.silcion.description = 非常有用的半导体,被用于太阳能电池板和很多复杂的电子设备。 +item.silicon.description = 非常有用的半导体,被用于太阳能电池板和很多复杂的电子设备。 item.plastanium.name = 塑料 item.plastanium.description = 一种轻质,可延展的材料,用于高级的飞机和碎片弹药。 item.phase-matter.name = 相位问题 diff --git a/core/assets/bundles/bundle_zh_TW.properties b/core/assets/bundles/bundle_zh_TW.properties index 33b55cb0d9..134e7c6124 100644 --- a/core/assets/bundles/bundle_zh_TW.properties +++ b/core/assets/bundles/bundle_zh_TW.properties @@ -428,7 +428,7 @@ item.titanium.description = A rare super-light metal used extensively in liquid item.thorium.name = Thorium 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.silicon.description = An extremely useful semiconductor, with applications in solar panels and many complex electronics. item.plastanium.name = Plastanium item.plastanium.description = A light, ductile material used in advanced aircraft and fragmentation ammunition. item.phase-matter.name = Phase Matter diff --git a/core/assets/sprites/sprites.atlas b/core/assets/sprites/sprites.atlas index 56b77270ce..e498df9613 100644 --- a/core/assets/sprites/sprites.atlas +++ b/core/assets/sprites/sprites.atlas @@ -314,21 +314,21 @@ mass-driver-turret index: -1 phase-conveyor-arrow rotate: false - xy: 209, 182 + xy: 201, 27 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 phase-conveyor-bridge rotate: false - xy: 209, 172 + xy: 201, 17 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 phase-conveyor-end rotate: false - xy: 204, 162 + xy: 201, 7 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -865,121 +865,121 @@ metalflooredge orig: 12, 12 offset: 0, 0 index: -1 -oiledge - rotate: false - xy: 420, 336 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 rock2 rotate: false - xy: 206, 92 + xy: 214, 132 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 sand2 rotate: false - xy: 216, 112 + xy: 206, 112 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 sand3 rotate: false - xy: 216, 102 + xy: 206, 102 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 sandedge rotate: false - xy: 434, 336 + xy: 420, 336 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 shrubshadow rotate: false - xy: 211, 22 + xy: 220, 62 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 snow2 rotate: false - xy: 211, 12 + xy: 220, 52 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 snow3 rotate: false - xy: 221, 42 + xy: 211, 42 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 snowedge rotate: false - xy: 448, 336 + xy: 420, 322 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 spaceedge rotate: false - xy: 434, 322 + xy: 448, 336 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 stone-cliff-edge rotate: false - xy: 229, 178 + xy: 229, 198 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 stone-cliff-edge-1 rotate: false - xy: 239, 188 + xy: 219, 178 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 stone-cliff-edge-2 rotate: false - xy: 239, 178 + xy: 239, 198 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 stone-cliff-side rotate: false - xy: 249, 186 + xy: 229, 188 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 stone2 rotate: false - xy: 239, 198 + xy: 219, 198 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 stone3 rotate: false - xy: 229, 188 + xy: 219, 188 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 stoneedge rotate: false - xy: 448, 322 + xy: 420, 308 + size: 12, 12 + orig: 12, 12 + offset: 0, 0 + index: -1 +taredge + rotate: false + xy: 434, 308 size: 12, 12 orig: 12, 12 offset: 0, 0 @@ -1154,7 +1154,7 @@ nuclearreactor-shadow index: -1 place-arrow rotate: false - xy: 204, 152 + xy: 209, 192 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -1294,7 +1294,7 @@ shadow-rounded-2 index: -1 shadow-shock-mine rotate: false - xy: 211, 42 + xy: 210, 52 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -1476,70 +1476,70 @@ liquid-tank-top index: -1 phase-conduit-arrow rotate: false - xy: 201, 17 + xy: 191, 17 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 phase-conduit-bridge rotate: false - xy: 201, 7 + xy: 191, 7 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 phase-conduit-end rotate: false - xy: 209, 192 + xy: 201, 37 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 pulse-conduit-top-0 rotate: false - xy: 204, 142 + xy: 209, 182 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 pulse-conduit-top-1 rotate: false - xy: 204, 132 + xy: 209, 172 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 pulse-conduit-top-2 rotate: false - xy: 204, 122 + xy: 204, 162 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 pulse-conduit-top-3 rotate: false - xy: 214, 162 + xy: 204, 152 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 pulse-conduit-top-4 rotate: false - xy: 214, 152 + xy: 204, 142 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 pulse-conduit-top-5 rotate: false - xy: 214, 142 + xy: 204, 132 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 pulse-conduit-top-6 rotate: false - xy: 214, 132 + xy: 204, 122 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -1644,7 +1644,7 @@ fusion-reactor-top index: -1 rtg-generator-top rotate: false - xy: 206, 82 + xy: 214, 122 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -1840,7 +1840,7 @@ lavasmelter index: -1 oilrefinery rotate: false - xy: 174, 157 + xy: 179, 177 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -1875,21 +1875,21 @@ plastanium-compressor-top index: -1 pulverizer rotate: false - xy: 214, 122 + xy: 214, 162 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 pulverizer-rotator rotate: false - xy: 206, 112 + xy: 214, 152 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 separator-liquid rotate: false - xy: 220, 52 + xy: 210, 62 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -1910,7 +1910,7 @@ core-top index: -1 sortedunloader rotate: false - xy: 221, 2 + xy: 221, 32 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -2092,21 +2092,21 @@ salvo-panel-right index: -1 scatter rotate: false - xy: 210, 52 + xy: 216, 92 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 scorch rotate: false - xy: 220, 72 + xy: 216, 82 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 scorch-shoot rotate: false - xy: 220, 62 + xy: 210, 72 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -2232,7 +2232,7 @@ reconstructor-open index: -1 repair-point-turret rotate: false - xy: 206, 102 + xy: 214, 142 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -2512,7 +2512,7 @@ shell-back index: -1 shot rotate: false - xy: 211, 32 + xy: 220, 72 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -3224,20 +3224,6 @@ metalfloor1 orig: 8, 8 offset: 0, 0 index: -1 -block-icon-oil - rotate: false - xy: 836, 352 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -oil - rotate: false - xy: 836, 352 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 block-icon-oil-extractor rotate: false xy: 113, 189 @@ -3275,14 +3261,14 @@ overdrive-projector index: -1 block-icon-overflow-gate rotate: false - xy: 476, 324 + xy: 836, 352 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 overflow-gate rotate: false - xy: 476, 324 + xy: 836, 352 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -3296,42 +3282,42 @@ block-icon-phantom-factory index: -1 block-icon-phase-conduit rotate: false - xy: 474, 314 + xy: 476, 324 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 phase-conduit rotate: false - xy: 474, 314 + xy: 476, 324 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-phase-conveyor rotate: false - xy: 474, 304 + xy: 474, 314 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 phase-conveyor rotate: false - xy: 474, 304 + xy: 474, 314 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-phase-wall rotate: false - xy: 474, 294 + xy: 474, 304 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 phase-wall rotate: false - xy: 474, 294 + xy: 474, 304 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -3387,14 +3373,14 @@ block-icon-pneumatic-drill index: -1 block-icon-power-node rotate: false - xy: 480, 284 + xy: 474, 294 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 power-node rotate: false - xy: 480, 284 + xy: 474, 294 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -3415,42 +3401,42 @@ power-node-large index: -1 block-icon-powerinfinite rotate: false - xy: 480, 274 + xy: 480, 284 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 powerinfinite rotate: false - xy: 480, 274 + xy: 480, 284 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-powervoid rotate: false - xy: 480, 264 + xy: 480, 274 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 powervoid rotate: false - xy: 480, 264 + xy: 480, 274 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-pulse-conduit rotate: false - xy: 480, 254 + xy: 480, 264 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-pulverizer rotate: false - xy: 21, 1 + xy: 480, 254 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -3513,14 +3499,14 @@ wraith-factory index: -1 block-icon-repair-point rotate: false - xy: 31, 1 + xy: 21, 1 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 repair-point rotate: false - xy: 31, 1 + xy: 21, 1 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -3541,14 +3527,14 @@ block-icon-ripple index: -1 block-icon-rock rotate: false - xy: 41, 1 + xy: 31, 1 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 rock1 rotate: false - xy: 41, 1 + xy: 31, 1 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -3569,14 +3555,14 @@ rotary-pump index: -1 block-icon-router rotate: false - xy: 144, 155 + xy: 41, 1 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 router rotate: false - xy: 144, 155 + xy: 41, 1 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -3604,63 +3590,63 @@ block-icon-salvo index: -1 block-icon-sand rotate: false - xy: 144, 145 + xy: 144, 155 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 sand1 rotate: false - xy: 144, 145 + xy: 144, 155 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-scorch rotate: false - xy: 144, 135 + xy: 144, 145 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-separator rotate: false - xy: 144, 125 + xy: 144, 135 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 separator rotate: false - xy: 144, 125 + xy: 144, 135 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-shock-mine rotate: false - xy: 144, 115 + xy: 144, 125 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 shock-mine rotate: false - xy: 144, 115 + xy: 144, 125 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-shrub rotate: false - xy: 154, 156 + xy: 144, 115 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 shrub rotate: false - xy: 154, 156 + xy: 144, 115 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -3681,42 +3667,42 @@ silicon-smelter index: -1 block-icon-smelter rotate: false - xy: 154, 146 + xy: 154, 156 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 smelter rotate: false - xy: 154, 146 + xy: 154, 156 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-snow rotate: false - xy: 154, 136 + xy: 154, 146 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 snow1 rotate: false - xy: 154, 136 + xy: 154, 146 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-solar-panel rotate: false - xy: 154, 126 + xy: 154, 136 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 solar-panel rotate: false - xy: 154, 126 + xy: 154, 136 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -3737,56 +3723,56 @@ solar-panel-large index: -1 block-icon-solidifer rotate: false - xy: 154, 116 + xy: 154, 126 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 solidifer rotate: false - xy: 154, 116 + xy: 154, 126 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-sorter rotate: false - xy: 159, 175 + xy: 154, 116 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 sorter rotate: false - xy: 159, 175 + xy: 154, 116 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-space rotate: false - xy: 164, 156 + xy: 159, 175 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 space rotate: false - xy: 164, 156 + xy: 159, 175 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-spawn rotate: false - xy: 164, 146 + xy: 164, 156 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 spawn rotate: false - xy: 164, 146 + xy: 164, 156 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -3807,28 +3793,28 @@ block-icon-spirit-factory index: -1 block-icon-stone rotate: false - xy: 164, 136 + xy: 164, 146 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 stone1 rotate: false - xy: 164, 136 + xy: 164, 146 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 block-icon-surge-wall rotate: false - xy: 164, 126 + xy: 164, 136 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 surge-wall rotate: false - xy: 164, 126 + xy: 164, 136 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -3854,6 +3840,20 @@ block-icon-swarmer orig: 16, 16 offset: 0, 0 index: -1 +block-icon-tar + rotate: false + xy: 164, 126 + size: 8, 8 + orig: 8, 8 + offset: 0, 0 + index: -1 +tar + rotate: false + xy: 164, 126 + size: 8, 8 + orig: 8, 8 + offset: 0, 0 + index: -1 block-icon-tau-mech-pad rotate: false xy: 268, 287 @@ -4253,744 +4253,744 @@ metalfloor-cliff-side orig: 8, 8 offset: 0, 0 index: -1 -oil-cliff-edge - rotate: false - xy: 179, 177 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -oil-cliff-edge-1 +ore-coal-blackstone1 rotate: false xy: 179, 167 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 -oil-cliff-edge-2 +ore-coal-blackstone2 rotate: false xy: 189, 177 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 -oil-cliff-side +ore-coal-blackstone3 rotate: false xy: 189, 167 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 -ore-coal-blackstone1 - rotate: false - xy: 174, 147 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-coal-blackstone2 - rotate: false - xy: 184, 157 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-coal-blackstone3 - rotate: false - xy: 174, 137 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 ore-coal-grass1 rotate: false - xy: 184, 147 + xy: 174, 157 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-grass2 rotate: false - xy: 174, 127 + xy: 174, 147 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-grass3 rotate: false - xy: 184, 137 + xy: 184, 157 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-ice1 rotate: false - xy: 174, 117 + xy: 174, 137 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-ice2 rotate: false - xy: 184, 127 + xy: 184, 147 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-ice3 rotate: false - xy: 184, 117 + xy: 174, 127 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-sand1 rotate: false - xy: 176, 107 + xy: 184, 137 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-sand2 rotate: false - xy: 176, 97 + xy: 174, 117 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-sand3 rotate: false - xy: 176, 87 + xy: 184, 127 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-snow1 rotate: false - xy: 176, 77 + xy: 184, 117 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-snow2 rotate: false - xy: 186, 107 + xy: 176, 107 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-snow3 rotate: false - xy: 186, 97 + xy: 176, 97 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-stone1 rotate: false - xy: 186, 87 + xy: 176, 87 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-stone2 rotate: false - xy: 186, 77 + xy: 176, 77 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-coal-stone3 rotate: false - xy: 200, 202 + xy: 186, 107 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-copper-blackstone1 rotate: false - xy: 199, 192 + xy: 186, 97 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-copper-blackstone2 rotate: false - xy: 199, 182 + xy: 186, 87 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-copper-blackstone3 rotate: false - xy: 199, 172 + xy: 186, 77 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-copper-grass1 rotate: false - xy: 194, 157 + xy: 200, 202 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-copper-grass2 rotate: false - xy: 194, 147 + xy: 199, 192 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-copper-grass3 rotate: false - xy: 194, 137 + xy: 199, 182 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-copper-ice1 rotate: false - xy: 194, 127 + xy: 199, 172 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-copper-ice2 rotate: false - xy: 194, 117 + xy: 194, 157 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-copper-ice3 rotate: false - xy: 196, 107 + xy: 194, 147 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-copper-sand1 rotate: false - xy: 196, 97 + xy: 194, 137 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-copper-sand2 rotate: false - xy: 196, 87 + xy: 194, 127 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-copper-sand3 rotate: false - xy: 196, 77 + xy: 194, 117 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-copper-snow1 rotate: false - xy: 150, 66 + xy: 196, 107 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-copper-snow2 rotate: false - xy: 150, 56 + xy: 196, 97 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-copper-snow3 rotate: false - xy: 160, 66 + xy: 196, 87 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-copper-stone1 rotate: false - xy: 150, 46 + xy: 196, 77 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-copper-stone2 rotate: false - xy: 160, 56 + xy: 150, 66 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-copper-stone3 rotate: false - xy: 160, 46 + xy: 150, 56 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-blackstone1 rotate: false - xy: 170, 66 + xy: 160, 66 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-blackstone2 rotate: false - xy: 170, 56 + xy: 150, 46 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-blackstone3 rotate: false - xy: 170, 46 + xy: 160, 56 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-grass1 rotate: false - xy: 180, 67 + xy: 160, 46 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-grass2 rotate: false - xy: 180, 57 + xy: 170, 66 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-grass3 rotate: false - xy: 190, 67 + xy: 170, 56 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-ice1 rotate: false - xy: 180, 47 + xy: 170, 46 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-ice2 rotate: false - xy: 190, 57 + xy: 180, 67 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-ice3 rotate: false - xy: 190, 47 + xy: 180, 57 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-sand1 rotate: false - xy: 200, 67 + xy: 190, 67 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-sand2 rotate: false - xy: 200, 57 + xy: 180, 47 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-sand3 rotate: false - xy: 200, 47 + xy: 190, 57 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-snow1 rotate: false - xy: 322, 170 + xy: 190, 47 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-snow2 rotate: false - xy: 332, 170 + xy: 200, 67 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-snow3 rotate: false - xy: 342, 170 + xy: 200, 57 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-stone1 rotate: false - xy: 352, 170 + xy: 200, 47 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-stone2 rotate: false - xy: 362, 170 + xy: 322, 170 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-lead-stone3 rotate: false - xy: 372, 170 + xy: 332, 170 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-blackstone1 rotate: false - xy: 382, 171 + xy: 342, 170 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-blackstone2 rotate: false - xy: 392, 171 + xy: 352, 170 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-blackstone3 rotate: false - xy: 438, 198 + xy: 362, 170 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-grass1 rotate: false - xy: 438, 188 + xy: 372, 170 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-grass2 rotate: false - xy: 448, 198 + xy: 382, 171 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-grass3 rotate: false - xy: 448, 188 + xy: 392, 171 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-ice1 rotate: false - xy: 458, 198 + xy: 438, 198 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-ice2 rotate: false - xy: 458, 188 + xy: 438, 188 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-ice3 rotate: false - xy: 446, 178 + xy: 448, 198 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-sand1 rotate: false - xy: 456, 178 + xy: 448, 188 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-sand2 rotate: false - xy: 446, 168 + xy: 458, 198 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-sand3 rotate: false - xy: 456, 168 + xy: 458, 188 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-snow1 rotate: false - xy: 468, 198 + xy: 446, 178 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-snow2 rotate: false - xy: 468, 188 + xy: 456, 178 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-snow3 rotate: false - xy: 466, 178 + xy: 446, 168 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-stone1 rotate: false - xy: 466, 168 + xy: 456, 168 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-stone2 rotate: false - xy: 476, 178 + xy: 468, 198 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-thorium-stone3 rotate: false - xy: 476, 168 + xy: 468, 188 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-blackstone1 rotate: false - xy: 161, 36 + xy: 466, 178 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-blackstone2 rotate: false - xy: 161, 26 + xy: 466, 168 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-blackstone3 rotate: false - xy: 161, 16 + xy: 476, 178 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-grass1 rotate: false - xy: 161, 6 + xy: 476, 168 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-grass2 rotate: false - xy: 171, 36 + xy: 161, 36 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-grass3 rotate: false - xy: 171, 26 + xy: 161, 26 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-ice1 rotate: false - xy: 171, 16 + xy: 161, 16 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-ice2 rotate: false - xy: 171, 6 + xy: 161, 6 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-ice3 rotate: false - xy: 181, 37 + xy: 171, 36 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-sand1 rotate: false - xy: 181, 27 + xy: 171, 26 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-sand2 rotate: false - xy: 191, 37 + xy: 171, 16 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-sand3 rotate: false - xy: 181, 17 + xy: 171, 6 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-snow1 rotate: false - xy: 191, 27 + xy: 181, 37 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-snow2 rotate: false - xy: 181, 7 + xy: 181, 27 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-snow3 rotate: false - xy: 191, 17 + xy: 191, 37 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-stone1 rotate: false - xy: 191, 7 + xy: 181, 17 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-stone2 rotate: false - xy: 201, 37 + xy: 191, 27 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 ore-titanium-stone3 rotate: false - xy: 201, 27 + xy: 181, 7 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 sand-cliff-edge rotate: false - xy: 216, 92 + xy: 206, 92 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 sand-cliff-edge-1 rotate: false - xy: 216, 82 + xy: 206, 82 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 sand-cliff-edge-2 rotate: false - xy: 210, 72 + xy: 216, 112 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 sand-cliff-side rotate: false - xy: 210, 62 + xy: 216, 102 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 snow-cliff-edge rotate: false - xy: 221, 32 + xy: 211, 32 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 snow-cliff-edge-1 rotate: false - xy: 221, 22 + xy: 211, 22 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 snow-cliff-edge-2 rotate: false - xy: 221, 12 + xy: 211, 12 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 snow-cliff-side rotate: false - xy: 211, 2 + xy: 221, 42 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 space-cliff-edge rotate: false - xy: 219, 198 + xy: 221, 22 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 space-cliff-edge-1 rotate: false - xy: 219, 188 + xy: 221, 12 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 space-cliff-edge-2 rotate: false - xy: 229, 198 + xy: 211, 2 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 space-cliff-side rotate: false - xy: 219, 178 + xy: 221, 2 + size: 8, 8 + orig: 8, 8 + offset: 0, 0 + index: -1 +tar-cliff-edge + rotate: false + xy: 229, 178 + size: 8, 8 + orig: 8, 8 + offset: 0, 0 + index: -1 +tar-cliff-edge-1 + rotate: false + xy: 239, 188 + size: 8, 8 + orig: 8, 8 + offset: 0, 0 + index: -1 +tar-cliff-edge-2 + rotate: false + xy: 239, 178 + size: 8, 8 + orig: 8, 8 + offset: 0, 0 + index: -1 +tar-cliff-side + rotate: false + xy: 249, 186 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -5072,7 +5072,7 @@ item-lead orig: 8, 8 offset: 0, 0 index: -1 -item-phase-matter +item-phase-fabric rotate: false xy: 876, 344 size: 8, 8 @@ -6440,14 +6440,14 @@ unit-icon-revenant index: -1 spirit rotate: false - xy: 420, 308 + xy: 434, 322 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 unit-icon-spirit rotate: false - xy: 420, 308 + xy: 434, 322 size: 12, 12 orig: 12, 12 offset: 0, 0 @@ -6524,14 +6524,14 @@ heal-blaster-equip index: -1 shockgun-equip rotate: false - xy: 420, 322 + xy: 434, 336 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 swarmer-equip rotate: false - xy: 434, 308 + xy: 448, 322 size: 12, 12 orig: 12, 12 offset: 0, 0 diff --git a/core/assets/sprites/sprites.png b/core/assets/sprites/sprites.png index a9eab3b1a6..5ff4b5d82b 100644 Binary files a/core/assets/sprites/sprites.png and b/core/assets/sprites/sprites.png differ diff --git a/core/assets/ui/square.fnt b/core/assets/ui/square.fnt index 7a74b6069e..6f1f6cc9cc 100644 --- a/core/assets/ui/square.fnt +++ b/core/assets/ui/square.fnt @@ -3,15 +3,15 @@ common lineHeight=32 base=26 scaleW=2048 scaleH=2048 pages=3 packed=0 page id=0 file="square1.png" page id=1 file="square2.png" page id=2 file="square3.png" -chars count=11449 -char id=13 x=0 y=0 width=0 height=0 xoffset=-1 yoffset=0 xadvance=0 page=0 chnl=0 +chars count=11450 +char id=10 x=0 y=0 width=0 height=0 xoffset=-1 yoffset=0 xadvance=0 page=0 chnl=0 char id=32 x=0 y=0 width=0 height=0 xoffset=-1 yoffset=0 xadvance=16 page=0 chnl=0 char id=33 x=2039 y=147 width=7 height=23 xoffset=-1 yoffset=4 xadvance=8 page=0 chnl=0 char id=34 x=147 y=2032 width=15 height=11 xoffset=-1 yoffset=4 xadvance=16 page=0 chnl=0 char id=36 x=7 y=0 width=23 height=31 xoffset=-1 yoffset=0 xadvance=24 page=0 chnl=0 char id=39 x=2040 y=263 width=7 height=11 xoffset=-1 yoffset=4 xadvance=8 page=0 chnl=0 char id=40 x=2036 y=1278 width=11 height=23 xoffset=-1 yoffset=4 xadvance=12 page=0 chnl=0 -char id=41 x=2036 y=1365 width=11 height=23 xoffset=-1 yoffset=4 xadvance=12 page=0 chnl=0 +char id=41 x=2034 y=1365 width=11 height=23 xoffset=-1 yoffset=4 xadvance=12 page=0 chnl=0 char id=44 x=2040 y=263 width=7 height=11 xoffset=-1 yoffset=20 xadvance=8 page=0 chnl=0 char id=45 x=196 y=2032 width=23 height=7 xoffset=-1 yoffset=12 xadvance=24 page=0 chnl=0 char id=46 x=2037 y=292 width=7 height=7 xoffset=-1 yoffset=20 xadvance=8 page=0 chnl=0 @@ -27,39 +27,39 @@ char id=96 x=2033 y=1829 width=11 height=9 xoffset=3 yoffset=2 x char id=113 x=2022 y=1249 width=23 height=27 xoffset=-1 yoffset=4 xadvance=24 page=0 chnl=0 char id=124 x=0 y=0 width=7 height=31 xoffset=-1 yoffset=0 xadvance=8 page=0 chnl=0 char id=126 x=177 y=2032 width=19 height=9 xoffset=-1 yoffset=6 xadvance=16 page=0 chnl=0 -char id=192 x=2031 y=669 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 -char id=193 x=2027 y=698 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 +char id=192 x=2029 y=640 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 +char id=193 x=2031 y=669 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 char id=194 x=2022 y=292 width=15 height=29 xoffset=1 yoffset=-2 xadvance=16 page=0 chnl=0 -char id=195 x=2029 y=814 width=17 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 -char id=196 x=2029 y=843 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 +char id=195 x=2027 y=698 width=17 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 +char id=196 x=2029 y=814 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 char id=197 x=2027 y=321 width=15 height=29 xoffset=1 yoffset=-2 xadvance=16 page=0 chnl=0 -char id=199 x=2029 y=901 width=15 height=27 xoffset=1 yoffset=6 xadvance=16 page=0 chnl=0 -char id=200 x=2029 y=930 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 -char id=201 x=2029 y=959 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 +char id=199 x=2029 y=843 width=15 height=27 xoffset=1 yoffset=6 xadvance=16 page=0 chnl=0 +char id=200 x=2029 y=901 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 +char id=201 x=2029 y=930 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 char id=202 x=2022 y=350 width=15 height=29 xoffset=1 yoffset=-2 xadvance=16 page=0 chnl=0 -char id=203 x=2029 y=1191 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 +char id=203 x=2029 y=959 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 char id=204 x=2036 y=1133 width=11 height=27 xoffset=3 yoffset=0 xadvance=16 page=0 chnl=0 char id=205 x=2033 y=1162 width=11 height=27 xoffset=3 yoffset=0 xadvance=16 page=0 chnl=0 char id=206 x=2022 y=408 width=15 height=29 xoffset=1 yoffset=-2 xadvance=16 page=0 chnl=0 -char id=207 x=2029 y=1220 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 -char id=209 x=2019 y=1365 width=17 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 -char id=210 x=2024 y=1423 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 -char id=211 x=2030 y=1510 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 +char id=207 x=2029 y=1191 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 +char id=209 x=2029 y=1220 width=17 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 +char id=210 x=2019 y=1365 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 +char id=211 x=2024 y=1423 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 char id=212 x=2024 y=466 width=15 height=29 xoffset=1 yoffset=-2 xadvance=16 page=0 chnl=0 -char id=213 x=2023 y=1539 width=17 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 -char id=214 x=2030 y=1568 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 -char id=217 x=2023 y=1597 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 -char id=218 x=2022 y=1655 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 +char id=213 x=2030 y=1510 width=17 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 +char id=214 x=2023 y=1539 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 +char id=217 x=2030 y=1568 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 +char id=218 x=2023 y=1597 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 char id=219 x=2023 y=524 width=15 height=29 xoffset=1 yoffset=-2 xadvance=16 page=0 chnl=0 -char id=220 x=2024 y=1684 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 -char id=221 x=2024 y=1742 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 +char id=220 x=2022 y=1655 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 +char id=221 x=2024 y=1684 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 char id=224 x=2023 y=1974 width=15 height=25 xoffset=1 yoffset=2 xadvance=16 page=0 chnl=0 -char id=253 x=30 y=0 width=17 height=31 xoffset=-1 yoffset=2 xadvance=16 page=0 chnl=0 -char id=254 x=2023 y=1800 width=15 height=27 xoffset=1 yoffset=6 xadvance=16 page=0 chnl=0 -char id=255 x=2029 y=553 width=17 height=29 xoffset=-1 yoffset=4 xadvance=16 page=0 chnl=0 -char id=1031 x=2029 y=582 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 -char id=1049 x=2029 y=640 width=17 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 +char id=1025 x=2024 y=1742 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 +char id=1031 x=2029 y=553 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 +char id=1038 x=2023 y=1800 width=15 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 +char id=1049 x=2029 y=582 width=17 height=27 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=0 char id=1081 x=2029 y=1916 width=17 height=25 xoffset=1 yoffset=2 xadvance=16 page=0 chnl=0 +char id=1118 x=30 y=0 width=17 height=31 xoffset=-1 yoffset=2 xadvance=16 page=0 chnl=0 char id=1168 x=2029 y=1858 width=15 height=25 xoffset=1 yoffset=2 xadvance=16 page=0 chnl=0 char id=12623 x=2033 y=31 width=13 height=29 xoffset=13 yoffset=0 xadvance=32 page=0 chnl=0 char id=12624 x=2031 y=89 width=13 height=29 xoffset=11 yoffset=0 xadvance=32 page=0 chnl=0 @@ -4704,29 +4704,32 @@ char id=48697 x=1923 y=2003 width=29 height=29 xoffset=1 yoffset=0 x char id=48698 x=1952 y=2003 width=31 height=29 xoffset=1 yoffset=0 xadvance=32 page=0 chnl=0 char id=48699 x=1983 y=2003 width=29 height=29 xoffset=1 yoffset=0 xadvance=32 page=0 chnl=0 char id=48700 x=2012 y=2003 width=31 height=29 xoffset=1 yoffset=0 xadvance=32 page=0 chnl=0 -char id=47 x=2029 y=1885 width=15 height=23 xoffset=-1 yoffset=4 xadvance=16 page=1 chnl=0 -char id=49 x=2029 y=1334 width=15 height=23 xoffset=-1 yoffset=4 xadvance=16 page=1 chnl=0 -char id=60 x=2030 y=1653 width=15 height=23 xoffset=-1 yoffset=4 xadvance=16 page=1 chnl=0 -char id=62 x=2031 y=1856 width=15 height=23 xoffset=-1 yoffset=4 xadvance=16 page=1 chnl=0 -char id=65 x=2024 y=1450 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=1 chnl=0 -char id=66 x=2023 y=1566 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=1 chnl=0 -char id=67 x=2024 y=1769 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=1 chnl=0 -char id=68 x=2019 y=1827 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=1 chnl=0 +char id=47 x=2030 y=1653 width=15 height=23 xoffset=-1 yoffset=4 xadvance=16 page=1 chnl=0 +char id=49 x=2028 y=1160 width=15 height=23 xoffset=-1 yoffset=4 xadvance=16 page=1 chnl=0 +char id=60 x=2026 y=1508 width=15 height=23 xoffset=-1 yoffset=4 xadvance=16 page=1 chnl=0 +char id=62 x=2029 y=1624 width=15 height=23 xoffset=-1 yoffset=4 xadvance=16 page=1 chnl=0 +char id=65 x=2023 y=1218 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=1 chnl=0 +char id=66 x=2024 y=1450 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=1 chnl=0 +char id=67 x=2023 y=1566 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=1 chnl=0 +char id=68 x=2024 y=1769 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=1 chnl=0 +char id=69 x=2019 y=1827 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=1 chnl=0 char id=73 x=2032 y=1015 width=15 height=23 xoffset=-1 yoffset=4 xadvance=16 page=1 chnl=0 -char id=92 x=2029 y=1943 width=15 height=23 xoffset=-1 yoffset=4 xadvance=16 page=1 chnl=0 +char id=92 x=2031 y=1856 width=15 height=23 xoffset=-1 yoffset=4 xadvance=16 page=1 chnl=0 char id=105 x=2032 y=1015 width=15 height=23 xoffset=-1 yoffset=4 xadvance=16 page=1 chnl=0 -char id=123 x=2026 y=1508 width=15 height=23 xoffset=-1 yoffset=4 xadvance=16 page=1 chnl=0 -char id=125 x=2029 y=1624 width=15 height=23 xoffset=-1 yoffset=4 xadvance=16 page=1 chnl=0 +char id=123 x=2027 y=1305 width=15 height=23 xoffset=-1 yoffset=4 xadvance=16 page=1 chnl=0 +char id=125 x=2029 y=1334 width=15 height=23 xoffset=-1 yoffset=4 xadvance=16 page=1 chnl=0 char id=215 x=1131 y=2030 width=15 height=17 xoffset=1 yoffset=8 xadvance=16 page=1 chnl=0 char id=225 x=2029 y=58 width=15 height=25 xoffset=1 yoffset=2 xadvance=16 page=1 chnl=0 char id=226 x=2029 y=87 width=15 height=25 xoffset=1 yoffset=2 xadvance=16 page=1 chnl=0 -char id=227 x=2029 y=1972 width=17 height=23 xoffset=1 yoffset=4 xadvance=16 page=1 chnl=0 -char id=228 x=2029 y=2001 width=15 height=23 xoffset=1 yoffset=4 xadvance=16 page=1 chnl=0 +char id=227 x=2029 y=1885 width=17 height=23 xoffset=1 yoffset=4 xadvance=16 page=1 chnl=0 +char id=228 x=2029 y=1943 width=15 height=23 xoffset=1 yoffset=4 xadvance=16 page=1 chnl=0 char id=229 x=2029 y=145 width=15 height=25 xoffset=1 yoffset=2 xadvance=16 page=1 chnl=0 char id=230 x=1146 y=2030 width=19 height=17 xoffset=-1 yoffset=10 xadvance=16 page=1 chnl=0 +char id=231 x=2029 y=1972 width=15 height=23 xoffset=1 yoffset=10 xadvance=16 page=1 chnl=0 char id=232 x=2029 y=174 width=15 height=25 xoffset=1 yoffset=2 xadvance=16 page=1 chnl=0 char id=233 x=2029 y=203 width=15 height=25 xoffset=1 yoffset=2 xadvance=16 page=1 chnl=0 char id=234 x=2019 y=232 width=15 height=25 xoffset=1 yoffset=2 xadvance=16 page=1 chnl=0 +char id=235 x=2029 y=2001 width=15 height=23 xoffset=1 yoffset=4 xadvance=16 page=1 chnl=0 char id=236 x=2019 y=319 width=15 height=25 xoffset=1 yoffset=2 xadvance=16 page=1 chnl=0 char id=237 x=2029 y=406 width=15 height=25 xoffset=1 yoffset=2 xadvance=16 page=1 chnl=0 char id=238 x=2029 y=435 width=15 height=25 xoffset=1 yoffset=2 xadvance=16 page=1 chnl=0 @@ -4734,13 +4737,9 @@ char id=242 x=2029 y=464 width=15 height=25 xoffset=1 yoffset=2 x char id=243 x=2028 y=493 width=15 height=25 xoffset=1 yoffset=2 xadvance=16 page=1 chnl=0 char id=244 x=2019 y=580 width=15 height=25 xoffset=1 yoffset=2 xadvance=16 page=1 chnl=0 char id=247 x=1165 y=2030 width=15 height=17 xoffset=1 yoffset=8 xadvance=16 page=1 chnl=0 -char id=248 x=1180 y=2030 width=15 height=17 xoffset=1 yoffset=10 xadvance=16 page=1 chnl=0 -char id=249 x=2024 y=725 width=15 height=25 xoffset=1 yoffset=2 xadvance=16 page=1 chnl=0 -char id=250 x=2025 y=754 width=15 height=25 xoffset=1 yoffset=2 xadvance=16 page=1 chnl=0 -char id=251 x=2023 y=841 width=15 height=25 xoffset=1 yoffset=2 xadvance=16 page=1 chnl=0 -char id=1044 x=2020 y=1044 width=19 height=23 xoffset=-1 yoffset=6 xadvance=16 page=1 chnl=0 -char id=1062 x=2023 y=1218 width=17 height=23 xoffset=1 yoffset=6 xadvance=16 page=1 chnl=0 -char id=1065 x=2027 y=1305 width=17 height=23 xoffset=1 yoffset=6 xadvance=16 page=1 chnl=0 +char id=1044 x=2024 y=725 width=19 height=23 xoffset=-1 yoffset=6 xadvance=16 page=1 chnl=0 +char id=1062 x=2020 y=1044 width=17 height=23 xoffset=1 yoffset=6 xadvance=16 page=1 chnl=0 +char id=1065 x=2026 y=1131 width=17 height=23 xoffset=1 yoffset=6 xadvance=16 page=1 chnl=0 char id=1072 x=787 y=2030 width=15 height=17 xoffset=1 yoffset=10 xadvance=16 page=1 chnl=0 char id=1074 x=802 y=2030 width=15 height=17 xoffset=1 yoffset=10 xadvance=16 page=1 chnl=0 char id=1075 x=817 y=2030 width=15 height=17 xoffset=1 yoffset=10 xadvance=16 page=1 chnl=0 @@ -4754,20 +4753,23 @@ char id=1084 x=945 y=2030 width=17 height=17 xoffset=1 yoffset=10 x char id=1085 x=962 y=2030 width=15 height=17 xoffset=1 yoffset=10 xadvance=16 page=1 chnl=0 char id=1086 x=977 y=2030 width=15 height=17 xoffset=1 yoffset=10 xadvance=16 page=1 chnl=0 char id=1087 x=992 y=2030 width=15 height=17 xoffset=1 yoffset=10 xadvance=16 page=1 chnl=0 -char id=1088 x=2029 y=986 width=15 height=23 xoffset=1 yoffset=10 xadvance=16 page=1 chnl=0 +char id=1088 x=2029 y=928 width=15 height=23 xoffset=1 yoffset=10 xadvance=16 page=1 chnl=0 char id=1089 x=1007 y=2030 width=15 height=17 xoffset=1 yoffset=10 xadvance=16 page=1 chnl=0 char id=1090 x=1022 y=2030 width=15 height=17 xoffset=1 yoffset=10 xadvance=16 page=1 chnl=0 -char id=1091 x=2026 y=1131 width=17 height=23 xoffset=-1 yoffset=10 xadvance=16 page=1 chnl=0 -char id=1092 x=2028 y=1160 width=17 height=23 xoffset=1 yoffset=8 xadvance=16 page=1 chnl=0 +char id=1091 x=2029 y=957 width=17 height=23 xoffset=-1 yoffset=10 xadvance=16 page=1 chnl=0 +char id=1092 x=2029 y=986 width=17 height=23 xoffset=1 yoffset=8 xadvance=16 page=1 chnl=0 char id=1093 x=1037 y=2030 width=15 height=17 xoffset=1 yoffset=10 xadvance=16 page=1 chnl=0 char id=1095 x=1052 y=2030 width=15 height=17 xoffset=1 yoffset=10 xadvance=16 page=1 chnl=0 char id=1096 x=1067 y=2030 width=17 height=17 xoffset=1 yoffset=10 xadvance=16 page=1 chnl=0 +char id=1098 x=1197 y=2030 width=17 height=17 xoffset=-1 yoffset=10 xadvance=16 page=1 chnl=0 +char id=1099 x=1180 y=2030 width=17 height=17 xoffset=1 yoffset=10 xadvance=16 page=1 chnl=0 char id=1100 x=1084 y=2030 width=15 height=17 xoffset=1 yoffset=10 xadvance=16 page=1 chnl=0 +char id=1101 x=1214 y=2030 width=15 height=17 xoffset=1 yoffset=10 xadvance=16 page=1 chnl=0 char id=1102 x=1099 y=2030 width=17 height=17 xoffset=1 yoffset=10 xadvance=16 page=1 chnl=0 char id=1103 x=1116 y=2030 width=15 height=17 xoffset=1 yoffset=10 xadvance=16 page=1 chnl=0 char id=1108 x=847 y=2030 width=15 height=17 xoffset=1 yoffset=10 xadvance=16 page=1 chnl=0 -char id=1110 x=2029 y=928 width=15 height=23 xoffset=1 yoffset=4 xadvance=16 page=1 chnl=0 -char id=1111 x=2029 y=957 width=15 height=23 xoffset=1 yoffset=4 xadvance=16 page=1 chnl=0 +char id=1110 x=2025 y=754 width=15 height=23 xoffset=1 yoffset=4 xadvance=16 page=1 chnl=0 +char id=1111 x=2023 y=841 width=15 height=23 xoffset=1 yoffset=4 xadvance=16 page=1 chnl=0 char id=12593 x=0 y=2030 width=27 height=17 xoffset=3 yoffset=6 xadvance=32 page=1 chnl=0 char id=12594 x=27 y=2030 width=27 height=17 xoffset=3 yoffset=6 xadvance=32 page=1 chnl=0 char id=12595 x=486 y=2030 width=27 height=17 xoffset=3 yoffset=6 xadvance=32 page=1 chnl=0 @@ -9401,7 +9403,7 @@ char id=53338 x=1905 y=2001 width=31 height=29 xoffset=1 yoffset=0 x char id=53339 x=1936 y=2001 width=31 height=29 xoffset=1 yoffset=0 xadvance=32 page=1 chnl=0 char id=53340 x=1967 y=2001 width=31 height=29 xoffset=1 yoffset=0 xadvance=32 page=1 chnl=0 char id=53341 x=1998 y=2001 width=31 height=29 xoffset=1 yoffset=0 xadvance=32 page=1 chnl=0 -char id=0 x=125 y=864 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=0 x=127 y=864 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 char id=35 x=1503 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 char id=37 x=1457 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 char id=38 x=1526 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 @@ -9418,95 +9420,94 @@ char id=56 x=1342 y=839 width=23 height=23 xoffset=-1 yoffset=4 x char id=57 x=1365 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 char id=63 x=1411 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 char id=64 x=1434 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=69 x=2019 y=29 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=70 x=2020 y=377 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=71 x=2020 y=522 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=72 x=2023 y=638 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=74 x=744 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=75 x=767 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=76 x=790 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=77 x=813 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=78 x=836 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=79 x=859 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=80 x=882 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=82 x=905 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=83 x=928 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=84 x=951 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=85 x=974 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=86 x=997 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=87 x=1020 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=88 x=1043 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=89 x=1066 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=90 x=1089 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=97 x=1112 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=98 x=1135 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=99 x=1158 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=100 x=1181 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=101 x=2019 y=29 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=102 x=2020 y=377 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=103 x=2020 y=522 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=104 x=2023 y=638 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=106 x=744 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=107 x=767 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=108 x=790 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=109 x=813 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=110 x=836 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=111 x=859 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=112 x=882 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=114 x=905 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=115 x=928 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=116 x=951 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=117 x=974 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=118 x=997 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=119 x=1020 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=120 x=1043 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=121 x=1066 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=122 x=1089 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 -char id=198 x=1984 y=839 width=17 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=208 x=2001 y=839 width=17 height=21 xoffset=-1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=216 x=2018 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=222 x=0 y=864 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=223 x=15 y=864 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=231 x=2029 y=87 width=15 height=23 xoffset=1 yoffset=10 xadvance=16 page=2 chnl=0 -char id=235 x=2029 y=116 width=15 height=23 xoffset=1 yoffset=4 xadvance=16 page=2 chnl=0 -char id=239 x=2029 y=174 width=15 height=23 xoffset=1 yoffset=4 xadvance=16 page=2 chnl=0 -char id=240 x=30 y=864 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=241 x=2029 y=203 width=17 height=23 xoffset=1 yoffset=4 xadvance=16 page=2 chnl=0 -char id=245 x=2029 y=232 width=17 height=23 xoffset=1 yoffset=4 xadvance=16 page=2 chnl=0 -char id=246 x=2029 y=464 width=15 height=23 xoffset=1 yoffset=4 xadvance=16 page=2 chnl=0 -char id=252 x=2029 y=493 width=15 height=23 xoffset=1 yoffset=4 xadvance=16 page=2 chnl=0 -char id=1028 x=1647 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1040 x=2029 y=667 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1041 x=2026 y=696 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1042 x=1587 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1043 x=1602 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1045 x=1632 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1046 x=1662 y=839 width=19 height=21 xoffset=-1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1047 x=1681 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1048 x=1696 y=839 width=17 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1050 x=1713 y=839 width=17 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1051 x=1730 y=839 width=17 height=21 xoffset=-1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1052 x=1747 y=839 width=17 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1053 x=1764 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1054 x=1779 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1055 x=1794 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1056 x=1809 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1057 x=1824 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1058 x=1839 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1059 x=1854 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1060 x=1869 y=839 width=19 height=21 xoffset=-1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1061 x=1888 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1063 x=1903 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1064 x=1918 y=839 width=17 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1068 x=1935 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1070 x=1950 y=839 width=19 height=21 xoffset=-1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1071 x=1969 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1073 x=1572 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=1076 x=72 y=864 width=19 height=19 xoffset=-1 yoffset=10 xadvance=16 page=2 chnl=0 -char id=1094 x=91 y=864 width=17 height=19 xoffset=1 yoffset=10 xadvance=16 page=2 chnl=0 -char id=1097 x=108 y=864 width=17 height=19 xoffset=1 yoffset=10 xadvance=16 page=2 chnl=0 -char id=1169 x=1617 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 -char id=12622 x=45 y=864 width=27 height=19 xoffset=3 yoffset=4 xadvance=32 page=2 chnl=0 +char id=70 x=2019 y=29 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=71 x=2020 y=377 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=72 x=2020 y=522 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=74 x=2023 y=638 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=75 x=744 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=76 x=767 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=77 x=790 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=78 x=813 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=79 x=836 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=80 x=859 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=82 x=882 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=83 x=905 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=84 x=928 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=85 x=951 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=86 x=974 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=87 x=997 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=88 x=1020 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=89 x=1043 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=90 x=1066 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=97 x=1089 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=98 x=1112 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=99 x=1135 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=100 x=1158 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=101 x=1181 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=102 x=2019 y=29 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=103 x=2020 y=377 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=104 x=2020 y=522 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=106 x=2023 y=638 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=107 x=744 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=108 x=767 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=109 x=790 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=110 x=813 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=111 x=836 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=112 x=859 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=114 x=882 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=115 x=905 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=116 x=928 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=117 x=951 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=118 x=974 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=119 x=997 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=120 x=1020 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=121 x=1043 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=122 x=1066 y=839 width=23 height=23 xoffset=-1 yoffset=4 xadvance=24 page=2 chnl=0 +char id=198 x=1954 y=839 width=17 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=208 x=1971 y=839 width=17 height=21 xoffset=-1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=216 x=1988 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=222 x=2003 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=223 x=2018 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=239 x=2029 y=87 width=15 height=23 xoffset=1 yoffset=4 xadvance=16 page=2 chnl=0 +char id=240 x=0 y=864 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=241 x=2029 y=116 width=17 height=23 xoffset=1 yoffset=4 xadvance=16 page=2 chnl=0 +char id=245 x=2029 y=174 width=17 height=23 xoffset=1 yoffset=4 xadvance=16 page=2 chnl=0 +char id=246 x=2029 y=203 width=15 height=23 xoffset=1 yoffset=4 xadvance=16 page=2 chnl=0 +char id=1028 x=1617 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1040 x=2029 y=464 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1041 x=2029 y=493 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1042 x=2026 y=696 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1043 x=1572 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1045 x=1602 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1046 x=1632 y=839 width=19 height=21 xoffset=-1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1047 x=1651 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1048 x=1666 y=839 width=17 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1050 x=1683 y=839 width=17 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1051 x=1700 y=839 width=17 height=21 xoffset=-1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1052 x=1717 y=839 width=17 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1053 x=1734 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1054 x=1749 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1055 x=1764 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1056 x=1779 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1057 x=1794 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1058 x=1809 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1059 x=1824 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1060 x=1839 y=839 width=19 height=21 xoffset=-1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1061 x=1858 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1063 x=1873 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1064 x=1888 y=839 width=17 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1067 x=15 y=864 width=17 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1068 x=1905 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1069 x=32 y=864 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1070 x=1920 y=839 width=19 height=21 xoffset=-1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1071 x=1939 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1073 x=2029 y=667 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=1076 x=74 y=864 width=19 height=19 xoffset=-1 yoffset=10 xadvance=16 page=2 chnl=0 +char id=1094 x=93 y=864 width=17 height=19 xoffset=1 yoffset=10 xadvance=16 page=2 chnl=0 +char id=1097 x=110 y=864 width=17 height=19 xoffset=1 yoffset=10 xadvance=16 page=2 chnl=0 +char id=1105 x=2029 y=232 width=15 height=23 xoffset=1 yoffset=4 xadvance=16 page=2 chnl=0 +char id=1169 x=1587 y=839 width=15 height=21 xoffset=1 yoffset=6 xadvance=16 page=2 chnl=0 +char id=12622 x=47 y=864 width=27 height=19 xoffset=3 yoffset=4 xadvance=32 page=2 chnl=0 char id=12632 x=1797 y=783 width=33 height=29 xoffset=1 yoffset=0 xadvance=32 page=2 chnl=0 char id=12633 x=1830 y=783 width=31 height=29 xoffset=1 yoffset=0 xadvance=32 page=2 chnl=0 char id=12634 x=1861 y=783 width=29 height=29 xoffset=1 yoffset=0 xadvance=32 page=2 chnl=0 diff --git a/core/assets/ui/square1.png b/core/assets/ui/square1.png index f30da8e2b8..b208ef603a 100644 Binary files a/core/assets/ui/square1.png and b/core/assets/ui/square1.png differ diff --git a/core/assets/ui/square2.png b/core/assets/ui/square2.png index 81ce45b94a..ae060da171 100644 Binary files a/core/assets/ui/square2.png and b/core/assets/ui/square2.png differ diff --git a/core/assets/ui/square3.png b/core/assets/ui/square3.png index 1e1c5bc994..6309efd0cd 100644 Binary files a/core/assets/ui/square3.png and b/core/assets/ui/square3.png differ diff --git a/core/src/io/anuke/mindustry/Vars.java b/core/src/io/anuke/mindustry/Vars.java index a51431a503..968dfcc39b 100644 --- a/core/src/io/anuke/mindustry/Vars.java +++ b/core/src/io/anuke/mindustry/Vars.java @@ -78,8 +78,6 @@ public class Vars{ public static boolean mobile; public static boolean ios; public static boolean android; - //shorthand for whether or not this is running on GWT - public static boolean gwt; //main data directory public static FileHandle dataDirectory; //directory for user-created map data @@ -139,7 +137,7 @@ public class Vars{ } } - Arrays.sort(locales, (l1, l2) -> Platform.instance.getLocaleName(l1).compareTo(Platform.instance.getLocaleName(l2))); + Arrays.sort(locales, (l1, l2) -> l1.getDisplayName(l1).compareTo(l2.getDisplayName(l2))); Version.init(); content = new ContentLoader(); @@ -166,18 +164,15 @@ public class Vars{ }); } - threads = new ThreadHandler(Platform.instance.getThreadProvider()); + threads = new ThreadHandler(); mobile = Gdx.app.getType() == ApplicationType.Android || Gdx.app.getType() == ApplicationType.iOS || testMobile; ios = Gdx.app.getType() == ApplicationType.iOS; android = Gdx.app.getType() == ApplicationType.Android; - gwt = Gdx.app.getType() == ApplicationType.WebGL; - if(!gwt){ - dataDirectory = OS.getAppDataDirectory(appName); - customMapDirectory = dataDirectory.child("maps/"); - saveDirectory = dataDirectory.child("saves/"); - } + dataDirectory = OS.getAppDataDirectory(appName); + customMapDirectory = dataDirectory.child("maps/"); + saveDirectory = dataDirectory.child("saves/"); fontScale = Math.max(Unit.dp.scl(1f) / 2f, 0.5f); baseCameraScale = Math.round(Unit.dp.scl(4)); diff --git a/core/src/io/anuke/mindustry/ai/BlockIndexer.java b/core/src/io/anuke/mindustry/ai/BlockIndexer.java index 07ec34b2e9..7fdd7ada51 100644 --- a/core/src/io/anuke/mindustry/ai/BlockIndexer.java +++ b/core/src/io/anuke/mindustry/ai/BlockIndexer.java @@ -128,7 +128,11 @@ public class BlockIndexer{ for(int ty = ry * structQuadrantSize; ty < (ry + 1) * structQuadrantSize && ty < world.height(); ty++){ Tile other = world.tile(tx, ty); - if(other == null || other.entity == null || other.getTeam() != team || !pred.test(other) || !other.block().targetable) continue; + if(other == null) continue; + + other = other.target(); + + if(other.entity == null || other.getTeam() != team || !pred.test(other) || !other.block().targetable) continue; TileEntity e = other.entity; diff --git a/core/src/io/anuke/mindustry/content/Items.java b/core/src/io/anuke/mindustry/content/Items.java index 688cbcc9a6..a19a2a4048 100644 --- a/core/src/io/anuke/mindustry/content/Items.java +++ b/core/src/io/anuke/mindustry/content/Items.java @@ -7,7 +7,7 @@ import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemType; public class Items implements ContentList{ - public static Item stone, copper, lead, densealloy, coal, titanium, thorium, silicon, plastanium, phasematter, surgealloy, + public static Item stone, copper, lead, densealloy, coal, titanium, thorium, silicon, plastanium, phasefabric, surgealloy, biomatter, sand, blastCompound, pyratite; @Override @@ -71,9 +71,11 @@ public class Items implements ContentList{ cost = 1.6f; }}; - phasematter = new Item("phase-matter", Color.valueOf("f4ba6e")){{ + phasefabric = new Item("phase-fabric", Color.valueOf("f4ba6e")){{ type = ItemType.material; cost = 1.5f; + fluxiness = 0.9f; + radioactivity = 0.3f; }}; surgealloy = new Item("surge-alloy", Color.valueOf("f3e979")){{ @@ -82,7 +84,7 @@ public class Items implements ContentList{ biomatter = new Item("biomatter", Color.valueOf("648b55")){{ flammability = 0.4f; - fluxiness = 0.2f; + fluxiness = 0.3f; }}; sand = new Item("sand", Color.valueOf("e3d39e")){{ diff --git a/core/src/io/anuke/mindustry/content/Recipes.java b/core/src/io/anuke/mindustry/content/Recipes.java index 30b4eb6a3b..bdc35d2cbd 100644 --- a/core/src/io/anuke/mindustry/content/Recipes.java +++ b/core/src/io/anuke/mindustry/content/Recipes.java @@ -36,8 +36,8 @@ public class Recipes implements ContentList{ new Recipe(defense, DefenseBlocks.thoriumWall, new ItemStack(Items.thorium, 12)); new Recipe(defense, DefenseBlocks.thoriumWallLarge, new ItemStack(Items.thorium, 12 * 4)); - new Recipe(defense, DefenseBlocks.phaseWall, new ItemStack(Items.phasematter, 12)); - new Recipe(defense, DefenseBlocks.phaseWallLarge, new ItemStack(Items.phasematter, 12 * 4)); + new Recipe(defense, DefenseBlocks.phaseWall, new ItemStack(Items.phasefabric, 12)); + new Recipe(defense, DefenseBlocks.phaseWallLarge, new ItemStack(Items.phasefabric, 12 * 4)); new Recipe(defense, DefenseBlocks.surgeWall, new ItemStack(Items.surgealloy, 12)); new Recipe(defense, DefenseBlocks.surgeWallLarge, new ItemStack(Items.surgealloy, 12 * 4)); @@ -68,7 +68,7 @@ public class Recipes implements ContentList{ //DISTRIBUTION new Recipe(distribution, DistributionBlocks.conveyor, new ItemStack(Items.copper, 1)).setAlwaysUnlocked(true); new Recipe(distribution, DistributionBlocks.titaniumconveyor, new ItemStack(Items.copper, 2), new ItemStack(Items.titanium, 1)); - new Recipe(distribution, DistributionBlocks.phaseConveyor, new ItemStack(Items.phasematter, 10), new ItemStack(Items.silicon, 15), new ItemStack(Items.lead, 20), new ItemStack(Items.densealloy, 20)); + new Recipe(distribution, DistributionBlocks.phaseConveyor, new ItemStack(Items.phasefabric, 10), new ItemStack(Items.silicon, 15), new ItemStack(Items.lead, 20), new ItemStack(Items.densealloy, 20)); //starter lead transportation new Recipe(distribution, DistributionBlocks.junction, new ItemStack(Items.copper, 2)).setAlwaysUnlocked(true); @@ -125,11 +125,11 @@ public class Recipes implements ContentList{ //generators - solar new Recipe(power, PowerBlocks.solarPanel, new ItemStack(Items.lead, 20), new ItemStack(Items.silicon, 30)); - new Recipe(power, PowerBlocks.largeSolarPanel, new ItemStack(Items.lead, 200), new ItemStack(Items.silicon, 290), new ItemStack(Items.phasematter, 30)); + new Recipe(power, PowerBlocks.largeSolarPanel, new ItemStack(Items.lead, 200), new ItemStack(Items.silicon, 290), new ItemStack(Items.phasefabric, 30)); //generators - nuclear new Recipe(power, PowerBlocks.thoriumReactor, new ItemStack(Items.lead, 600), new ItemStack(Items.silicon, 400), new ItemStack(Items.densealloy, 300), new ItemStack(Items.thorium, 300)); - new Recipe(power, PowerBlocks.rtgGenerator, new ItemStack(Items.lead, 200), new ItemStack(Items.silicon, 150), new ItemStack(Items.phasematter, 50), new ItemStack(Items.plastanium, 150), new ItemStack(Items.thorium, 100)); + new Recipe(power, PowerBlocks.rtgGenerator, new ItemStack(Items.lead, 200), new ItemStack(Items.silicon, 150), new ItemStack(Items.phasefabric, 50), new ItemStack(Items.plastanium, 150), new ItemStack(Items.thorium, 100)); new Recipe(distribution, StorageBlocks.unloader, new ItemStack(Items.densealloy, 40), new ItemStack(Items.silicon, 50)); new Recipe(distribution, StorageBlocks.container, new ItemStack(Items.densealloy, 200)); @@ -138,7 +138,7 @@ public class Recipes implements ContentList{ /*new Recipe(distribution, StorageBlocks.core, new ItemStack(Items.copper, 2000), new ItemStack(Items.densealloy, 1500), new ItemStack(Items.silicon, 1500), new ItemStack(Items.thorium, 500), - new ItemStack(Items.surgealloy, 500), new ItemStack(Items.phasematter, 750) + new ItemStack(Items.surgealloy, 500), new ItemStack(Items.phasefabric, 750) );*/ //DRILLS, PRODUCERS @@ -156,7 +156,7 @@ public class Recipes implements ContentList{ //bodies new Recipe(units, UpgradeBlocks.dartPad, new ItemStack(Items.lead, 150), new ItemStack(Items.copper, 150), new ItemStack(Items.silicon, 200), new ItemStack(Items.titanium, 240)).setVisible(RecipeVisibility.desktopOnly); new Recipe(units, UpgradeBlocks.tridentPad, new ItemStack(Items.lead, 250), new ItemStack(Items.copper, 250), new ItemStack(Items.silicon, 250), new ItemStack(Items.titanium, 300), new ItemStack(Items.plastanium, 200)); - new Recipe(units, UpgradeBlocks.javelinPad, new ItemStack(Items.lead, 350), new ItemStack(Items.silicon, 450), new ItemStack(Items.titanium, 500), new ItemStack(Items.plastanium, 400), new ItemStack(Items.phasematter, 200)); + new Recipe(units, UpgradeBlocks.javelinPad, new ItemStack(Items.lead, 350), new ItemStack(Items.silicon, 450), new ItemStack(Items.titanium, 500), new ItemStack(Items.plastanium, 400), new ItemStack(Items.phasefabric, 200)); new Recipe(units, UpgradeBlocks.glaivePad, new ItemStack(Items.lead, 450), new ItemStack(Items.silicon, 650), new ItemStack(Items.titanium, 700), new ItemStack(Items.plastanium, 600), new ItemStack(Items.surgealloy, 200)); new Recipe(units, UpgradeBlocks.alphaPad, new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 100), new ItemStack(Items.copper, 150)).setVisible(RecipeVisibility.mobileOnly); @@ -170,7 +170,7 @@ public class Recipes implements ContentList{ new Recipe(units, UnitBlocks.daggerFactory, new ItemStack(Items.lead, 90), new ItemStack(Items.silicon, 70)); new Recipe(units, UnitBlocks.titanFactory, new ItemStack(Items.thorium, 90), new ItemStack(Items.lead, 140), new ItemStack(Items.silicon, 90)); - new Recipe(units, UnitBlocks.fortressFactory, new ItemStack(Items.thorium, 200), new ItemStack(Items.lead, 220), new ItemStack(Items.silicon, 150), new ItemStack(Items.surgealloy, 100), new ItemStack(Items.phasematter, 50)); + new Recipe(units, UnitBlocks.fortressFactory, new ItemStack(Items.thorium, 200), new ItemStack(Items.lead, 220), new ItemStack(Items.silicon, 150), new ItemStack(Items.surgealloy, 100), new ItemStack(Items.phasefabric, 50)); new Recipe(units, UnitBlocks.wraithFactory, new ItemStack(Items.titanium, 60), new ItemStack(Items.lead, 80), new ItemStack(Items.silicon, 90)); new Recipe(units, UnitBlocks.ghoulFactory, new ItemStack(Items.plastanium, 80), new ItemStack(Items.titanium, 100), new ItemStack(Items.lead, 130), new ItemStack(Items.silicon, 220)); @@ -182,7 +182,7 @@ public class Recipes implements ContentList{ //LIQUIDS new Recipe(liquid, LiquidBlocks.conduit, new ItemStack(Items.lead, 1)).setDependencies(CraftingBlocks.smelter); 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.phaseConduit, new ItemStack(Items.phasefabric, 10), new ItemStack(Items.silicon, 15), new ItemStack(Items.lead, 20), new ItemStack(Items.titanium, 20)); new Recipe(liquid, LiquidBlocks.liquidRouter, new ItemStack(Items.titanium, 4), new ItemStack(Items.lead, 4)); new Recipe(liquid, LiquidBlocks.liquidtank, new ItemStack(Items.titanium, 50), new ItemStack(Items.lead, 50)); diff --git a/core/src/io/anuke/mindustry/content/UnitTypes.java b/core/src/io/anuke/mindustry/content/UnitTypes.java index a06bc45885..33b4a7cacf 100644 --- a/core/src/io/anuke/mindustry/content/UnitTypes.java +++ b/core/src/io/anuke/mindustry/content/UnitTypes.java @@ -52,7 +52,6 @@ public class UnitTypes implements ContentList{ drag = 0.4f; hitsize = 8f; mass = 1.75f; - range = 40f; weapon = Weapons.chainBlaster; health = 130; }}; @@ -62,7 +61,6 @@ public class UnitTypes implements ContentList{ speed = 0.18f; drag = 0.4f; mass = 3.5f; - range = 10f; hitsize = 9f; rotatespeed = 0.1f; weapon = Weapons.flamethrower; @@ -75,7 +73,6 @@ public class UnitTypes implements ContentList{ drag = 0.4f; mass = 5f; hitsize = 10f; - range = 10f; rotatespeed = 0.06f; weaponOffsetX = 1; targetAir = false; @@ -111,6 +108,7 @@ public class UnitTypes implements ContentList{ speed = 0.14f; maxVelocity = 1.3f; drag = 0.01f; + range = 80f; isFlying = true; weapon = Weapons.laserBurster; }}; diff --git a/core/src/io/anuke/mindustry/content/blocks/Blocks.java b/core/src/io/anuke/mindustry/content/blocks/Blocks.java index d4fbd0d319..da606c6851 100644 --- a/core/src/io/anuke/mindustry/content/blocks/Blocks.java +++ b/core/src/io/anuke/mindustry/content/blocks/Blocks.java @@ -16,7 +16,7 @@ import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.util.Mathf; public class Blocks extends BlockList implements ContentList{ - public static Block air, blockpart, spawn, space, metalfloor, deepwater, water, lava, oil, stone, blackstone, dirt, sand, ice, snow, grass, shrub, rock, icerock, blackrock; + public static Block air, blockpart, spawn, space, metalfloor, deepwater, water, lava, tar, stone, blackstone, dirt, sand, ice, snow, grass, shrub, rock, icerock, blackrock; @Override @@ -100,11 +100,11 @@ public class Blocks extends BlockList implements ContentList{ minimapColor = Color.valueOf("ed5334"); }}; - oil = new Floor("oil"){{ + tar = new Floor("tar"){{ liquidColor = Color.valueOf("292929"); status = StatusEffects.tarred; statusIntensity = 1f; - speedMultiplier = 0.2f; + speedMultiplier = 0.19f; variants = 0; liquidDrop = Liquids.oil; isLiquid = true; diff --git a/core/src/io/anuke/mindustry/content/blocks/CraftingBlocks.java b/core/src/io/anuke/mindustry/content/blocks/CraftingBlocks.java index f5ab2fa73c..aed1ecf0a0 100644 --- a/core/src/io/anuke/mindustry/content/blocks/CraftingBlocks.java +++ b/core/src/io/anuke/mindustry/content/blocks/CraftingBlocks.java @@ -75,7 +75,7 @@ public class CraftingBlocks extends BlockList implements ContentList{ phaseWeaver = new PhaseWeaver("phase-weaver"){{ craftEffect = BlockFx.smeltsmoke; - result = Items.phasematter; + result = Items.phasefabric; craftTime = 120f; powerCapacity = 50f; size = 2; diff --git a/core/src/io/anuke/mindustry/content/blocks/DebugBlocks.java b/core/src/io/anuke/mindustry/content/blocks/DebugBlocks.java index bc6c5e37cc..db663a422a 100644 --- a/core/src/io/anuke/mindustry/content/blocks/DebugBlocks.java +++ b/core/src/io/anuke/mindustry/content/blocks/DebugBlocks.java @@ -22,8 +22,8 @@ import io.anuke.ucore.scene.ui.ButtonGroup; import io.anuke.ucore.scene.ui.ImageButton; import io.anuke.ucore.scene.ui.layout.Table; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import static io.anuke.mindustry.Vars.*; @@ -182,12 +182,12 @@ public class DebugBlocks extends BlockList implements ContentList{ public Liquid source = Liquids.water; @Override - public void write(DataOutputStream stream) throws IOException{ + public void writeConfig(DataOutput stream) throws IOException{ stream.writeByte(source.id); } @Override - public void read(DataInputStream stream) throws IOException{ + public void readConfig(DataInput stream) throws IOException{ source = content.liquid(stream.readByte()); } } diff --git a/core/src/io/anuke/mindustry/content/blocks/DefenseBlocks.java b/core/src/io/anuke/mindustry/content/blocks/DefenseBlocks.java index 687b2c1aea..6a8b586c7b 100644 --- a/core/src/io/anuke/mindustry/content/blocks/DefenseBlocks.java +++ b/core/src/io/anuke/mindustry/content/blocks/DefenseBlocks.java @@ -73,19 +73,19 @@ public class DefenseBlocks extends BlockList implements ContentList{ mendProjector = new MendProjector("mend-projector"){{ consumes.power(0.2f); size = 2; - consumes.item(Items.phasematter).optional(true); + consumes.item(Items.phasefabric).optional(true); }}; overdriveProjector = new OverdriveProjector("overdrive-projector"){{ consumes.power(0.35f); size = 2; - consumes.item(Items.phasematter).optional(true); + consumes.item(Items.phasefabric).optional(true); }}; forceProjector = new ForceProjector("force-projector"){{ consumes.power(0.2f); size = 3; - consumes.item(Items.phasematter).optional(true); + consumes.item(Items.phasefabric).optional(true); }}; shockMine = new ShockMine("shock-mine"){{ diff --git a/core/src/io/anuke/mindustry/content/blocks/ProductionBlocks.java b/core/src/io/anuke/mindustry/content/blocks/ProductionBlocks.java index 740f841e0a..8bd571620b 100644 --- a/core/src/io/anuke/mindustry/content/blocks/ProductionBlocks.java +++ b/core/src/io/anuke/mindustry/content/blocks/ProductionBlocks.java @@ -38,7 +38,7 @@ public class ProductionBlocks extends BlockList implements ContentList{ updateEffect = BlockFx.pulverizeMedium; drillEffect = BlockFx.mineBig; - consumes.power(0.16f); + consumes.power(0.11f); }}; blastDrill = new Drill("blast-drill"){{ @@ -80,7 +80,7 @@ public class ProductionBlocks extends BlockList implements ContentList{ liquidCapacity = 30f; rotateSpeed = 1.4f; - consumes.power(0.1f); + consumes.power(0.09f); }}; oilExtractor = new Fracker("oil-extractor"){{ diff --git a/core/src/io/anuke/mindustry/core/ContentLoader.java b/core/src/io/anuke/mindustry/core/ContentLoader.java index 030b22f349..9f32f06c27 100644 --- a/core/src/io/anuke/mindustry/core/ContentLoader.java +++ b/core/src/io/anuke/mindustry/core/ContentLoader.java @@ -35,6 +35,7 @@ import io.anuke.ucore.util.ThreadArray; @SuppressWarnings("unchecked") public class ContentLoader{ private boolean loaded = false; + private boolean verbose = true; private ObjectMap[] contentNameMap = new ObjectMap[ContentType.values().length]; private Array[] contentMap = new Array[ContentType.values().length]; @@ -152,12 +153,14 @@ public class ContentLoader{ throw new ImpendingDoomException("THE TIME HAS COME. More than 256 blocks have been created."); } - Log.info("--- CONTENT INFO ---"); - for(int k = 0; k < contentMap.length; k ++){ - Log.info("[{0}]: loaded {1}", ContentType.values()[k].name(), contentMap[k].size); + if(verbose){ + Log.info("--- CONTENT INFO ---"); + for(int k = 0; k < contentMap.length; k++){ + Log.info("[{0}]: loaded {1}", ContentType.values()[k].name(), contentMap[k].size); + } + Log.info("Total content loaded: {0}", total); + Log.info("-------------------"); } - Log.info("Total content loaded: {0}", total); - Log.info("-------------------"); loaded = true; } @@ -175,6 +178,10 @@ public class ContentLoader{ initialization.add(callable); } + public void verbose(boolean verbose){ + this.verbose = verbose; + } + public void dispose(){ //clear all content, currently not needed } @@ -203,7 +210,7 @@ public class ContentLoader{ if(id < 0) id += 256; if(temporaryMapper != null && temporaryMapper[type.ordinal()] != null && temporaryMapper[type.ordinal()].length != 0){ - if(temporaryMapper[type.ordinal()][id] == null){ + if(temporaryMapper[type.ordinal()].length <= id || temporaryMapper[type.ordinal()][id] == null){ return getByID(type, 0); //default value is always ID 0 } return (T)temporaryMapper[type.ordinal()][id]; diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index dca67baded..a126e0c699 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -26,10 +26,7 @@ import io.anuke.mindustry.ui.dialogs.FloatingDialog; import io.anuke.ucore.core.*; import io.anuke.ucore.entities.EntityQuery; import io.anuke.ucore.modules.Module; -import io.anuke.ucore.util.Atlas; -import io.anuke.ucore.util.Bundles; -import io.anuke.ucore.util.Strings; -import io.anuke.ucore.util.Timer; +import io.anuke.ucore.util.*; import java.io.IOException; @@ -60,7 +57,7 @@ public class Control extends Module{ saves = new Saves(); unlocks = new Unlocks(); - Inputs.useControllers(!gwt); + Inputs.useControllers(true); Gdx.input.setCatchBackKey(true); @@ -397,7 +394,7 @@ public class Control extends Module{ } }else{ - if(!state.is(State.paused) || Net.active()){ + if(!state.isPaused()){ Timers.update(); } } diff --git a/core/src/io/anuke/mindustry/core/Logic.java b/core/src/io/anuke/mindustry/core/Logic.java index ee9433d7d0..fb1feb196d 100644 --- a/core/src/io/anuke/mindustry/core/Logic.java +++ b/core/src/io/anuke/mindustry/core/Logic.java @@ -10,6 +10,7 @@ import io.anuke.mindustry.game.EventType.*; import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Teams; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.world.Tile; @@ -21,7 +22,6 @@ import io.anuke.ucore.entities.EntityQuery; import io.anuke.ucore.modules.Module; import static io.anuke.mindustry.Vars.*; -import io.anuke.mindustry.gen.Call; /** * Logic module. @@ -159,16 +159,13 @@ public class Logic extends Module{ if(!state.is(State.menu)){ - if(!state.is(State.paused) || Net.active()){ - Timers.update(); - } - if(!Net.client() && !world.isInvalidMap()){ updateSectors(); checkGameOver(); } - if(!state.is(State.paused) || Net.active()){ + if(!state.isPaused()){ + Timers.update(); if(!state.mode.disableWaveTimer && !state.mode.disableWaves){ state.wavetime -= Timers.delta(); diff --git a/core/src/io/anuke/mindustry/core/NetClient.java b/core/src/io/anuke/mindustry/core/NetClient.java index ba61968ce9..baebe42cc8 100644 --- a/core/src/io/anuke/mindustry/core/NetClient.java +++ b/core/src/io/anuke/mindustry/core/NetClient.java @@ -21,7 +21,6 @@ import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net.SendMode; import io.anuke.mindustry.net.NetworkIO; import io.anuke.mindustry.net.Packets.*; -import io.anuke.mindustry.net.TraceInfo; import io.anuke.mindustry.net.ValidateException; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.modules.ItemModule; @@ -207,12 +206,6 @@ public class NetClient extends Module{ players[0].y = y; } - @Remote(variants = Variant.one) - public static void onTraceInfo(TraceInfo info){ - Player player = playerGroup.getByID(info.playerid); - ui.traces.show(player, info); - } - @Remote public static void onPlayerDisconnect(int playerid){ playerGroup.removeByID(playerid); diff --git a/core/src/io/anuke/mindustry/core/NetServer.java b/core/src/io/anuke/mindustry/core/NetServer.java index 8223661499..6fefd332ba 100644 --- a/core/src/io/anuke/mindustry/core/NetServer.java +++ b/core/src/io/anuke/mindustry/core/NetServer.java @@ -106,11 +106,9 @@ public class NetServer extends Module{ connection.hasBegunConnecting = true; - TraceInfo trace = admins.getTraceByID(uuid); PlayerInfo info = admins.getInfo(uuid); - trace.uuid = uuid; - trace.ip = connection.address; - trace.android = packet.mobile; + + connection.mobile = packet.mobile; if(admins.isIDBanned(uuid)){ kick(id, KickReason.banned); @@ -150,7 +148,7 @@ public class NetServer extends Module{ return; } - Log.info("Recieved connect packet for player '{0}' / UUID {1} / IP {2}", packet.name, uuid, trace.ip); + Log.info("Recieved connect packet for player '{0}' / UUID {1} / IP {2}", packet.name, uuid, connection.address); String ip = Net.getConnection(id).address; @@ -162,7 +160,7 @@ public class NetServer extends Module{ } if(packet.version == -1){ - trace.modclient = true; + connection.modclient = true; } Player player = new Player(); @@ -207,8 +205,6 @@ public class NetServer extends Module{ connections.put(id, player); - trace.playerid = player.id; - sendWorldData(player, id); Platform.instance.updateRPC(); @@ -327,9 +323,9 @@ public class NetServer extends Module{ player.getPlaceQueue().clear(); for(BuildRequest req : requests){ //auto-skip done requests - if(req.remove && world.tile(req.x, req.y).block() == Blocks.air){ + if(req.breaking && world.tile(req.x, req.y).block() == Blocks.air){ continue; - }else if(!req.remove && world.tile(req.x, req.y).block() == req.recipe.result && (!req.recipe.result.rotate || world.tile(req.x, req.y).getRotation() == req.rotation)){ + }else if(!req.breaking && world.tile(req.x, req.y).block() == req.recipe.result && (!req.recipe.result.rotate || world.tile(req.x, req.y).getRotation() == req.rotation)){ continue; } player.getPlaceQueue().addLast(req); @@ -395,11 +391,11 @@ public class NetServer extends Module{ netServer.kick(other.con.id, KickReason.kick); Log.info("&lc{0} has kicked {1}.", player.name, other.name); }else if(action == AdminAction.trace){ - //TODO + //TODO implement if(player.con != null){ - Call.onTraceInfo(player.con.id, netServer.admins.getTraceByID(other.uuid)); + //Call.onTraceInfo(player.con.id, other.con.trace); }else{ - NetClient.onTraceInfo(netServer.admins.getTraceByID(other.uuid)); + //NetClient.onTraceInfo(other.con.trace); } Log.info("&lc{0} has requested trace info of {1}.", player.name, other.name); } @@ -424,7 +420,6 @@ public class NetServer extends Module{ if(!headless && !closing && Net.server() && state.is(State.menu)){ closing = true; - reset(); threads.runGraphics(() -> ui.loadfrag.show("$text.server.closing")); Timers.runTask(5f, () -> { Net.closeServer(); @@ -438,10 +433,6 @@ public class NetServer extends Module{ } } - public void reset(){ - admins.clearTraces(); - } - public void kickAll(KickReason reason){ for(NetConnection con : Net.getConnections()){ kick(con.id, reason); diff --git a/core/src/io/anuke/mindustry/core/Platform.java b/core/src/io/anuke/mindustry/core/Platform.java index 16291b2bfa..9f47a307c2 100644 --- a/core/src/io/anuke/mindustry/core/Platform.java +++ b/core/src/io/anuke/mindustry/core/Platform.java @@ -2,13 +2,11 @@ package io.anuke.mindustry.core; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.utils.Base64Coder; -import io.anuke.mindustry.core.ThreadHandler.ThreadProvider; import io.anuke.ucore.core.Settings; import io.anuke.ucore.function.Consumer; import io.anuke.ucore.scene.ui.TextField; import java.util.Date; -import java.util.Locale; import java.util.Random; public abstract class Platform { @@ -36,10 +34,6 @@ public abstract class Platform { public boolean canDonate(){ return false; } - /**Return the localized name for the locale. This is basically a workaround for GWT not supporting getName().*/ - public String getLocaleName(Locale locale){ - return locale.toString(); - } /**Must be a base64 string 8 bytes in length.*/ public String getUUID(){ String uuid = Settings.getString("uuid", ""); @@ -55,8 +49,6 @@ public abstract class Platform { } /**Only used for iOS or android: open the share menu for a map or save.*/ public void shareFile(FileHandle file){} - /**Download a file. Only used on GWT backend.*/ - public void downloadFile(String name, byte[] bytes){} /**Show a file chooser. Desktop only. * @@ -67,17 +59,6 @@ public abstract class Platform { * @param filetype File extension to filter */ public void showFileChooser(String text, String content, Consumer cons, boolean open, String filetype){} - /**Use the default thread provider from the kryonet module for this.*/ - public ThreadProvider getThreadProvider(){ - return new ThreadProvider() { - @Override public boolean isOnThread() {return true;} - @Override public void sleep(long ms) {} - @Override public void start(Runnable run) {} - @Override public void stop() {} - @Override public void notify(Object object) {} - @Override public void wait(Object object) {} - }; - } /**Forces the app into landscape mode. Currently Android only.*/ public void beginForceLandscape(){} diff --git a/core/src/io/anuke/mindustry/core/ThreadHandler.java b/core/src/io/anuke/mindustry/core/ThreadHandler.java index 66522df150..f439a6670e 100644 --- a/core/src/io/anuke/mindustry/core/ThreadHandler.java +++ b/core/src/io/anuke/mindustry/core/ThreadHandler.java @@ -6,13 +6,15 @@ import com.badlogic.gdx.utils.TimeUtils; import io.anuke.ucore.core.Settings; import io.anuke.ucore.core.Timers; import io.anuke.ucore.util.Log; +import io.anuke.ucore.util.Threads; +import io.anuke.ucore.util.Threads.ThreadInfoProvider; import static io.anuke.mindustry.Vars.control; import static io.anuke.mindustry.Vars.logic; -public class ThreadHandler{ +public class ThreadHandler implements ThreadInfoProvider{ private final Queue toRun = new Queue<>(); - private final ThreadProvider impl; + private Thread thread, graphicsThread; private final Object updateLock = new Object(); private float delta = 1f; private float smoothDelta = 1f; @@ -22,11 +24,12 @@ public class ThreadHandler{ private boolean rendered = true; private long lastFrameTime; - public ThreadHandler(ThreadProvider impl){ - this.impl = impl; + public ThreadHandler(){ + Threads.setThreadInfoProvider(this); + graphicsThread = Thread.currentThread(); Timers.setDeltaProvider(() -> { - float result = impl.isOnThread() ? delta : Gdx.graphics.getDeltaTime() * 60f; + float result = isOnThread() ? delta : Gdx.graphics.getDeltaTime() * 60f; return Math.min(Float.isNaN(result) ? 1f : result, 15f); }); } @@ -86,7 +89,7 @@ public class ThreadHandler{ long elapsed = TimeUtils.timeSinceMillis(lastFrameTime); if(elapsed < target){ try{ - impl.sleep(target - elapsed); + Thread.sleep(target - elapsed); }catch(InterruptedException e){ e.printStackTrace(); } @@ -99,7 +102,7 @@ public class ThreadHandler{ synchronized(updateLock){ rendered = true; - impl.notify(updateLock); + updateLock.notify(); } } @@ -111,12 +114,25 @@ public class ThreadHandler{ if(enabled){ logic.doUpdate = false; Timers.runTask(2f, () -> { - impl.start(this::runLogic); + if(thread != null){ + thread.interrupt(); + thread = null; + } + + thread = new Thread(this::runLogic); + thread.setDaemon(true); + thread.setName("Update Thread"); + thread.start(); + Log.info("Starting logic thread."); + this.enabled = true; }); }else{ this.enabled = false; - impl.stop(); + if(thread != null){ + thread.interrupt(); + thread = null; + } Timers.runTask(2f, () -> { logic.doUpdate = true; }); @@ -128,7 +144,17 @@ public class ThreadHandler{ } public boolean isOnThread(){ - return impl.isOnThread(); + return Thread.currentThread() == thread; + } + + @Override + public boolean isOnLogicThread() { + return !enabled || Thread.currentThread() == thread; + } + + @Override + public boolean isOnGraphicsThread() { + return !enabled || Thread.currentThread() == graphicsThread; } private void runLogic(){ @@ -157,12 +183,12 @@ public class ThreadHandler{ long target = (long) ((1000) / 60f); if(elapsed < target){ - impl.sleep(target - elapsed); + Thread.sleep(target - elapsed); } synchronized(updateLock){ while(!rendered){ - impl.wait(updateLock); + updateLock.wait(); } rendered = false; } @@ -184,18 +210,4 @@ public class ThreadHandler{ control.setError(ex); } } - - public interface ThreadProvider{ - boolean isOnThread(); - - void sleep(long ms) throws InterruptedException; - - void start(Runnable run); - - void stop(); - - void wait(Object object) throws InterruptedException; - - void notify(Object object); - } } diff --git a/core/src/io/anuke/mindustry/core/UI.java b/core/src/io/anuke/mindustry/core/UI.java index 750f34b0e4..e62742648b 100644 --- a/core/src/io/anuke/mindustry/core/UI.java +++ b/core/src/io/anuke/mindustry/core/UI.java @@ -3,6 +3,7 @@ package io.anuke.mindustry.core; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input.Keys; import com.badlogic.gdx.graphics.Colors; +import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.math.Interpolation; import com.badlogic.gdx.utils.Align; import io.anuke.mindustry.Vars; @@ -25,7 +26,6 @@ import io.anuke.ucore.scene.ui.TextField.TextFieldFilter; import io.anuke.ucore.scene.ui.TooltipManager; import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.scene.ui.layout.Unit; -import io.anuke.ucore.util.Structs; import static io.anuke.mindustry.Vars.*; import static io.anuke.ucore.scene.actions.Actions.*; @@ -108,12 +108,11 @@ public class UI extends SceneModule{ @Override protected void loadSkin(){ skin = new Skin(Gdx.files.internal("ui/uiskin.json"), Core.atlas); - Structs.each(font -> { + + for(BitmapFont font : skin.getAll(BitmapFont.class).values()){ font.setUseIntegerPositions(false); font.getData().setScale(Vars.fontScale); - font.getData().down += Unit.dp.scl(3f); - font.getData().lineHeight -= Unit.dp.scl(3f); - }, skin.font(), skin.getFont("default-font-chat"), skin.getFont("trad-chinese"), skin.getFont("simp-chinese")); + } } @Override diff --git a/core/src/io/anuke/mindustry/core/World.java b/core/src/io/anuke/mindustry/core/World.java index e337a94d1f..50469edacf 100644 --- a/core/src/io/anuke/mindustry/core/World.java +++ b/core/src/io/anuke/mindustry/core/World.java @@ -243,7 +243,7 @@ public class World extends Module{ EntityQuery.resizeTree(0, 0, width * tilesize, height * tilesize); try{ - generator.loadTileData(tiles, MapIO.readTileData(map, true), map.meta.hasOreGen(), 0); + generator.loadTileData(tiles, MapIO.readTileData(map, true), map.meta.hasOreGen(), Mathf.random(99999)); } catch(Exception e){ Log.err(e); if(!headless){ @@ -257,6 +257,8 @@ public class World extends Module{ endMapLoad(); + invalidMap = false; + if(!headless){ if(state.teams.get(players[0].getTeam()).cores.size == 0){ ui.showError("$text.map.nospawn"); diff --git a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java index 22a885c7fe..f54039e77f 100644 --- a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java @@ -38,7 +38,6 @@ import io.anuke.ucore.util.Log; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Strings; -import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; @@ -113,73 +112,40 @@ public class MapEditorDialog extends Dialog implements Disposable{ }, true, mapExtension); }, "$text.editor.importimage", "$text.editor.importimage.description", "icon-file-image", (Runnable)() -> { - if(gwt){ - ui.showError("$text.web.unsupported"); - }else { - Platform.instance.showFileChooser("$text.loadimage", "Image Files", file -> { - ui.loadGraphics(() -> { - try{ - MapTileData data = MapIO.readLegacyPixmap(new Pixmap(file)); + Platform.instance.showFileChooser("$text.loadimage", "Image Files", file -> { + ui.loadGraphics(() -> { + try{ + MapTileData data = MapIO.readLegacyPixmap(new Pixmap(file)); - editor.beginEdit(data, editor.getTags(), false); - view.clearStack(); - }catch (Exception e){ - ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false))); - Log.err(e); - } - }); - }, true, "png"); - } + editor.beginEdit(data, editor.getTags(), false); + view.clearStack(); + }catch (Exception e){ + ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false))); + Log.err(e); + } + }); + }, true, "png"); })); t.addImageTextButton("$text.editor.export", "icon-save-map", isize, () -> createDialog("$text.editor.export", "$text.editor.exportfile", "$text.editor.exportfile.description", "icon-file", (Runnable) () -> { - if(!gwt){ - Platform.instance.showFileChooser("$text.saveimage", "Map Files", file -> { - file = file.parent().child(file.nameWithoutExtension() + "." + mapExtension); - FileHandle result = file; - ui.loadGraphics(() -> { + Platform.instance.showFileChooser("$text.saveimage", "Map Files", file -> { + file = file.parent().child(file.nameWithoutExtension() + "." + mapExtension); + FileHandle result = file; + ui.loadGraphics(() -> { - try{ - if(!editor.getTags().containsKey("name")){ - editor.getTags().put("name", result.nameWithoutExtension()); - } - MapIO.writeMap(result.write(false), editor.getTags(), editor.getMap()); - }catch(Exception e){ - ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false))); - Log.err(e); + try{ + if(!editor.getTags().containsKey("name")){ + editor.getTags().put("name", result.nameWithoutExtension()); } - }); - }, false, mapExtension); - }else{ - try{ - ByteArrayOutputStream ba = new ByteArrayOutputStream(); - MapIO.writeMap(ba, editor.getTags(), editor.getMap()); - Platform.instance.downloadFile(editor.getTags().get("name", "unknown") + "." + mapExtension, ba.toByteArray()); - }catch(IOException e){ - ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false))); - Log.err(e); - } - } - }/*, - "$text.editor.exportimage", "$text.editor.exportimage.description", "icon-file-image", (Listenable)() -> { - if(gwt){ - ui.showError("$text.web.unsupported"); - }else{ - Platform.instance.showFileChooser("$text.saveimage", "Image Files", file -> { - file = file.parent().child(file.nameWithoutExtension() + ".png"); - FileHandle result = file; - ui.loadGraphics(() -> { - try{ - Pixmaps.write(MapIO.generatePixmap(editor.getMap()), result); - }catch (Exception e){ - ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false))); - Log.err(e); - } - }); - }, false, "png"); - } - }*/)); + MapIO.writeMap(result.write(false), editor.getTags(), editor.getMap()); + }catch(Exception e){ + ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false))); + Log.err(e); + } + }); + }, false, mapExtension); + })); t.row(); @@ -475,6 +441,14 @@ public class MapEditorDialog extends Dialog implements Disposable{ mid.table("button", t -> { Slider slider = new Slider(0, MapEditor.brushSizes.length - 1, 1, false); slider.moved(f -> editor.setBrushSize(MapEditor.brushSizes[(int) (float) f])); + slider.update(() -> { + for(int j = 0; j < MapEditor.brushSizes.length; j++){ + if(editor.getBrushSize() == j){ + slider.setValue(j); + return; + } + } + }); t.top(); t.add("$text.editor.brush"); diff --git a/core/src/io/anuke/mindustry/editor/MapLoadDialog.java b/core/src/io/anuke/mindustry/editor/MapLoadDialog.java index e557a1fe10..2c44d6befe 100644 --- a/core/src/io/anuke/mindustry/editor/MapLoadDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapLoadDialog.java @@ -1,5 +1,6 @@ package io.anuke.mindustry.editor; +import com.badlogic.gdx.utils.Scaling; import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.ui.BorderImage; import io.anuke.mindustry.ui.dialogs.FloatingDialog; @@ -58,7 +59,7 @@ public class MapLoadDialog extends FloatingDialog{ for(Map map : world.maps.all()){ TextButton button = new TextButton(map.getDisplayName(), "toggle"); - button.add(new BorderImage(map.texture, 2f)).size(16 * 4f); + button.add(new BorderImage(map.texture, 2f).setScaling(Scaling.fit)).size(16 * 4f); button.getCells().reverse(); button.clicked(() -> selected = map); button.getLabelCell().grow().left().padLeft(5f); diff --git a/core/src/io/anuke/mindustry/editor/MapView.java b/core/src/io/anuke/mindustry/editor/MapView.java index e50885787a..7748c46ff1 100644 --- a/core/src/io/anuke/mindustry/editor/MapView.java +++ b/core/src/io/anuke/mindustry/editor/MapView.java @@ -295,7 +295,7 @@ public class MapView extends Element implements GestureListener{ } //todo is it really math.max? - float scaling = zoom * Math.min(width, height) / Math.max(editor.getMap().width(), editor.getMap().height()); + float scaling = zoom * Math.min(width, height) / editor.getMap().width(); Draw.color(Palette.accent); Lines.stroke(Unit.dp.scl(1f * zoom)); diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/Player.java index dd3e18ce1a..c8f595fb08 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/Player.java @@ -420,7 +420,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra for(BuildRequest request : getPlaceQueue()){ if(getCurrentRequest() == request) continue; - if(request.remove){ + if(request.breaking){ Block block = world.tile(request.x, request.y).target().block(); //draw removal request diff --git a/core/src/io/anuke/mindustry/entities/TileEntity.java b/core/src/io/anuke/mindustry/entities/TileEntity.java index ea3af6d622..cec34d962d 100644 --- a/core/src/io/anuke/mindustry/entities/TileEntity.java +++ b/core/src/io/anuke/mindustry/entities/TileEntity.java @@ -28,8 +28,8 @@ import io.anuke.ucore.entities.trait.HealthTrait; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Timer; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import static io.anuke.mindustry.Vars.tileGroup; @@ -120,11 +120,13 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ return dead || tile.entity != this; } - public void write(DataOutputStream stream) throws IOException{ - } + public void write(DataOutput stream) throws IOException{} - public void read(DataInputStream stream) throws IOException{ - } + public void writeConfig(DataOutput stream) throws IOException{} + + public void read(DataInput stream) throws IOException{} + + public void readConfig(DataInput stream) throws IOException{} public boolean collide(Bullet other){ return true; diff --git a/core/src/io/anuke/mindustry/entities/Units.java b/core/src/io/anuke/mindustry/entities/Units.java index a67974fce0..f8e271fc5b 100644 --- a/core/src/io/anuke/mindustry/entities/Units.java +++ b/core/src/io/anuke/mindustry/entities/Units.java @@ -41,16 +41,12 @@ public class Units{ return target == null || (range != Float.MAX_VALUE && target.distanceTo(x, y) > range) || target.getTeam() == team || !target.isValid(); } - /** - * See {@link #invalidateTarget(TargetTrait, Team, float, float, float)} - */ + /**See {@link #invalidateTarget(TargetTrait, Team, float, float, float)}*/ public static boolean invalidateTarget(TargetTrait target, Team team, float x, float y){ return invalidateTarget(target, team, x, y, Float.MAX_VALUE); } - /** - * See {@link #invalidateTarget(TargetTrait, Team, float, float, float)} - */ + /**See {@link #invalidateTarget(TargetTrait, Team, float, float, float)}*/ public static boolean invalidateTarget(TargetTrait target, Unit targeter){ return invalidateTarget(target, targeter.team, targeter.x, targeter.y, targeter.getWeapon().getAmmo().getRange()); } @@ -129,16 +125,12 @@ public class Units{ return value[0]; } - /** - * Returns the neareset ally tile in a range. - */ + /**Returns the neareset ally tile in a range.*/ public static TileEntity findAllyTile(Team team, float x, float y, float range, Predicate pred){ return world.indexer.findTile(team, x, y, range, pred); } - /** - * Returns the neareset enemy tile in a range. - */ + /**Returns the neareset enemy tile in a range.*/ public static TileEntity findEnemyTile(Team team, float x, float y, float range, Predicate pred){ for(Team enemy : state.teams.enemiesOf(team)){ TileEntity entity = world.indexer.findTile(enemy, x, y, range, pred); @@ -149,9 +141,7 @@ public class Units{ return null; } - /** - * Iterates over all units on all teams, including players. - */ + /**Iterates over all units on all teams, including players.*/ public static void allUnits(Consumer cons){ //check all unit groups first for(EntityGroup group : unitGroups){ @@ -183,9 +173,7 @@ public class Units{ } } - /** - * Returns the closest enemy of this team. Filter by predicate. - */ + /**Returns the closest enemy of this team. Filter by predicate.*/ public static Unit getClosestEnemy(Team team, float x, float y, float range, Predicate predicate){ result = null; cdist = 0f; @@ -208,9 +196,7 @@ public class Units{ return result; } - /** - * Returns the closest ally of this team. Filter by predicate. - */ + /**Returns the closest ally of this team. Filter by predicate.*/ public static Unit getClosest(Team team, float x, float y, float range, Predicate predicate){ result = null; cdist = 0f; @@ -233,9 +219,7 @@ public class Units{ return result; } - /** - * Iterates over all units in a rectangle. - */ + /**Iterates over all units in a rectangle.*/ public static void getNearby(Team team, Rectangle rect, Consumer cons){ EntityGroup group = unitGroups[team.ordinal()]; @@ -249,9 +233,7 @@ public class Units{ }); } - /** - * Iterates over all units in a circle around this position. - */ + /**Iterates over all units in a circle around this position.*/ public static void getNearby(Team team, float x, float y, float radius, Consumer cons){ rect.setSize(radius * 2).setCenter(x, y); @@ -272,9 +254,7 @@ public class Units{ }); } - /** - * Iterates over all units in a rectangle. - */ + /**Iterates over all units in a rectangle.*/ public static void getNearby(Rectangle rect, Consumer cons){ for(Team team : Team.all){ @@ -288,9 +268,7 @@ public class Units{ EntityQuery.getNearby(playerGroup, rect, player -> cons.accept((Unit) player)); } - /** - * Iterates over all units that are enemies of this team. - */ + /**Iterates over all units that are enemies of this team.*/ public static void getNearbyEnemies(Team team, Rectangle rect, Consumer cons){ EnumSet targets = state.teams.enemiesOf(team); @@ -309,9 +287,7 @@ public class Units{ }); } - /** - * Iterates over all units. - */ + /**Iterates over all units.*/ public static void getAllUnits(Consumer cons){ for(Team team : Team.all){ @@ -327,5 +303,4 @@ public class Units{ } } - } diff --git a/core/src/io/anuke/mindustry/entities/effect/Puddle.java b/core/src/io/anuke/mindustry/entities/effect/Puddle.java index 16c2f310b3..84e66eaedb 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Puddle.java +++ b/core/src/io/anuke/mindustry/entities/effect/Puddle.java @@ -57,29 +57,21 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai private float accepting; private byte generation; - /** - * Deserialization use only! - */ + /**Deserialization use only!*/ public Puddle(){ } - /** - * Deposists a puddle between tile and source. - */ + /**Deposists a puddle between tile and source.*/ public static void deposit(Tile tile, Tile source, Liquid liquid, float amount){ deposit(tile, source, liquid, amount, 0); } - /** - * Deposists a puddle at a tile. - */ + /**Deposists a puddle at a tile.*/ public static void deposit(Tile tile, Liquid liquid, float amount){ deposit(tile, tile, liquid, amount, 0); } - /** - * Returns the puddle on the specified tile. May return null. - */ + /**Returns the puddle on the specified tile. May return null.*/ public static Puddle getPuddle(Tile tile){ return map.get(tile.packedPosition()); } @@ -119,7 +111,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai p.lastRipple = Timers.time(); } }else{ - p.amount -= reactPuddle(p.liquid, liquid, amount, p.tile, p.x, p.y); + p.amount += reactPuddle(p.liquid, liquid, amount, p.tile, p.x, p.y); } } @@ -131,9 +123,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai return liquid == Liquids.oil && other == Liquids.water; } - /** - * Reacts two liquids together at a location. - */ + /**Reacts two liquids together at a location.*/ private static float reactPuddle(Liquid dest, Liquid liquid, float amount, Tile tile, float x, float y){ if((dest.flammability > 0.3f && liquid.temperature > 0.7f) || (liquid.flammability > 0.3f && dest.temperature > 0.7f)){ //flammable liquid + hot liquid diff --git a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java index 2b1ff13c11..a086bea466 100644 --- a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java @@ -8,6 +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.game.EventType.BuildSelectEvent; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.net.Net; @@ -18,6 +19,7 @@ import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.BuildBlock; import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity; import io.anuke.ucore.core.Effects; +import io.anuke.ucore.core.Events; import io.anuke.ucore.core.Timers; import io.anuke.ucore.entities.trait.Entity; import io.anuke.ucore.graphics.Draw; @@ -65,10 +67,10 @@ public interface BuilderTrait extends Entity{ BuildRequest request = getCurrentRequest(); if(request != null){ - output.writeByte(request.remove ? 1 : 0); + output.writeByte(request.breaking ? 1 : 0); output.writeInt(world.toPacked(request.x, request.y)); output.writeFloat(request.progress); - if(!request.remove){ + if(!request.breaking){ output.writeByte(request.recipe.id); output.writeByte(request.rotation); } @@ -181,18 +183,16 @@ public interface BuilderTrait extends Entity{ setMineTile(null); } - - Tile tile = world.tile(current.x, current.y); 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)){ + if(!(tile.block() instanceof BuildBlock)){ + if(canCreateBlocks() && !current.breaking && 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)){ + }else if(canCreateBlocks() && current.breaking && Build.validBreak(unit.getTeam(), current.x, current.y)){ Build.beginBreak(unit.getTeam(), current.x, current.y); }else{ getPlaceQueue().removeFirst(); @@ -222,7 +222,7 @@ public interface BuilderTrait extends Entity{ //progress is synced, thus not updated clientside if(!Net.client()){ //deconstructing is 2x as fast - if(current.remove){ + if(current.breaking){ entity.deconstruct(unit, core, 2f / entity.buildCost * Timers.delta() * getBuildPower(tile)); }else{ entity.construct(unit, core, 1f / entity.buildCost * Timers.delta() * getBuildPower(tile)); @@ -232,6 +232,11 @@ public interface BuilderTrait extends Entity{ }else{ entity.progress = current.progress; } + + if(!current.initialized){ + Events.fire(new BuildSelectEvent(tile, unit.getTeam(), this, current.breaking)); + current.initialized = true; + } } /**Do not call directly.*/ @@ -352,9 +357,10 @@ public interface BuilderTrait extends Entity{ class BuildRequest{ public final int x, y, rotation; public final Recipe recipe; - public final boolean remove; + public final boolean breaking; public float progress; + public boolean initialized; /**This creates a build request.*/ public BuildRequest(int x, int y, int rotation, Recipe recipe){ @@ -362,7 +368,7 @@ public interface BuilderTrait extends Entity{ this.y = y; this.rotation = rotation; this.recipe = recipe; - this.remove = false; + this.breaking = false; } /**This creates a remove request.*/ @@ -371,7 +377,7 @@ public interface BuilderTrait extends Entity{ this.y = y; this.rotation = -1; this.recipe = Recipe.getByResult(world.tile(x, y).block()); - this.remove = true; + this.breaking = true; } } } diff --git a/core/src/io/anuke/mindustry/entities/traits/CarryTrait.java b/core/src/io/anuke/mindustry/entities/traits/CarryTrait.java index bbf89e58e6..fdc052f787 100644 --- a/core/src/io/anuke/mindustry/entities/traits/CarryTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/CarryTrait.java @@ -9,9 +9,10 @@ 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) static void dropSelf(Player player){ - if(player.getCarrier() != null){ + if(player != null && player.getCarrier() != null){ player.getCarrier().dropCarry(); } } @@ -40,24 +41,16 @@ public interface CarryTrait extends TeamTrait, SolidTrait, TargetTrait{ } } - /** - * Returns the thing this carrier is carrying. - */ + /**Returns the thing this carrier is carrying.*/ CarriableTrait getCarry(); - /** - * Sets the carrying unit. Internal use only! Use {@link #carry(CarriableTrait)} to set state. - */ + /**Sets the carrying unit. Internal use only! Use {@link #carry(CarriableTrait)} to set state.*/ void setCarry(CarriableTrait unit); - /** - * Returns maximum mass this carrier can carry. - */ + /**Returns maximum mass this carrier can carry.*/ float getCarryWeight(); - /** - * Drops the unit that is being carried, if applicable. - */ + /**Drops the unit that is being carried, if applicable.*/ default void dropCarry(){ carry(null); } diff --git a/core/src/io/anuke/mindustry/entities/units/BaseUnit.java b/core/src/io/anuke/mindustry/entities/units/BaseUnit.java index d75d7011f3..f0f8a54226 100644 --- a/core/src/io/anuke/mindustry/entities/units/BaseUnit.java +++ b/core/src/io/anuke/mindustry/entities/units/BaseUnit.java @@ -190,7 +190,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ } public void targetClosest(){ - target = Units.getClosestTarget(team, x, y, getWeapon().getAmmo().getRange(), u -> type.targetAir || !u.isFlying()); + target = Units.getClosestTarget(team, x, y, Math.max(getWeapon().getAmmo().getRange(), type.range), u -> type.targetAir || !u.isFlying()); } public TileEntity getClosestEnemyCore(){ diff --git a/core/src/io/anuke/mindustry/entities/units/FlyingUnit.java b/core/src/io/anuke/mindustry/entities/units/FlyingUnit.java index c06a07a7fd..e72390c51e 100644 --- a/core/src/io/anuke/mindustry/entities/units/FlyingUnit.java +++ b/core/src/io/anuke/mindustry/entities/units/FlyingUnit.java @@ -76,7 +76,7 @@ public abstract class FlyingUnit extends BaseUnit implements CarryTrait{ attack(150f); if((Mathf.angNear(angleTo(target), rotation, 15f) || !getWeapon().getAmmo().bullet.keepVelocity) //bombers don't care about rotation - && distanceTo(target) < getWeapon().getAmmo().getRange()){ + && distanceTo(target) < Math.max(getWeapon().getAmmo().getRange(), type.range)){ AmmoType ammo = getWeapon().getAmmo(); Vector2 to = Predict.intercept(FlyingUnit.this, target, ammo.bullet.speed); diff --git a/core/src/io/anuke/mindustry/entities/units/UnitType.java b/core/src/io/anuke/mindustry/entities/units/UnitType.java index 6fa0e8627e..5087df0b81 100644 --- a/core/src/io/anuke/mindustry/entities/units/UnitType.java +++ b/core/src/io/anuke/mindustry/entities/units/UnitType.java @@ -29,7 +29,7 @@ public class UnitType extends UnlockableContent{ public float hitsize = 7f; public float hitsizeTile = 4f; public float speed = 0.4f; - public float range = 160; + public float range = 0; public float rotatespeed = 0.2f; public float baseRotateSpeed = 0.1f; public float mass = 1f; 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 9e2e288873..244f5ef455 100644 --- a/core/src/io/anuke/mindustry/entities/units/types/Drone.java +++ b/core/src/io/anuke/mindustry/entities/units/types/Drone.java @@ -4,6 +4,7 @@ import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.utils.Queue; import io.anuke.mindustry.content.blocks.Blocks; 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; import io.anuke.mindustry.entities.traits.BuilderTrait; @@ -12,7 +13,7 @@ import io.anuke.mindustry.entities.units.BaseUnit; import io.anuke.mindustry.entities.units.FlyingUnit; import io.anuke.mindustry.entities.units.UnitCommand; import io.anuke.mindustry.entities.units.UnitState; -import io.anuke.mindustry.game.EventType.BlockBuildEvent; +import io.anuke.mindustry.game.EventType.BuildSelectEvent; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.net.Net; @@ -35,7 +36,8 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -import static io.anuke.mindustry.Vars.*; +import static io.anuke.mindustry.Vars.unitGroups; +import static io.anuke.mindustry.Vars.world; public class Drone extends FlyingUnit implements BuilderTrait{ protected static float discoverRange = 120f; @@ -44,6 +46,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{ protected Item targetItem; protected Tile mineTile; protected Queue placeQueue = new ThreadQueue<>(); + protected boolean isBreaking; public final UnitState @@ -66,9 +69,13 @@ public class Drone extends FlyingUnit implements BuilderTrait{ if(core == null) return; - if(entity.progress() < 1f && entity.tile.block() instanceof BuildBlock){ //building is valid + if((entity.progress() < 1f || entity.progress() > 0f) && entity.tile.block() instanceof BuildBlock){ //building is valid if(!isBuilding() && distanceTo(target) < placeDistance * 0.9f){ //within distance, begin placing - getPlaceQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y, entity.tile.getRotation(), entity.recipe)); + if(isBreaking){ + getPlaceQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y)); + }else{ + getPlaceQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y, entity.tile.getRotation(), entity.recipe)); + } } //if it's missing requirements, try and mine them @@ -234,27 +241,39 @@ public class Drone extends FlyingUnit implements BuilderTrait{ }; static{ - Events.on(BlockBuildEvent.class, event -> { + + Events.on(BuildSelectEvent.class, event -> { EntityGroup group = unitGroups[event.team.ordinal()]; - if(!(event.tile.entity instanceof BuildEntity)) return; + if(!(event.builder instanceof Player) || !(event.tile.entity instanceof BuildEntity)) return; BuildEntity entity = event.tile.entity(); for(BaseUnit unit : group.all()){ if(unit instanceof Drone){ - ((Drone) unit).notifyPlaced(entity); + Drone drone = (Drone)unit; + synchronized(drone.getPlaceQueue()){ + if(drone.isBuilding()){ + //stop building if opposite building begins. + BuildRequest req = drone.getCurrentRequest(); + if(req.breaking != event.breaking && req.x == event.tile.x && req.y == event.tile.y){ + drone.clearBuilding(); + drone.setState(drone.repair); + } + } + } + + drone.notifyPlaced(entity, event.breaking); } } }); } - private void notifyPlaced(BuildEntity entity){ - float timeToBuild = entity.recipe.cost; + private void notifyPlaced(BuildEntity entity, boolean isBreaking){ float dist = Math.min(entity.distanceTo(x, y) - placeDistance, 0); - if(dist / type.maxVelocity < timeToBuild * 0.9f){ - //Call.onDroneBeginBuild(this, entity.tile, entity.recipe); + if(!state.is(build) && dist / type.maxVelocity < entity.buildCost * 0.9f){ target = entity; + this.isBreaking = isBreaking; setState(build); } } diff --git a/core/src/io/anuke/mindustry/game/EventType.java b/core/src/io/anuke/mindustry/game/EventType.java index bb66dea689..f2e91965f9 100644 --- a/core/src/io/anuke/mindustry/game/EventType.java +++ b/core/src/io/anuke/mindustry/game/EventType.java @@ -1,6 +1,7 @@ package io.anuke.mindustry.game; import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.entities.traits.BuilderTrait; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.function.Event; @@ -76,14 +77,33 @@ public class EventType{ } } - /**Called when block building begins. The tile's block will nearly always be a BuildBlock.*/ - public static class BlockBuildEvent implements Event{ + /**Called when block building begins by placing down the BuildBlock. + * The tile's block will nearly always be a BuildBlock.*/ + public static class BlockBuildBeginEvent implements Event{ public final Tile tile; public final Team team; + public final boolean breaking; - public BlockBuildEvent(Tile tile, Team team){ + public BlockBuildBeginEvent(Tile tile, Team team, boolean breaking){ this.tile = tile; this.team = team; + this.breaking = breaking; + } + } + + /**Called when a player or drone begins building something. + * This does not necessarily happen when a new BuildBlock is created.*/ + public static class BuildSelectEvent implements Event{ + public final Tile tile; + public final Team team; + public final BuilderTrait builder; + public final boolean breaking; + + public BuildSelectEvent(Tile tile, Team team, BuilderTrait builder, boolean breaking){ + this.tile = tile; + this.team = team; + this.builder = builder; + this.breaking = breaking; } } diff --git a/core/src/io/anuke/mindustry/game/Saves.java b/core/src/io/anuke/mindustry/game/Saves.java index 4ca1c5c42d..3947d578cd 100644 --- a/core/src/io/anuke/mindustry/game/Saves.java +++ b/core/src/io/anuke/mindustry/game/Saves.java @@ -256,9 +256,7 @@ public class Saves{ } public void delete(){ - if(!gwt){ //can't delete files - SaveIO.fileFor(index).delete(); - } + SaveIO.fileFor(index).delete(); saves.removeValue(this, true); saveMap.remove(index); if(this == current){ diff --git a/core/src/io/anuke/mindustry/graphics/Palette.java b/core/src/io/anuke/mindustry/graphics/Palette.java index 5b40c78a12..e39d55d733 100644 --- a/core/src/io/anuke/mindustry/graphics/Palette.java +++ b/core/src/io/anuke/mindustry/graphics/Palette.java @@ -60,14 +60,15 @@ public class Palette{ bar = Color.SLATE, interact = Color.ORANGE, accent = Color.valueOf("f4ba6e"), - accentBack = new Color(accent.r * 0.8f, accent.g * 0.8f, accent.b * 0.8f, 1f), + accentBack = Color.valueOf("d58c4b"), place = Color.valueOf("6335f8"), remove = Color.valueOf("e55454"), removeBack = Color.valueOf("a73e3e"), placeRotate = accent, breakInvalid = Color.valueOf("d44b3d"), range = Color.valueOf("f4ba6e"), - power = Color.valueOf("fbd367"), + power = Color.valueOf("fbad67"), + powerLight = Color.valueOf("fbd367"), placing = Color.valueOf("616161"), lightTrail = Color.valueOf("ffe2a9"), diff --git a/core/src/io/anuke/mindustry/input/DesktopInput.java b/core/src/io/anuke/mindustry/input/DesktopInput.java index f9c2ac0a39..69fc108654 100644 --- a/core/src/io/anuke/mindustry/input/DesktopInput.java +++ b/core/src/io/anuke/mindustry/input/DesktopInput.java @@ -222,7 +222,7 @@ public class DesktopInput extends InputHandler{ player.isShooting = true; } }else if(Inputs.keyTap(section, "deselect") && (recipe != null || mode != none || player.isBuilding()) && - !(player.getCurrentRequest() != null && player.getCurrentRequest().remove && KeyBinds.get(section, "deselect") == KeyBinds.get(section, "break"))){ + !(player.getCurrentRequest() != null && player.getCurrentRequest().breaking && KeyBinds.get(section, "deselect") == KeyBinds.get(section, "break"))){ if(recipe == null){ player.clearBuilding(); } diff --git a/core/src/io/anuke/mindustry/input/InputHandler.java b/core/src/io/anuke/mindustry/input/InputHandler.java index 6018ad91f3..3c2921145e 100644 --- a/core/src/io/anuke/mindustry/input/InputHandler.java +++ b/core/src/io/anuke/mindustry/input/InputHandler.java @@ -14,6 +14,7 @@ import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.ValidateException; +import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.Recipe; import io.anuke.mindustry.ui.fragments.OverlayFragment; @@ -76,10 +77,11 @@ public abstract class InputHandler extends InputAdapter{ player.isTransferring = true; - ItemStack stack = player.inventory.getItem(); - int accepted = tile.block().acceptStack(stack.item, stack.amount, tile, player); + Item item = player.inventory.getItem().item; + int amount = player.inventory.getItem().amount; + int accepted = tile.block().acceptStack(item, amount, tile, player); + player.inventory.getItem().amount -= accepted; - boolean clear = stack.amount == accepted; int sent = Mathf.clamp(accepted / 4, 1, 8); int removed = accepted / sent; int[] remaining = {accepted, accepted}; @@ -88,29 +90,24 @@ public abstract class InputHandler extends InputAdapter{ for(int i = 0; i < sent; i++){ boolean end = i == sent - 1; Timers.run(i * 3, () -> { - tile.block().getStackOffset(stack.item, tile, stackTrns); + tile.block().getStackOffset(item, tile, stackTrns); - ItemTransfer.create(stack.item, + ItemTransfer.create(item, player.x + Angles.trnsx(player.rotation + 180f, backTrns), player.y + Angles.trnsy(player.rotation + 180f, backTrns), new Translator(tile.drawx() + stackTrns.x, tile.drawy() + stackTrns.y), () -> { if(tile.block() != block || tile.entity == null) return; - tile.block().handleStack(stack.item, removed, tile, player); + tile.block().handleStack(item, removed, tile, player); remaining[1] -= removed; if(end && remaining[1] > 0){ - tile.block().handleStack(stack.item, remaining[1], tile, player); + tile.block().handleStack(item, remaining[1], tile, player); } }); - stack.amount -= removed; remaining[0] -= removed; if(end){ - stack.amount -= remaining[0]; - if(clear){ - player.inventory.clearItem(); - } player.isTransferring = false; } }); diff --git a/core/src/io/anuke/mindustry/io/SaveFileVersion.java b/core/src/io/anuke/mindustry/io/SaveFileVersion.java index 5f3d005030..b4b60634a9 100644 --- a/core/src/io/anuke/mindustry/io/SaveFileVersion.java +++ b/core/src/io/anuke/mindustry/io/SaveFileVersion.java @@ -67,6 +67,7 @@ public abstract class SaveFileVersion{ if(tile.entity.liquids != null) tile.entity.liquids.write(stream); if(tile.entity.cons != null) tile.entity.cons.write(stream); + tile.entity.writeConfig(stream); tile.entity.write(stream); }else if(tile.block() == Blocks.air){ int consecutives = 0; @@ -152,6 +153,7 @@ public abstract class SaveFileVersion{ if(tile.entity.liquids != null) tile.entity.liquids.read(stream); if(tile.entity.cons != null) tile.entity.cons.read(stream); + tile.entity.readConfig(stream); tile.entity.read(stream); if(tile.block() == StorageBlocks.core){ diff --git a/core/src/io/anuke/mindustry/io/SaveIO.java b/core/src/io/anuke/mindustry/io/SaveIO.java index 51120ce987..af0e9287b2 100644 --- a/core/src/io/anuke/mindustry/io/SaveIO.java +++ b/core/src/io/anuke/mindustry/io/SaveIO.java @@ -2,12 +2,10 @@ package io.anuke.mindustry.io; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.Base64Coder; import com.badlogic.gdx.utils.IntArray; import com.badlogic.gdx.utils.IntMap; import io.anuke.mindustry.Vars; import io.anuke.mindustry.io.versions.Save16; -import io.anuke.ucore.core.Settings; import java.io.*; import java.util.zip.DeflaterOutputStream; @@ -33,40 +31,23 @@ public class SaveIO{ } public static void saveToSlot(int slot){ - if(gwt){ - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - write(stream); - Settings.putString("save-" + slot + "-data", new String(Base64Coder.encode(stream.toByteArray()))); - Settings.save(); - }else{ - FileHandle file = fileFor(slot); - boolean exists = file.exists(); - if(exists) file.moveTo(file.sibling(file.name() + "-backup." + file.extension())); - try{ - write(fileFor(slot)); - }catch(Exception e){ - if(exists) file.sibling(file.name() + "-backup." + file.extension()).moveTo(file); - throw new RuntimeException(e); - } + FileHandle file = fileFor(slot); + boolean exists = file.exists(); + if(exists) file.moveTo(file.sibling(file.name() + "-backup." + file.extension())); + try{ + write(fileFor(slot)); + }catch(Exception e){ + if(exists) file.sibling(file.name() + "-backup." + file.extension()).moveTo(file); + throw new RuntimeException(e); } } public static void loadFromSlot(int slot){ - if(gwt){ - load(getSlotStream(slot)); - }else{ - load(fileFor(slot)); - } + load(fileFor(slot)); } public static DataInputStream getSlotStream(int slot){ - if(gwt){ - String string = Settings.getString("save-" + slot + "-data", ""); - byte[] bytes = Base64Coder.decode(string); - return new DataInputStream(new ByteArrayInputStream(bytes)); - }else{ - return new DataInputStream(new InflaterInputStream(fileFor(slot).read())); - } + return new DataInputStream(new InflaterInputStream(fileFor(slot).read())); } public static boolean isSaveValid(int slot){ @@ -165,6 +146,7 @@ public class SaveIO{ stream.close(); }catch(Exception e){ + content.setTemporaryMapper(null); throw new RuntimeException(e); } } diff --git a/core/src/io/anuke/mindustry/io/TypeIO.java b/core/src/io/anuke/mindustry/io/TypeIO.java index d10b7ef744..7a0f2d3069 100644 --- a/core/src/io/anuke/mindustry/io/TypeIO.java +++ b/core/src/io/anuke/mindustry/io/TypeIO.java @@ -1,7 +1,6 @@ package io.anuke.mindustry.io; import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.utils.Base64Coder; import io.anuke.annotations.Annotations.ReadClass; import io.anuke.annotations.Annotations.WriteClass; import io.anuke.mindustry.entities.Player; @@ -17,7 +16,6 @@ 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; -import io.anuke.mindustry.net.TraceInfo; import io.anuke.mindustry.type.*; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -26,13 +24,14 @@ import io.anuke.ucore.core.Effects.Effect; import io.anuke.ucore.entities.Entities; import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; +import java.nio.charset.Charset; import static io.anuke.mindustry.Vars.*; /** Class for specifying read/write methods for code generation.*/ @SuppressWarnings("unused") public class TypeIO{ + private static final Charset charset = Charset.forName("UTF-8"); @WriteClass(Player.class) public static void writePlayer(ByteBuffer buffer, Player player){ @@ -164,9 +163,9 @@ public class TypeIO{ public static void writeRequests(ByteBuffer buffer, BuildRequest[] requests){ buffer.putShort((short)requests.length); for(BuildRequest request : requests){ - buffer.put(request.remove ? (byte) 1 : 0); + buffer.put(request.breaking ? (byte) 1 : 0); buffer.putInt(world.toPacked(request.x, request.y)); - if(!request.remove){ + if(!request.breaking){ buffer.put(request.recipe.id); buffer.put((byte) request.rotation); } @@ -330,7 +329,7 @@ public class TypeIO{ @WriteClass(String.class) public static void writeString(ByteBuffer buffer, String string){ if(string != null){ - byte[] bytes = string.getBytes(StandardCharsets.UTF_8); + byte[] bytes = string.getBytes(charset); buffer.putShort((short) bytes.length); buffer.put(bytes); }else{ @@ -344,7 +343,7 @@ public class TypeIO{ if(length != -1){ byte[] bytes = new byte[length]; buffer.get(bytes); - return new String(bytes, StandardCharsets.UTF_8); + return new String(bytes, charset); }else{ return null; } @@ -363,45 +362,4 @@ public class TypeIO{ buffer.get(bytes); return bytes; } - - @WriteClass(TraceInfo.class) - public static void writeTrace(ByteBuffer buffer, TraceInfo info){ - buffer.putInt(info.playerid); - buffer.putShort((short) info.ip.getBytes().length); - buffer.put(info.ip.getBytes()); - buffer.put(info.modclient ? (byte) 1 : 0); - buffer.put(info.android ? (byte) 1 : 0); - - buffer.putInt(info.totalBlocksBroken); - buffer.putInt(info.structureBlocksBroken); - buffer.putInt(info.lastBlockBroken.id); - - buffer.putInt(info.totalBlocksPlaced); - buffer.putInt(info.lastBlockPlaced.id); - buffer.put(Base64Coder.decode(info.uuid)); - } - - @ReadClass(TraceInfo.class) - public static TraceInfo readTrace(ByteBuffer buffer){ - int id = buffer.getInt(); - short iplen = buffer.getShort(); - byte[] ipb = new byte[iplen]; - buffer.get(ipb); - - TraceInfo info = new TraceInfo(new String(ipb)); - - info.playerid = id; - info.modclient = buffer.get() == 1; - info.android = buffer.get() == 1; - info.totalBlocksBroken = buffer.getInt(); - info.structureBlocksBroken = buffer.getInt(); - info.lastBlockBroken = content.block(buffer.getInt()); - info.totalBlocksPlaced = buffer.getInt(); - info.lastBlockPlaced = content.block(buffer.getInt()); - byte[] uuid = new byte[8]; - buffer.get(uuid); - - info.uuid = new String(Base64Coder.encode(uuid)); - return info; - } } diff --git a/core/src/io/anuke/mindustry/maps/Maps.java b/core/src/io/anuke/mindustry/maps/Maps.java index 6493bbb0f3..74936f00f8 100644 --- a/core/src/io/anuke/mindustry/maps/Maps.java +++ b/core/src/io/anuke/mindustry/maps/Maps.java @@ -4,16 +4,16 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.Base64Coder; import com.badlogic.gdx.utils.Disposable; import com.badlogic.gdx.utils.ObjectMap; import io.anuke.mindustry.io.MapIO; -import io.anuke.ucore.core.Settings; import io.anuke.ucore.function.Supplier; import io.anuke.ucore.util.Log; import io.anuke.ucore.util.ThreadArray; -import java.io.*; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; import static io.anuke.mindustry.Vars.*; @@ -29,8 +29,6 @@ public class Maps implements Disposable{ private Array allMaps = new ThreadArray<>(); /**Temporary array used for returning things.*/ private Array returnArray = new ThreadArray<>(); - /**Used for storing a list of custom map names for GWT.*/ - private Array customMapNames; /**Returns a list of all maps, including custom ones.*/ public Array all(){ @@ -76,25 +74,14 @@ public class Maps implements Disposable{ /**Save a map. This updates all values and stored data necessary.*/ public void saveMap(String name, MapTileData data, ObjectMap tags){ - try { + try{ //create copy of tags to prevent mutation later ObjectMap newTags = new ObjectMap<>(); newTags.putAll(tags); tags = newTags; - if (!gwt) { - FileHandle file = customMapDirectory.child(name + "." + mapExtension); - MapIO.writeMap(file.write(false), tags, data); - } else { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - MapIO.writeMap(stream, tags, data); - Settings.putString("map-data-" + name, new String(Base64Coder.encode(stream.toByteArray()))); - if(!customMapNames.contains(name, false)){ - customMapNames.add(name); - Settings.putObject("custom-maps", customMapNames); - } - Settings.save(); - } + FileHandle file = customMapDirectory.child(name + "." + mapExtension); + MapIO.writeMap(file.write(false), tags, data); if(maps.containsKey(name)){ if(maps.get(name).texture != null) { @@ -105,7 +92,7 @@ public class Maps implements Disposable{ } Map map = new Map(name, new MapMeta(version, tags, data.width(), data.height(), null), true, getStreamFor(name)); - if (!headless){ + if(!headless){ map.texture = new Texture(MapIO.generatePixmap(data)); } allMaps.add(map); @@ -126,14 +113,7 @@ public class Maps implements Disposable{ maps.remove(map.name); allMaps.removeValue(map, true); - if (!gwt) { - customMapDirectory.child(map.name + "." + mapExtension).delete(); - } else { - customMapNames.removeValue(map.name, false); - Settings.putString("map-data-" + map.name, ""); - Settings.putObject("custom-maps", customMapNames); - Settings.save(); - } + customMapDirectory.child(map.name + "." + mapExtension).delete(); } private void loadMap(String name, Supplier supplier, boolean custom) throws IOException{ @@ -151,43 +131,21 @@ public class Maps implements Disposable{ } private void loadCustomMaps(){ - if(!gwt){ - for(FileHandle file : customMapDirectory.list()){ - try{ - if(file.extension().equalsIgnoreCase(mapExtension)){ - loadMap(file.nameWithoutExtension(), file::read, true); - } - }catch (Exception e){ - Log.err("Failed to load custom map file '{0}'!", file); - Log.err(e); - } - } - - }else{ - customMapNames = Settings.getObject("custom-maps", Array.class, Array::new); - - for(String name : customMapNames){ - try{ - String data = Settings.getString("map-data-" + name, ""); - byte[] bytes = Base64Coder.decode(data); - loadMap(name, () -> new ByteArrayInputStream(bytes), true); - }catch (Exception e){ - Log.err("Failed to load custom map '{0}'!", name); - Log.err(e); + for(FileHandle file : customMapDirectory.list()){ + try{ + if(file.extension().equalsIgnoreCase(mapExtension)){ + loadMap(file.nameWithoutExtension(), file::read, true); } + }catch (Exception e){ + Log.err("Failed to load custom map file '{0}'!", file); + Log.err(e); } } } /**Returns an input stream supplier for a given map name.*/ private Supplier getStreamFor(String name){ - if(!gwt){ - return customMapDirectory.child(name + "." + mapExtension)::read; - }else{ - String data = Settings.getString("map-data-" + name, ""); - byte[] bytes = Base64Coder.decode(data); - return () -> new ByteArrayInputStream(bytes); - } + return customMapDirectory.child(name + "." + mapExtension)::read; } @Override diff --git a/core/src/io/anuke/mindustry/maps/missions/BlockLocMission.java b/core/src/io/anuke/mindustry/maps/missions/BlockLocMission.java index 387c0c55dc..00a596e81a 100644 --- a/core/src/io/anuke/mindustry/maps/missions/BlockLocMission.java +++ b/core/src/io/anuke/mindustry/maps/missions/BlockLocMission.java @@ -52,7 +52,7 @@ public class BlockLocMission extends Mission{ float rot = players[0].angleTo(x * tilesize + block.offset(), y * tilesize + block.offset()); float len = 12f; - Draw.color(Palette.accent.r * 0.8f,Palette.accent.g * 0.8f,Palette.accent.b * 0.8f); + Draw.color(Palette.accentBack); Draw.rect("icon-arrow", players[0].x + Angles.trnsx(rot, len), players[0].y + Angles.trnsy(rot, len), rot); Draw.color(Palette.accent); Draw.rect("icon-arrow", players[0].x + Angles.trnsx(rot, len), players[0].y + Angles.trnsy(rot, len) + 1f, rot); diff --git a/core/src/io/anuke/mindustry/net/Administration.java b/core/src/io/anuke/mindustry/net/Administration.java index 48454fa1a6..73164c91fe 100644 --- a/core/src/io/anuke/mindustry/net/Administration.java +++ b/core/src/io/anuke/mindustry/net/Administration.java @@ -2,6 +2,7 @@ package io.anuke.mindustry.net; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.ObjectMap; +import com.badlogic.gdx.utils.ObjectSet; import io.anuke.annotations.Annotations.Serialize; import io.anuke.ucore.core.Settings; @@ -11,8 +12,6 @@ public class Administration{ /**All player info. Maps UUIDs to info. This persists throughout restarts.*/ private ObjectMap playerInfo = new ObjectMap<>(); - /**Maps UUIDs to trace infos. This is wiped when a player logs off.*/ - private ObjectMap traceInfo = new ObjectMap<>(); private Array bannedIPs = new Array<>(); public Administration(){ @@ -41,9 +40,7 @@ public class Administration{ Settings.save(); } - /** - * Call when a player joins to update their information here. - */ + /**Call when a player joins to update their information here.*/ public void updatePlayerJoined(String id, String ip, String name){ PlayerInfo info = getCreateInfo(id); info.lastName = name; @@ -53,17 +50,8 @@ public class Administration{ if(!info.ips.contains(ip, false)) info.ips.add(ip); } - /** - * Returns trace info by UUID. - */ - public TraceInfo getTraceByID(String uuid){ - if(!traceInfo.containsKey(uuid)) traceInfo.put(uuid, new TraceInfo(uuid)); - - return traceInfo.get(uuid); - } - - public void clearTraces(){ - traceInfo.clear(); + public boolean banPlayer(String uuid){ + return banPlayerID(uuid) || banPlayerIP(getInfo(uuid).lastIP); } /** @@ -86,9 +74,7 @@ public class Administration{ return true; } - /** - * Bans a player by UUID; returns whether this player was already banned. - */ + /**Bans a player by UUID; returns whether this player was already banned.*/ public boolean banPlayerID(String id){ if(playerInfo.containsKey(id) && playerInfo.get(id).banned) return false; @@ -215,11 +201,13 @@ public class Administration{ return info.admin && usip.equals(info.adminUsid); } - public Array findByName(String name, boolean last){ - Array result = new Array<>(); + /**Finds player info by IP, UUID and name.*/ + public ObjectSet findByName(String name){ + ObjectSet result = new ObjectSet<>(); for(PlayerInfo info : playerInfo.values()){ - if(info.lastName.toLowerCase().equals(name.toLowerCase()) || (last && info.names.contains(name, false))){ + if(info.lastName.toLowerCase().equals(name.toLowerCase()) || (info.names.contains(name, false)) + || info.ips.contains(name, false) || info.id.equals(name)){ result.add(info); } } @@ -287,8 +275,6 @@ public class Administration{ public String adminUsid; public int timesKicked; public int timesJoined; - public int totalBlockPlaced; - public int totalBlocksBroken; public boolean banned, admin; public long lastKicked; //last kicked timestamp diff --git a/core/src/io/anuke/mindustry/net/Net.java b/core/src/io/anuke/mindustry/net/Net.java index 5a1b6133c8..78941f012f 100644 --- a/core/src/io/anuke/mindustry/net/Net.java +++ b/core/src/io/anuke/mindustry/net/Net.java @@ -17,13 +17,14 @@ import io.anuke.mindustry.net.Streamable.StreamBuilder; import io.anuke.ucore.core.Timers; import io.anuke.ucore.function.BiConsumer; import io.anuke.ucore.function.Consumer; +import io.anuke.ucore.util.Bundles; import io.anuke.ucore.util.Log; import io.anuke.ucore.util.Pooling; +import io.anuke.ucore.util.Threads; import java.io.IOException; -import static io.anuke.mindustry.Vars.headless; -import static io.anuke.mindustry.Vars.ui; +import static io.anuke.mindustry.Vars.*; public class Net{ private static boolean server; @@ -46,15 +47,43 @@ public class Net{ return serverProvider != null; } - /** - * Display a network error. - */ - public static void showError(String text){ + /**Display a network error. Call on the graphics thread.*/ + public static void showError(Throwable e){ + if(!headless){ - ui.showError(text); - }else{ - Log.err(text); + Threads.assertGraphics(); + + Throwable t = e; + while(t.getCause() != null){ + t = t.getCause(); + } + + String error = t.getMessage() == null ? "" : t.getMessage().toLowerCase(); + String type = error.getClass().toString().toLowerCase(); + + if(error.equals("mismatch")){ + error = Bundles.get("text.error.mismatch"); + }else if(error.contains("port out of range") || error.contains("invalid argument") || (error.contains("invalid") && error.contains("address"))){ + error = Bundles.get("text.error.invalidaddress"); + }else if(error.contains("connection refused") || error.contains("route to host") || type.contains("unknownhost")){ + error = Bundles.get("text.error.unreachable"); + }else if(type.contains("timeout")){ + error = Bundles.get("text.error.timeout"); + }else if(error.equals("alreadyconnected")){ + error = Bundles.get("text.error.alreadyconnected"); + }else if(!error.isEmpty()){ + error = Bundles.get("text.error.any"); + } + + ui.showText("", Bundles.format("text.connectfail", error)); + ui.loadfrag.hide(); + + if(Net.client()){ + netClient.disconnectQuietly(); + } } + + Log.err(e); } /** @@ -77,14 +106,18 @@ public class Net{ /** * Connect to an address. */ - public static void connect(String ip, int port) throws IOException{ - lastIP = ip + ":" + port; - if(!active){ - clientProvider.connect(ip, port); - active = true; - server = false; - }else{ - throw new IOException("Already connected!"); + public static void connect(String ip, int port, Runnable success){ + try{ + lastIP = ip + ":" + port; + if(!active){ + clientProvider.connect(ip, port, success); + active = true; + server = false; + }else{ + throw new IOException("alreadyconnected"); + } + }catch(IOException e){ + showError(e); } } @@ -132,7 +165,7 @@ public class Net{ } /** - * Starts discovering servers on a different thread. Does not work with GWT. + * Starts discovering servers on a different thread. * Callback is run on the main libGDX thread. */ public static void discoverServers(Consumer cons, Runnable done){ @@ -346,7 +379,7 @@ public class Net{ /**Client implementation.*/ public interface ClientProvider{ /**Connect to a server.*/ - void connect(String ip, int port) throws IOException; + void connect(String ip, int port, Runnable success) throws IOException; /**Send an object to the server.*/ void send(Object object, SendMode mode); diff --git a/core/src/io/anuke/mindustry/net/NetConnection.java b/core/src/io/anuke/mindustry/net/NetConnection.java index 7314caae55..3b572d0bb5 100644 --- a/core/src/io/anuke/mindustry/net/NetConnection.java +++ b/core/src/io/anuke/mindustry/net/NetConnection.java @@ -6,6 +6,9 @@ public abstract class NetConnection{ public final int id; public final String address; + public boolean modclient; + public boolean mobile; + public int lastSentSnapshotID = -1; /**ID of last recieved client snapshot.*/ diff --git a/core/src/io/anuke/mindustry/net/NetworkIO.java b/core/src/io/anuke/mindustry/net/NetworkIO.java index f6a3abf58b..5f23abf5b3 100644 --- a/core/src/io/anuke/mindustry/net/NetworkIO.java +++ b/core/src/io/anuke/mindustry/net/NetworkIO.java @@ -73,6 +73,7 @@ public class NetworkIO{ if(tile.entity.liquids != null) tile.entity.liquids.write(stream); if(tile.entity.cons != null) tile.entity.cons.write(stream); + tile.entity.writeConfig(stream); tile.entity.write(stream); }else if(tile.block() == Blocks.air){ int consecutives = 0; @@ -229,6 +230,7 @@ public class NetworkIO{ if(tile.entity.liquids != null) tile.entity.liquids.read(stream); if(tile.entity.cons != null) tile.entity.cons.read(stream); + tile.entity.readConfig(stream); tile.entity.read(stream); }else if(wallid == 0){ int consecutives = stream.readUnsignedByte(); diff --git a/core/src/io/anuke/mindustry/net/TraceInfo.java b/core/src/io/anuke/mindustry/net/TraceInfo.java deleted file mode 100644 index 0b62ec54d2..0000000000 --- a/core/src/io/anuke/mindustry/net/TraceInfo.java +++ /dev/null @@ -1,27 +0,0 @@ -package io.anuke.mindustry.net; - -import com.badlogic.gdx.utils.IntIntMap; -import io.anuke.mindustry.content.blocks.Blocks; -import io.anuke.mindustry.world.Block; - -public class TraceInfo{ - public int playerid; - public String ip; - public boolean modclient; - public boolean android; - - public IntIntMap fastShots = new IntIntMap(); - - public int totalBlocksBroken; - public int structureBlocksBroken; - public Block lastBlockBroken = Blocks.air; - - public int totalBlocksPlaced; - public Block lastBlockPlaced = Blocks.air; - - public String uuid; - - public TraceInfo(String uuid){ - this.uuid = uuid; - } -} diff --git a/core/src/io/anuke/mindustry/ui/BorderImage.java b/core/src/io/anuke/mindustry/ui/BorderImage.java index bc9ed30002..66d3913500 100644 --- a/core/src/io/anuke/mindustry/ui/BorderImage.java +++ b/core/src/io/anuke/mindustry/ui/BorderImage.java @@ -13,6 +13,7 @@ public class BorderImage extends Image{ private float thickness = 3f; public BorderImage(){ + } public BorderImage(Texture texture){ diff --git a/core/src/io/anuke/mindustry/ui/ItemImage.java b/core/src/io/anuke/mindustry/ui/ItemImage.java index b07b3dba1c..aa1a370efd 100644 --- a/core/src/io/anuke/mindustry/ui/ItemImage.java +++ b/core/src/io/anuke/mindustry/ui/ItemImage.java @@ -3,6 +3,7 @@ package io.anuke.mindustry.ui; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.g2d.TextureRegion; import io.anuke.mindustry.type.ItemStack; +import io.anuke.ucore.core.Core; import io.anuke.ucore.function.Supplier; import io.anuke.ucore.scene.ui.Image; import io.anuke.ucore.scene.ui.layout.Stack; @@ -14,7 +15,7 @@ public class ItemImage extends Stack{ public ItemImage(TextureRegion region, Supplier text){ Table t = new Table().left().bottom(); - t.label(text).color(Color.DARK_GRAY).padBottom(-20).get().setFontScale(Unit.dp.scl(0.5f)); + t.label(text).color(Color.DARK_GRAY).padBottom(-Core.skin.font().getData().capHeight * 2).get().setFontScale(Unit.dp.scl(0.5f)); t.row(); t.label(text).get().setFontScale(Unit.dp.scl(0.5f)); @@ -25,7 +26,7 @@ public class ItemImage extends Stack{ public ItemImage(ItemStack stack){ Table t = new Table().left().bottom(); - t.add(stack.amount + "").color(Color.DARK_GRAY).padBottom(-20).get().setFontScale(Unit.dp.scl(0.5f)); + t.add(stack.amount + "").color(Color.DARK_GRAY).padBottom(-Core.skin.font().getData().capHeight * 2).get().setFontScale(Unit.dp.scl(0.5f)); t.row(); t.add(stack.amount + "").get().setFontScale(Unit.dp.scl(0.5f)); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/AdminsDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/AdminsDialog.java index 46f533c286..c2917a0654 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/AdminsDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/AdminsDialog.java @@ -20,8 +20,6 @@ public class AdminsDialog extends FloatingDialog{ private void setup(){ content().clear(); - if(gwt) return; - float w = 400f, h = 80f; Table table = new Table(); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/BansDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/BansDialog.java index 012bbe6ee1..9045c6e7cc 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/BansDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/BansDialog.java @@ -21,8 +21,6 @@ public class BansDialog extends FloatingDialog{ private void setup(){ content().clear(); - if(gwt) return; - float w = 400f, h = 80f; Table table = new Table(); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java index cfc87d4e67..b9a4305c87 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java @@ -3,6 +3,7 @@ package io.anuke.mindustry.ui.dialogs; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.utils.Align; +import com.badlogic.gdx.utils.Scaling; import io.anuke.mindustry.game.Difficulty; import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.maps.Map; @@ -48,7 +49,7 @@ public class CustomGameDialog extends FloatingDialog{ modes.marginBottom(5); for(GameMode mode : GameMode.values()){ - if(mode.hidden || (mode.isPvp && gwt)) continue; + if(mode.hidden) continue; modes.addButton("$mode." + mode.name() + ".name", "toggle", () -> state.mode = mode) .update(b -> b.setChecked(state.mode == mode)).group(group).size(140f, 54f).padBottom(-5); @@ -106,6 +107,7 @@ public class CustomGameDialog extends FloatingDialog{ image.label((() -> Bundles.format("text.level.highscore", Settings.getInt("hiscore" + map.name, 0)))).pad(3f); BorderImage border = new BorderImage(map.texture, 3f); + border.setScaling(Scaling.fit); image.replaceImage(border); image.clicked(() -> { diff --git a/core/src/io/anuke/mindustry/ui/dialogs/FileChooser.java b/core/src/io/anuke/mindustry/ui/dialogs/FileChooser.java index ac5f78457b..be56e08427 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/FileChooser.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/FileChooser.java @@ -21,15 +21,13 @@ import io.anuke.ucore.util.Pooling; import java.util.Arrays; -import static io.anuke.mindustry.Vars.gwt; - public class FileChooser extends FloatingDialog{ public static Predicate pngFilter = file -> file.extension().equalsIgnoreCase("png"); public static Predicate mapFilter = file -> file.extension().equalsIgnoreCase(Vars.mapExtension); public static Predicate jpegFilter = file -> file.extension().equalsIgnoreCase("png") || file.extension().equalsIgnoreCase("jpg") || file.extension().equalsIgnoreCase("jpeg"); public static Predicate defaultFilter = file -> true; private Table files; - private FileHandle homeDirectory = gwt ? Gdx.files.internal("") : Gdx.files.absolute(OS.isMac ? OS.getProperty("user.home") + "/Downloads/" : + private FileHandle homeDirectory = Gdx.files.absolute(OS.isMac ? OS.getProperty("user.home") + "/Downloads/" : Gdx.files.getExternalStoragePath()); private FileHandle directory = homeDirectory; private ScrollPane pane; @@ -175,7 +173,7 @@ public class FileChooser extends FloatingDialog{ Arrays.sort(handles, (a, b) -> { if(a.isDirectory() && !b.isDirectory()) return -1; if(!a.isDirectory() && b.isDirectory()) return 1; - return a.name().toUpperCase().compareTo(b.name().toUpperCase()); + return String.CASE_INSENSITIVE_ORDER.compare(a.name(), b.name()); }); return handles; } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java index edbd6133c2..0cbd003d69 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java @@ -18,7 +18,6 @@ import io.anuke.ucore.scene.ui.layout.Cell; 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; import static io.anuke.mindustry.Vars.*; @@ -248,16 +247,14 @@ public class JoinDialog extends FloatingDialog{ } void refreshLocal(){ - if(!Vars.gwt){ - totalHosts = 0; + totalHosts = 0; - local.clear(); - local.background((Drawable)null); - local.table("button", t -> { - t.label(() -> "[accent]" + Bundles.get("text.hosts.discovering") + Strings.animated(4, 10f, ".")).pad(10f); - }).growX(); - Net.discoverServers(this::addLocalHost, this::finishLocalHosts); - } + local.clear(); + local.background((Drawable)null); + local.table("button", t -> { + t.label(() -> "[accent]" + Bundles.get("text.hosts.discovering") + Strings.animated(4, 10f, ".")).pad(10f); + }).growX(); + Net.discoverServers(this::addLocalHost, this::finishLocalHosts); } void finishLocalHosts(){ @@ -300,34 +297,11 @@ public class JoinDialog extends FloatingDialog{ }); Timers.runTask(2f, () -> { - try{ - Vars.netClient.beginConnecting(); - Net.connect(ip, port); + Vars.netClient.beginConnecting(); + Net.connect(ip, port, () -> { hide(); add.hide(); - }catch(Exception e){ - Throwable t = e; - while(t.getCause() != null){ - t = t.getCause(); - } - //TODO localize - String error = t.getMessage() == null ? "" : t.getMessage().toLowerCase(); - if(error.contains("connection refused")){ - error = "connection refused"; - }else if(error.contains("port out of range")){ - error = "invalid port!"; - }else if(error.contains("invalid argument")){ - error = "invalid IP or port!"; - }else if(t.getClass().toString().toLowerCase().contains("sockettimeout")){ - error = "timed out!\nmake sure the host has port forwarding set up,\nand that the address is correct!"; - }else{ - error = Strings.parseException(e, false); - } - ui.showError(Bundles.format("text.connectfail", error)); - ui.loadfrag.hide(); - - Log.err(e); - } + }); }); } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/LanguageDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/LanguageDialog.java index b6cc42752c..9360b214cb 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/LanguageDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/LanguageDialog.java @@ -1,6 +1,5 @@ package io.anuke.mindustry.ui.dialogs; -import io.anuke.mindustry.core.Platform; import io.anuke.ucore.core.Settings; import io.anuke.ucore.scene.ui.ButtonGroup; import io.anuke.ucore.scene.ui.ScrollPane; @@ -31,7 +30,7 @@ public class LanguageDialog extends FloatingDialog{ ButtonGroup group = new ButtonGroup<>(); for(Locale loc : locales){ - TextButton button = new TextButton(Platform.instance.getLocaleName(loc), "toggle"); + TextButton button = new TextButton(loc.getDisplayName(loc), "toggle"); button.clicked(() -> { if(getLocale().equals(loc)) return; Settings.putString("locale", loc.toString()); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java index 75f9c0c923..8452cab889 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java @@ -86,28 +86,27 @@ public class LoadDialog extends FloatingDialog{ }); }).size(14 * 3).right(); - if(!gwt){ - t.addImageButton("icon-save", "empty", 14 * 3, () -> { - if(!ios){ - Platform.instance.showFileChooser(Bundles.get("text.save.export"), "Mindustry Save", file -> { - try{ - slot.exportFile(file); - setup(); - }catch(IOException e){ - ui.showError(Bundles.format("text.save.export.fail", Strings.parseException(e, false))); - } - }, false, saveExtension); - }else{ + t.addImageButton("icon-save", "empty", 14 * 3, () -> { + if(!ios){ + Platform.instance.showFileChooser(Bundles.get("text.save.export"), "Mindustry Save", file -> { try{ - FileHandle file = Gdx.files.local("save-" + slot.getName() + "." + Vars.saveExtension); slot.exportFile(file); - Platform.instance.shareFile(file); - }catch(Exception e){ + setup(); + }catch(IOException e){ ui.showError(Bundles.format("text.save.export.fail", Strings.parseException(e, false))); } + }, false, saveExtension); + }else{ + try{ + FileHandle file = Gdx.files.local("save-" + slot.getName() + "." + Vars.saveExtension); + slot.exportFile(file); + Platform.instance.shareFile(file); + }catch(Exception e){ + ui.showError(Bundles.format("text.save.export.fail", Strings.parseException(e, false))); } - }).size(14 * 3).right(); - } + } + }).size(14 * 3).right(); + }).padRight(-10).growX(); @@ -153,7 +152,7 @@ public class LoadDialog extends FloatingDialog{ slots.row(); - if(gwt || ios) return; + if(ios) return; slots.addImageTextButton("$text.save.import", "icon-add", "clear", 14 * 3, () -> { Platform.instance.showFileChooser(Bundles.get("text.save.import"), "Mindustry Save", file -> { diff --git a/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java index 65d6e2717d..dfc9ebb832 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java @@ -93,7 +93,7 @@ public class MapsDialog extends FloatingDialog{ button.row(); button.addImage("white").growX().pad(4).color(Color.GRAY); button.row(); - ((Image) button.stack(new Image(map.texture), new BorderImage(map.texture)).size(mapsize - 20f).get().getChildren().first()).setScaling(Scaling.fit); + button.stack(new Image(map.texture).setScaling(Scaling.fit), new BorderImage(map.texture).setScaling(Scaling.fit)).size(mapsize - 20f); button.row(); button.add(map.custom ? "$text.custom" : "$text.builtin").color(Color.GRAY).padTop(3); @@ -114,7 +114,7 @@ public class MapsDialog extends FloatingDialog{ 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); + table.stack(new Image(map.texture).setScaling(Scaling.fit), new BorderImage(map.texture).setScaling(Scaling.fit)).size(mapsize); table.table("clear", desc -> { desc.top(); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java index afd5b8dbcd..6aa1dfa80a 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java @@ -61,25 +61,14 @@ public class PausedDialog extends FloatingDialog{ content().addButton("$text.settings", ui.settings::show); content().row(); - content().addButton("$text.savegame", () -> { - save.show(); - }).disabled(s -> world.getSector() != null); + content().addButton("$text.savegame", save::show).disabled(s -> world.getSector() != null); content().row(); - content().addButton("$text.loadgame", () -> { - load.show(); - }).disabled(b -> Net.active()); + content().addButton("$text.loadgame", load::show).disabled(b -> Net.active()); content().row(); - content().addButton("$text.hostserver", () -> { - if(!gwt){ - ui.host.show(); - }else{ - ui.showInfo("$text.web.unsupported"); - } - }).disabled(b -> Net.active()); - + content().addButton("$text.hostserver", ui.host::show).disabled(b -> Net.active()); content().row(); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java index b94cc4eea0..69a7e9479a 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java @@ -175,11 +175,8 @@ public class SettingsMenuDialog extends SettingsDialog{ Settings.prefs().put(map); Settings.save(); - if(!gwt){ - Settings.prefs().clear(); - for(FileHandle file : dataDirectory.list()){ - file.deleteDirectory(); - } + for(FileHandle file : dataDirectory.list()){ + file.deleteDirectory(); } Gdx.app.exit(); @@ -193,19 +190,15 @@ public class SettingsMenuDialog extends SettingsDialog{ } }); - if(!gwt){ - graphics.sliderPref("fpscap", 125, 5, 125, 5, s -> (s > 120 ? Bundles.get("setting.fpscap.none") : Bundles.format("setting.fpscap.text", s))); + graphics.sliderPref("fpscap", 125, 5, 125, 5, s -> (s > 120 ? Bundles.get("setting.fpscap.none") : Bundles.format("setting.fpscap.text", s))); + graphics.checkPref("multithread", mobile, threads::setEnabled); + + if(Settings.getBool("multithread")){ + threads.setEnabled(true); } - if(!gwt){ - graphics.checkPref("multithread", mobile, threads::setEnabled); - if(Settings.getBool("multithread")){ - threads.setEnabled(true); - } - } - - if(!mobile && !gwt){ + if(!mobile){ graphics.checkPref("vsync", true, b -> Gdx.graphics.setVSync(b)); graphics.checkPref("fullscreen", false, b -> { if(b){ diff --git a/core/src/io/anuke/mindustry/ui/dialogs/TraceDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/TraceDialog.java index 2cb70b4346..7c58101b03 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/TraceDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/TraceDialog.java @@ -1,10 +1,5 @@ package io.anuke.mindustry.ui.dialogs; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.net.TraceInfo; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.util.Bundles; - public class TraceDialog extends FloatingDialog{ public TraceDialog(){ @@ -12,14 +7,15 @@ public class TraceDialog extends FloatingDialog{ addCloseButton(); } - - public void show(Player player, TraceInfo info){ +/* + public void show(Player player, SessionInfo info){ content().clear(); Table table = new Table("clear"); table.margin(14); table.defaults().pad(1); + /* table.defaults().left(); table.add(Bundles.format("text.trace.playername", player.name)); table.row(); @@ -50,10 +46,10 @@ public class TraceDialog extends FloatingDialog{ table.add(Bundles.format("text.trace.totalblocksplaced", info.totalBlocksPlaced)); table.row(); table.add(Bundles.format("text.trace.lastblockplaced", info.lastBlockPlaced.formalName)); - table.row();*/ + table.row(); content().add(table); show(); - } + }*/ } diff --git a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java index db13164fb4..125a26dd4d 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java @@ -127,7 +127,7 @@ public class HudFragment extends Fragment{ t.label(() -> tps.get(threads.getTPS())).visible(() -> threads.isEnabled()); t.row(); if(Net.hasClient()){ - t.label(() -> ping.get(Net.getPing())).visible(() -> Net.client() && !gwt).colspan(2); + t.label(() -> ping.get(Net.getPing())).visible(Net::client).colspan(2); } }).size(-1).visible(() -> Settings.getBool("fps")).update(t -> t.setTranslation(0, (!waves.isVisible() ? wavetable.getHeight() : Math.min(wavetable.getTranslation().y, wavetable.getHeight())) )).get(); diff --git a/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java b/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java index 703a8a6fb9..d86e3a51db 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java @@ -132,9 +132,7 @@ public class MenuFragment extends Fragment{ out.row(); - if(!gwt){ - out.add(new MenuButton("icon-exit", "$text.quit", Gdx.app::exit)).width(bw).colspan(2); - } + out.add(new MenuButton("icon-exit", "$text.quit", Gdx.app::exit)).width(bw).colspan(2); }); } @@ -153,12 +151,8 @@ public class MenuFragment extends Fragment{ dialog.content().row(); dialog.content().add(new MenuButton("icon-add", "$text.joingame", () -> { - if(!gwt){ - ui.join.show(); - dialog.hide(); - }else{ - ui.showInfo("$text.web.unsupported"); - } + ui.join.show(); + dialog.hide(); })); dialog.content().add(new MenuButton("icon-editor", "$text.customgame", () -> { diff --git a/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java b/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java index 2bd79e4a63..8b8633baf3 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java @@ -3,14 +3,12 @@ package io.anuke.mindustry.ui.fragments; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.g2d.Batch; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.NetConnection; import io.anuke.mindustry.net.Packets.AdminAction; import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Timers; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.scene.Group; @@ -73,7 +71,7 @@ public class PlayerListFragment extends Fragment{ float h = 74f; playerGroup.forEach(player -> { - NetConnection connection = gwt ? null : player.con; + NetConnection connection = player.con; if(connection == null && Net.server() && !player.isLocal) return; @@ -119,7 +117,7 @@ public class PlayerListFragment extends Fragment{ t.addImageButton("icon-admin", "toggle", 14 * 2, () -> { if(Net.client()) return; - String id = netServer.admins.getTraceByID(player.uuid).uuid; + String id = player.uuid; if(netServer.admins.isAdmin(id, connection.address)){ ui.showConfirm("$text.confirm", "$text.confirmunadmin", () -> netServer.admins.unAdminPlayer(id)); diff --git a/core/src/io/anuke/mindustry/world/BaseBlock.java b/core/src/io/anuke/mindustry/world/BaseBlock.java index 9561bf9449..6cc2c79119 100644 --- a/core/src/io/anuke/mindustry/world/BaseBlock.java +++ b/core/src/io/anuke/mindustry/world/BaseBlock.java @@ -40,9 +40,7 @@ public abstract class BaseBlock extends MappableContent{ return true; } - /** - * Returns the amount of items this block can accept. - */ + /**Returns the amount of items this block can accept.*/ public int acceptStack(Item item, int amount, Tile tile, Unit source){ if(acceptItem(item, tile, tile) && hasItems && (source == null || source.getTeam() == tile.getTeam())){ return Math.min(getMaximumAccepted(tile, item), amount); @@ -52,12 +50,10 @@ public abstract class BaseBlock extends MappableContent{ } public int getMaximumAccepted(Tile tile, Item item){ - return itemCapacity - (tile.entity.items.total() - tile.entity.items.get(item)); + return itemCapacity; } - /** - * Remove a stack from this inventory, and return the amount removed. - */ + /**Remove a stack from this inventory, and return the amount removed.*/ public int removeStack(Tile tile, Item item, int amount){ tile.entity.noSleep(); tile.entity.items.remove(item, amount); @@ -88,7 +84,8 @@ public abstract class BaseBlock extends MappableContent{ } public boolean acceptItem(Item item, Tile tile, Tile source){ - return tile.entity != null && consumes.has(ConsumeItem.class) && consumes.item() == item && tile.entity.items.get(item) < getMaximumAccepted(tile, item); + return tile.entity != null && consumes.has(ConsumeItem.class) && consumes.item() == item && + tile.entity.items.get(item) < getMaximumAccepted(tile, item); } public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ diff --git a/core/src/io/anuke/mindustry/world/Build.java b/core/src/io/anuke/mindustry/world/Build.java index 6bf1762586..d596422410 100644 --- a/core/src/io/anuke/mindustry/world/Build.java +++ b/core/src/io/anuke/mindustry/world/Build.java @@ -5,7 +5,7 @@ import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; import io.anuke.mindustry.content.blocks.Blocks; import io.anuke.mindustry.entities.Units; -import io.anuke.mindustry.game.EventType.BlockBuildEvent; +import io.anuke.mindustry.game.EventType.BlockBuildBeginEvent; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.Recipe; @@ -59,6 +59,8 @@ public class Build{ } } + Tile ftile = tile; + threads.runDelay(() -> Events.fire(new BlockBuildBeginEvent(ftile, team, true))); } /**Places a BuildBlock at this location.*/ @@ -100,8 +102,7 @@ public class Build{ } } - - threads.runDelay(() -> Events.fire(new BlockBuildEvent(tile, team))); + threads.runDelay(() -> Events.fire(new BlockBuildBeginEvent(tile, team, false))); } /**Returns whether a tile can be placed at this location by this team.*/ @@ -131,7 +132,7 @@ public class Build{ if(tile == null) return false; if(type.isMultiblock()){ - if(type.canReplace(tile.block()) && tile.block().size == type.size){ + if(type.canReplace(tile.block()) && tile.block().size == type.size && type.canPlaceOn(tile)){ return true; } diff --git a/core/src/io/anuke/mindustry/world/LegacyColorMapper.java b/core/src/io/anuke/mindustry/world/LegacyColorMapper.java index ea2232f4dc..bf35c27995 100644 --- a/core/src/io/anuke/mindustry/world/LegacyColorMapper.java +++ b/core/src/io/anuke/mindustry/world/LegacyColorMapper.java @@ -38,7 +38,7 @@ public class LegacyColorMapper implements ContentList{ map("f7feff", Blocks.snow, 1); map("6e501e", Blocks.dirt, 0); map("ed5334", Blocks.lava, 0); - map("292929", Blocks.oil, 0); + map("292929", Blocks.tar, 0); map("c3a490", OreBlocks.get(Blocks.stone, Items.copper), 0); map("161616", OreBlocks.get(Blocks.stone, Items.coal), 0); map("6277bc", OreBlocks.get(Blocks.stone, Items.titanium), 0); diff --git a/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java b/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java index be34438d0c..e2fe0f5865 100644 --- a/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java @@ -28,8 +28,8 @@ import io.anuke.ucore.core.Graphics; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Mathf; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import static io.anuke.mindustry.Vars.*; @@ -302,7 +302,7 @@ public class BuildBlock extends Block{ } @Override - public void write(DataOutputStream stream) throws IOException{ + public void write(DataOutput stream) throws IOException{ stream.writeFloat(progress); stream.writeShort(previous == null ? -1 : previous.id); stream.writeShort(recipe == null ? -1 : recipe.result.id); @@ -319,7 +319,7 @@ public class BuildBlock extends Block{ } @Override - public void read(DataInputStream stream) throws IOException{ + public void read(DataInput stream) throws IOException{ progress = stream.readFloat(); short pid = stream.readShort(); short rid = stream.readShort(); diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/Door.java b/core/src/io/anuke/mindustry/world/blocks/defense/Door.java index 6ae5589fc8..1c17e6e9d0 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/Door.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/Door.java @@ -12,8 +12,8 @@ import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Effects.Effect; import io.anuke.ucore.graphics.Draw; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import static io.anuke.mindustry.Vars.threads; @@ -89,14 +89,12 @@ public class Door extends Wall{ public boolean open = false; @Override - public void write(DataOutputStream stream) throws IOException{ - super.write(stream); + public void write(DataOutput stream) throws IOException{ stream.writeBoolean(open); } @Override - public void read(DataInputStream stream) throws IOException{ - super.read(stream); + public void read(DataInput stream) throws IOException{ open = stream.readBoolean(); } } diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/ForceProjector.java b/core/src/io/anuke/mindustry/world/blocks/defense/ForceProjector.java index 41ddb64976..343faa4a9e 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/ForceProjector.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/ForceProjector.java @@ -25,17 +25,17 @@ import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Fill; import io.anuke.ucore.util.Mathf; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import static io.anuke.mindustry.Vars.*; public class ForceProjector extends Block { protected int timerUse = timers ++; - protected float phaseUseTime = 250f; + protected float phaseUseTime = 350f; - protected float phaseRadiusBoost = 60f; + protected float phaseRadiusBoost = 80f; protected float radius = 100f; protected float breakage = 550f; protected float cooldownNormal = 1.75f; @@ -89,7 +89,7 @@ public class ForceProjector extends Block { entity.phaseHeat = Mathf.lerpDelta(entity.phaseHeat, (float)entity.items.get(consumes.item()) / itemCapacity, 0.1f); - if(!entity.broken && entity.timer.get(timerUse, phaseUseTime) && entity.items.total() > 0){ + if(entity.cons.valid() && !entity.broken && entity.timer.get(timerUse, phaseUseTime) && entity.items.total() > 0){ entity.items.remove(consumes.item(), 1); } @@ -197,7 +197,7 @@ public class ForceProjector extends Block { float phaseHeat; @Override - public void write(DataOutputStream stream) throws IOException{ + public void write(DataOutput stream) throws IOException{ stream.writeBoolean(broken); stream.writeFloat(buildup); stream.writeFloat(radscl); @@ -206,7 +206,7 @@ public class ForceProjector extends Block { } @Override - public void read(DataInputStream stream) throws IOException{ + public void read(DataInput stream) throws IOException{ broken = stream.readBoolean(); buildup = stream.readFloat(); radscl = stream.readFloat(); diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/MendProjector.java b/core/src/io/anuke/mindustry/world/blocks/defense/MendProjector.java index c8951d62c9..1119cf311f 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/MendProjector.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/MendProjector.java @@ -16,8 +16,8 @@ import io.anuke.ucore.graphics.Hue; import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.util.Mathf; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import static io.anuke.mindustry.Vars.tilesize; @@ -35,8 +35,8 @@ public class MendProjector extends Block{ protected float range = 50f; protected float healPercent = 6f; protected float phaseBoost = 12f; - protected float phaseRangeBoost = 40f; - protected float useTime = 300f; + protected float phaseRangeBoost = 50f; + protected float useTime = 400f; public MendProjector(String name){ super(name); @@ -61,7 +61,7 @@ public class MendProjector extends Block{ entity.phaseHeat = Mathf.lerpDelta(entity.phaseHeat, (float)entity.items.get(consumes.item()) / itemCapacity, 0.1f); - if(entity.timer.get(timerUse, useTime) && entity.items.total() > 0){ + if(entity.cons.valid() && entity.timer.get(timerUse, useTime) && entity.items.total() > 0){ entity.items.remove(consumes.item(), 1); } @@ -71,27 +71,25 @@ public class MendProjector extends Block{ Effects.effect(BlockFx.healWaveMend, Hue.mix(color, phase, entity.phaseHeat), tile.drawx(), tile.drawy(), realRange); entity.charge = 0f; - Timers.run(10f, () -> { - int tileRange = (int)(realRange / tilesize); - healed.clear(); + int tileRange = (int)(realRange / tilesize); + healed.clear(); - for(int x = -tileRange + tile.x; x <= tileRange + tile.x; x++){ - for(int y = -tileRange + tile.y; y <= tileRange + tile.y; y++){ - if(Vector2.dst(x, y, tile.x, tile.y) > realRange) continue; + for(int x = -tileRange + tile.x; x <= tileRange + tile.x; x++){ + for(int y = -tileRange + tile.y; y <= tileRange + tile.y; y++){ + if(Vector2.dst(x, y, tile.x, tile.y) > realRange) continue; - Tile other = world.tile(x, y); + Tile other = world.tile(x, y); - if(other == null) continue; - other = other.target(); + if(other == null) continue; + other = other.target(); - if(other.getTeamID() == tile.getTeamID() && !healed.contains(other.packedPosition()) && other.entity != null && other.entity.health < other.entity.maxHealth()){ - other.entity.healBy(other.entity.maxHealth() * (healPercent + entity.phaseHeat*phaseBoost)/100f); - Effects.effect(BlockFx.healBlockFull, Hue.mix(color, phase, entity.phaseHeat), other.drawx(), other.drawy(), other.block().size); - healed.add(other.packedPosition()); - } + if(other.getTeamID() == tile.getTeamID() && !healed.contains(other.packedPosition()) && other.entity != null && other.entity.health < other.entity.maxHealth()){ + other.entity.healBy(other.entity.maxHealth() * (healPercent + entity.phaseHeat*phaseBoost)/100f); + Effects.effect(BlockFx.healBlockFull, Hue.mix(color, phase, entity.phaseHeat), other.drawx(), other.drawy(), other.block().size); + healed.add(other.packedPosition()); } } - }); + } } } @@ -133,13 +131,13 @@ public class MendProjector extends Block{ float phaseHeat; @Override - public void write(DataOutputStream stream) throws IOException{ + public void write(DataOutput stream) throws IOException{ stream.writeFloat(heat); stream.writeFloat(phaseHeat); } @Override - public void read(DataInputStream stream) throws IOException{ + public void read(DataInput stream) throws IOException{ heat = stream.readFloat(); phaseHeat = stream.readFloat(); } diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/OverdriveProjector.java b/core/src/io/anuke/mindustry/world/blocks/defense/OverdriveProjector.java index 51bd6d852f..cb340d1e40 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/OverdriveProjector.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/OverdriveProjector.java @@ -16,8 +16,8 @@ import io.anuke.ucore.graphics.Hue; import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.util.Mathf; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import static io.anuke.mindustry.Vars.tilesize; @@ -34,8 +34,8 @@ public class OverdriveProjector extends Block{ protected float reload = 260f; protected float range = 80f; protected float speedBoost = 1.5f; - protected float speedBoostPhase = 0.5f; - protected float useTime = 300f; + protected float speedBoostPhase = 0.75f; + protected float useTime = 400f; public OverdriveProjector(String name){ super(name); @@ -133,13 +133,13 @@ public class OverdriveProjector extends Block{ float phaseHeat; @Override - public void write(DataOutputStream stream) throws IOException{ + public void write(DataOutput stream) throws IOException{ stream.writeFloat(heat); stream.writeFloat(phaseHeat); } @Override - public void read(DataInputStream stream) throws IOException{ + public void read(DataInput stream) throws IOException{ heat = stream.readFloat(); phaseHeat = stream.readFloat(); } 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 b6f394d74c..4d71e00681 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 @@ -122,7 +122,7 @@ public abstract class LiquidTurret extends Turret{ @Override public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ return super.acceptLiquid(tile, source, liquid, amount) && liquidAmmoMap.get(liquid) != null - && (tile.entity.liquids.current() == liquid || tile.entity.liquids.get(tile.entity.liquids.current()) < 0.01f); + && (tile.entity.liquids.current() == liquid || (liquidAmmoMap.containsKey(tile.entity.liquids.current()) && tile.entity.liquids.get(tile.entity.liquids.current()) <= liquidAmmoMap.get(tile.entity.liquids.current()).quantityMultiplier + 0.001f)); } } 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 1d86095bd8..5026064b88 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 @@ -31,8 +31,8 @@ import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.util.*; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import static io.anuke.mindustry.Vars.content; @@ -354,7 +354,7 @@ public abstract class Turret extends Block{ public TargetTrait target; @Override - public void write(DataOutputStream stream) throws IOException{ + public void write(DataOutput stream) throws IOException{ stream.writeByte(ammo.size); for(AmmoEntry entry : ammo){ stream.writeByte(entry.type.id); @@ -363,7 +363,7 @@ public abstract class Turret extends Block{ } @Override - public void read(DataInputStream stream) throws IOException{ + public void read(DataInput stream) throws IOException{ byte amount = stream.readByte(); for(int i = 0; i < amount; i++){ AmmoType type = content.getByID(ContentType.ammo, stream.readByte()); 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 cfc357c5bb..1abaf16411 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Conduit.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Conduit.java @@ -9,8 +9,8 @@ import io.anuke.mindustry.world.modules.LiquidModule; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Mathf; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; public class Conduit extends LiquidBlock{ @@ -136,12 +136,12 @@ public class Conduit extends LiquidBlock{ int blendshadowrot; @Override - public void write(DataOutputStream stream) throws IOException{ + public void write(DataOutput stream) throws IOException{ stream.writeFloat(smoothLiquid); } @Override - public void read(DataInputStream stream) throws IOException{ + public void read(DataInput stream) throws IOException{ smoothLiquid = stream.readFloat(); } } 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 63a2680e43..0a3af1b97d 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Conveyor.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Conveyor.java @@ -16,8 +16,8 @@ import io.anuke.ucore.core.Timers; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.*; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import static io.anuke.mindustry.Vars.*; @@ -159,7 +159,7 @@ public class Conveyor extends Block{ if(pos.item == null) continue; tr1.trns(rotation * 90, tilesize, 0); - tr2.trns(rotation * 90, -tilesize / 2, pos.x * tilesize / 2); + tr2.trns(rotation * 90, -tilesize / 2f, pos.x * tilesize / 2f); Draw.rect(pos.item.region, (int) (tile.x * tilesize + tr1.x * pos.y + tr2.x), @@ -384,7 +384,7 @@ public class Conveyor extends Block{ float clogHeat = 0f; @Override - public void write(DataOutputStream stream) throws IOException{ + public void write(DataOutput stream) throws IOException{ stream.writeInt(convey.size); for(int i = 0; i < convey.size; i++){ @@ -393,7 +393,7 @@ public class Conveyor extends Block{ } @Override - public void read(DataInputStream stream) throws IOException{ + public void read(DataInput stream) throws IOException{ convey.clear(); int amount = stream.readInt(); convey.ensureCapacity(amount); 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 ed3b5c3ebe..20bcb47b7a 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/ItemBridge.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/ItemBridge.java @@ -23,8 +23,8 @@ import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.util.Geometry; import io.anuke.ucore.util.Mathf; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import static io.anuke.mindustry.Vars.tilesize; @@ -325,7 +325,7 @@ public class ItemBridge extends Block{ public float cycleSpeed = 1f; @Override - public void write(DataOutputStream stream) throws IOException{ + public void write(DataOutput stream) throws IOException{ stream.writeInt(link); stream.writeFloat(uptime); stream.writeByte(incoming.size); @@ -338,7 +338,7 @@ public class ItemBridge extends Block{ } @Override - public void read(DataInputStream stream) throws IOException{ + public void read(DataInput stream) throws IOException{ link = stream.readInt(); uptime = stream.readFloat(); byte links = stream.readByte(); 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 7301b1a30f..8e33ea1e4d 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/MassDriver.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/MassDriver.java @@ -30,8 +30,8 @@ import io.anuke.ucore.util.Angles; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Pooling; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import static io.anuke.mindustry.Vars.*; @@ -322,13 +322,13 @@ public class MassDriver extends Block{ } @Override - public void write(DataOutputStream stream) throws IOException{ + public void write(DataOutput stream) throws IOException{ stream.writeInt(link); stream.writeFloat(rotation); } @Override - public void read(DataInputStream stream) throws IOException{ + public void read(DataInput stream) throws IOException{ link = stream.readInt(); rotation = stream.readFloat(); } 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 f942c6650c..f9da9999b8 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Sorter.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Sorter.java @@ -14,8 +14,8 @@ import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.util.Mathf; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import static io.anuke.mindustry.Vars.*; @@ -122,12 +122,12 @@ public class Sorter extends Block implements SelectionTrait{ public Item sortItem = content.item(0); @Override - public void write(DataOutputStream stream) throws IOException{ + public void writeConfig(DataOutput stream) throws IOException{ stream.writeByte(sortItem.id); } @Override - public void read(DataInputStream stream) throws IOException{ + public void readConfig(DataInput stream) throws IOException{ sortItem = content.items().get(stream.readByte()); } } 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 f034b3969c..5ea2c97709 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/WarpGate.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/WarpGate.java @@ -27,8 +27,8 @@ import io.anuke.ucore.scene.ui.ImageButton; import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.util.Mathf; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import static io.anuke.mindustry.Vars.tilesize; @@ -342,7 +342,7 @@ public class WarpGate extends PowerBlock{ public float time; @Override - public void write(DataOutputStream stream) throws IOException{ + public void write(DataOutput stream) throws IOException{ stream.writeByte(color); stream.writeBoolean(active); stream.writeFloat(activeScl); @@ -351,7 +351,7 @@ public class WarpGate extends PowerBlock{ } @Override - public void read(DataInputStream stream) throws IOException{ + public void read(DataInput stream) throws IOException{ color = stream.readByte(); active = stream.readBoolean(); activeScl = stream.readFloat(); diff --git a/core/src/io/anuke/mindustry/world/blocks/power/ItemGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/ItemGenerator.java index 450c984787..285cebb5fc 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/ItemGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/ItemGenerator.java @@ -17,8 +17,8 @@ import io.anuke.ucore.core.Timers; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Mathf; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import static io.anuke.mindustry.Vars.tilesize; @@ -121,12 +121,12 @@ public abstract class ItemGenerator extends PowerGenerator{ public float explosiveness; @Override - public void write(DataOutputStream stream) throws IOException{ + public void write(DataOutput stream) throws IOException{ stream.writeFloat(efficiency); } @Override - public void read(DataInputStream stream) throws IOException{ + public void read(DataInput stream) throws IOException{ efficiency = stream.readFloat(); } } diff --git a/core/src/io/anuke/mindustry/world/blocks/power/NuclearReactor.java b/core/src/io/anuke/mindustry/world/blocks/power/NuclearReactor.java index 8202f66615..43831f738c 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/NuclearReactor.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/NuclearReactor.java @@ -20,8 +20,8 @@ import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Translator; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import static io.anuke.mindustry.Vars.tilesize; @@ -202,14 +202,12 @@ public class NuclearReactor extends PowerGenerator{ public float flash; @Override - public void write(DataOutputStream stream) throws IOException{ - super.write(stream); + public void write(DataOutput stream) throws IOException{ stream.writeFloat(heat); } @Override - public void read(DataInputStream stream) throws IOException{ - super.read(stream); + public void read(DataInput stream) throws IOException{ heat = stream.readFloat(); } } 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 38e9963441..21d50003f1 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/PowerNode.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/PowerNode.java @@ -8,7 +8,6 @@ import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Layer; import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.world.Edges; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.PowerBlock; import io.anuke.mindustry.world.meta.BlockStat; @@ -17,7 +16,6 @@ import io.anuke.ucore.core.Settings; import io.anuke.ucore.core.Timers; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Lines; -import io.anuke.ucore.graphics.Shapes; import io.anuke.ucore.util.Angles; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Translator; @@ -99,6 +97,12 @@ public class PowerNode extends PowerBlock{ public void playerPlaced(Tile tile){ Tile before = world.tile(lastPlaced); if(linkValid(tile, before) && before.block() instanceof PowerNode){ + for(Tile near : before.entity.proximity()){ + if(near.target() == tile){ + lastPlaced = tile.packedPosition(); + return; + } + } Call.linkPowerNodes(null, tile, before); } @@ -139,11 +143,10 @@ public class PowerNode extends PowerBlock{ public void drawSelect(Tile tile){ super.drawSelect(tile); - Draw.color(Palette.power); Lines.stroke(1f); - Lines.poly(Edges.getPixelPolygon(laserRange), tile.worldx() - tilesize / 2, tile.worldy() - tilesize / 2, tilesize); - + Draw.color(Palette.accent); + Lines.poly(tile.drawx(), tile.drawy(), 50, laserRange*tilesize); Draw.reset(); } @@ -154,14 +157,10 @@ public class PowerNode extends PowerBlock{ Draw.color(Palette.accent); Lines.stroke(1f); - Lines.square(tile.drawx(), tile.drawy(), + Lines.circle(tile.drawx(), tile.drawy(), tile.block().size * tilesize / 2f + 1f + Mathf.absin(Timers.time(), 4f, 1f)); - Lines.stroke(1f); - - Lines.poly(Edges.getPixelPolygon(laserRange), tile.worldx() - tilesize / 2, tile.worldy() - tilesize / 2, tilesize); - - Draw.color(Palette.power); + Lines.poly(tile.drawx(), tile.drawy(), 50, laserRange*tilesize); for(int x = (int) (tile.x - laserRange); x <= tile.x + laserRange; x++){ for(int y = (int) (tile.y - laserRange); y <= tile.y + laserRange; y++){ @@ -172,7 +171,7 @@ public class PowerNode extends PowerBlock{ boolean linked = linked(tile, link); Draw.color(linked ? Palette.place : Palette.breakInvalid); - Lines.square(link.drawx(), link.drawy(), + Lines.circle(link.drawx(), link.drawy(), link.block().size * tilesize / 2f + 1f + (linked ? 0f : Mathf.absin(Timers.time(), 4f, 1f))); if((entity.power.links.size >= maxNodes || (link.block() instanceof PowerNode && link.entity.power.links.size >= ((PowerNode) link.block()).maxNodes)) && !linked){ @@ -188,11 +187,9 @@ public class PowerNode extends PowerBlock{ @Override public void drawPlace(int x, int y, int rotation, boolean valid){ - Draw.color(Palette.placing); Lines.stroke(1f); - - Lines.poly(Edges.getPixelPolygon(laserRange), x * tilesize - tilesize / 2, y * tilesize - tilesize / 2, tilesize); - + Draw.color(Palette.placing); + Lines.poly(x * tilesize + offset(), y * tilesize + offset(), 50, laserRange*tilesize); Draw.reset(); } @@ -202,14 +199,15 @@ public class PowerNode extends PowerBlock{ TileEntity entity = tile.entity(); - Draw.color(Palette.powerLaserFrom, Palette.powerLaserTo, 0f * (1f - flashScl) + Mathf.sin(Timers.time(), 1.7f, flashScl)); - for(int i = 0; i < entity.power.links.size; i++){ Tile link = world.tile(entity.power.links.get(i)); - if(linkValid(tile, link)) drawLaser(tile, link); + if(linkValid(tile, link) && (!(link.block() instanceof PowerNode) + || ((tile.block().size > link.block().size) || (tile.block().size == link.block().size && tile.id() < link.id())))){ + drawLaser(tile, link); + } } - Draw.color(); + Draw.reset(); } protected boolean linked(Tile tile, Tile other){ @@ -227,12 +225,12 @@ public class PowerNode extends PowerBlock{ TileEntity oe = link.entity(); return Vector2.dst(tile.drawx(), tile.drawy(), link.drawx(), link.drawy()) <= Math.max(laserRange * tilesize, - ((PowerNode) link.block()).laserRange * tilesize) - tilesize / 2f + ((PowerNode) link.block()).laserRange * tilesize) + (link.block().size - 1) * tilesize / 2f + (tile.block().size - 1) * tilesize / 2f && (!checkMaxNodes || (oe.power.links.size < ((PowerNode) link.block()).maxNodes || oe.power.links.contains(tile.packedPosition()))); }else{ return Vector2.dst(tile.drawx(), tile.drawy(), link.drawx(), link.drawy()) - <= laserRange * tilesize - tilesize / 2f + (link.block().size - 1) * tilesize; + <= laserRange * tilesize + (link.block().size - 1) * tilesize; } } @@ -243,11 +241,31 @@ public class PowerNode extends PowerBlock{ float angle1 = Angles.angle(x1, y1, x2, y2); float angle2 = angle1 + 180f; - t1.trns(angle1, tile.block().size * tilesize / 2f + 1f); - t2.trns(angle2, target.block().size * tilesize / 2f + 1f); + t1.trns(angle1, tile.block().size * tilesize / 2f - 1f); + t2.trns(angle2, target.block().size * tilesize / 2f - 1f); - Shapes.laser("laser", "laser-end", x1 + t1.x, y1 + t1.y, - x2 + t2.x, y2 + t2.y, thicknessScl); + x1 += t1.x; + y1 += t1.y; + x2 += t2.x; + y2 += t2.y; + + float space = Vector2.dst(x1, y1, x2, y2); + float scl = 4f, mag = 2f, tscl = 4f, segscl = 3f; + + int segments = Mathf.ceil(space / segscl); + + Draw.color(Palette.power, Palette.powerLight, Mathf.absin(Timers.time(), 5f, 1f)); + Lines.stroke(1f); + + for(int i = 0; i < segments; i++){ + float f1 = (float)i / segments; + float f2 = (float)(i+1) / segments; + t1.trns(angle1 + 90f, Mathf.lerp(Mathf.sin(tile.entity.id * 124f + Timers.time()/tscl + f1 * space, scl, mag), 0f, Math.abs(f1 - 0.5f)*2f)); + t2.trns(angle1 + 90f, Mathf.lerp(Mathf.sin(tile.entity.id * 124f + Timers.time()/tscl + f2 * space, scl, mag), 0f, Math.abs(f2 - 0.5f)*2f)); + + Lines.line(x1 + (x2 - x1) * f1 + t1.x, y1 + (y2 - y1) * f1 + t1.y, + x1 + (x2 - x1) * f2 + t2.x, y1 + (y2 - y1) * f2 + t2.y); + } } } diff --git a/core/src/io/anuke/mindustry/world/blocks/production/Cultivator.java b/core/src/io/anuke/mindustry/world/blocks/production/Cultivator.java index 02256c0646..65eacb6ef7 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Cultivator.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Cultivator.java @@ -15,8 +15,8 @@ import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.SeedRandom; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; public class Cultivator extends Drill{ @@ -113,12 +113,12 @@ public class Cultivator extends Drill{ public float warmup; @Override - public void write(DataOutputStream stream) throws IOException{ + public void write(DataOutput stream) throws IOException{ stream.writeFloat(warmup); } @Override - public void read(DataInputStream stream) throws IOException{ + public void read(DataInput stream) throws IOException{ warmup = stream.readFloat(); } } 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 3de1799dd3..a0e08537f3 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/GenericCrafter.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/GenericCrafter.java @@ -18,8 +18,8 @@ import io.anuke.ucore.core.Timers; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Mathf; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; public class GenericCrafter extends Block{ @@ -125,13 +125,13 @@ public class GenericCrafter extends Block{ public float warmup; @Override - public void write(DataOutputStream stream) throws IOException{ + public void write(DataOutput stream) throws IOException{ stream.writeFloat(progress); stream.writeFloat(warmup); } @Override - public void read(DataInputStream stream) throws IOException{ + public void read(DataInput stream) throws IOException{ progress = stream.readFloat(); warmup = stream.readFloat(); } 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 0b25ea2782..a1e587315a 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/PowerSmelter.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/PowerSmelter.java @@ -19,8 +19,8 @@ import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Fill; import io.anuke.ucore.util.Mathf; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import static io.anuke.mindustry.Vars.*; @@ -172,7 +172,7 @@ public class PowerSmelter extends PowerBlock{ @Override public int getMaximumAccepted(Tile tile, Item item){ - return itemCapacity - tile.entity.items.get(item); + return itemCapacity; } @Override @@ -210,12 +210,12 @@ public class PowerSmelter extends PowerBlock{ public float craftTime; @Override - public void write(DataOutputStream stream) throws IOException{ + public void write(DataOutput stream) throws IOException{ stream.writeFloat(heat); } @Override - public void read(DataInputStream stream) throws IOException{ + public void read(DataInput stream) throws IOException{ heat = stream.readFloat(); } } 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 37b412a012..49042d4180 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Smelter.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Smelter.java @@ -154,7 +154,7 @@ public class Smelter extends Block{ @Override public int getMaximumAccepted(Tile tile, Item item){ - return itemCapacity - tile.entity.items.get(item); + return itemCapacity; } @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 3df2db69d3..591344afdb 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java @@ -30,8 +30,8 @@ import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.util.EnumSet; import io.anuke.ucore.util.Mathf; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import static io.anuke.mindustry.Vars.*; @@ -246,13 +246,13 @@ public class CoreBlock extends StorageBlock{ } @Override - public void write(DataOutputStream stream) throws IOException{ + public void write(DataOutput stream) throws IOException{ stream.writeBoolean(solid); stream.writeInt(droneID); } @Override - public void read(DataInputStream stream) throws IOException{ + public void read(DataInput stream) throws IOException{ solid = stream.readBoolean(); droneID = stream.readInt(); } 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 c4677747e5..c50509f413 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/SortedUnloader.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/SortedUnloader.java @@ -12,8 +12,8 @@ import io.anuke.mindustry.world.blocks.SelectionTrait; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.scene.ui.layout.Table; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import static io.anuke.mindustry.Vars.*; @@ -75,12 +75,12 @@ public class SortedUnloader extends Unloader implements SelectionTrait{ public Item sortItem = null; @Override - public void write(DataOutputStream stream) throws IOException{ + public void writeConfig(DataOutput stream) throws IOException{ stream.writeByte(sortItem == null ? -1 : sortItem.id); } @Override - public void read(DataInputStream stream) throws IOException{ + public void readConfig(DataInput stream) throws IOException{ byte id = stream.readByte(); sortItem = id == -1 ? null : content.items().get(id); } 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 25c816a52a..87e672e337 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/CommandCenter.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/CommandCenter.java @@ -24,8 +24,8 @@ import io.anuke.ucore.scene.ui.ImageButton; import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.util.EnumSet; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import static io.anuke.mindustry.Vars.*; @@ -115,12 +115,12 @@ public class CommandCenter extends Block{ public UnitCommand command = UnitCommand.attack; @Override - public void write(DataOutputStream stream) throws IOException{ + public void writeConfig(DataOutput stream) throws IOException{ stream.writeByte(command.ordinal()); } @Override - public void read(DataInputStream stream) throws IOException{ + public void readConfig(DataInput stream) throws IOException{ command = UnitCommand.values()[stream.readByte()]; } } diff --git a/core/src/io/anuke/mindustry/world/blocks/units/DropPoint.java b/core/src/io/anuke/mindustry/world/blocks/units/DropPoint.java deleted file mode 100644 index 8acdf20be9..0000000000 --- a/core/src/io/anuke/mindustry/world/blocks/units/DropPoint.java +++ /dev/null @@ -1,28 +0,0 @@ -package io.anuke.mindustry.world.blocks.units; - -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Tile; - -public class DropPoint extends Block{ - - public DropPoint(String name){ - super(name); - - hasItems = true; - solid = true; - update = true; - } - - @Override - public boolean acceptItem(Item item, Tile tile, Tile source){ - return false; - } - - @Override - public void update(Tile tile){ - if(tile.entity.items.total() > 0){ - tryDump(tile); - } - } -} diff --git a/core/src/io/anuke/mindustry/world/blocks/units/MechPad.java b/core/src/io/anuke/mindustry/world/blocks/units/MechPad.java index 2370dbe295..38cec398f8 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/MechPad.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/MechPad.java @@ -27,8 +27,8 @@ import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.util.Geometry; import io.anuke.ucore.util.Mathf; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import static io.anuke.mindustry.Vars.mobile; @@ -237,14 +237,14 @@ public class MechPad extends Block{ } @Override - public void write(DataOutputStream stream) throws IOException{ + public void write(DataOutput stream) throws IOException{ stream.writeFloat(progress); stream.writeFloat(time); stream.writeFloat(heat); } @Override - public void read(DataInputStream stream) throws IOException{ + public void read(DataInput stream) throws IOException{ progress = stream.readFloat(); time = stream.readFloat(); heat = stream.readFloat(); 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 b55fe56774..066f8584f2 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/Reconstructor.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/Reconstructor.java @@ -23,8 +23,8 @@ import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.util.Mathf; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import static io.anuke.mindustry.Vars.*; @@ -329,12 +329,12 @@ public class Reconstructor extends Block{ } @Override - public void write(DataOutputStream stream) throws IOException{ + public void write(DataOutput stream) throws IOException{ stream.writeInt(link); } @Override - public void read(DataInputStream stream) throws IOException{ + public void read(DataInput stream) throws IOException{ link = stream.readInt(); } } diff --git a/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java b/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java index ae28270215..ae7b2f98c5 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java @@ -30,8 +30,8 @@ import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.util.EnumSet; import io.anuke.ucore.util.Mathf; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; public class UnitFactory extends Block{ @@ -227,13 +227,13 @@ public class UnitFactory extends Block{ public float warmup; //only for enemy spawners @Override - public void write(DataOutputStream stream) throws IOException{ + public void write(DataOutput stream) throws IOException{ stream.writeFloat(buildTime); stream.writeFloat(warmup); } @Override - public void read(DataInputStream stream) throws IOException{ + public void read(DataInput stream) throws IOException{ buildTime = stream.readFloat(); warmup = stream.readFloat(); } diff --git a/core/src/io/anuke/mindustry/world/modules/BlockModule.java b/core/src/io/anuke/mindustry/world/modules/BlockModule.java index 225b7c3e9d..3d3e003b4e 100644 --- a/core/src/io/anuke/mindustry/world/modules/BlockModule.java +++ b/core/src/io/anuke/mindustry/world/modules/BlockModule.java @@ -4,8 +4,8 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; +/**A class that represents compartmentalized tile entity state.*/ public abstract class BlockModule{ public abstract void write(DataOutput stream) throws IOException; - public abstract void read(DataInput stream) throws IOException; } diff --git a/core/src/io/anuke/mindustry/world/modules/PowerModule.java b/core/src/io/anuke/mindustry/world/modules/PowerModule.java index 9a376ab2bf..96b889209a 100644 --- a/core/src/io/anuke/mindustry/world/modules/PowerModule.java +++ b/core/src/io/anuke/mindustry/world/modules/PowerModule.java @@ -9,26 +9,9 @@ import java.io.IOException; public class PowerModule extends BlockModule{ public float amount; - public float capacity = 10f; - public float voltage = 0.0001f; public PowerGraph graph = new PowerGraph(); public IntArray links = new IntArray(); - public boolean acceptsPower(){ - return amount + 0.001f <= capacity; - } - - public float addPower(float add){ - if(add < voltage){ - return add; - } - - float canAccept = Math.min(capacity - amount, add); - amount += canAccept; - - return canAccept; - } - @Override public void write(DataOutput stream) throws IOException{ stream.writeFloat(amount); diff --git a/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java b/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java index 1aa16995f2..5dfbea48eb 100644 --- a/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java +++ b/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java @@ -6,11 +6,9 @@ import club.minnced.discord.rpc.DiscordRichPresence; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Base64Coder; -import io.anuke.kryonet.DefaultThreadImpl; import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.Platform; -import io.anuke.mindustry.core.ThreadHandler.ThreadProvider; import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.ui.dialogs.FileChooser; @@ -24,7 +22,6 @@ import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Enumeration; -import java.util.Locale; import static io.anuke.mindustry.Vars.*; @@ -60,11 +57,6 @@ public class DesktopPlatform extends Platform{ return NumberFormat.getIntegerInstance().format(number); } - @Override - public String getLocaleName(Locale locale){ - return locale.getDisplayName(locale); - } - @Override public void updateRPC(){ @@ -74,7 +66,9 @@ public class DesktopPlatform extends Platform{ if(!state.is(State.menu)){ presence.state = Strings.capitalize(state.mode.name()); - if(state.mode == GameMode.noWaves){ + if(world.getMap() == null){ + presence.details = "Unknown Map"; + }else if(state.mode.disableWaves){ presence.details = Strings.capitalize(world.getMap().name); }else{ presence.details = Strings.capitalize(world.getMap().name) + " | Wave " + state.wave; @@ -110,11 +104,6 @@ public class DesktopPlatform extends Platform{ if(useDiscord) DiscordRPC.INSTANCE.Discord_Shutdown(); } - @Override - public ThreadProvider getThreadProvider(){ - return new DefaultThreadImpl(); - } - @Override public String getUUID(){ try{ diff --git a/html/build.gradle b/html/build.gradle deleted file mode 100644 index 6b49291540..0000000000 --- a/html/build.gradle +++ /dev/null @@ -1,65 +0,0 @@ -apply plugin: "java" - -gwt { - gwtVersion='2.8.0' // Should match the gwt version used for building the gwt backend - maxHeapSize="2G" // Default 256m is not enough for gwt compiler. GWT is HUNGRY - minHeapSize="1G" - - src = files(file("src/")) // Needs to be in front of "modules" below. - modules 'io.anuke.mindustry.GdxDefinition' - devModules 'io.anuke.mindustry.GdxDefinitionSuperdev' - project.webAppDirName = 'webapp' - - compiler { - strict = true - disableCastChecking = true - //style = de.richsource.gradle.plugins.gwt.Style.DETAILED - } -} - -task dist(dependsOn: [clean, compileGwt]) { - doLast { - file("build/dist").mkdirs() - copy { - from "build/gwt/out" - into "build/dist" - } - copy { - from "webapp" - into "build/dist" - } - copy { - from "war" - into "build/dist" - } - } -} - -task distZip(type: Zip, dependsOn: dist){ - from "build/dist" - archiveName appName + "-html5.zip" - destinationDir(file("build/dist-zipped")) -} - -draftWar { - from "war" -} - -task addSource{ - doLast{ - sourceSets.main.compileClasspath += files(project(':core').sourceSets.main.allJava.srcDirs) - //this WILL fail if uCore is not a module - sourceSets.main.compileClasspath += files(project(':uCore').sourceSets.main.allJava.srcDirs) - } -} - -tasks.compileGwt.dependsOn(addSource) -tasks.draftCompileGwt.dependsOn(addSource) - -sourceCompatibility = 1.8 -sourceSets.main.java.srcDirs = [ "src/" ] - - -eclipse.project { - name = appName + "-html" -} diff --git a/html/src/io/anuke/mindustry/GdxDefinition.gwt.xml b/html/src/io/anuke/mindustry/GdxDefinition.gwt.xml deleted file mode 100644 index 15601ef897..0000000000 --- a/html/src/io/anuke/mindustry/GdxDefinition.gwt.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/html/src/io/anuke/mindustry/GdxDefinitionSuperdev.gwt.xml b/html/src/io/anuke/mindustry/GdxDefinitionSuperdev.gwt.xml deleted file mode 100644 index 2066c6820b..0000000000 --- a/html/src/io/anuke/mindustry/GdxDefinitionSuperdev.gwt.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/html/src/io/anuke/mindustry/client/HtmlLauncher.java b/html/src/io/anuke/mindustry/client/HtmlLauncher.java deleted file mode 100644 index 5215771eda..0000000000 --- a/html/src/io/anuke/mindustry/client/HtmlLauncher.java +++ /dev/null @@ -1,224 +0,0 @@ -package io.anuke.mindustry.client; - -import com.badlogic.gdx.ApplicationListener; -import com.badlogic.gdx.backends.gwt.GwtApplication; -import com.badlogic.gdx.backends.gwt.GwtApplicationConfiguration; -import com.badlogic.gdx.backends.gwt.preloader.Preloader.PreloaderCallback; -import com.badlogic.gdx.backends.gwt.preloader.Preloader.PreloaderState; -import com.badlogic.gdx.files.FileHandle; -import com.badlogic.gdx.utils.Base64Coder; -import com.google.gwt.core.client.GWT; -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.NodeList; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.i18n.client.NumberFormat; -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.ucore.function.Consumer; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.Date; - -public class HtmlLauncher extends GwtApplication { - static final int WIDTH = 800; - static final int HEIGHT = 600; - static HtmlLauncher instance; - static Consumer fileCons; - - @Override - public PreloaderCallback getPreloaderCallback () { - final Panel preloaderPanel = new VerticalPanel(); - preloaderPanel.setStyleName("gdx-preloader"); - final Image logo = new Image(GWT.getModuleBaseURL() + "logo.png"); - logo.setStyleName("logo"); - preloaderPanel.add(logo); - final Panel meterPanel = new SimplePanel(); - meterPanel.setStyleName("gdx-meter"); - meterPanel.addStyleName("red"); - final InlineHTML meter = new InlineHTML(); - final Style meterStyle = meter.getElement().getStyle(); - meterStyle.setWidth(0, Unit.PCT); - meterPanel.add(meter); - preloaderPanel.add(meterPanel); - getRootPanel().add(preloaderPanel); - return new PreloaderCallback() { - @Override - public void error (String file) { - System.out.println("error: " + file); - } - - @Override - public void update (PreloaderState state) { - meterStyle.setWidth(100f * state.getProgress(), Unit.PCT); - } - }; - } - - @Override - public GwtApplicationConfiguration getConfig() { - GwtApplicationConfiguration config = new GwtApplicationConfiguration(WIDTH, HEIGHT); - - Element element = Document.get().getElementById("embed-html"); - VerticalPanel panel = new VerticalPanel(); - panel.setWidth("100%"); - panel.setHeight("100%"); - panel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER); - panel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE); - element.appendChild(panel.getElement()); - config.rootPanel = panel; - config.width = 2000; - config.height = 2000; - - return config; - } - - @Override - public ApplicationListener createApplicationListener() { - instance = this; - setLogLevel(LOG_NONE); - setLoadingListener(new LoadingListener() { - @Override - public void beforeSetup() { - - } - - @Override - public void afterSetup() { - scaleCanvas(); - setupResizeHook(); - } - }); - - Platform.instance = new Platform(){ - DateTimeFormat format = DateTimeFormat.getFormat("EEE, dd MMM yyyy HH:mm:ss"); - - @Override - public void showFileChooser(String text, String content, Consumer cons, boolean open, String filetype) { - if(!open) return; //can't save files on gwt - - fileCons = cons; - createFileChooser(); - } - - @Override - public String format(Date date){ - return format.format(date); - } - - @Override - public String format(int number){ - return NumberFormat.getDecimalFormat().format(number); - } - - @Override - public void downloadFile(String name, byte[] bytes) { - downloadBytes(name, new String(Base64Coder.encode(bytes))); - } - }; - - return new Mindustry(); - } - - void scaleCanvas() { - Element element = Document.get().getElementById("embed-html"); - int innerWidth = getWindowInnerWidth(); - int innerHeight = getWindowInnerHeight(); - int newWidth = innerWidth; - int newHeight = innerHeight; - float ratio = innerWidth / (float) innerHeight; - float viewRatio = WIDTH / (float) HEIGHT; - - if (ratio > viewRatio) { - newWidth = (int) (innerHeight * viewRatio); - } else { - newHeight = (int) (innerWidth / viewRatio); - } - - NodeList nl = element.getElementsByTagName("canvas"); - - if (nl != null && nl.getLength() > 0) { - Element canvas = nl.getItem(0); - canvas.setAttribute("width", "" + newWidth + "px"); - canvas.setAttribute("height", "" + newHeight + "px"); - canvas.getStyle().setWidth(newWidth, Style.Unit.PX); - canvas.getStyle().setHeight(newHeight, Style.Unit.PX); - canvas.getStyle().setTop((int) ((innerHeight - newHeight) * 0.5f), Style.Unit.PX); - canvas.getStyle().setLeft((int) ((innerWidth - newWidth) * 0.5f), Style.Unit.PX); - canvas.getStyle().setPosition(Style.Position.ABSOLUTE); - } - } - - native void createFileChooser() /*-{ - function getBase64(file, callback) { - var reader = new FileReader(); - reader.readAsDataURL(file); - reader.onload = function(){ callback(reader.result); } - reader.onerror = function(error){ console.log(error); } - } - - var input = document.createElement('input'); - input.type = 'file'; - input.onchange = function() { - getBase64(input.files[0], function(data){ @io.anuke.mindustry.client.HtmlLauncher::handleFileSelect(Ljava/lang/String;)(data); }); - }; - input.click(); - }-*/; - - native void downloadBytes(String name, String base64) /*-{ - var binaryString = window.atob(base64); - var binaryLen = binaryString.length; - var bytes = new Uint8Array(binaryLen); - for (var i = 0; i < binaryLen; i++) { - var ascii = binaryString.charCodeAt(i); - bytes[i] = ascii; - } - - var blob = new Blob([bytes]); - var link = document.createElement('a'); - link.href = window.URL.createObjectURL(blob); - link.download = name; - link.click(); - }-*/; - - native int getWindowInnerWidth() /*-{ - return $wnd.innerWidth; - }-*/; - - native int getWindowInnerHeight() /*-{ - return $wnd.innerHeight; - }-*/; - - native void setupResizeHook() /*-{ - var htmlLauncher_onWindowResize = $entry(@io.anuke.mindustry.client.HtmlLauncher::handleResize()); - $wnd.addEventListener('resize', htmlLauncher_onWindowResize, false); - }-*/; - - public static void handleResize() { - instance.scaleCanvas(); - } - - public static void handleFileSelect(String base64){ - ByteArrayInputStream stream = new ByteArrayInputStream(Base64Coder.decode(base64.substring("data:;base64,".length()))); - fileCons.accept(new FileHandle(){ - @Override - public InputStream read() { - return stream; - } - - @Override - public String nameWithoutExtension() { - return "unknown"; - } - - @Override - public String name() { - return "unknown"; - } - }); - } -} diff --git a/html/webapp/WEB-INF/web.xml b/html/webapp/WEB-INF/web.xml deleted file mode 100644 index 4301df2483..0000000000 --- a/html/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/html/webapp/html/logo.png b/html/webapp/html/logo.png deleted file mode 100644 index be1282d3c5..0000000000 Binary files a/html/webapp/html/logo.png and /dev/null differ diff --git a/html/webapp/index.html b/html/webapp/index.html deleted file mode 100644 index 9418769dab..0000000000 --- a/html/webapp/index.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - Mindustry - - - - - - - -
- - - - diff --git a/html/webapp/soundmanager2-jsmin.js b/html/webapp/soundmanager2-jsmin.js deleted file mode 100644 index ed5bf17df4..0000000000 --- a/html/webapp/soundmanager2-jsmin.js +++ /dev/null @@ -1,113 +0,0 @@ -/** @license - - - SoundManager 2: JavaScript Sound for the Web - ---------------------------------------------- - http://schillmania.com/projects/soundmanager2/ - - Copyright (c) 2007, Scott Schiller. All rights reserved. - Code provided under the BSD License: - http://schillmania.com/projects/soundmanager2/license.txt - - V2.97a.20150601 -*/ -(function(h,g){function K(sb,K){function ha(b){return c.preferFlash&&H&&!c.ignoreFlash&&c.flash[b]!==g&&c.flash[b]}function r(b){return function(d){var e=this._s;e&&e._a?d=b.call(this,d):(e&&e.id?c._wD(e.id+": Ignoring "+d.type):c._wD("HTML5::Ignoring "+d.type),d=null);return d}}this.setupOptions={url:sb||null,flashVersion:8,debugMode:!1,debugFlash:!1,useConsole:!0,consoleOnly:!0,waitForWindowLoad:!1,bgColor:"#ffffff",useHighPerformance:!1,flashPollingInterval:null,html5PollingInterval:null,flashLoadTimeout:1E3, -wmode:null,allowScriptAccess:"always",useFlashBlock:!1,useHTML5Audio:!0,forceUseGlobalHTML5Audio:!1,ignoreMobileRestrictions:!1,html5Test:/^(probably|maybe)$/i,preferFlash:!1,noSWFCache:!1,idPrefix:"sound"};this.defaultOptions={autoLoad:!1,autoPlay:!1,from:null,loops:1,onid3:null,onload:null,whileloading:null,onplay:null,onpause:null,onresume:null,whileplaying:null,onposition:null,onstop:null,onfailure:null,onfinish:null,multiShot:!0,multiShotEvents:!1,position:null,pan:0,stream:!0,to:null,type:null, -usePolicyFile:!1,volume:100};this.flash9Options={isMovieStar:null,usePeakData:!1,useWaveformData:!1,useEQData:!1,onbufferchange:null,ondataerror:null};this.movieStarOptions={bufferTime:3,serverURL:null,onconnect:null,duration:null};this.audioFormats={mp3:{type:['audio/mpeg; codecs="mp3"',"audio/mpeg","audio/mp3","audio/MPA","audio/mpa-robust"],required:!0},mp4:{related:["aac","m4a","m4b"],type:['audio/mp4; codecs="mp4a.40.2"',"audio/aac","audio/x-m4a","audio/MP4A-LATM","audio/mpeg4-generic"],required:!1}, -ogg:{type:["audio/ogg; codecs=vorbis"],required:!1},opus:{type:["audio/ogg; codecs=opus","audio/opus"],required:!1},wav:{type:['audio/wav; codecs="1"',"audio/wav","audio/wave","audio/x-wav"],required:!1}};this.movieID="sm2-container";this.id=K||"sm2movie";this.debugID="soundmanager-debug";this.debugURLParam=/([#?&])debug=1/i;this.versionNumber="V2.97a.20150601";this.altURL=this.movieURL=this.version=null;this.enabled=this.swfLoaded=!1;this.oMC=null;this.sounds={};this.soundIDs=[];this.didFlashBlock= -this.muted=!1;this.filePattern=null;this.filePatterns={flash8:/\.mp3(\?.*)?$/i,flash9:/\.mp3(\?.*)?$/i};this.features={buffering:!1,peakData:!1,waveformData:!1,eqData:!1,movieStar:!1};this.sandbox={type:null,types:{remote:"remote (domain-based) rules",localWithFile:"local with file access (no internet access)",localWithNetwork:"local with network (internet access only, no local access)",localTrusted:"local, trusted (local+internet access)"},description:null,noRemote:null,noLocal:null};this.html5= -{usingFlash:null};this.flash={};this.ignoreFlash=this.html5Only=!1;var W,c=this,Ya=null,l=null,F,v=navigator.userAgent,ia=h.location.href.toString(),m=document,ya,Za,za,n,I=[],Aa=!0,D,X=!1,Y=!1,q=!1,y=!1,ja=!1,p,tb=0,Z,A,Ba,R,Ca,P,S,T,$a,Da,Ea,ka,z,la,Q,Fa,aa,ma,na,U,ab,Ga,bb=["log","info","warn","error"],cb,Ha,db,ba=null,Ia=null,t,Ja,V,eb,oa,pa,L,w,ca=!1,Ka=!1,fb,gb,hb,qa=0,da=null,ra,M=[],ea,u=null,ib,sa,fa,N,ta,La,jb,x,kb=Array.prototype.slice,C=!1,Ma,H,Na,lb,J,mb,Oa,ua,nb=0,Pa,Qa=v.match(/(ipad|iphone|ipod)/i), -Ra=v.match(/android/i),O=v.match(/msie/i),ub=v.match(/webkit/i),va=v.match(/safari/i)&&!v.match(/chrome/i),Sa=v.match(/opera/i),wa=v.match(/(mobile|pre\/|xoom)/i)||Qa||Ra,Ta=!ia.match(/usehtml5audio/i)&&!ia.match(/sm2\-ignorebadua/i)&&va&&!v.match(/silk/i)&&v.match(/OS X 10_6_([3-7])/i),Ua=h.console!==g&&console.log!==g,Va=m.hasFocus!==g?m.hasFocus():null,xa=va&&(m.hasFocus===g||!m.hasFocus()),ob=!xa,pb=/(mp3|mp4|mpa|m4a|m4b)/i,ga=m.location?m.location.protocol.match(/http/i):null,vb=ga?"":"http://", -qb=/^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i,rb="mpeg4 aac flv mov mp4 m4v f4v m4a m4b mp4v 3gp 3g2".split(" "),wb=new RegExp("\\.("+rb.join("|")+")(\\?.*)?$","i");this.mimePattern=/^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i;this.useAltURL=!ga;var Wa;try{Wa=Audio!==g&&(Sa&&opera!==g&&10>opera.version()?new Audio(null):new Audio).canPlayType!==g}catch(xb){Wa=!1}this.hasHTML5=Wa;this.setup=function(b){var d=!c.url;b!==g&&q&&u&&c.ok()&&(b.flashVersion!==g|| -b.url!==g||b.html5Test!==g)&&L(t("setupLate"));Ba(b);if(!C)if(wa){if(!c.setupOptions.ignoreMobileRestrictions||c.setupOptions.forceUseGlobalHTML5Audio)M.push(z.globalHTML5),C=!0}else c.setupOptions.forceUseGlobalHTML5Audio&&(M.push(z.globalHTML5),C=!0);if(!Pa&&wa)if(c.setupOptions.ignoreMobileRestrictions)M.push(z.ignoreMobile);else if(c.setupOptions.useHTML5Audio&&!c.setupOptions.preferFlash||c._wD(z.mobileUA),c.setupOptions.useHTML5Audio=!0,c.setupOptions.preferFlash=!1,Qa)c.ignoreFlash=!0;else if(Ra&& -!v.match(/android\s2\.3/i)||!Ra)c._wD(z.globalHTML5),C=!0;b&&(d&&aa&&b.url!==g&&c.beginDelayedInit(),aa||b.url===g||"complete"!==m.readyState||setTimeout(Q,1));Pa=!0;return c};this.supported=this.ok=function(){return u?q&&!y:c.useHTML5Audio&&c.hasHTML5};this.getMovie=function(c){return F(c)||m[c]||h[c]};this.createSound=function(b,d){function e(){f=oa(f);c.sounds[f.id]=new W(f);c.soundIDs.push(f.id);return c.sounds[f.id]}var a,f;a=null;a="soundManager.createSound(): "+t(q?"notOK":"notReady");if(!q|| -!c.ok())return L(a),!1;d!==g&&(b={id:b,url:d});f=A(b);f.url=ra(f.url);f.id===g&&(f.id=c.setupOptions.idPrefix+nb++);f.id.toString().charAt(0).match(/^[0-9]$/)&&c._wD("soundManager.createSound(): "+t("badID",f.id),2);c._wD("soundManager.createSound(): "+f.id+(f.url?" ("+f.url+")":""),1);if(w(f.id,!0))return c._wD("soundManager.createSound(): "+f.id+" exists",1),c.sounds[f.id];if(sa(f))a=e(),c.html5Only||c._wD(f.id+": Using HTML5"),a._setup_html5(f);else{if(c.html5Only)return c._wD(f.id+": No HTML5 support for this sound, and no Flash. Exiting."), -e();if(c.html5.usingFlash&&f.url&&f.url.match(/data\:/i))return c._wD(f.id+": data: URIs not supported via Flash. Exiting."),e();8a.instanceCount?(m(),e=a._setup_html5(),a.setPosition(a._iO.position),e.play()):(c._wD(a.id+": Cloning Audio() for instance #"+ -a.instanceCount+"..."),k=new Audio(a._iO.url),G=function(){x.remove(k,"ended",G);a._onfinish(a);ta(k);k=null},h=function(){x.remove(k,"canplay",h);try{k.currentTime=a._iO.position/1E3}catch(c){L(a.id+": multiShot play() failed to apply position of "+a._iO.position/1E3)}k.play()},x.add(k,"ended",G),a._iO.volume!==g&&(k.volume=Math.max(0,Math.min(1,a._iO.volume/100))),a.muted&&(k.muted=!0),a._iO.position?x.add(k,"canplay",h):k.play()):(B=l._start(a.id,a._iO.loops||1,9===n?a.position:a.position/1E3, -a._iO.multiShot||!1),9!==n||B||(c._wD(e+"No sound hardware, or 32-sound ceiling hit",2),a._iO.onplayerror&&a._iO.onplayerror.apply(a)))}return a};this.stop=function(b){var d=a._iO;1===a.playState&&(c._wD(a.id+": stop()"),a._onbufferchange(0),a._resetOnPosition(0),a.paused=!1,a.isHTML5||(a.playState=0),Xa(),d.to&&a.clearOnPosition(d.to),a.isHTML5?a._a&&(b=a.position,a.setPosition(0),a.position=b,a._a.pause(),a.playState=0,a._onTimer(),G()):(l._stop(a.id,b),d.serverURL&&a.unload()),a.instanceCount= -0,a._iO={},d.onstop&&d.onstop.apply(a));return a};this.setAutoPlay=function(b){c._wD(a.id+": Autoplay turned "+(b?"on":"off"));a._iO.autoPlay=b;a.isHTML5||(l._setAutoPlay(a.id,b),b&&!a.instanceCount&&1===a.readyState&&(a.instanceCount++,c._wD(a.id+": Incremented instance count to "+a.instanceCount)))};this.getAutoPlay=function(){return a._iO.autoPlay};this.setPosition=function(b){b===g&&(b=0);var d=a.isHTML5?Math.max(b,0):Math.min(a.duration||a._iO.duration,Math.max(b,0));a.position=d;b=a.position/ -1E3;a._resetOnPosition(a.position);a._iO.position=d;if(!a.isHTML5)b=9===n?a.position:b,a.readyState&&2!==a.readyState&&l._setPosition(a.id,b,a.paused||!a.playState,a._iO.multiShot);else if(a._a){if(a._html5_canplay){if(a._a.currentTime!==b){c._wD(a.id+": setPosition("+b+")");try{a._a.currentTime=b,(0===a.playState||a.paused)&&a._a.pause()}catch(e){c._wD(a.id+": setPosition("+b+") failed: "+e.message,2)}}}else if(b)return c._wD(a.id+": setPosition("+b+"): Cannot seek yet, sound not ready",2),a;a.paused&& -a._onTimer(!0)}return a};this.pause=function(b){if(a.paused||0===a.playState&&1!==a.readyState)return a;c._wD(a.id+": pause()");a.paused=!0;a.isHTML5?(a._setup_html5().pause(),G()):(b||b===g)&&l._pause(a.id,a._iO.multiShot);a._iO.onpause&&a._iO.onpause.apply(a);return a};this.resume=function(){var b=a._iO;if(!a.paused)return a;c._wD(a.id+": resume()");a.paused=!1;a.playState=1;a.isHTML5?(a._setup_html5().play(),m()):(b.isMovieStar&&!b.serverURL&&a.setPosition(a.position),l._pause(a.id,b.multiShot)); -!r&&b.onplay?(b.onplay.apply(a),r=!0):b.onresume&&b.onresume.apply(a);return a};this.togglePause=function(){c._wD(a.id+": togglePause()");if(0===a.playState)return a.play({position:9!==n||a.isHTML5?a.position/1E3:a.position}),a;a.paused?a.resume():a.pause();return a};this.setPan=function(c,b){c===g&&(c=0);b===g&&(b=!1);a.isHTML5||l._setPan(a.id,c);a._iO.pan=c;b||(a.pan=c,a.options.pan=c);return a};this.setVolume=function(b,d){b===g&&(b=100);d===g&&(d=!1);a.isHTML5?a._a&&(c.muted&&!a.muted&&(a.muted= -!0,a._a.muted=!0),a._a.volume=Math.max(0,Math.min(1,b/100))):l._setVolume(a.id,c.muted&&!a.muted||a.muted?0:b);a._iO.volume=b;d||(a.volume=b,a.options.volume=b);return a};this.mute=function(){a.muted=!0;a.isHTML5?a._a&&(a._a.muted=!0):l._setVolume(a.id,0);return a};this.unmute=function(){a.muted=!1;var b=a._iO.volume!==g;a.isHTML5?a._a&&(a._a.muted=!1):l._setVolume(a.id,b?a._iO.volume:a.options.volume);return a};this.toggleMute=function(){return a.muted?a.unmute():a.mute()};this.onposition=this.onPosition= -function(b,c,d){E.push({position:parseInt(b,10),method:c,scope:d!==g?d:a,fired:!1});return a};this.clearOnPosition=function(a,b){var c;a=parseInt(a,10);if(isNaN(a))return!1;for(c=0;c=b)return!1;for(--b;0<=b;b--)c=E[b],!c.fired&&a.position>=c.position&&(c.fired=!0,v++,c.method.apply(c.scope,[c.position]));return!0};this._resetOnPosition= -function(a){var b,c;b=E.length;if(!b)return!1;for(--b;0<=b;b--)c=E[b],c.fired&&a<=c.position&&(c.fired=!1,v--);return!0};y=function(){var b=a._iO,d=b.from,e=b.to,f,g;g=function(){c._wD(a.id+': "To" time of '+e+" reached.");a.clearOnPosition(e,g);a.stop()};f=function(){c._wD(a.id+': Playing "from" '+d);if(null!==e&&!isNaN(e))a.onPosition(e,g)};null===d||isNaN(d)||(b.position=d,b.multiShot=!1,f());return b};q=function(){var b,c=a._iO.onposition;if(c)for(b in c)if(c.hasOwnProperty(b))a.onPosition(parseInt(b, -10),c[b])};Xa=function(){var b,c=a._iO.onposition;if(c)for(b in c)c.hasOwnProperty(b)&&a.clearOnPosition(parseInt(b,10))};m=function(){a.isHTML5&&fb(a)};G=function(){a.isHTML5&&gb(a)};f=function(b){b||(E=[],v=0);r=!1;a._hasTimer=null;a._a=null;a._html5_canplay=!1;a.bytesLoaded=null;a.bytesTotal=null;a.duration=a._iO&&a._iO.duration?a._iO.duration:null;a.durationEstimate=null;a.buffered=[];a.eqData=[];a.eqData.left=[];a.eqData.right=[];a.failures=0;a.isBuffering=!1;a.instanceOptions={};a.instanceCount= -0;a.loaded=!1;a.metadata={};a.readyState=0;a.muted=!1;a.paused=!1;a.peakData={left:0,right:0};a.waveformData={left:[],right:[]};a.playState=0;a.position=null;a.id3={}};f();this._onTimer=function(b){var c,f=!1,g={};if(a._hasTimer||b)return a._a&&(b||(0opera.version()?new Audio(null):new Audio,c=a._a,c._called_load=!1,C&&(Ya=c);a.isHTML5=!0;a._a=c;c._s=a;h();a._apply_loop(c,b.loops);b.autoLoad||b.autoPlay?a.load():(c.autobuffer=!1,c.preload="auto");return c};h=function(){if(a._a._added_events)return!1;var b;a._a._added_events=!0;for(b in J)J.hasOwnProperty(b)&&a._a&&a._a.addEventListener(b,J[b],!1);return!0};k=function(){var b; -c._wD(a.id+": Removing event listeners");a._a._added_events=!1;for(b in J)J.hasOwnProperty(b)&&a._a&&a._a.removeEventListener(b,J[b],!1)};this._onload=function(b){var d=!!b||!a.isHTML5&&8===n&&a.duration;b=a.id+": ";c._wD(b+(d?"onload()":"Failed to load / invalid sound?"+(a.duration?" -":" Zero-length duration reported.")+" ("+a.url+")"),d?1:2);d||a.isHTML5||(!0===c.sandbox.noRemote&&c._wD(b+t("noNet"),1),!0===c.sandbox.noLocal&&c._wD(b+t("noLocal"),1));a.loaded=d;a.readyState=d?3:2;a._onbufferchange(0); -a._iO.onload&&ua(a,function(){a._iO.onload.apply(a,[d])});return!0};this._onbufferchange=function(b){if(0===a.playState||b&&a.isBuffering||!b&&!a.isBuffering)return!1;a.isBuffering=1===b;a._iO.onbufferchange&&(c._wD(a.id+": Buffer state change: "+b),a._iO.onbufferchange.apply(a,[b]));return!0};this._onsuspend=function(){a._iO.onsuspend&&(c._wD(a.id+": Playback suspended"),a._iO.onsuspend.apply(a));return!0};this._onfailure=function(b,d,e){a.failures++;c._wD(a.id+": Failure ("+a.failures+"): "+b); -if(a._iO.onfailure&&1===a.failures)a._iO.onfailure(b,d,e);else c._wD(a.id+": Ignoring failure")};this._onwarning=function(b,c,d){if(a._iO.onwarning)a._iO.onwarning(b,c,d)};this._onfinish=function(){var b=a._iO.onfinish;a._onbufferchange(0);a._resetOnPosition(0);a.instanceCount&&(a.instanceCount--,a.instanceCount||(Xa(),a.playState=0,a.paused=!1,a.instanceCount=0,a.instanceOptions={},a._iO={},G(),a.isHTML5&&(a.position=0)),a.instanceCount&&!a._iO.multiShotEvents||!b||(c._wD(a.id+": onfinish()"),ua(a, -function(){b.apply(a)})))};this._whileloading=function(b,c,d,e){var f=a._iO;a.bytesLoaded=b;a.bytesTotal=c;a.duration=Math.floor(d);a.bufferLength=e;a.durationEstimate=a.isHTML5||f.isMovieStar?a.duration:f.duration?a.duration>f.duration?a.duration:f.duration:parseInt(a.bytesTotal/a.bytesLoaded*a.duration,10);a.isHTML5||(a.buffered=[{start:0,end:a.duration}]);(3!==a.readyState||a.isHTML5)&&f.whileloading&&f.whileloading.apply(a)};this._whileplaying=function(b,c,d,e,f){var k=a._iO;if(isNaN(b)||null=== -b)return!1;a.position=Math.max(0,b);a._processOnPosition();!a.isHTML5&&8opera.version()?new Audio(null):new Audio:null,e,a,f={},h,k;h=c.audioFormats;for(e in h)if(h.hasOwnProperty(e)&&(a="audio/"+e,f[e]=b(h[e].type),f[a]=f[e],e.match(pb)?(c.flash[e]=!0,c.flash[a]=!0):(c.flash[e]=!1,c.flash[a]=!1),h[e]&&h[e].related))for(k=h[e].related.length-1;0<=k;k--)f["audio/"+h[e].related[k]]= -f[e],c.html5[h[e].related[k]]=f[e],c.flash[h[e].related[k]]=f[e];f.canPlayType=d?b:null;c.html5=A(c.html5,f);c.html5.usingFlash=ib();u=c.html5.usingFlash;return!0};z={notReady:"Unavailable - wait until onready() has fired.",notOK:"Audio support is not available.",domError:"soundManagerexception caught while appending SWF to DOM.",spcWmode:"Removing wmode, preventing known SWF loading issue(s)",swf404:"soundManager: Verify that %s is a valid path.",tryDebug:"Try soundManager.debugFlash = true for more security details (output goes to SWF.)", -checkSWF:"See SWF output for more debug info.",localFail:"soundManager: Non-HTTP page ("+m.location.protocol+" URL?) Review Flash player security settings for this special case:\nhttp://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html\nMay need to add/allow path, eg. c:/sm2/ or /users/me/sm2/",waitFocus:"soundManager: Special case: Waiting for SWF to load with window focus...",waitForever:"soundManager: Waiting indefinitely for Flash (will recover if unblocked)...", -waitSWF:"soundManager: Waiting for 100% SWF load...",needFunction:"soundManager: Function object expected for %s",badID:'Sound ID "%s" should be a string, starting with a non-numeric character',currentObj:"soundManager: _debug(): Current sound objects",waitOnload:"soundManager: Waiting for window.onload()",docLoaded:"soundManager: Document already loaded",onload:"soundManager: initComplete(): calling soundManager.onload()",onloadOK:"soundManager.onload() complete",didInit:"soundManager: init(): Already called?", -secNote:"Flash security note: Network/internet URLs will not load due to security restrictions. Access can be configured via Flash Player Global Security Settings Page: http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html",badRemove:"soundManager: Failed to remove Flash node.",shutdown:"soundManager.disable(): Shutting down",queue:"soundManager: Queueing %s handler",smError:"SMSound.load(): Exception: JS-Flash communication failed, or JS error.",fbTimeout:"No flash response, applying .swf_timedout CSS...", -fbLoaded:"Flash loaded",fbHandler:"soundManager: flashBlockHandler()",manURL:"SMSound.load(): Using manually-assigned URL",onURL:"soundManager.load(): current URL already assigned.",badFV:'soundManager.flashVersion must be 8 or 9. "%s" is invalid. Reverting to %s.',as2loop:"Note: Setting stream:false so looping can work (flash 8 limitation)",noNSLoop:"Note: Looping not implemented for MovieStar formats",needfl9:"Note: Switching to flash 9, required for MP4 formats.",mfTimeout:"Setting flashLoadTimeout = 0 (infinite) for off-screen, mobile flash case", -needFlash:"soundManager: Fatal error: Flash is needed to play some required formats, but is not available.",gotFocus:"soundManager: Got window focus.",policy:"Enabling usePolicyFile for data access",setup:"soundManager.setup(): allowed parameters: %s",setupError:'soundManager.setup(): "%s" cannot be assigned with this method.',setupUndef:'soundManager.setup(): Could not find option "%s"',setupLate:"soundManager.setup(): url, flashVersion and html5Test property changes will not take effect until reboot().", -noURL:"soundManager: Flash URL required. Call soundManager.setup({url:...}) to get started.",sm2Loaded:"SoundManager 2: Ready. "+String.fromCharCode(10003),reset:"soundManager.reset(): Removing event callbacks",mobileUA:"Mobile UA detected, preferring HTML5 by default.",globalHTML5:"Using singleton HTML5 Audio() pattern for this device.",ignoreMobile:"Ignoring mobile restrictions for this device."};t=function(){var b,c,e,a;b=kb.call(arguments);c=b.shift();if((a=z&&z[c]?z[c]:"")&&b&&b.length)for(c= -0,e=b.length;cn&&(c._wD(t("needfl9")),c.flashVersion=n=9);c.version=c.versionNumber+(c.html5Only?" (HTML5-only mode)":9===n?" (AS3/Flash 9)":" (AS2/Flash 8)");8'}if(X&&Y)return!1;if(c.html5Only)return Ea(),e(),c.oMC=F(c.movieID),za(),Y=X=!0,!1;var f=d||c.url,h=c.altURL||f,k=ma(),l=V(), -n=null,n=m.getElementsByTagName("html")[0],p,r,q,n=n&&n.dir&&n.dir.match(/rtl/i);b=b===g?c.id:b;Ea();c.url=db(ga?f:h);d=c.url;c.wmode=!c.wmode&&c.useHighPerformance?"transparent":c.wmode;null!==c.wmode&&(v.match(/msie 8/i)||!O&&!c.useHighPerformance)&&navigator.platform.match(/win32|win64/i)&&(M.push(z.spcWmode),c.wmode=null);k={name:b,id:b,src:d,quality:"high",allowScriptAccess:c.allowScriptAccess,bgcolor:c.bgColor,pluginspage:vb+"www.macromedia.com/go/getflashplayer",title:"JS/Flash audio component (SoundManager 2)", -type:"application/x-shockwave-flash",wmode:c.wmode,hasPriority:"true"};c.debugFlash&&(k.FlashVars="debug=1");c.wmode||delete k.wmode;if(O)f=m.createElement("div"),r=['',a("movie",d),a("AllowScriptAccess",c.allowScriptAccess),a("quality",k.quality),c.wmode?a("wmode",c.wmode):"",a("bgcolor", -c.bgColor),a("hasPriority","true"),c.debugFlash?a("FlashVars",k.FlashVars):"",""].join("");else for(p in f=m.createElement("embed"),k)k.hasOwnProperty(p)&&f.setAttribute(p,k[p]);Ga();l=V();if(k=ma())if(c.oMC=F(c.movieID)||m.createElement("div"),c.oMC.id)q=c.oMC.className,c.oMC.className=(q?q+" ":"movieContainer")+(l?" "+l:""),c.oMC.appendChild(f),O&&(p=c.oMC.appendChild(m.createElement("div")),p.className="sm2-object-box",p.innerHTML=r),Y=!0;else{c.oMC.id=c.movieID;c.oMC.className="movieContainer "+ -l;p=l=null;c.useFlashBlock||(c.useHighPerformance?l={position:"fixed",width:"8px",height:"8px",bottom:"0px",left:"0px",overflow:"hidden"}:(l={position:"absolute",width:"6px",height:"6px",top:"-9999px",left:"-9999px"},n&&(l.left=Math.abs(parseInt(l.left,10))+"px")));ub&&(c.oMC.style.zIndex=1E4);if(!c.debugFlash)for(q in l)l.hasOwnProperty(q)&&(c.oMC.style[q]=l[q]);try{O||c.oMC.appendChild(f),k.appendChild(c.oMC),O&&(p=c.oMC.appendChild(m.createElement("div")),p.className="sm2-object-box",p.innerHTML= -r),Y=!0}catch(u){throw Error(t("domError")+" \n"+u.toString());}}X=!0;e();return!0};la=function(){if(c.html5Only)return na(),!1;if(l)return!1;if(!c.url)return p("noURL"),!1;l=c.getMovie(c.id);l||(ba?(O?c.oMC.innerHTML=Ia:c.oMC.appendChild(ba),ba=null,X=!0):na(c.id,c.url),l=c.getMovie(c.id));"function"===typeof c.oninitmovie&&setTimeout(c.oninitmovie,1);Oa();return!0};T=function(){setTimeout($a,1E3)};Da=function(){h.setTimeout(function(){L("soundManager: useFlashBlock is false, 100% HTML5 mode is possible. Rebooting with preferFlash: false..."); -c.setup({preferFlash:!1}).reboot();c.didFlashBlock=!0;c.beginDelayedInit()},1)};$a=function(){var b,d=!1;if(!c.url||ca)return!1;ca=!0;x.remove(h,"load",T);if(H&&xa&&!Va)return p("waitFocus"),!1;q||(b=c.getMoviePercent(),0b&&(d=!0));setTimeout(function(){b=c.getMoviePercent();if(d)return ca=!1,c._wD(t("waitSWF")),h.setTimeout(T,1),!1;q||(c._wD("soundManager: No Flash response within expected time. Likely causes: "+(0===b?"SWF load failed, ":"")+"Flash blocked or JS-Flash security error."+(c.debugFlash? -" "+t("checkSWF"):""),2),!ga&&b&&(p("localFail",2),c.debugFlash||p("tryDebug",2)),0===b&&c._wD(t("swf404",c.url),1),D("flashtojs",!1,": Timed out"+(ga?" (Check flash security or flash blockers)":" (No plugin/missing SWF?)")));!q&&ob&&(null===b?c.useFlashBlock||0===c.flashLoadTimeout?(c.useFlashBlock&&Ja(),p("waitForever")):!c.useFlashBlock&&ea?Da():(p("waitForever"),P({type:"ontimeout",ignoreInit:!0,error:{type:"INIT_FLASHBLOCK"}})):0===c.flashLoadTimeout?p("waitForever"):!c.useFlashBlock&&ea?Da(): -Ha(!0))},c.flashLoadTimeout)};ka=function(){if(Va||!xa)return x.remove(h,"focus",ka),!0;Va=ob=!0;p("gotFocus");ca=!1;T();x.remove(h,"focus",ka);return!0};Oa=function(){M.length&&(c._wD("SoundManager 2: "+M.join(" "),1),M=[])};mb=function(){Oa();var b,d=[];if(c.useHTML5Audio&&c.hasHTML5){for(b in c.audioFormats)c.audioFormats.hasOwnProperty(b)&&d.push(b+" = "+c.html5[b]+(!c.html5[b]&&u&&c.flash[b]?" (using flash)":c.preferFlash&&c.flash[b]&&u?" (preferring flash)":c.html5[b]?"":" ("+(c.audioFormats[b].required? -"required, ":"")+"and no flash support)"));c._wD("SoundManager 2 HTML5 support: "+d.join(", "),1)}};Z=function(b){if(q)return!1;if(c.html5Only)return p("sm2Loaded",1),q=!0,S(),D("onload",!0),!0;var d=!0,e;c.useFlashBlock&&c.flashLoadTimeout&&!c.getMoviePercent()||(q=!0);e={type:!H&&u?"NO_FLASH":"INIT_TIMEOUT"};c._wD("SoundManager 2 "+(y?"failed to load":"loaded")+" ("+(y?"Flash security/load error":"OK")+") "+String.fromCharCode(y?10006:10003),y?2:1);y||b?(c.useFlashBlock&&c.oMC&&(c.oMC.className= -V()+" "+(null===c.getMoviePercent()?"swf_timedout":"swf_error")),P({type:"ontimeout",error:e,ignoreInit:!0}),D("onload",!1),U(e),d=!1):D("onload",!0);y||(c.waitForWindowLoad&&!ja?(p("waitOnload"),x.add(h,"load",S)):(c.waitForWindowLoad&&ja&&p("docLoaded"),S()));return d};Za=function(){var b,d=c.setupOptions;for(b in d)d.hasOwnProperty(b)&&(c[b]===g?c[b]=d[b]:c[b]!==d[b]&&(c.setupOptions[b]=c[b]))};za=function(){if(q)return p("didInit"),!1;if(c.html5Only)return q||(x.remove(h,"load",c.beginDelayedInit), -c.enabled=!0,Z()),!0;la();try{l._externalInterfaceTest(!1),ab(!0,c.flashPollingInterval||(c.useHighPerformance?10:50)),c.debugMode||l._disableDebug(),c.enabled=!0,D("jstoflash",!0),c.html5Only||x.add(h,"unload",ya)}catch(b){return c._wD("js/flash exception: "+b.toString()),D("jstoflash",!1),U({type:"JS_TO_FLASH_EXCEPTION",fatal:!0}),Ha(!0),Z(),!1}Z();x.remove(h,"load",c.beginDelayedInit);return!0};Q=function(){if(aa)return!1;aa=!0;Za();Ga();!H&&c.hasHTML5&&(c._wD("SoundManager 2: No Flash detected"+ -(c.useHTML5Audio?". Trying HTML5-only mode.":", enabling HTML5."),1),c.setup({useHTML5Audio:!0,preferFlash:!1}));jb();!H&&u&&(M.push(z.needFlash),c.setup({flashLoadTimeout:1}));m.removeEventListener&&m.removeEventListener("DOMContentLoaded",Q,!1);la();return!0};La=function(){"complete"===m.readyState&&(Q(),m.detachEvent("onreadystatechange",La));return!0};Fa=function(){ja=!0;Q();x.remove(h,"load",Fa)};Na();x.add(h,"focus",ka);x.add(h,"load",T);x.add(h,"load",Fa);m.addEventListener?m.addEventListener("DOMContentLoaded", -Q,!1):m.attachEvent?m.attachEvent("onreadystatechange",La):(D("onload",!1),U({type:"NO_DOM2_EVENTS",fatal:!0}))}if(!h||!h.document)throw Error("SoundManager requires a browser with window and document objects.");var W=null;h.SM2_DEFER!==g&&SM2_DEFER||(W=new K);"object"===typeof module&&module&&"object"===typeof module.exports?(module.exports.SoundManager=K,module.exports.soundManager=W):"function"===typeof define&&define.amd&&define(function(){return{constructor:K,getInstance:function(g){!h.soundManager&& -g instanceof Function&&(g=g(K),g instanceof K&&(h.soundManager=g));return h.soundManager}}});h.SoundManager=K;h.soundManager=W})(window); diff --git a/html/webapp/soundmanager2-setup.js b/html/webapp/soundmanager2-setup.js deleted file mode 100644 index 4d0ac6630d..0000000000 --- a/html/webapp/soundmanager2-setup.js +++ /dev/null @@ -1 +0,0 @@ -window.SM2_DEFER = true; \ No newline at end of file diff --git a/html/webapp/styles.css b/html/webapp/styles.css deleted file mode 100644 index a0aa688653..0000000000 --- a/html/webapp/styles.css +++ /dev/null @@ -1,23 +0,0 @@ -canvas { - cursor: default; - outline: none; - padding: 0px; - margin: 0px; -} - -body { - background-color: #191919; - margin: 0px; - padding: 0px; -} - -.gdx-meter.red > span { - background-color: #e44d3c !important; - background-image: -moz-linear-gradient(top, #f4ba6e, #d29d58) !important; - background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #f4ba6e),color-stop(1, #d29d58)) !important; - background-image: -webkit-linear-gradient(#f4ba6e, #d29d58) !important; -} - -.gdx-meter { - max-width: 100% !important; -} diff --git a/ios/src/io/anuke/mindustry/IOSLauncher.java b/ios/src/io/anuke/mindustry/IOSLauncher.java index afc17656a4..576a84a96f 100644 --- a/ios/src/io/anuke/mindustry/IOSLauncher.java +++ b/ios/src/io/anuke/mindustry/IOSLauncher.java @@ -4,13 +4,11 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.backends.iosrobovm.IOSApplication; import com.badlogic.gdx.backends.iosrobovm.IOSApplicationConfiguration; import com.badlogic.gdx.files.FileHandle; -import io.anuke.kryonet.DefaultThreadImpl; import io.anuke.kryonet.KryoClient; import io.anuke.kryonet.KryoServer; import io.anuke.mindustry.core.Platform; -import io.anuke.mindustry.core.ThreadHandler; -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.ucore.scene.ui.TextField; import io.anuke.ucore.scene.ui.layout.Unit; @@ -73,11 +71,6 @@ public class IOSLauncher extends IOSApplication.Delegate { return locale.getDisplayName(locale); } - @Override - public ThreadHandler.ThreadProvider getThreadProvider() { - return new DefaultThreadImpl(); - } - @Override public void shareFile(FileHandle file){ FileHandle to = Gdx.files.absolute(getDocumentsDirectory()).child(file.name()); diff --git a/kryonet/src/io/anuke/kryonet/DefaultThreadImpl.java b/kryonet/src/io/anuke/kryonet/DefaultThreadImpl.java deleted file mode 100644 index 9a50a4f51e..0000000000 --- a/kryonet/src/io/anuke/kryonet/DefaultThreadImpl.java +++ /dev/null @@ -1,67 +0,0 @@ -package io.anuke.kryonet; - -import io.anuke.mindustry.core.ThreadHandler.ThreadProvider; -import io.anuke.ucore.util.Threads; -import io.anuke.ucore.util.Threads.ThreadInfoProvider; -import io.anuke.ucore.util.Log; - -public class DefaultThreadImpl implements ThreadProvider, ThreadInfoProvider{ - private Thread thread; - - public DefaultThreadImpl(){ - Threads.setThreadInfoProvider(this); - } - - @Override - public boolean isOnLogicThread(){ - return thread == null || isOnThread(); - } - - @Override - public boolean isOnGraphicsThread(){ - return thread == null || !isOnThread(); - } - - @Override - public boolean isOnThread() { - return Thread.currentThread() == thread; - } - - @Override - public void sleep(long ms) throws InterruptedException{ - Thread.sleep(ms); - } - - @Override - public void start(Runnable run) { - if(thread != null){ - thread.interrupt(); - thread = null; - } - - thread = new Thread(run); - thread.setDaemon(true); - thread.setName("Update Thread"); - thread.start(); - Log.info("Starting logic thread."); - } - - @Override - public void stop() { - if(thread != null){ - thread.interrupt(); - thread = null; - } - } - - @Override - public void wait(Object object) throws InterruptedException{ - object.wait(); - } - - @Override - public void notify(Object object) { - object.notify(); - } - -} diff --git a/kryonet/src/io/anuke/kryonet/KryoClient.java b/kryonet/src/io/anuke/kryonet/KryoClient.java index 2719df75a4..d0f6783fe6 100644 --- a/kryonet/src/io/anuke/kryonet/KryoClient.java +++ b/kryonet/src/io/anuke/kryonet/KryoClient.java @@ -3,7 +3,6 @@ package io.anuke.kryonet; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.utils.Array; import com.esotericsoftware.kryonet.*; -import com.esotericsoftware.minlog.Log; import io.anuke.mindustry.net.Host; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net.ClientProvider; @@ -13,12 +12,14 @@ import io.anuke.mindustry.net.Packets.Connect; import io.anuke.mindustry.net.Packets.Disconnect; import io.anuke.ucore.function.Consumer; import io.anuke.ucore.util.Pooling; -import io.anuke.ucore.util.Strings; import net.jpountz.lz4.LZ4Factory; import net.jpountz.lz4.LZ4FastDecompressor; import java.io.IOException; -import java.net.*; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.NetworkInterface; import java.nio.ByteBuffer; import java.nio.channels.ClosedSelectorException; @@ -75,10 +76,12 @@ public class KryoClient implements ClientProvider{ @Override public void disconnected (Connection connection) { - Disconnect c = new Disconnect(); + if(connection.getLastProtocolError() != null){ + netClient.setQuiet(); + } + Disconnect c = new Disconnect(); threads.runDelay(() -> Net.handleClientReceived(c)); - if(connection.getLastProtocolError() != null) Log.error("\n\n\n\nProtocol error: " + connection.getLastProtocolError() + "\n\n\n\n"); } @Override @@ -89,13 +92,7 @@ public class KryoClient implements ClientProvider{ try{ Net.handleClientReceived(object); }catch (Exception e){ - e.printStackTrace(); - if(e instanceof KryoNetException && e.getMessage() != null && e.getMessage().toLowerCase().contains("incorrect")) { - Net.showError("$text.server.mismatch"); - netClient.disconnectQuietly(); - }else{ - throw new RuntimeException(e); - } + handleException(e); } }); @@ -128,21 +125,28 @@ public class KryoClient implements ClientProvider{ } @Override - public void connect(String ip, int port) throws IOException { - //just in case - client.stop(); - - Thread updateThread = new Thread(() -> { + public void connect(String ip, int port, Runnable success){ + runAsync(() -> { try{ - client.run(); - }catch (Exception e){ - if(!(e instanceof ClosedSelectorException)) handleException(e); - } - }, "Kryonet Client"); - updateThread.setDaemon(true); - updateThread.start(); + //just in case + client.stop(); - client.connect(5000, ip, port, port); + Thread updateThread = new Thread(() -> { + try{ + client.run(); + }catch(Exception e){ + if(!(e instanceof ClosedSelectorException)) handleException(e); + } + }, "Kryonet Client"); + updateThread.setDaemon(true); + updateThread.start(); + + client.connect(5000, ip, port, port); + success.run(); + }catch(Exception e){ + handleException(e); + } + }); } @Override @@ -222,12 +226,10 @@ public class KryoClient implements ClientProvider{ } private void handleException(Exception e){ - e.printStackTrace(); if(e instanceof KryoNetException){ - Gdx.app.postRunnable(() -> Net.showError("$text.server.mismatch")); + Gdx.app.postRunnable(() -> Net.showError(new IOException("mismatch"))); }else{ - Net.showError(Strings.parseException(e, true)); - disconnect(); + Gdx.app.postRunnable(() -> Net.showError(e)); } } diff --git a/server/src/io/anuke/mindustry/server/MindustryServer.java b/server/src/io/anuke/mindustry/server/MindustryServer.java index a1b835fa4b..8d7297cae9 100644 --- a/server/src/io/anuke/mindustry/server/MindustryServer.java +++ b/server/src/io/anuke/mindustry/server/MindustryServer.java @@ -24,6 +24,7 @@ public class MindustryServer extends ModuleCore{ headless = true; BundleLoader.load(); + content.verbose(false); content.load(); content.initialize(Content::init); diff --git a/server/src/io/anuke/mindustry/server/ServerControl.java b/server/src/io/anuke/mindustry/server/ServerControl.java index e9601b65dc..1688653ecd 100644 --- a/server/src/io/anuke/mindustry/server/ServerControl.java +++ b/server/src/io/anuke/mindustry/server/ServerControl.java @@ -2,6 +2,7 @@ package io.anuke.mindustry.server; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.utils.Array; +import com.badlogic.gdx.utils.ObjectSet; import com.badlogic.gdx.utils.Timer; import com.badlogic.gdx.utils.Timer.Task; import io.anuke.mindustry.core.GameState.State; @@ -18,7 +19,6 @@ import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.net.Administration.PlayerInfo; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Packets.KickReason; -import io.anuke.mindustry.net.TraceInfo; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemType; import io.anuke.mindustry.world.Tile; @@ -32,6 +32,8 @@ import io.anuke.ucore.util.Log; import io.anuke.ucore.util.Strings; import java.io.IOException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.Scanner; import static io.anuke.mindustry.Vars.*; @@ -57,6 +59,30 @@ public class ServerControl extends Module{ "port", port ); + Log.setLogger(new LogHandler(){ + DateTimeFormatter dateTime = DateTimeFormatter.ofPattern("MM-dd-yyyy | HH:mm:ss"); + + @Override + public void info(String text, Object... args){ + print("&lg&fb" + "[INFO] " + format(text, args)); + } + + @Override + public void err(String text, Object... args){ + print("&lr&fb" + "[ERR!] " + format(text, args)); + } + + @Override + public void warn(String text, Object... args){ + print("&ly&fb" + "[WARN] " + format(text, args)); + } + + @Override + public void print(String text, Object... args){ + System.out.println("[" + dateTime.format(LocalDateTime.now()) + "] " + format(text + "&fr", args)); + } + }); + Timers.setDeltaProvider(() -> Gdx.graphics.getDeltaTime() * 60f); Effects.setScreenShakeProvider((a, b) -> {}); Effects.setEffectProvider((a, b, c, d, e, f) -> {}); @@ -69,14 +95,14 @@ public class ServerControl extends Module{ if(args.length > 0){ commands = String.join(" ", args).split(","); - Log.info("&lmFound {0} command-line arguments to parse. {1}", commands.length); + info("&lmFound {0} command-line arguments to parse. {1}", commands.length); } for(String s : commands){ Response response = handler.handleMessage(s); if(response.type != ResponseType.valid){ - Log.err("Invalid command argument sent: '{0}': {1}", s, response.type.name()); - Log.err("Argument usage: &lc , "); + err("Invalid command argument sent: '{0}': {1}", s, response.type.name()); + err("Argument usage: &lc , "); System.exit(1); } } @@ -87,12 +113,12 @@ public class ServerControl extends Module{ thread.start(); if(Version.build == -1){ - err("WARNING: &lyYour server is running a custom build, which means that client checking is disabled.\n" + - "&lrWARNING: &lyIt is highly advised to specify which version you're using by building with gradle args &lc-Pbuildversion=&lm&ly so that clients know which version you are using."); + warn("&lyYour server is running a custom build, which means that client checking is disabled."); + warn("&lyIt is highly advised to specify which version you're using by building with gradle args &lc-Pbuildversion=&lm&ly."); } Events.on(SectorCompleteEvent.class, event -> { - Log.info("Sector complete."); + info("Sector complete."); world.sectors.completeSector(world.getSector().x, world.getSector().y); world.sectors.save(); gameOvers = 0; @@ -151,13 +177,14 @@ public class ServerControl extends Module{ }); info("&lcServer loaded. Type &ly'help'&lc for help."); + System.out.print("> "); } private void registerCommands(){ handler.register("help", "Displays this command list.", arg -> { info("Commands:"); for(Command command : handler.getCommandList()){ - print(" &y" + command.text + (command.paramText.isEmpty() ? "" : " ") + command.paramText + " - &lm" + command.description); + info(" &y" + command.text + (command.paramText.isEmpty() ? "" : " ") + command.paramText + " - &lm" + command.description); } }); @@ -176,8 +203,7 @@ public class ServerControl extends Module{ Net.closeServer(); if(lastTask != null) lastTask.cancel(); state.set(State.menu); - netServer.reset(); - Log.info("Stopped server."); + info("Stopped server."); }); handler.register("host", "[mapname] [mode]", "Open the server with a specific map.", arg -> { @@ -222,7 +248,7 @@ public class ServerControl extends Module{ logic.play(); }else{ - info("&ly&fiNo map specified. Loading sector {0}, {1}.", Settings.getInt("sector_x"), Settings.getInt("sector_y")); + info("&fiNo map specified. Loading sector {0}, {1}.", Settings.getInt("sector_x"), Settings.getInt("sector_y")); playSectorMap(false); } @@ -255,39 +281,26 @@ public class ServerControl extends Module{ handler.register("status", "Display server status.", arg -> { if(state.is(State.menu)){ - info("&lyStatus: &rserver closed"); + info("Status: &rserver closed"); }else{ - info("&lyStatus: &lcPlaying on map &fi{0}&fb &lb/&lc Wave {1} &lb/&lc {2} &lb/&lc {3}", - Strings.capitalize(world.getMap().name), state.wave, Strings.capitalize(state.difficulty.name()), Strings.capitalize(state.mode.name())); + info("Status:"); + info(" &lyPlaying on map &fi{0}&fb &lb/&ly Wave {1} &lb/&ly {2} &lb/&ly {3}", Strings.capitalize(world.getMap().name), state.wave, Strings.capitalize(state.difficulty.name()), Strings.capitalize(state.mode.name())); + if(state.mode.disableWaveTimer){ - info("&ly{0} enemies.", unitGroups[Team.red.ordinal()].size()); + info("&ly {0} enemies.", unitGroups[Team.red.ordinal()].size()); }else{ - info("&ly{0} seconds until next wave.", (int) (state.wavetime / 60)); + info("&ly {0} seconds until next wave.", (int) (state.wavetime / 60)); } - if(playerGroup.size() > 0){ - info("&lyPlayers: {0}", playerGroup.size()); - for(Player p : playerGroup.all()){ - print(" &y" + p.name); - } - }else{ - info("&lyNo players connected."); - } - info("&lbFPS: {0}", (int) (60f / Timers.delta())); - } - }); + info(" &ly{0} FPS.", (int) (60f / Timers.delta())); - handler.register("players", "Display player info.", arg -> { - if(state.is(State.menu)){ - info("&lyServer is closed."); - }else{ if(playerGroup.size() > 0){ - info("&lyPlayers: {0}", playerGroup.size()); + info(" &lyPlayers: {0}", playerGroup.size()); for(Player p : playerGroup.all()){ - print(" &y{0} / Connection {1} / IP: {2}", p.name, p.con.id, p.con.address); + info(" &y{0} / {1}", p.name, p.uuid); } }else{ - info("&lyNo players connected."); + info(" &lyNo players connected."); } } }); @@ -384,14 +397,7 @@ public class ServerControl extends Module{ return; } - Player target = null; - - for(Player player : playerGroup.all()){ - if(player.name.equalsIgnoreCase(arg[0])){ - target = player; - break; - } - } + Player target = playerGroup.find(p -> p.name.equals(arg[0])); if(target != null){ netServer.kick(target.con.id, KickReason.kick); @@ -401,28 +407,23 @@ public class ServerControl extends Module{ } }); - handler.register("ban", "", "Ban a person by name.", arg -> { - if(!state.is(State.playing)){ - err("Can't ban people by name with no players."); - return; - } - - Player target = null; - - for(Player player : playerGroup.all()){ - if(player.name.equalsIgnoreCase(arg[0])){ - target = player; + handler.register("ban", " ", "Ban a person.", arg -> { + if(arg[0].equals("id")){ + netServer.admins.banPlayerID(arg[1]); + info("Banned."); + }else if(arg[0].equals("name")){ + Player target = playerGroup.find(p -> p.name.equalsIgnoreCase(arg[1])); + if(target != null){ + netServer.admins.banPlayer(target.uuid); + info("Banned."); + }else{ + err("No matches found."); } - } - - if(target != null){ - String ip = target.con.address; - netServer.admins.banPlayerIP(ip); - netServer.admins.banPlayerID(target.uuid); - netServer.kick(target.con.id, KickReason.banned); - info("Banned player by IP and ID: {0} / {1}", ip, target.uuid); + }else if(arg[0].equals("ip")){ + netServer.admins.banPlayerIP(arg[1]); + info("Banned."); }else{ - info("Nobody with that name could be found."); + err("Invalid type."); } }); @@ -430,119 +431,76 @@ public class ServerControl extends Module{ Array bans = netServer.admins.getBanned(); if(bans.size == 0){ - Log.info("No ID-banned players have been found."); + info("No ID-banned players have been found."); }else{ - Log.info("&lyBanned players [ID]:"); + info("&lyBanned players [ID]:"); for(PlayerInfo info : bans){ - Log.info(" &ly {0} / Last known name: '{1}'", info.id, info.lastName); + info(" &ly {0} / Last known name: '{1}'", info.id, info.lastName); } } Array ipbans = netServer.admins.getBannedIPs(); if(ipbans.size == 0){ - Log.info("No IP-banned players have been found."); + info("No IP-banned players have been found."); }else{ - Log.info("&lmBanned players [IP]:"); + info("&lmBanned players [IP]:"); for(String string : ipbans){ PlayerInfo info = netServer.admins.findByIP(string); if(info != null){ - Log.info(" &lm '{0}' / Last known name: '{1}' / ID: '{2}'", string, info.lastName, info.id); + info(" &lm '{0}' / Last known name: '{1}' / ID: '{2}'", string, info.lastName, info.id); }else{ - Log.info(" &lm '{0}' (No known name or info)", string); + info(" &lm '{0}' (No known name or info)", string); } } } }); - handler.register("banip", "", "Ban a person by IP.", arg -> { - if(netServer.admins.banPlayerIP(arg[0])){ - info("Banned player by IP: {0}.", arg[0]); - - for(Player player : playerGroup.all()){ - if(player.con.address != null && - player.con.address.equals(arg[0])){ - netServer.kick(player.con.id, KickReason.banned); - } + handler.register("unban", "", "Completely unban a person by IP or ID.", arg -> { + if(arg[0].contains(".")){ + if(netServer.admins.unbanPlayerIP(arg[0])){ + info("Unbanned player by IP: {0}.", arg[0]); + }else{ + err("That IP is not banned!"); } }else{ - err("That IP is already banned!"); - } - }); - - handler.register("banid", "", "Ban a person by their unique ID.", arg -> { - if(netServer.admins.banPlayerID(arg[0])){ - info("Banned player by ID: {0}.", arg[0]); - - for(Player player : playerGroup.all()){ - if(player.uuid.equals(arg[0])){ - netServer.kick(player.con.id, KickReason.banned); - } + if(netServer.admins.unbanPlayerID(arg[0])){ + info("Unbanned player by ID: {0}.", arg[0]); + }else{ + err("That ID is not banned!"); } - }else{ - err("That ID is already banned!"); } }); - handler.register("unbanip", "", "Completely unban a person by IP.", arg -> { - if(netServer.admins.unbanPlayerIP(arg[0])){ - info("Unbanned player by IP: {0}.", arg[0]); - }else{ - err("That IP is not banned!"); - } - }); - - handler.register("unbanid", "", "Completely unban a person by ID.", arg -> { - if(netServer.admins.unbanPlayerID(arg[0])){ - info("&lmUnbanned player by ID: {0}.", arg[0]); - }else{ - err("That IP is not banned!"); - } - }); - - handler.register("admin", "", "Make a user admin", arg -> { + handler.register("admin", "", "Make an online user admin", arg -> { if(!state.is(State.playing)){ err("Open the server first."); return; } - Player target = null; - - for(Player player : playerGroup.all()){ - if(player.name.equalsIgnoreCase(arg[0])){ - target = player; - break; - } - } + Player target = playerGroup.find(p -> p.name.equals(arg[0])); if(target != null){ netServer.admins.adminPlayer(target.uuid, target.usid); target.isAdmin = true; - info("Admin-ed player by ID: {0} / {1}", target.uuid, arg[0]); + info("Admin-ed player: {0}", arg[0]); }else{ info("Nobody with that name could be found."); } }); - handler.register("unadmin", "", "Removes admin status from a player", arg -> { + handler.register("unadmin", "", "Removes admin status from an online player", arg -> { if(!state.is(State.playing)){ err("Open the server first."); return; } - Player target = null; - - for(Player player : playerGroup.all()){ - if(player.name.equalsIgnoreCase(arg[0])){ - target = player; - break; - } - } + Player target = playerGroup.find(p -> p.name.equals(arg[0])); if(target != null){ netServer.admins.unAdminPlayer(target.uuid); target.isAdmin = false; - info("Un-admin-ed player by ID: {0} / {1}", target.uuid, arg[0]); + info("Un-admin-ed player: {0}", arg[0]); }else{ info("Nobody with that name could be found."); } @@ -552,11 +510,11 @@ public class ServerControl extends Module{ Array admins = netServer.admins.getAdmins(); if(admins.size == 0){ - Log.info("No admins have been found."); + info("No admins have been found."); }else{ - Log.info("&lyAdmins:"); + info("&lyAdmins:"); for(PlayerInfo info : admins){ - Log.info(" &lm {0} / ID: '{1}' / IP: '{2}'", info.lastName, info.id, info.lastIP); + info(" &lm {0} / ID: '{1}' / IP: '{2}'", info.lastName, info.id, info.lastIP); } } }); @@ -610,37 +568,6 @@ public class ServerControl extends Module{ }); }); - handler.register("griefers", "[min-break:place-ratio] [min-breakage]", "Find possible griefers currently online.", arg -> { - if(!state.is(State.playing)){ - err("Open the server first."); - return; - } - - try{ - - float ratio = arg.length > 0 ? Float.parseFloat(arg[0]) : 0.5f; - int minbreak = arg.length > 1 ? Integer.parseInt(arg[1]) : 100; - - boolean found = false; - - for(Player player : playerGroup.all()){ - TraceInfo info = netServer.admins.getTraceByID(player.uuid); - if(info.totalBlocksBroken >= minbreak && info.totalBlocksBroken / Math.max(info.totalBlocksPlaced, 1f) >= ratio){ - info("&ly - Player '{0}' / UUID &lm{1}&ly found: &lc{2}&ly broken and &lc{3}&ly placed.", - player.name, info.uuid, info.totalBlocksBroken, info.totalBlocksPlaced); - found = true; - } - } - - if(!found){ - info("No griefers matching the criteria have been found."); - } - - }catch(NumberFormatException e){ - err("Invalid number format."); - } - }); - handler.register("gameover", "Force a game over.", arg -> { if(state.is(State.menu)){ info("Not playing a map."); @@ -667,120 +594,34 @@ public class ServerControl extends Module{ result.append(arr.get(i * 2 + 1)); result.append("\n"); } - Log.info("&ly{0}", result); + info("&ly{0}", result); }else{ - Log.info("No tile entity for that block."); + info("No tile entity for that block."); } }else{ - Log.info("No tile at that location."); + info("No tile at that location."); } }catch(NumberFormatException e){ - Log.err("Invalid coordinates passed."); + err("Invalid coordinates passed."); } }); - handler.register("find", "", "Find player info(s) by name. Can optionally check for all names a player has had.", arg -> { - boolean checkAll = true; + handler.register("info", "", "Find player info(s). Can optionally check for all names or IPs a player has had.", arg -> { - Array infos = netServer.admins.findByName(arg[0], checkAll); + ObjectSet infos = netServer.admins.findByName(arg[0]); - if(infos.size == 1){ - PlayerInfo info = infos.peek(); - Log.info("&lcTrace info for player '{0}' / UUID {1}:", info.lastName, info.id); - Log.info(" &lyall names used: {0}", info.names); - Log.info(" &lyIP: {0}", info.lastIP); - Log.info(" &lyall IPs used: {0}", info.ips); - Log.info(" &lytimes joined: {0}", info.timesJoined); - Log.info(" &lytimes kicked: {0}", info.timesKicked); - Log.info(""); - Log.info(" &lytotal blocks broken: {0}", info.totalBlocksBroken); - Log.info(" &lytotal blocks placed: {0}", info.totalBlockPlaced); - }else if(infos.size > 1){ - Log.info("&lcMultiple people have been found with that name:"); + if(infos.size > 0){ + info("&lgPlayers found: {0}", infos.size); + + int i = 0; for(PlayerInfo info : infos){ - Log.info(" &ly{0}", info.id); + info("&lc[{0}] Trace info for player '{1}' / UUID {2}", i ++, info.lastName, info.id); + info(" &lyall names used: {0}", info.names); + info(" &lyIP: {0}", info.lastIP); + info(" &lyall IPs used: {0}", info.ips); + info(" &lytimes joined: {0}", info.timesJoined); + info(" &lytimes kicked: {0}", info.timesKicked); } - Log.info("&lcUse the info command to examine each person individually."); - }else{ - info("Nobody with that name could be found."); - } - }); - - handler.register("findip", "", "Find player info(s) by IP.", arg -> { - - Array infos = netServer.admins.findByIPs(arg[0]); - - if(infos.size == 1){ - PlayerInfo info = infos.peek(); - Log.info("&lcTrace info for player '{0}' / UUID {1}:", info.lastName, info.id); - Log.info(" &lyall names used: {0}", info.names); - Log.info(" &lyIP: {0}", info.lastIP); - Log.info(" &lyall IPs used: {0}", info.ips); - Log.info(" &lytimes joined: {0}", info.timesJoined); - Log.info(" &lytimes kicked: {0}", info.timesKicked); - Log.info(""); - Log.info(" &lytotal blocks broken: {0}", info.totalBlocksBroken); - Log.info(" &lytotal blocks placed: {0}", info.totalBlockPlaced); - }else if(infos.size > 1){ - Log.info("&lcMultiple people have been found with that IP:"); - for(PlayerInfo info : infos){ - Log.info(" &ly{0}", info.id); - } - Log.info("&lcUse the info command to examine each person individually."); - }else{ - info("Nobody with that IP could be found."); - } - }); - - - handler.register("info", "", "Get global info for a player's UUID.", arg -> { - PlayerInfo info = netServer.admins.getInfoOptional(arg[0]); - - if(info != null){ - Log.info("&lcTrace info for player '{0}':", info.lastName); - Log.info(" &lyall names used: {0}", info.names); - Log.info(" &lyIP: {0}", info.lastIP); - Log.info(" &lyall IPs used: {0}", info.ips); - Log.info(" &lytimes joined: {0}", info.timesJoined); - Log.info(" &lytimes kicked: {0}", info.timesKicked); - Log.info(""); - Log.info(" &lytotal blocks broken: {0}", info.totalBlocksBroken); - Log.info(" &lytotal blocks placed: {0}", info.totalBlockPlaced); - }else{ - info("Nobody with that UUID could be found."); - } - }); - - handler.register("trace", "", "Trace a player's actions", arg -> { - if(!state.is(State.playing)){ - err("Open the server first."); - return; - } - - Player target = null; - - for(Player player : playerGroup.all()){ - if(player.name.equalsIgnoreCase(arg[0])){ - target = player; - break; - } - } - - if(target != null){ - TraceInfo info = netServer.admins.getTraceByID(target.uuid); - Log.info("&lcTrace info for player '{0}':", target.name); - Log.info(" &lyEntity ID: {0}", info.playerid); - Log.info(" &lyIP: {0}", info.ip); - Log.info(" &lyUUID: {0}", info.uuid); - Log.info(" &lycustom client: {0}", info.modclient); - Log.info(" &lyandroid: {0}", info.android); - Log.info(""); - Log.info(" &lytotal blocks broken: {0}", info.totalBlocksBroken); - Log.info(" &lystructure blocks broken: {0}", info.structureBlocksBroken); - Log.info(" &lylast block broken: {0}", info.lastBlockBroken.formalName); - Log.info(""); - Log.info(" &lytotal blocks placed: {0}", info.totalBlocksPlaced); - Log.info(" &lylast block placed: {0}", info.lastBlockPlaced.formalName); }else{ info("Nobody with that name could be found."); } @@ -788,8 +629,9 @@ public class ServerControl extends Module{ } private void readCommands(){ + Scanner scan = new Scanner(System.in); - while(true){ + while(scan.hasNext()){ String line = scan.nextLine(); Gdx.app.postRunnable(() -> { @@ -818,6 +660,8 @@ public class ServerControl extends Module{ }else if(response.type == ResponseType.manyArguments){ err("Too many command arguments. Usage: " + response.command.text + " " + response.command.paramText); } + + System.out.print("> "); }); } } @@ -876,15 +720,8 @@ public class ServerControl extends Module{ Net.host(Settings.getInt("port")); info("&lcOpened a server on port {0}.", Settings.getInt("port")); }catch(IOException e){ - Log.err(e); + err(e); state.set(State.menu); } } - - @Override - public void update(){ - if(!inExtraRound && state.mode.isPvp){ - // checkPvPGameOver(); - } - } } diff --git a/settings.gradle b/settings.gradle index 5621bab462..e788ba34a4 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,4 @@ -include 'desktop', 'html', 'core', 'kryonet', 'server', 'ios', 'annotations', 'tools', 'tests' +include 'desktop', 'core', 'kryonet', 'server', 'ios', 'annotations', 'tools', 'tests' Properties properties = new Properties() diff --git a/tests/src/test/java/ApplicationTests.java b/tests/src/test/java/ApplicationTests.java index 435541b852..8c47aabbb4 100644 --- a/tests/src/test/java/ApplicationTests.java +++ b/tests/src/test/java/ApplicationTests.java @@ -164,7 +164,7 @@ public class ApplicationTests{ tile.entity.items.add(Items.coal, 5); tile.entity.items.add(Items.titanium, 50); assertEquals(tile.entity.items.total(), 55); - tile.entity.items.remove(Items.phasematter, 10); + tile.entity.items.remove(Items.phasefabric, 10); tile.entity.items.remove(Items.titanium, 10); assertEquals(tile.entity.items.total(), 45); }