From 56b3b469f6c3fc480fc0d2766acfbddc741476ca Mon Sep 17 00:00:00 2001 From: Anuken Date: Thu, 22 Feb 2018 20:16:55 -0500 Subject: [PATCH 01/18] Fixed two major crashes --- core/src/io/anuke/mindustry/core/Renderer.java | 6 ++++-- core/src/io/anuke/mindustry/entities/enemies/EnemyType.java | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/core/src/io/anuke/mindustry/core/Renderer.java b/core/src/io/anuke/mindustry/core/Renderer.java index 7581ba778d..99620f2aed 100644 --- a/core/src/io/anuke/mindustry/core/Renderer.java +++ b/core/src/io/anuke/mindustry/core/Renderer.java @@ -409,8 +409,10 @@ public class Renderer extends RendererModule{ Lines.dashCircle(spawn.start.worldx(), spawn.start.worldy(), enemyspawnspace); } - Draw.color(Color.LIME); - Lines.poly(world.getSpawnX(), world.getSpawnY(), 4, 6f, Timers.time()*2f); + if(world.getCore() != null) { + Draw.color(Color.LIME); + Lines.poly(world.getSpawnX(), world.getSpawnY(), 4, 6f, Timers.time() * 2f); + } if(input.breakMode == PlaceMode.holdDelete) input.breakMode.draw(tilex, tiley, 0, 0); diff --git a/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java b/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java index 27f0f4bd99..bdf27ae16c 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java +++ b/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java @@ -100,9 +100,10 @@ public class EnemyType { enemy.hitTime -= Timers.delta(); } - if(enemy.lane >= world.getSpawns().size) enemy.lane = 0; + if(enemy.lane >= world.getSpawns().size || enemy.lane < 0) enemy.lane = 0; - boolean waiting = world.getSpawns().get(enemy.lane).pathTiles == null || enemy.node <= 0; + boolean waiting = enemy.lane >= world.getSpawns().size || enemy.lane < 0 + || world.getSpawns().get(enemy.lane).pathTiles == null || enemy.node <= 0; move(enemy); From 9ff9684a04d0e93d98df030fce17d678f3d7e546 Mon Sep 17 00:00:00 2001 From: Anuken Date: Thu, 22 Feb 2018 23:19:03 -0500 Subject: [PATCH 02/18] Updated uCore, fixed some crashes --- build.gradle | 2 +- .../world/blocks/types/distribution/TunnelConveyor.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 2ba9f9dfad..07a590ff7c 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ allprojects { appName = 'Mindustry' gdxVersion = '1.9.8' aiVersion = '1.8.1' - uCoreVersion = '23e8c1c' + uCoreVersion = 'b4757b5' getVersionString = { String buildVersion = getBuildVersion() diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/TunnelConveyor.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/TunnelConveyor.java index 16e51b0556..c6864b138b 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/TunnelConveyor.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/TunnelConveyor.java @@ -94,6 +94,7 @@ public class TunnelConveyor extends Block{ Tile dest = tile; int rel = (tile.getRotation() + 2)%4; for(int i = 0; i < maxdist; i ++){ + if(dest == null) return null; dest = dest.getNearby(rel); if(dest != null && dest.block() instanceof TunnelConveyor && dest.getRotation() == rel && dest.getNearby(rel) != null From 07aab732b745883bd6ff012ab480922edcbe9bbc Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 23 Feb 2018 13:59:21 -0500 Subject: [PATCH 03/18] Better tunnel debugging, improved keybind dialog controller info --- build.gradle | 2 +- core/assets/ui/uiskin.json | 2 +- core/assets/version.properties | 4 +-- .../mindustry/ui/fragments/DebugFragment.java | 4 +++ .../blocks/types/distribution/Junction.java | 1 + .../types/distribution/TunnelConveyor.java | 25 +++++++++++++++++++ 6 files changed, 34 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 07a590ff7c..d1d219b811 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ allprojects { appName = 'Mindustry' gdxVersion = '1.9.8' aiVersion = '1.8.1' - uCoreVersion = 'b4757b5' + uCoreVersion = 'f484468' getVersionString = { String buildVersion = getBuildVersion() diff --git a/core/assets/ui/uiskin.json b/core/assets/ui/uiskin.json index 5a83f28256..3dc8e615f4 100644 --- a/core/assets/ui/uiskin.json +++ b/core/assets/ui/uiskin.json @@ -83,7 +83,7 @@ io.anuke.ucore.scene.ui.Window$WindowStyle: { dialog: {stageBackground: dialogDim, titleFont: default-font, background: window-empty, titleFontColor: accent } }, io.anuke.ucore.scene.ui.KeybindDialog$KeybindDialogStyle: { - default: {keyColor: accent, keyNameColor: white, paneStyle: clear}, + default: {keyColor: accent, keyNameColor: white, controllerColor: menuitem, paneStyle: clear}, }, io.anuke.ucore.scene.ui.Slider$SliderStyle: { default-horizontal: {background: slider, knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down}, diff --git a/core/assets/version.properties b/core/assets/version.properties index 119ee80449..44e6da5af2 100644 --- a/core/assets/version.properties +++ b/core/assets/version.properties @@ -1,7 +1,7 @@ #Autogenerated file. Do not modify. -#Wed Feb 21 19:47:18 EST 2018 +#Fri Feb 23 13:58:57 EST 2018 version=release -androidBuildCode=262 +androidBuildCode=265 name=Mindustry code=3.3 build=custom build diff --git a/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java b/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java index 4e680e25bf..6a13644caf 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java @@ -59,6 +59,10 @@ public class DebugFragment implements Fragment { row(); new button("wave", () -> state.wavetime = 0f); row(); + new button("time 0", () -> Timers.resetTime(0f)); + row(); + new button("time max", () -> Timers.resetTime(1080000 - 60*10)); + row(); new button("clear", () -> { enemyGroup.clear(); state.enemies = 0; diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Junction.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Junction.java index 177203884d..bfaa422cd0 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Junction.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Junction.java @@ -84,6 +84,7 @@ public class Junction extends Block{ return new JunctionEntity(); } + @Override public Array getDebugInfo(Tile tile){ JunctionEntity entity = tile.entity(); Array arr = super.getDebugInfo(tile); diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/TunnelConveyor.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/TunnelConveyor.java index c6864b138b..7106a5174a 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/TunnelConveyor.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/TunnelConveyor.java @@ -1,5 +1,6 @@ package io.anuke.mindustry.world.blocks.types.distribution; +import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.NumberUtils; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.resource.Item; @@ -90,6 +91,30 @@ public class TunnelConveyor extends Block{ return new TunnelEntity(); } + @Override + public Array getDebugInfo(Tile tile){ + TunnelEntity entity = tile.entity(); + Array arr = super.getDebugInfo(tile); + for(int i = 0; i < 4; i ++){ + arr.add("nearby." + i); + arr.add(tile.getNearby(i)); + } + + arr.add("buffer"); + arr.add(entity.index); + + for(int i = 0; i < entity.index; i++){ + long l = entity.items[i]; + float time = NumberUtils.intBitsToFloat(Bits.getLeftInt(l)); + Item item = Item.getByID(Bits.getRightInt(l)); + Tile dest = getDestTunnel(tile, item); + arr.add(" buffer.item"); + arr.add(time + " | " + item.name + " | " + dest.block() + ":" + dest.floor()); + } + + return arr; + } + Tile getDestTunnel(Tile tile, Item item){ Tile dest = tile; int rel = (tile.getRotation() + 2)%4; From a6737c5a54fd5376bf7f809c2a06d78f6ea54075 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 23 Feb 2018 14:49:33 -0500 Subject: [PATCH 04/18] Added german language --- core/assets/bundles/bundle_de.properties | 479 ++++++++++++++++++ core/assets/version.properties | 4 +- core/src/io/anuke/mindustry/Vars.java | 2 +- .../mindustry/ui/fragments/DebugFragment.java | 9 - .../types/distribution/TunnelConveyor.java | 2 +- 5 files changed, 483 insertions(+), 13 deletions(-) create mode 100644 core/assets/bundles/bundle_de.properties diff --git a/core/assets/bundles/bundle_de.properties b/core/assets/bundles/bundle_de.properties new file mode 100644 index 0000000000..1e7258c48a --- /dev/null +++ b/core/assets/bundles/bundle_de.properties @@ -0,0 +1,479 @@ +text.about = Erstellt von [ROYAL] Anuken. [] \nUrsprünglich ein Eintrag im [orange] GDL [] MM Jam.\n\nCredits: \n- SFX gemacht mit [yellow] bfxr [] - Musik gemacht von [green] RoccoW [] / gefunden auf [lime] FreeMusicArchive.org [] \n\nBesonderer Dank geht an: \n- [coral] MitchellFJN []: Umfangreicher Spieletest und Feedback \n- [sky] Luxray5474 []: Wiki-Arbeit, Code-Beiträge \n- Alle Beta-Tester auf itch.io und Google Play\n +text.discord = Trete dem Mindustry Discord bei! +text.gameover = Der Kern wurde zerstört. +text.highscore = [YELLOW] Neuer Highscore! +text.lasted = Du hast bis zur folgenden Welle überlebt +text.level.highscore = High Score: [accent] {0} +text.level.delete.title = Löschen bestätigen +text.level.delete = Bist du sicher, dass du die Karte \"[orange] {0}\" löschen möchtest? +text.level.select = Level Auswahl +text.level.mode = Spielmodus: +text.savegame = Spiel speichern +text.loadgame = Spiel laden +text.joingame = Spiel beitreten +text.quit = Verlassen +text.about.button = Info +text.name = Name: +text.public = Öffentlich +text.players = {0} Spieler online +text.players.single = {0} Spieler online +text.server.mismatch = Paketfehler: Mögliche Client / Server-Version stimmt nicht überein. Stell sicher, dass du und der Host die neueste Version von Mindustry haben! +text.server.closing = [accent] Server wird geschlossen... +text.server.kicked.kick = Du wurdest vom Server gekickt! +text.server.kicked.invalidPassword = Falsches Passwort. +text.server.connected = {0} ist beigetreten +text.server.disconnected = {0} hat die Verbindung getrennt. +text.nohost = Server kann nicht auf einer benutzerdefinierten Karte gehostet werden! +text.hostserver = Server hosten +text.host = Host +text.hosting = [accent] Server wird geöffnet... +text.hosts.refresh = Aktualisieren +text.hosts.discovering = Suche nach LAN-Spielen +text.server.refreshing = Server wird aktualisiert +text.hosts.none = [lightgray] Keine LAN Spiele gefunden! +text.host.invalid = [scarlet] Kann keine Verbindung zum Host herstellen. +text.server.add = Server hinzufügen +text.server.delete = Bist du dir sicher das du diesen Server löschen möchtest? +text.server.hostname = Host: {0} +text.server.edit = Server bearbeiten +text.joingame.byip = Über IP beitreten ... +text.joingame.title = Spiel beitreten +text.joingame.ip = IP: +text.disconnect = Verbindung unterbrochen. +text.connecting = [accent] Verbindet... +text.connecting.data = [accent] Weltdaten werden geladen... +text.connectfail = [crimson] Verbindung zum Server konnte nicht hergestellt werden: [orange]{0} +text.server.port = Port: +text.server.invalidport = Falscher Port! +text.server.error = [crimson] Fehler beim Hosten des Servers: [orange] {0} +text.tutorial.back = < Zurück +text.tutorial.next = Weiter > +text.save.new = Neuer Spielstand +text.save.overwrite = Möchten du diesen Spielstand wirklich überschreiben? +text.overwrite = Überschreiben +text.save.none = Keine Spielstände gefunden! +text.saveload = [accent] Speichern ... +text.savefail = Fehler beim Speichern des Spiels! +text.save.delete.confirm = Möchtest du diesen Spielstand wirklich löschen? +text.save.delete = Löschen +text.save.export = Spielstand exportieren +text.save.import.invalid = [orange] Dieser Spielstand ist ungültig! +text.save.import.fail = [crimson] Spielstand konnte nicht importiert werden: [orange] {0} +text.save.export.fail = [crimson] Spielstand konnte nicht exportiert werden: [orange] {0} +text.save.import = Spielstand importieren +text.save.newslot = Name speichern: +text.save.rename = Umbenennen +text.save.rename.text = Neuer Name +text.selectslot = Wähle einen Spielstand +text.slot = [accent] Platz {0} +text.save.corrupted = [orange] Datei beschädigt oder ungültig! +text.empty = +text.on = An +text.off = Aus +text.save.autosave = Automatisches Speichern: {0} +text.save.map = Karte: {0} +text.save.wave = Welle: {0} +text.save.date = Zuletzt gespeichert: {0} +text.confirm = Bestätigen +text.delete = Löschen +text.ok = OK +text.open = Öffnen +text.cancel = Abbruch +text.openlink = Link öffnen +text.back = Zurück +text.quit.confirm = Willst du wirklich aufhören? +text.loading = [accent] Wird geladen ... +text.wave = [orange] Welle {0} +text.wave.waiting = Welle in {0} +text.waiting = Warten... +text.enemies = {0} Feinde +text.enemies.single = {0} Feind +text.loadimage = Bild laden +text.saveimage = Bild speichern +text.editor.badsize = [orange]Ungültige Bildabmessungen! [] Gültige Kartenabmessungen: {0} +text.editor.errorimageload = Fehler beim Laden des Bildes: [orange] {0} +text.editor.errorimagesave = Fehler beim Speichern des Bildes: [orange] {0} +text.editor.generate = Generieren +text.editor.resize = Größe anpassen +text.editor.loadmap = Karte laden +text.editor.savemap = Karte speichern +text.editor.loadimage = Bild laden +text.editor.saveimage = Bild speichern +text.editor.unsaved = [crimson] Du hast Änderungen nicht gespeichert [] Möchtest du wirklich aufhören? +text.editor.brushsize = Pinselgröße: {0} +text.editor.noplayerspawn = Diese Karte hat keinen Spielerspawnpunkt! +text.editor.manyplayerspawns = Maps können nicht mehr als einen Spawnpunkt des Spielers haben! +text.editor.manyenemyspawns = Kann nicht mehr als {0} feindliche Spawnpunkte haben! +text.editor.resizemap = Größe der Karte ändern +text.editor.resizebig = [crimson] Warnung! [] Karten, die größer als 256 Einheiten sind, können ruckeln und instabil sein. +text.editor.mapname = Map Name +text.editor.overwrite = [accent] Warnung! Dies überschreibt eine vorhandene Map. +text.editor.failoverwrite = [crimson] Die Standardkarte kann nicht überschrieben werden! +text.editor.selectmap = Wähle eine Map zum Laden: +text.width = Breite: +text.height = Höhe: +text.randomize = Zufällig +text.apply = Anwenden +text.update = Aktualisieren +text.menu = Menü +text.play = Spielen +text.load = Laden +text.save = Speichern +text.settings = Einstellungen +text.tutorial = Tutorial +text.editor = Bearbeiter +text.mapeditor = Karten Bearbeiter +text.donate = Spenden +text.settings.reset = Auf Standard zurücksetzen +text.settings.controls = Steuerung +text.settings.game = Spiel +text.settings.sound = Audio +text.settings.graphics = Grafiken +text.upgrades = Verbesserungen +text.purchased = [LIME] Erstellt! +text.weapons = Waffen +text.paused = Pausiert +text.respawn = Respawn in +text.error.title = [crimson] Ein Fehler ist aufgetreten +text.error.crashmessage = [SCARLET] Es ist ein unerwarteter Fehler aufgetreten, der einen Absturz verursacht hätte. [] Bitte geben Sie die genauen Umstände an, unter denen dieser Fehler passiert ist, für den Entwickler: [ORANGE] anukendev@gmail.com [] +text.error.crashtitle = EIn Fehler ist aufgetreten! +text.mode.break = Zerstörungsmodus: {0} +text.mode.place = Platzierungsmodus: {0} +placemode.hold.name = Zeile +placemode.areadelete.name = Gebiet +placemode.touchdelete.name = berühren +placemode.holddelete.name = halten +placemode.none.name = keine +placemode.touch.name = berühren +placemode.cursor.name = Mauszeiger +text.blocks.extrainfo = [accent] Extra Blockinfo: +text.blocks.blockinfo = Blockinfo: +text.blocks.powercapacity = Energiekapazität +text.blocks.powershot = Energie / Schuss +text.blocks.powersecond = Energie / Sekunde +text.blocks.powerdraindamage = Energieabnahme / Schaden +text.blocks.shieldradius = Schildradius +text.blocks.itemspeedsecond = Gegenstands Geschwindigkeit / Sekunde +text.blocks.range = Reichweite +text.blocks.size = Größe +text.blocks.powerliquid = Energie / Flüssigkeit +text.blocks.maxliquidsecond = Max Flüssigkeit / Sekunde +text.blocks.liquidcapacity = Flüssigkeitskapazität +text.blocks.liquidsecond = Flüssigkeit / Sekunde +text.blocks.damageshot = Schaden / Schuss +text.blocks.ammocapacity = Munitionskapazität +text.blocks.ammo = Munition +text.blocks.ammoitem = Munition / Gegenstand +text.blocks.maxitemssecond = Max Gegenstände / Sekunde +text.blocks.powerrange = Energiereichweite +text.blocks.lasertilerange = Laser Reichweite +text.blocks.capacity = Kapazität +text.blocks.itemcapacity = Gegenstand Kapazität +text.blocks.maxpowergenerationsecond = Max Energieerzeugung / Sekunde +text.blocks.powergenerationsecond = Energieerzeugung / Sekunde +text.blocks.generationsecondsitem = Generation Sekunden / Gegenstand +text.blocks.input = Eingabe +text.blocks.inputliquid = Flüssigkeiten Eingabe +text.blocks.inputitem = Eingabe Gegenstand +text.blocks.output = Ausgabe +text.blocks.secondsitem = Sekunden / Item +text.blocks.maxpowertransfersecond = Max Energieübertragung / Sekunde +text.blocks.explosive = Hochexplosiv! +text.blocks.repairssecond = Reparaturen / Sekunde +text.blocks.health = Lebenspunkte +text.blocks.inaccuracy = Ungenauigkeit +text.blocks.shots = Schüsse +text.blocks.shotssecond = Schüsse / Sekunde +text.blocks.fuel = Treibstoff +text.blocks.fuelduration = Treibstoffdauer +text.blocks.maxoutputsecond = Max Ausgabe / Sekunde +text.blocks.inputcapacity = Eingabekapazität +text.blocks.outputcapacity = Ausgabekapazität +text.blocks.poweritem = Energie / Gegenstand +text.placemode = Platzierungsmodus +text.breakmode = Zerstörungsmodus +text.health = Lebenspunkte +setting.difficulty.easy = Leicht +setting.difficulty.normal = Normal +setting.difficulty.hard = Schwer +setting.difficulty.insane = Unmöglich +setting.difficulty.purge = Auslöschung +setting.difficulty.name = Schwierigkeit +setting.screenshake.name = Bildschirm wackeln +setting.smoothcam.name = Glatte Kamera +setting.indicators.name = Feind Indikatoren +setting.effects.name = Effekte anzeigen +setting.sensitivity.name = Kontroller Empfindlichkeit +setting.saveinterval.name = Autosave Häufigkeit +setting.seconds = {0} Sekunden +setting.fps.name = Zeige FPS +setting.vsync.name = VSync +setting.lasers.name = Zeige Energielaser +setting.healthbars.name = Zeige Objekt Lebensbalken +setting.pixelate.name = Pixel Bildschirm +setting.musicvol.name = Musiklautstärke +setting.mutemusic.name = Musik stummschalten +setting.sfxvol.name = Audioeffekte Lautstärke +setting.mutesound.name = Audioeffekte stummschalten +map.maze.name = Labyrinth +map.fortress.name = Festung +map.sinkhole.name = Sinkloch +map.caves.name = Höhlen +map.volcano.name = Vulkan +map.caldera.name = Lavakessel +map.scorch.name = Flammen +map.desert.name = Wüste +map.island.name = Insel +map.grassland.name = Grasland +map.tundra.name = Kältesteppe +map.spiral.name = Spirale +map.tutorial.name = Tutorial +tutorial.intro.text = [gelb] Willkommen zum Tutorial [] Um zu beginnen, drücke 'weiter'. +tutorial.moveDesktop.text = Verwende zum Verschieben die Tasten [orange] [[WASD] []. Halte [orange] Shift [] gedrückt, um zu erhöhen. Halte [orange] CTRL/STRG [] gedrückt, während du das [orange] Scrollrad [] zum Vergrößern oder Verkleinern verwendest. +tutorial.shoot.text = Ziele mit der Maus, halte die [orange] linke Maustaste [] gedrückt, um zu schießen. Versuche es mit dem [gelben] Ziel []. +tutorial.moveAndroid.text = Um die Ansicht zu verschieben, ziehe einen Finger über den Bildschirm. Drücke und ziehe, um zu vergrößern oder zu verkleinern. +tutorial.placeSelect.text = Versuche, ein [gelbes] Förderband [] aus dem Blockmenü unten rechts auszuwählen. +tutorial.placeConveyorDesktop.text = Verwende das [orange] [[scrollwheel] [], um das Förderband nach vorne zu bewegen [orange] vorwärts [], und platziere es dann an der [gelben] markierten Stelle [] mit [orange] [[linke Maustaste] []. +tutorial.placeConveyorAndroid.text = Verwende die [orange] [[rotieren-Taste] [], um das Förderband nach vorne [orange] zu drehen [], ziehe es mit einem Finger in Position und platziere es dann an der [gelben] markierten Stelle [] mit der [Orange] [[Häkchen][]. +tutorial.placeConveyorAndroidInfo.text = Alternativ kannst du das Fadenkreuzsymbol unten links drücken, um zum [orange] [[touch mode] [] zu wechseln, und Blöcke durch Tippen auf den Bildschirm platzieren. Im Touch-Modus können Blöcke mit dem Pfeil unten links gedreht werden. Drücke [gelb] neben [], um es auszuprobieren. +tutorial.placeDrill.text = Wähle nun einen [gelben] Steinbohrer [] an der markierten Stelle aus und platziere ihn. +tutorial.blockInfo.text = Wenn du mehr über einen Block erfahren möchtest, tippe oben rechts auf das [orange] Fragezeichen [], um dessen Beschreibung zu lesen. +tutorial.deselectDesktop.text = Du kannst einen Block mit [Orange] [[Rechte Maustaste] [] abwählen. +tutorial.deselectAndroid.text = Du kannst einen Block abwählen, indem du die [orange] X [] -Taste drücken. +tutorial.drillPlaced.text = Der Bohrer erzeugt nun [gelben] Stein, [] gib den Stein nun auf das Förderband aus und bewege ihn dann in den [gelben] Kern []. +tutorial.drillInfo.text = Verschiedene Erze benötigen unterschiedliche Bohrer. Stein erfordert Steinbohrer, Eisen erfordert Eisenbohrer usw. +tutorial.drillPlaced2.text = Wenn du Gegenstände in den Kern verschiebst, steckst du sie in dein [gelbes] Inventar [] oben links. Das Platzieren von Blöcken verwendet Gegenstände aus deinem Inventar. +tutorial.moreDrills.text = Du kannst so viele Bohrer und Förderer miteinander verbinden wie du lust hast. +tutorial.deleteBlock.text = Du kannst Blöcke löschen, indem du mit der [orange] rechte Maustaste [] auf dem Block klickst, den du löschen möchtest. Versuche, dieses Förderband zu löschen. +tutorial.deleteBlockAndroid.text = Du kannst Blöcke löschen, indem du [orange] das Fadenkreuz [] im [orange] Pausenmodusmenü [] links unten auswählst und auf einen Block tippst. Versuche, dieses Fließband zu löschen. +tutorial.placeTurret.text = Wähle nun einen [gelben] Turm [] an der [gelben] markierten Stelle [] und platziere ihn. +tutorial.placedTurretAmmo.text = Dieser Turm nimmt nun [gelbe] Munition [] vom Förderband an. Du kannst sehen, wie viel Munition es hat, indem du darüber schweben und den [grünen] grünen Balken [] prüfen. +tutorial.turretExplanation.text = Geschütze schießen automatisch auf den nächsten Feind in Reichweite, solange sie genug Munition haben. +tutorial.waves.text = Jede [yellow] 60 [] Sekunden wird eine Welle von [coral] Feinden [] an einem bestimmten Orten erscheinen und versuchen, den Kern zu zerstören. +tutorial.coreDestruction.text = Dein Ziel ist es, den Kern [yellow] zu verteidigen. Wenn der Kern zerstört wird, verlierst du [coral] das Spiel []. +tutorial.pausingDesktop.text = Wenn du jemals eine Pause machen möchtest, drücke die [orange] Pause-Taste [] oben links oder [orange]space[], um das Spiel anzuhalten. Du kannst auch Blöcke immer noch auswählen und platzieren, während du das Spiel pausiert ist, aber Sie können sich nicht bewegen oder schießen. +tutorial.pausingAndroid.text = Wenn du jemals eine Pause machen willst, drück einfach die [orange] Pause-Taste [] oben links, um das Spiel anzuhalten. Sie können immer noch Sachen auswählen und Blöcke während der Pause platzieren. +tutorial.purchaseWeapons.text = Du kannst neue [yellow] Waffen [] für deinen Mech kaufen, indem du das Verbesserungs-Menü unten links öffnest. +tutorial.switchWeapons.text = Schalte Waffen, indem du entweder auf das Symbol unten links klickst oder Nummern verwendest [orange] [[1-9] []. +tutorial.spawnWave.text = Hier kommt die erste Welle. Zerstöre sie. +tutorial.pumpDesc.text = In späteren Wellen müsst du möglicherweise [yellow] Pumpen [] verwenden, um Flüssigkeiten für Generatoren oder Extraktoren zu verteilen. +tutorial.pumpPlace.text = Pumpen arbeiten ähnlich wie Bohrer, außer dass sie anstelle von Gegenständen Flüssigkeiten produzieren. Versuch mal, eine Pumpe auf das [yellow] gekennzeichnete Öl [] zu setzen. +tutorial.conduitUse.text = Stellen Sie nun eine [orange] Leitungsrohr [] von der Pumpe weg. +tutorial.conduitUse2.text = Und noch ein paar mehr ... +tutorial.conduitUse3.text = Und noch ein paar mehr ... +tutorial.generator.text = Stellen Sie nun einen [orange] Verbrennungsgenerator [] Block am Ende des Leitungsrohres auf. +tutorial.generatorExplain.text = Dieser Generator erzeugt nun [yellow] Energie [] aus dem Öl. +tutorial.lasers.text = Die Energie wird mit [yellow] Energielasern [] verteilt. Drehe und platziere einen hier. +tutorial.laserExplain.text = Der Generator wird nun Energie in den Laserblock bewegen. Ein [yellow] undurchsichtiger [] Strahl bedeutet, dass er gerade Leistung überträgt, und ein [yellow] transparenter [] Strahl bedeutet, dass dies nicht der Fall ist. +tutorial.laserMore.text = Du kannst überprüfen, wie viel Energie ein Block hat, indem du darüber schweben und den [yellow] gelben Balken [] oben prüfen. +tutorial.healingTurret.text = Dieser Laser kann verwendet werden, um einen [lime] -Reparaturgeschütz [] anzutreiben. Platziere einen hier. +tutorial.healingTurretExplain.text = Solange er Kraft hat, repariert dieser Turm in der Nähe Blöcke. [] Wenn du spielst, stelle sicher, dass du so schnell wie möglich einen in deiner Basis bekommst! +tutorial.smeltery.text = Viele Blöcke benötigen [orange] Stahl [], um eine [orange] Schmelzer [] herzustellen. Platziere einen hier. +tutorial.smelterySetup.text = Diese Schmelzer wird nun [orange] Stahl [] aus dem Eingangs-Eisen produzieren, wobei Kohle als Brennstoff verwendet wird. +tutorial.end.text = Und damit ist das Tutorial abgeschlossen! Viel Glück! +keybind.move_x.name = bewege_x +keybind.move_y.name = bewege_y +keybind.select.name = wählen +keybind.break.name = Unterbrechung +keybind.shoot.name = Schieß +keybind.zoom_hold.name = zoomen_halten +keybind.zoom.name = zoomen +keybind.menu.name = Menü +keybind.pause.name = Pause +keybind.dash.name = Bindestrich +keybind.rotate_alt.name = drehen_alt +keybind.rotate.name = Drehen +keybind.weapon_1.name = Waffe_1 +keybind.weapon_2.name = Waffe_2 +keybind.weapon_3.name = Waffe_3 +keybind.weapon_4.name = Waffe_4 +keybind.weapon_5.name = Waffe_5 +keybind.weapon_6.name = Waffe_6 +mode.waves.name = Wellen +mode.sandbox.name = Sandkasten +mode.freebuild.name = Freier Bau +upgrade.standard.name = Standard +upgrade.standard.description = Der Standardmech. +upgrade.blaster.name = Blaster +upgrade.blaster.description = Schießt eine langsame, schwache Kugel. +upgrade.triblaster.name = Dreifach-Blaster +upgrade.triblaster.description = Schießt 3 Kugeln in einer Ausbreitung. +upgrade.clustergun.name = Klumpen-Waffe +upgrade.clustergun.description = Schießt eine ungenaue Verbreitung von explosiven Granaten. +upgrade.beam.name = Strahlkanone +upgrade.beam.description = Schießt einen weitreichenden durchdringenden Laserstrahl. +upgrade.vulcan.name = Vulkan +upgrade.vulcan.description = Schießt eine Flut von schnellen Kugeln. +upgrade.shockgun.name = Schock-Waffe +upgrade.shockgun.description = Erschießt eine verheerende Explosion von geladenen Granatsplittern. +item.stone.name = Stein +item.iron.name = Eisen +item.coal.name = Kohle +item.steel.name = Stahl +item.titanium.name = Titan +item.dirium.name = Dirium +item.uranium.name = Uran +item.sand.name = Sand +liquid.water.name = Wasser +liquid.plasma.name = Plasma +liquid.lava.name = Lava +liquid.oil.name = Öl +block.weaponfactory.name = Waffenfabrik +block.air.name = Luft +block.blockpart.name = Blockteil +block.deepwater.name = tiefes Wasser +block.water.name = Wasser +block.lava.name = Lava +block.oil.name = Öl +block.stone.name = Stein +block.blackstone.name = schwarzer Stein +block.iron.name = Eisen +block.coal.name = Kohle +block.titanium.name = Titan +block.uranium.name = Uran +block.dirt.name = Erde +block.sand.name = Sand +block.ice.name = Eis +block.snow.name = Schnee +block.grass.name = Gras +block.sandblock.name = Sandstein +block.snowblock.name = Schneeblock +block.stoneblock.name = Steinblock +block.blackstoneblock.name = Schwarzer Stein +block.grassblock.name = Grasblock +block.mossblock.name = Moosblock +block.shrub.name = Busch +block.rock.name = Felsen +block.icerock.name = Eisfelsen +block.blackrock.name = Schwarzer Felsen +block.dirtblock.name = Erdblock +block.stonewall.name = Steinwand +block.stonewall.fulldescription = Ein billiger Verteidigungsblock. Nützlich zum Schutz des Kerns und der Geschütztürme in den ersten Wellen. +block.ironwall.name = Eisenwand +block.ironwall.fulldescription = Ein grundlegender Verteidigungsblock. Bietet Schutz vor Feinden. +block.steelwall.name = Stahlwand +block.steelwall.fulldescription = Ein Standard-Verteidigungsblock. Bietet angemessen Schutz vor Feinden. +block.titaniumwall.name = Titanwand +block.titaniumwall.fulldescription = Eine starke Abwehrblockade. Bietet Schutz vor Feinden. +block.duriumwall.name = Diriumwand +block.duriumwall.fulldescription = Eine sehr starke Abwehrblockade. Bietet guten Schutz vor Feinden. +block.compositewall.name = Verbundende Wand +block.steelwall-large.name = große Stahlwand +block.steelwall-large.fulldescription = Ein Standard-Verteidigungsblock. Mehrere Blöcke groß. +block.titaniumwall-large.name = große Titanwand +block.titaniumwall-large.fulldescription = Eine starke Abwehrblockade. Mehrere Blöcke groß. +block.duriumwall-large.name = große Diriumwand +block.duriumwall-large.fulldescription = Eine sehr starke Abwehrblockade. Mehrere Blöcke groß. +block.titaniumshieldwall.name = geschützte Wand +block.titaniumshieldwall.fulldescription = Ein starker Abwehrblock mit einem extra eingebauten Schild. Benötigt Energie. Verwendet Energie, um feindliche Kugeln zu absorbieren. Es wird empfohlen, Verstärker zu verwenden, um diesem Block Energie zuzuführen. +block.repairturret.name = Reparaturgeschütz +block.repairturret.fulldescription = Repariert beschädigte Blöcke in der Nähe in einem langsamen Tempo. Nutzt geringe Mengen an Energie. +block.megarepairturret.name = Reparaturgeschütz II +block.megarepairturret.fulldescription = Repariert in der Nähe beschädigte Blöcke in Reichweite zu einem vernünftigen Preis. Verwendet Energie. +block.shieldgenerator.name = Schildgenerator +block.shieldgenerator.fulldescription = Ein fortgeschrittener Verteidigungsblock. Schützt alle Blöcke in einem Radius vor Angriffen. Bei keinem Betrieb langsamer Strom verbrauch, verliert bei Kugelkontakt jedoch schnell Energie. +block.door.name = Tür +block.door.fulldescription = Ein Block, der durch Antippen geöffnet und geschlossen werden kann. +block.door-large.name = große Tür +block.door-large.fulldescription = Ein Block der mehrere Felder groß ist und der durch Antippen geöffnet und geschlossen werden kann. +block.conduit.name = Leitungsrohr +block.conduit.fulldescription = Grundlegender Flüssigkeitstransportblock. Funktioniert wie ein Förderband, aber mit Flüssigkeiten. Am besten mit Pumpen oder anderen Leitungen verwenden. Kann als Brücke für Gegner und Spieler verwendet werden. +block.pulseconduit.name = Pulsleitungsrohr +block.pulseconduit.fulldescription = Fortschrittlicher Flüssigkeitstransportblock. Transportiert Flüssigkeiten schneller und speichert mehr als normale Leitungsrohre. +block.liquidrouter.name = flüssigkeiten verteiler +block.liquidrouter.fulldescription = Funktioniert ähnlich wie ein Router. Akzeptiert Flüssigkeit von einer Seite und gibt sie auf die anderen Seiten aus. Nützlich zum Aufspalten von Flüssigkeit aus eines einzelnen Leitungsrohres in mehrere andere Leitungensrohre. +block.conveyor.name = Förderband +block.conveyor.fulldescription = Grundelement Transport Block. Bewegt Gegenstände nach vorne und legt sie automatisch in Türmen oder ähnliches. Drehbar. Kann als Brücke für Gegner und Spieler verwendet werden. +block.steelconveyor.name = Stahlförderband +block.steelconveyor.fulldescription = Erweiterter Transportblock Bewegt Gegenstände schneller als Standardförderer. +block.poweredconveyor.name = Impulsförderband +block.poweredconveyor.fulldescription = Der ultimative Transportblock für Gegenstände. Bewegt Gegenstände noch schneller als Stahlförderer. +block.router.name = Verteiler +block.router.fulldescription = Akzeptiert Objekte aus einer Richtung und gibt sie in 3 andere Richtungen aus. Kann auch eine bestimmte Anzahl von Gegenständen speichern. Geeignet zum Aufteilen der Materialien von einem Bohrer in mehrere Geschütze. +block.junction.name = Kreuzung +block.junction.fulldescription = Fungiert als Brücke für zwei kreuzende Förderbänder. Nützlich in Situationen mit zwei verschiedenen Förderbänder, die unterschiedliche Materialien zu verschiedenen Orten transportieren. +block.conveyortunnel.name = Förderbandtunnel +block.conveyortunnel.fulldescription = Transportiert Artikel unter Blöcken. Verwendung für einen Tunnel, der in den zu untertunnelnden Block führt, und einen auf der anderen Seite. Stellen Sie sicher, dass beide Tunnel in entgegengesetzte Richtungen weisen, das heißt das die Tunnel voneinander weggucken. +block.liquidjunction.name = flüssigkeite Kreuzung +block.liquidjunction.fulldescription = Funktioniert als Brücke für zwei kreuzende Leitungsrohre. Nützlich in Situationen mit zwei verschiedenen Leitungen, die unterschiedliche Flüssigkeiten zu verschiedenen Orten transportieren. +block.liquiditemjunction.name = Flüssigkeit-Gegenstand-Kreuzung +block.liquiditemjunction.fulldescription = Fungiert als Brücke zum Überqueren von Leitungsrohre und Förderbändern. +block.powerbooster.name = Energieverstärker +block.powerbooster.fulldescription = Verteilt die Energie an alle Blöcke innerhalb seines Radius. +block.powerlaser.name = Energielaser +block.powerlaser.fulldescription = Erzeugt einen Laser, der die Kraft auf den Block davor überträgt. Erzeugt selbst keine Energie. Am besten mit Generatoren oder anderen Lasern verwendet. +block.powerlaserrouter.name = Laser Verteiler +block.powerlaserrouter.fulldescription = Laser, der die Kraft in drei Richtungen gleichzeitig verteilt. Nützlich in Situationen, in denen mehrere Blöcke von einem Generator mit Strom versorgt werden müssen. +block.powerlasercorner.name = Laser-Ecke +block.powerlasercorner.fulldescription = Laser, der die Kraft in zwei Richtungen gleichzeitig verteilt. Nützlich in Situationen, in denen mehrere Blöcke von einem Generator mit Strom versorgt werden müssen und ein Router ungenau ist. +block.teleporter.name = Teleporter +block.teleporter.fulldescription = Erweiterter Transportblock Teleporter geben Gegenstände in andere Teleporter derselben Farbe ein. Tut nichts, wenn keine Teleporter derselben Farbe existieren. Wenn mehrere Teleporter mit derselben Farbe existieren, wird eine zufällige ausgewählt. Verwendet Energie. Tippen, um die Farbe zu ändern. +block.sorter.name = Sortierer +block.sorter.fulldescription = Sortiert den Gegenstand nach Materialart. Das zu akzeptierende Material wird durch die Farbe im Block angezeigt. Alle Artikel, die dem Sortiermaterial entsprechen, werden vorwärts ausgegeben, alles andere wird nach links und rechts ausgegeben. +block.core.name = Kern +block.pump.name = Pumpe +block.pump.fulldescription = Pumpen Flüssigkeiten aus einem Quellblock - meist Wasser, Lava oder Öl. Gibt Flüssigkeit in benachbarte Leitungsrohre aus. +block.fluxpump.name = flux Pumpe +block.fluxpump.fulldescription = Eine erweiterte Version der Pumpe. Speichert mehr Flüssigkeit und pumpt Flüssigkeit schneller. +block.smelter.name = Schmelzer +block.smelter.fulldescription = Der essentielle Bastelblock. Wenn 1x Eisen und 1x Kohle eingegeben wird, wird 1x Stahl ausgegeben. +block.crucible.name = Tiegel +block.crucible.fulldescription = Ein fortgeschrittener Handwerksblock. Braucht Kohle um zu funktionieren. Wenn 1x Titan und 1x Stahl eingegeben wird, wird 1x Dirium ausgegeben. +block.coalpurifier.name = Kohle-Extraktor +block.coalpurifier.fulldescription = Ein einfacher Extraktorblock. Gibt Kohle aus, wenn der Block mit großen Mengen Wasser und Stein gefüllt wird. +block.titaniumpurifier.name = Titan-Extraktor +block.titaniumpurifier.fulldescription = Ein Standard-Extraktorblock. Gibt Titan aus wenn er mit großen Mengen Wasser und Eisen gefüllt wird. +block.oilrefinery.name = Ölraffinerie +block.oilrefinery.fulldescription = Veredelt große Mengen Öl zu Kohle. Nützlich für die Betankung von Blöcken die Kohle benutzen wie z.b. Waffentürme, wenn Kohleadern knapp sind. +block.stoneformer.name = Steinformer +block.stoneformer.fulldescription = Verfestigt flüssige Lava zu Stein. Nützlich für die Herstellung von großen Mengen von Stein für Kohle-Extraktor. +block.lavasmelter.name = Lava-Schmelzer +block.lavasmelter.fulldescription = Verwendet Lava, um Eisen zu Stahl schmelzen. Eine Alternative zum Schmelzer. Nützlich in Situationen, in denen Kohle knapp ist. +block.stonedrill.name = Steinbohrer +block.stonedrill.fulldescription = Der wesentliche Bohrer. Wenn er auf Steinplatten gelegt wird, gibt er Steine ​​mit einer langsamen Geschwindigkeit auf endlosen Zeit aus. +block.irondrill.name = Eisenbohrer +block.irondrill.fulldescription = Eine grundlegender Bohrer. Wenn es auf Eisenerz gelegt wird, gibt er Eisen auf endloser Zeit langsam aus. +block.coaldrill.name = Kohlenbohrer +block.coaldrill.fulldescription = Eine grundlegender Bohrer. Wenn es auf Kohleerz platziert wird, gibt er für endloser Zeit langsam Kohle aus. +block.uraniumdrill.name = Uran-Bohrer +block.uraniumdrill.fulldescription = Ein fortgeschrittener Bohrer. Wenn es auf Uranerz platziert wird, gibt er Uran mit einer langsamen Geschwindigkeit auf endloser Zeit ab. +block.titaniumdrill.name = Titan-Bohrer +block.titaniumdrill.fulldescription = Ein fortgeschrittener Bohrer. Wenn es auf Titanerz platziert wird, gibt er Titan langsam aus für undendlich langer Zeit +block.omnidrill.name = Omni-Bohrer +block.omnidrill.fulldescription = Der ultimative Bohrer. Baut in schnellem Tempo jegliches Erz ab. +block.coalgenerator.name = Kohle-Generator +block.coalgenerator.fulldescription = Der wesentliche Generator. Erzeugt Energie aus Kohle. Gibt Energie als Laser an seine 4 Seiten aus. +block.thermalgenerator.name = thermischer Generator +block.thermalgenerator.fulldescription = Erzeugt Energie aus Lava. Gibt Energie als Laser an seine 4 Seiten aus. +block.combustiongenerator.name = Verbrennungsgenerator +block.combustiongenerator.fulldescription = Erzeugt Energie aus Öl. Gibt Energie als Laser an seine 4 Seiten aus. +block.rtgenerator.name = RTG-Generator +block.rtgenerator.fulldescription = Erzeugt geringe Mengen an Energie aus dem radioaktiven Zerfall von Uran. Gibt Energie als Laser an seine 4 Seiten aus. +block.nuclearreactor.name = Kernreaktor +block.nuclearreactor.fulldescription = Eine erweiterte Version des RTG-Generators und der ultimative Energie Generator. Erzeugt Strom aus Uran. Erfordert konstante Wasserkühlung. Sehr heiß; explodiert heftig, wenn zu wenig Kühlmittel zugeführt wird. +block.turret.name = Geschütz +block.turret.fulldescription = Ein einfacher, billiger Turm. Verwendet Stein für Munition. Hat etwas mehr Reichweite als das Doppelgeschütz. +block.doubleturret.name = Doppelgeschütz +block.doubleturret.fulldescription = Eine etwas stärkere Version des Geschützes. Verwendet Stein für Munition. Hat deutlich mehr Schaden, hat aber eine geringere Reichweite. Schießt zwei Kugeln. +block.machineturret.name = Gatling Geschütz +block.machineturret.fulldescription = Ein Standard-Allround-Turm. Verwendet Eisen für Munition. Hat eine schnelle Feuerrate mit gutem Schaden. +block.shotgunturret.name = Splittergeschütz +block.shotgunturret.fulldescription = Ein Standard-Turm. Verwendet Eisen für Munition. Schießt 7 Kugeln auf einmal. Geringere Reichweite, aber höhere Schadensleistung als das Gatling Geschütz +block.flameturret.name = Flammenwerfer +block.flameturret.fulldescription = Fortschrittlicher Nahbereichswaffe. Verwendet Kohle für Munition. Hat eine sehr geringe Reichweite, aber sehr hohen Schaden. Gut für Nahkampf. Empfohlen für den Einsatz hinter Mauern. +block.sniperturret.name = Schienenkanone +block.sniperturret.fulldescription = Fortschrittliches Reichweitengeschütz. Verwendet Stahl für Munition. Sehr hoher Schaden, aber niedrige Feuerrate. Teuer zu verwenden, kann aber aufgrund seiner Reichweite weit entfernt von den feindlichen Linien platziert werden. +block.mortarturret.name = Flakgeschütz +block.mortarturret.fulldescription = Fortschrittlicher Flächen-Schaden Turm. Verwendet Kohle für Munition. Sehr langsame Feuerrate und Geschosse, aber sehr hoher Einzelziel- und Flächenschaden. Nützlich gegen große Mengen von Feinden. +block.laserturret.name = Laserturm +block.laserturret.fulldescription = Fortschrittlicher Einzelziel-Turm. Verwendet Strom. Guter Allround-Revolver für mittlere Reichweiten. Nur Einzelziel. Verfehlt nie. +block.waveturret.name = Teslakanone +block.waveturret.fulldescription = Erweiterter Mehrfach-Ziele-Turm. Verwendet Strom. Mittlere Reichweite. Verfehlt nie. Im Durchschnitt zu wenig Schaden, aber kann mehrere Feinde gleichzeitig mit Kettenblitz treffen. +block.plasmaturret.name = Plasmageschütz +block.plasmaturret.fulldescription = Hochentwickelte Version des Flammenwerfers. Verwendet Kohle als Munition. Sehr hoher Schaden, niedriger bis mittlerer Reichweite. +block.chainturret.name = Kettengeschütz +block.chainturret.fulldescription = Die ultimative Schnellfeuer Waffe. Verwendet Uran als Munition. Schießt große Kugeln mit hoher Feuerrate. Mittlere Reichweite. Mehrere Felder groß. Hält extrem viel aus. +block.titancannon.name = Titan Kanone +block.titancannon.fulldescription = Die ultimative Langstrecken Kanone. Verwendet Uran als Munition. Schießt große Flächen-Schadenden-Granaten mit einer mittleren Feuerrate ab. Lange Reichweite. Ist mehrere Felder groß. Hält extrem viel aus. +block.playerspawn.name = Spielerspawn +block.enemyspawn.name = Gegnerspawn diff --git a/core/assets/version.properties b/core/assets/version.properties index 44e6da5af2..49eb791369 100644 --- a/core/assets/version.properties +++ b/core/assets/version.properties @@ -1,7 +1,7 @@ #Autogenerated file. Do not modify. -#Fri Feb 23 13:58:57 EST 2018 +#Fri Feb 23 14:48:54 EST 2018 version=release -androidBuildCode=265 +androidBuildCode=266 name=Mindustry code=3.3 build=custom build diff --git a/core/src/io/anuke/mindustry/Vars.java b/core/src/io/anuke/mindustry/Vars.java index 73c10dbab9..cb5f7584ae 100644 --- a/core/src/io/anuke/mindustry/Vars.java +++ b/core/src/io/anuke/mindustry/Vars.java @@ -93,7 +93,7 @@ public class Vars{ public static final int tilesize = 8; public static final Locale[] locales = {new Locale("en"), new Locale("fr", "FR"), new Locale("ru"), new Locale("pl", "PL"), - new Locale("es", "LA"), new Locale("pt", "BR"), new Locale("ko"), new Locale("in", "ID")}; + new Locale("de"), new Locale("es", "LA"), new Locale("pt", "BR"), new Locale("ko"), new Locale("in", "ID")}; public static final Color[] playerColors = { Color.valueOf("82759a"), diff --git a/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java b/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java index 6a13644caf..bc71c1312f 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java @@ -55,8 +55,6 @@ public class DebugFragment implements Fragment { row(); new button("paths", "toggle", () -> showPaths = !showPaths); row(); - new button("infammo", "toggle", () -> infiniteAmmo = !infiniteAmmo); - row(); new button("wave", () -> state.wavetime = 0f); row(); new button("time 0", () -> Timers.resetTime(0f)); @@ -75,13 +73,6 @@ public class DebugFragment implements Fragment { } }); row(); - new button("time", () -> { - Timers.resetTime(1080000 - 60*10); - }); - row(); - new button("time2", () -> { - Timers.resetTime(0); - }); }}.end(); row(); diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/TunnelConveyor.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/TunnelConveyor.java index 7106a5174a..0e6d91c202 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/TunnelConveyor.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/TunnelConveyor.java @@ -109,7 +109,7 @@ public class TunnelConveyor extends Block{ Item item = Item.getByID(Bits.getRightInt(l)); Tile dest = getDestTunnel(tile, item); arr.add(" buffer.item"); - arr.add(time + " | " + item.name + " | " + dest.block() + ":" + dest.floor()); + arr.add(time + " | " + item.name + " | " + ( dest == null ? "no dest" : dest.block() + ":" + dest.floor())); } return arr; From 2adacccf7d88c69933745d1f390bc138f49cbb32 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 23 Feb 2018 15:01:32 -0500 Subject: [PATCH 05/18] Fixed a few more crashes --- core/src/io/anuke/mindustry/input/InputHandler.java | 3 ++- .../io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java | 3 --- .../mindustry/world/blocks/types/defense/LaserTurret.java | 7 ++++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/core/src/io/anuke/mindustry/input/InputHandler.java b/core/src/io/anuke/mindustry/input/InputHandler.java index ae0a9c64f9..1aae96c7c1 100644 --- a/core/src/io/anuke/mindustry/input/InputHandler.java +++ b/core/src/io/anuke/mindustry/input/InputHandler.java @@ -88,7 +88,8 @@ public abstract class InputHandler extends InputAdapter{ public boolean validPlace(int x, int y, Block type){ - for(SpawnPoint spawn : world.getSpawns()){ + for(int i = 0; i < world.getSpawns().size; i ++){ + SpawnPoint spawn = world.getSpawns().get(i); if(Vector2.dst(x * tilesize, y * tilesize, spawn.start.worldx(), spawn.start.worldy()) < enemyspawnspace){ return false; } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java index ca0c126cf6..34d8404065 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java @@ -42,9 +42,6 @@ public class SettingsMenuDialog extends SettingsDialog{ shown(()->{ if(!state.is(State.menu)){ wasPaused = state.is(State.paused); - if(menu.getScene() != null){ - wasPaused = ((PausedDialog)menu).wasPaused; - } if(!Net.active()) state.set(State.paused); ui.paused.hide(); } diff --git a/core/src/io/anuke/mindustry/world/blocks/types/defense/LaserTurret.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/LaserTurret.java index 16efe1fcd2..fb75fbd9b2 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/defense/LaserTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/LaserTurret.java @@ -43,13 +43,14 @@ public class LaserTurret extends PowerTurret{ @Override public void drawLayer2(Tile tile){ TurretEntity entity = tile.entity(); + Enemy enemy = entity.target; - if(entity.target != null && - Angles.angleDist(entity.rotation, Angles.angle(tile.drawx(), tile.drawy(), entity.target.x, entity.target.y)) <= cone){ + if(enemy != null && + Angles.angleDist(entity.rotation, Angles.angle(tile.drawx(), tile.drawy(), enemy.x, enemy.y)) <= cone){ float len = 4f; float x = tile.drawx() + Angles.trnsx(entity.rotation, len), y = tile.drawy() + Angles.trnsy(entity.rotation, len); - float x2 = entity.target.x, y2 = entity.target.y; + float x2 = enemy.x, y2 = enemy.y; float lighten = (MathUtils.sin(Timers.time()/1.2f) + 1f) / 10f; From de340255fea4f4cc85c934cbab6774ab6ed0493c Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 23 Feb 2018 15:11:42 -0500 Subject: [PATCH 06/18] Updated to build 28 --- core/assets/version.properties | 6 +++--- .../io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java | 7 +++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/core/assets/version.properties b/core/assets/version.properties index 49eb791369..7fe28e0b4f 100644 --- a/core/assets/version.properties +++ b/core/assets/version.properties @@ -1,7 +1,7 @@ #Autogenerated file. Do not modify. -#Fri Feb 23 14:48:54 EST 2018 +#Fri Feb 23 15:06:51 EST 2018 version=release -androidBuildCode=266 +androidBuildCode=267 name=Mindustry code=3.3 -build=custom build +build=28 diff --git a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java index 34d8404065..6d2e79c610 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java @@ -32,16 +32,19 @@ public class SettingsMenuDialog extends SettingsDialog{ public SettingsMenuDialog(){ setStyle(Core.skin.get("dialog", WindowStyle.class)); - hidden(()->{ + hidden(() -> { if(!state.is(State.menu)){ if(!wasPaused || Net.active()) state.set(State.playing); } }); - shown(()->{ + shown(() -> { if(!state.is(State.menu)){ wasPaused = state.is(State.paused); + if(ui.paused.getScene() != null){ + wasPaused = ui.paused.wasPaused; + } if(!Net.active()) state.set(State.paused); ui.paused.hide(); } From 9985a19e6ac7ec7d7d1e5a25b89ca74e4cfd98d5 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 23 Feb 2018 21:42:05 -0500 Subject: [PATCH 07/18] Better net error messages, bugfixes, new command handler --- build.gradle | 2 +- core/assets/bundles/bundle_de.properties | 86 +++++++++---------- core/assets/version.properties | 6 +- .../io/anuke/mindustry/core/NetClient.java | 6 -- .../mindustry/entities/enemies/EnemyType.java | 15 +++- core/src/io/anuke/mindustry/net/Net.java | 4 +- .../mindustry/ui/fragments/MenuFragment.java | 35 ++++---- kryonet/src/io/anuke/kryonet/KryoClient.java | 7 +- .../anuke/mindustry/server/ServerControl.java | 12 +-- 9 files changed, 89 insertions(+), 84 deletions(-) diff --git a/build.gradle b/build.gradle index d1d219b811..af80efa582 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ allprojects { appName = 'Mindustry' gdxVersion = '1.9.8' aiVersion = '1.8.1' - uCoreVersion = 'f484468' + uCoreVersion = '1b29d6c' getVersionString = { String buildVersion = getBuildVersion() diff --git a/core/assets/bundles/bundle_de.properties b/core/assets/bundles/bundle_de.properties index 1e7258c48a..be8fa12cf5 100644 --- a/core/assets/bundles/bundle_de.properties +++ b/core/assets/bundles/bundle_de.properties @@ -18,7 +18,7 @@ text.public = Öffentlich text.players = {0} Spieler online text.players.single = {0} Spieler online text.server.mismatch = Paketfehler: Mögliche Client / Server-Version stimmt nicht überein. Stell sicher, dass du und der Host die neueste Version von Mindustry haben! -text.server.closing = [accent] Server wird geschlossen... +.server.closing = [accent] Server wird geschlossen... text.server.kicked.kick = Du wurdest vom Server gekickt! text.server.kicked.invalidPassword = Falsches Passwort. text.server.connected = {0} ist beigetreten @@ -94,18 +94,18 @@ text.editor.badsize = [orange]Ungültige Bildabmessungen! [] Gültige Kartenabme text.editor.errorimageload = Fehler beim Laden des Bildes: [orange] {0} text.editor.errorimagesave = Fehler beim Speichern des Bildes: [orange] {0} text.editor.generate = Generieren -text.editor.resize = Größe anpassen -text.editor.loadmap = Karte laden -text.editor.savemap = Karte speichern -text.editor.loadimage = Bild laden -text.editor.saveimage = Bild speichern +text.editor.resize = Grösse\nanpassen +text.editor.loadmap = Karte\nladen +text.editor.savemap = Karte\nspeichern +text.editor.loadimage = Bild\nladen +text.editor.saveimage = Bild\nspeichern text.editor.unsaved = [crimson] Du hast Änderungen nicht gespeichert [] Möchtest du wirklich aufhören? -text.editor.brushsize = Pinselgröße: {0} +text.editor.brushsize = Pinselgrösse: {0} text.editor.noplayerspawn = Diese Karte hat keinen Spielerspawnpunkt! text.editor.manyplayerspawns = Maps können nicht mehr als einen Spawnpunkt des Spielers haben! text.editor.manyenemyspawns = Kann nicht mehr als {0} feindliche Spawnpunkte haben! -text.editor.resizemap = Größe der Karte ändern -text.editor.resizebig = [crimson] Warnung! [] Karten, die größer als 256 Einheiten sind, können ruckeln und instabil sein. +text.editor.resizemap = Grösse der Karte ändern +text.editor.resizebig = [crimson] Warnung! [] Karten, die grösser als 256 Einheiten sind, können ruckeln und instabil sein. text.editor.mapname = Map Name text.editor.overwrite = [accent] Warnung! Dies überschreibt eine vorhandene Map. text.editor.failoverwrite = [crimson] Die Standardkarte kann nicht überschrieben werden! @@ -155,7 +155,7 @@ text.blocks.powerdraindamage = Energieabnahme / Schaden text.blocks.shieldradius = Schildradius text.blocks.itemspeedsecond = Gegenstands Geschwindigkeit / Sekunde text.blocks.range = Reichweite -text.blocks.size = Größe +text.blocks.size = Grösse text.blocks.powerliquid = Energie / Flüssigkeit text.blocks.maxliquidsecond = Max Flüssigkeit / Sekunde text.blocks.liquidcapacity = Flüssigkeitskapazität @@ -229,9 +229,9 @@ map.tundra.name = Kältesteppe map.spiral.name = Spirale map.tutorial.name = Tutorial tutorial.intro.text = [gelb] Willkommen zum Tutorial [] Um zu beginnen, drücke 'weiter'. -tutorial.moveDesktop.text = Verwende zum Verschieben die Tasten [orange] [[WASD] []. Halte [orange] Shift [] gedrückt, um zu erhöhen. Halte [orange] CTRL/STRG [] gedrückt, während du das [orange] Scrollrad [] zum Vergrößern oder Verkleinern verwendest. -tutorial.shoot.text = Ziele mit der Maus, halte die [orange] linke Maustaste [] gedrückt, um zu schießen. Versuche es mit dem [gelben] Ziel []. -tutorial.moveAndroid.text = Um die Ansicht zu verschieben, ziehe einen Finger über den Bildschirm. Drücke und ziehe, um zu vergrößern oder zu verkleinern. +tutorial.moveDesktop.text = Verwende zum Verschieben die Tasten [orange] [[WASD] []. Halte [orange] Shift [] gedrückt, um zu erhöhen. Halte [orange] CTRL/STRG [] gedrückt, während du das [orange] Scrollrad [] zum Vergrössern oder Verkleinern verwendest. +tutorial.shoot.text = Ziele mit der Maus, halte die [orange] linke Maustaste [] gedrückt, um zu schiessen. Versuche es mit dem [gelben] Ziel []. +tutorial.moveAndroid.text = Um die Ansicht zu verschieben, ziehe einen Finger über den Bildschirm. Drücke und ziehe, um zu vergrössern oder zu verkleinern. tutorial.placeSelect.text = Versuche, ein [gelbes] Förderband [] aus dem Blockmenü unten rechts auszuwählen. tutorial.placeConveyorDesktop.text = Verwende das [orange] [[scrollwheel] [], um das Förderband nach vorne zu bewegen [orange] vorwärts [], und platziere es dann an der [gelben] markierten Stelle [] mit [orange] [[linke Maustaste] []. tutorial.placeConveyorAndroid.text = Verwende die [orange] [[rotieren-Taste] [], um das Förderband nach vorne [orange] zu drehen [], ziehe es mit einem Finger in Position und platziere es dann an der [gelben] markierten Stelle [] mit der [Orange] [[Häkchen][]. @@ -245,19 +245,19 @@ tutorial.drillInfo.text = Verschiedene Erze benötigen unterschiedliche Bohrer. tutorial.drillPlaced2.text = Wenn du Gegenstände in den Kern verschiebst, steckst du sie in dein [gelbes] Inventar [] oben links. Das Platzieren von Blöcken verwendet Gegenstände aus deinem Inventar. tutorial.moreDrills.text = Du kannst so viele Bohrer und Förderer miteinander verbinden wie du lust hast. tutorial.deleteBlock.text = Du kannst Blöcke löschen, indem du mit der [orange] rechte Maustaste [] auf dem Block klickst, den du löschen möchtest. Versuche, dieses Förderband zu löschen. -tutorial.deleteBlockAndroid.text = Du kannst Blöcke löschen, indem du [orange] das Fadenkreuz [] im [orange] Pausenmodusmenü [] links unten auswählst und auf einen Block tippst. Versuche, dieses Fließband zu löschen. +tutorial.deleteBlockAndroid.text = Du kannst Blöcke löschen, indem du [orange] das Fadenkreuz [] im [orange] Pausenmodusmenü [] links unten auswählst und auf einen Block tippst. Versuche, dieses Fliessband zu löschen. tutorial.placeTurret.text = Wähle nun einen [gelben] Turm [] an der [gelben] markierten Stelle [] und platziere ihn. tutorial.placedTurretAmmo.text = Dieser Turm nimmt nun [gelbe] Munition [] vom Förderband an. Du kannst sehen, wie viel Munition es hat, indem du darüber schweben und den [grünen] grünen Balken [] prüfen. -tutorial.turretExplanation.text = Geschütze schießen automatisch auf den nächsten Feind in Reichweite, solange sie genug Munition haben. +tutorial.turretExplanation.text = Geschütze schiessen automatisch auf den nächsten Feind in Reichweite, solange sie genug Munition haben. tutorial.waves.text = Jede [yellow] 60 [] Sekunden wird eine Welle von [coral] Feinden [] an einem bestimmten Orten erscheinen und versuchen, den Kern zu zerstören. tutorial.coreDestruction.text = Dein Ziel ist es, den Kern [yellow] zu verteidigen. Wenn der Kern zerstört wird, verlierst du [coral] das Spiel []. -tutorial.pausingDesktop.text = Wenn du jemals eine Pause machen möchtest, drücke die [orange] Pause-Taste [] oben links oder [orange]space[], um das Spiel anzuhalten. Du kannst auch Blöcke immer noch auswählen und platzieren, während du das Spiel pausiert ist, aber Sie können sich nicht bewegen oder schießen. +tutorial.pausingDesktop.text = Wenn du jemals eine Pause machen möchtest, drücke die [orange] Pause-Taste [] oben links oder [orange]space[], um das Spiel anzuhalten. Du kannst auch Blöcke immer noch auswählen und platzieren, während du das Spiel pausiert ist, aber Sie können sich nicht bewegen oder schiessen. tutorial.pausingAndroid.text = Wenn du jemals eine Pause machen willst, drück einfach die [orange] Pause-Taste [] oben links, um das Spiel anzuhalten. Sie können immer noch Sachen auswählen und Blöcke während der Pause platzieren. tutorial.purchaseWeapons.text = Du kannst neue [yellow] Waffen [] für deinen Mech kaufen, indem du das Verbesserungs-Menü unten links öffnest. tutorial.switchWeapons.text = Schalte Waffen, indem du entweder auf das Symbol unten links klickst oder Nummern verwendest [orange] [[1-9] []. tutorial.spawnWave.text = Hier kommt die erste Welle. Zerstöre sie. tutorial.pumpDesc.text = In späteren Wellen müsst du möglicherweise [yellow] Pumpen [] verwenden, um Flüssigkeiten für Generatoren oder Extraktoren zu verteilen. -tutorial.pumpPlace.text = Pumpen arbeiten ähnlich wie Bohrer, außer dass sie anstelle von Gegenständen Flüssigkeiten produzieren. Versuch mal, eine Pumpe auf das [yellow] gekennzeichnete Öl [] zu setzen. +tutorial.pumpPlace.text = Pumpen arbeiten ähnlich wie Bohrer, ausser dass sie anstelle von Gegenständen Flüssigkeiten produzieren. Versuch mal, eine Pumpe auf das [yellow] gekennzeichnete Öl [] zu setzen. tutorial.conduitUse.text = Stellen Sie nun eine [orange] Leitungsrohr [] von der Pumpe weg. tutorial.conduitUse2.text = Und noch ein paar mehr ... tutorial.conduitUse3.text = Und noch ein paar mehr ... @@ -275,7 +275,7 @@ keybind.move_x.name = bewege_x keybind.move_y.name = bewege_y keybind.select.name = wählen keybind.break.name = Unterbrechung -keybind.shoot.name = Schieß +keybind.shoot.name = Schiess keybind.zoom_hold.name = zoomen_halten keybind.zoom.name = zoomen keybind.menu.name = Menü @@ -295,17 +295,17 @@ mode.freebuild.name = Freier Bau upgrade.standard.name = Standard upgrade.standard.description = Der Standardmech. upgrade.blaster.name = Blaster -upgrade.blaster.description = Schießt eine langsame, schwache Kugel. +upgrade.blaster.description = Schiesst eine langsame, schwache Kugel. upgrade.triblaster.name = Dreifach-Blaster -upgrade.triblaster.description = Schießt 3 Kugeln in einer Ausbreitung. +upgrade.triblaster.description = Schiesst 3 Kugeln in einer Ausbreitung. upgrade.clustergun.name = Klumpen-Waffe -upgrade.clustergun.description = Schießt eine ungenaue Verbreitung von explosiven Granaten. +upgrade.clustergun.description = Schiesst eine ungenaue Verbreitung von explosiven Granaten. upgrade.beam.name = Strahlkanone -upgrade.beam.description = Schießt einen weitreichenden durchdringenden Laserstrahl. +upgrade.beam.description = Schiesst einen weitreichenden durchdringenden Laserstrahl. upgrade.vulcan.name = Vulkan -upgrade.vulcan.description = Schießt eine Flut von schnellen Kugeln. +upgrade.vulcan.description = Schiesst eine Flut von schnellen Kugeln. upgrade.shockgun.name = Schock-Waffe -upgrade.shockgun.description = Erschießt eine verheerende Explosion von geladenen Granatsplittern. +upgrade.shockgun.description = Erschiesst eine verheerende Explosion von geladenen Granatsplittern. item.stone.name = Stein item.iron.name = Eisen item.coal.name = Kohle @@ -358,12 +358,12 @@ block.titaniumwall.fulldescription = Eine starke Abwehrblockade. Bietet Schutz v block.duriumwall.name = Diriumwand block.duriumwall.fulldescription = Eine sehr starke Abwehrblockade. Bietet guten Schutz vor Feinden. block.compositewall.name = Verbundende Wand -block.steelwall-large.name = große Stahlwand -block.steelwall-large.fulldescription = Ein Standard-Verteidigungsblock. Mehrere Blöcke groß. -block.titaniumwall-large.name = große Titanwand -block.titaniumwall-large.fulldescription = Eine starke Abwehrblockade. Mehrere Blöcke groß. -block.duriumwall-large.name = große Diriumwand -block.duriumwall-large.fulldescription = Eine sehr starke Abwehrblockade. Mehrere Blöcke groß. +block.steelwall-large.name = grosse Stahlwand +block.steelwall-large.fulldescription = Ein Standard-Verteidigungsblock. Mehrere Blöcke gross. +block.titaniumwall-large.name = grosse Titanwand +block.titaniumwall-large.fulldescription = Eine starke Abwehrblockade. Mehrere Blöcke gross. +block.duriumwall-large.name = grosse Diriumwand +block.duriumwall-large.fulldescription = Eine sehr starke Abwehrblockade. Mehrere Blöcke gross. block.titaniumshieldwall.name = geschützte Wand block.titaniumshieldwall.fulldescription = Ein starker Abwehrblock mit einem extra eingebauten Schild. Benötigt Energie. Verwendet Energie, um feindliche Kugeln zu absorbieren. Es wird empfohlen, Verstärker zu verwenden, um diesem Block Energie zuzuführen. block.repairturret.name = Reparaturgeschütz @@ -374,8 +374,8 @@ block.shieldgenerator.name = Schildgenerator block.shieldgenerator.fulldescription = Ein fortgeschrittener Verteidigungsblock. Schützt alle Blöcke in einem Radius vor Angriffen. Bei keinem Betrieb langsamer Strom verbrauch, verliert bei Kugelkontakt jedoch schnell Energie. block.door.name = Tür block.door.fulldescription = Ein Block, der durch Antippen geöffnet und geschlossen werden kann. -block.door-large.name = große Tür -block.door-large.fulldescription = Ein Block der mehrere Felder groß ist und der durch Antippen geöffnet und geschlossen werden kann. +block.door-large.name = grosse Tür +block.door-large.fulldescription = Ein Block der mehrere Felder gross ist und der durch Antippen geöffnet und geschlossen werden kann. block.conduit.name = Leitungsrohr block.conduit.fulldescription = Grundlegender Flüssigkeitstransportblock. Funktioniert wie ein Förderband, aber mit Flüssigkeiten. Am besten mit Pumpen oder anderen Leitungen verwenden. Kann als Brücke für Gegner und Spieler verwendet werden. block.pulseconduit.name = Pulsleitungsrohr @@ -393,7 +393,7 @@ block.router.fulldescription = Akzeptiert Objekte aus einer Richtung und gibt si block.junction.name = Kreuzung block.junction.fulldescription = Fungiert als Brücke für zwei kreuzende Förderbänder. Nützlich in Situationen mit zwei verschiedenen Förderbänder, die unterschiedliche Materialien zu verschiedenen Orten transportieren. block.conveyortunnel.name = Förderbandtunnel -block.conveyortunnel.fulldescription = Transportiert Artikel unter Blöcken. Verwendung für einen Tunnel, der in den zu untertunnelnden Block führt, und einen auf der anderen Seite. Stellen Sie sicher, dass beide Tunnel in entgegengesetzte Richtungen weisen, das heißt das die Tunnel voneinander weggucken. +block.conveyortunnel.fulldescription = Transportiert Artikel unter Blöcken. Verwendung für einen Tunnel, der in den zu untertunnelnden Block führt, und einen auf der anderen Seite. Stellen Sie sicher, dass beide Tunnel in entgegengesetzte Richtungen weisen, das heisst das die Tunnel voneinander weggucken. block.liquidjunction.name = flüssigkeite Kreuzung block.liquidjunction.fulldescription = Funktioniert als Brücke für zwei kreuzende Leitungsrohre. Nützlich in Situationen mit zwei verschiedenen Leitungen, die unterschiedliche Flüssigkeiten zu verschiedenen Orten transportieren. block.liquiditemjunction.name = Flüssigkeit-Gegenstand-Kreuzung @@ -420,13 +420,13 @@ block.smelter.fulldescription = Der essentielle Bastelblock. Wenn 1x Eisen und 1 block.crucible.name = Tiegel block.crucible.fulldescription = Ein fortgeschrittener Handwerksblock. Braucht Kohle um zu funktionieren. Wenn 1x Titan und 1x Stahl eingegeben wird, wird 1x Dirium ausgegeben. block.coalpurifier.name = Kohle-Extraktor -block.coalpurifier.fulldescription = Ein einfacher Extraktorblock. Gibt Kohle aus, wenn der Block mit großen Mengen Wasser und Stein gefüllt wird. +block.coalpurifier.fulldescription = Ein einfacher Extraktorblock. Gibt Kohle aus, wenn der Block mit grossen Mengen Wasser und Stein gefüllt wird. block.titaniumpurifier.name = Titan-Extraktor -block.titaniumpurifier.fulldescription = Ein Standard-Extraktorblock. Gibt Titan aus wenn er mit großen Mengen Wasser und Eisen gefüllt wird. +block.titaniumpurifier.fulldescription = Ein Standard-Extraktorblock. Gibt Titan aus wenn er mit grossen Mengen Wasser und Eisen gefüllt wird. block.oilrefinery.name = Ölraffinerie -block.oilrefinery.fulldescription = Veredelt große Mengen Öl zu Kohle. Nützlich für die Betankung von Blöcken die Kohle benutzen wie z.b. Waffentürme, wenn Kohleadern knapp sind. +block.oilrefinery.fulldescription = Veredelt grosse Mengen Öl zu Kohle. Nützlich für die Betankung von Blöcken die Kohle benutzen wie z.b. Waffentürme, wenn Kohleadern knapp sind. block.stoneformer.name = Steinformer -block.stoneformer.fulldescription = Verfestigt flüssige Lava zu Stein. Nützlich für die Herstellung von großen Mengen von Stein für Kohle-Extraktor. +block.stoneformer.fulldescription = Verfestigt flüssige Lava zu Stein. Nützlich für die Herstellung von grossen Mengen von Stein für Kohle-Extraktor. block.lavasmelter.name = Lava-Schmelzer block.lavasmelter.fulldescription = Verwendet Lava, um Eisen zu Stahl schmelzen. Eine Alternative zum Schmelzer. Nützlich in Situationen, in denen Kohle knapp ist. block.stonedrill.name = Steinbohrer @@ -450,21 +450,21 @@ block.combustiongenerator.fulldescription = Erzeugt Energie aus Öl. Gibt Energi block.rtgenerator.name = RTG-Generator block.rtgenerator.fulldescription = Erzeugt geringe Mengen an Energie aus dem radioaktiven Zerfall von Uran. Gibt Energie als Laser an seine 4 Seiten aus. block.nuclearreactor.name = Kernreaktor -block.nuclearreactor.fulldescription = Eine erweiterte Version des RTG-Generators und der ultimative Energie Generator. Erzeugt Strom aus Uran. Erfordert konstante Wasserkühlung. Sehr heiß; explodiert heftig, wenn zu wenig Kühlmittel zugeführt wird. +block.nuclearreactor.fulldescription = Eine erweiterte Version des RTG-Generators und der ultimative Energie Generator. Erzeugt Strom aus Uran. Erfordert konstante Wasserkühlung. Sehr heiss; explodiert heftig, wenn zu wenig Kühlmittel zugeführt wird. block.turret.name = Geschütz block.turret.fulldescription = Ein einfacher, billiger Turm. Verwendet Stein für Munition. Hat etwas mehr Reichweite als das Doppelgeschütz. block.doubleturret.name = Doppelgeschütz -block.doubleturret.fulldescription = Eine etwas stärkere Version des Geschützes. Verwendet Stein für Munition. Hat deutlich mehr Schaden, hat aber eine geringere Reichweite. Schießt zwei Kugeln. +block.doubleturret.fulldescription = Eine etwas stärkere Version des Geschützes. Verwendet Stein für Munition. Hat deutlich mehr Schaden, hat aber eine geringere Reichweite. Schiesst zwei Kugeln. block.machineturret.name = Gatling Geschütz block.machineturret.fulldescription = Ein Standard-Allround-Turm. Verwendet Eisen für Munition. Hat eine schnelle Feuerrate mit gutem Schaden. block.shotgunturret.name = Splittergeschütz -block.shotgunturret.fulldescription = Ein Standard-Turm. Verwendet Eisen für Munition. Schießt 7 Kugeln auf einmal. Geringere Reichweite, aber höhere Schadensleistung als das Gatling Geschütz +block.shotgunturret.fulldescription = Ein Standard-Turm. Verwendet Eisen für Munition. Schiesst 7 Kugeln auf einmal. Geringere Reichweite, aber höhere Schadensleistung als das Gatling Geschütz block.flameturret.name = Flammenwerfer block.flameturret.fulldescription = Fortschrittlicher Nahbereichswaffe. Verwendet Kohle für Munition. Hat eine sehr geringe Reichweite, aber sehr hohen Schaden. Gut für Nahkampf. Empfohlen für den Einsatz hinter Mauern. block.sniperturret.name = Schienenkanone block.sniperturret.fulldescription = Fortschrittliches Reichweitengeschütz. Verwendet Stahl für Munition. Sehr hoher Schaden, aber niedrige Feuerrate. Teuer zu verwenden, kann aber aufgrund seiner Reichweite weit entfernt von den feindlichen Linien platziert werden. block.mortarturret.name = Flakgeschütz -block.mortarturret.fulldescription = Fortschrittlicher Flächen-Schaden Turm. Verwendet Kohle für Munition. Sehr langsame Feuerrate und Geschosse, aber sehr hoher Einzelziel- und Flächenschaden. Nützlich gegen große Mengen von Feinden. +block.mortarturret.fulldescription = Fortschrittlicher Flächen-Schaden Turm. Verwendet Kohle für Munition. Sehr langsame Feuerrate und Geschosse, aber sehr hoher Einzelziel- und Flächenschaden. Nützlich gegen grosse Mengen von Feinden. block.laserturret.name = Laserturm block.laserturret.fulldescription = Fortschrittlicher Einzelziel-Turm. Verwendet Strom. Guter Allround-Revolver für mittlere Reichweiten. Nur Einzelziel. Verfehlt nie. block.waveturret.name = Teslakanone @@ -472,8 +472,8 @@ block.waveturret.fulldescription = Erweiterter Mehrfach-Ziele-Turm. Verwendet St block.plasmaturret.name = Plasmageschütz block.plasmaturret.fulldescription = Hochentwickelte Version des Flammenwerfers. Verwendet Kohle als Munition. Sehr hoher Schaden, niedriger bis mittlerer Reichweite. block.chainturret.name = Kettengeschütz -block.chainturret.fulldescription = Die ultimative Schnellfeuer Waffe. Verwendet Uran als Munition. Schießt große Kugeln mit hoher Feuerrate. Mittlere Reichweite. Mehrere Felder groß. Hält extrem viel aus. +block.chainturret.fulldescription = Die ultimative Schnellfeuer Waffe. Verwendet Uran als Munition. Schiesst grosse Kugeln mit hoher Feuerrate. Mittlere Reichweite. Mehrere Felder gross. Hält extrem viel aus. block.titancannon.name = Titan Kanone -block.titancannon.fulldescription = Die ultimative Langstrecken Kanone. Verwendet Uran als Munition. Schießt große Flächen-Schadenden-Granaten mit einer mittleren Feuerrate ab. Lange Reichweite. Ist mehrere Felder groß. Hält extrem viel aus. +block.titancannon.fulldescription = Die ultimative Langstrecken Kanone. Verwendet Uran als Munition. Schiesst grosse Flächen-Schadenden-Granaten mit einer mittleren Feuerrate ab. Lange Reichweite. Ist mehrere Felder gross. Hält extrem viel aus. block.playerspawn.name = Spielerspawn block.enemyspawn.name = Gegnerspawn diff --git a/core/assets/version.properties b/core/assets/version.properties index 7fe28e0b4f..0013aa0d32 100644 --- a/core/assets/version.properties +++ b/core/assets/version.properties @@ -1,7 +1,7 @@ #Autogenerated file. Do not modify. -#Fri Feb 23 15:06:51 EST 2018 +#Fri Feb 23 21:37:45 EST 2018 version=release -androidBuildCode=267 +androidBuildCode=275 name=Mindustry code=3.3 -build=28 +build=custom build diff --git a/core/src/io/anuke/mindustry/core/NetClient.java b/core/src/io/anuke/mindustry/core/NetClient.java index 97d037ec44..13b9b687b1 100644 --- a/core/src/io/anuke/mindustry/core/NetClient.java +++ b/core/src/io/anuke/mindustry/core/NetClient.java @@ -329,12 +329,6 @@ public class NetClient extends Module { } } - //TODO remove. - public void test(){ - gotData = false; - connecting = true; - } - public boolean hasData(){ return gotData; } diff --git a/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java b/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java index bdf27ae16c..3fb7a182b3 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java +++ b/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java @@ -17,6 +17,7 @@ import io.anuke.ucore.core.Graphics; import io.anuke.ucore.core.Timers; import io.anuke.ucore.entities.Entities; import io.anuke.ucore.graphics.Draw; +import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Strings; @@ -82,6 +83,12 @@ public class EnemyType { Graphics.flush(); + if(isCalculating(enemy)){ + Draw.color(Color.SKY); + Lines.polySeg(20, 0, 5, enemy.x, enemy.y, 11f, Timers.time() * 2f + enemy.id*52153f); + Draw.color(); + } + if(showPaths){ Draw.tscl(0.25f); Draw.text((int)enemy.idletime + " " + enemy.node + " " + enemy.id + "\n" + Strings.toFixed(enemy.totalMove.x, 2) + ", " @@ -157,6 +164,8 @@ public class EnemyType { Tile core = world.getCore(); + if(core == null) return; + if(enemy.idletime > maxIdleLife && enemy.node > 0){ enemy.onDeath(); return; @@ -190,7 +199,7 @@ public class EnemyType { }else if(dst < avoidRange){ calc.set((enemy.x - other.x), (enemy.y - other.y)).setLength(avoidSpeed); shift.add(calc.scl(1.1f)); - }else if(dst < attractRange && !nearCore){ + }else if(dst < attractRange && !nearCore && !isCalculating(enemy)){ calc.set((enemy.x - other.x), (enemy.y - other.y)).setLength(avoidSpeed); shift.add(calc.scl(-1)); } @@ -268,6 +277,10 @@ public class EnemyType { } } + public boolean isCalculating(Enemy enemy){ + return enemy.node < 0 && !Net.client(); + } + public static EnemyType getByID(byte id){ return types.get(id); } diff --git a/core/src/io/anuke/mindustry/net/Net.java b/core/src/io/anuke/mindustry/net/Net.java index 6473924085..5fe94ccade 100644 --- a/core/src/io/anuke/mindustry/net/Net.java +++ b/core/src/io/anuke/mindustry/net/Net.java @@ -210,7 +210,7 @@ public class Net{ } /**Pings a host in an new thread. If an error occured, failed() should be called with the exception. */ - public static void pingHost(String address, int port, Consumer valid, Consumer failed){ + public static void pingHost(String address, int port, Consumer valid, Consumer failed){ clientProvider.pingHost(address, port, valid, failed); } @@ -285,7 +285,7 @@ public class Net{ * Callback should be run on libGDX main thread.*/ void discover(Consumer> callback); /**Ping a host. If an error occured, failed() should be called with the exception. */ - void pingHost(String address, int port, Consumer valid, Consumer failed); + void pingHost(String address, int port, Consumer valid, Consumer failed); /**Close all connections.*/ void dispose(); } diff --git a/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java b/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java index 9dd218414c..c972b744d6 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java @@ -16,10 +16,10 @@ import static io.anuke.mindustry.Vars.*; public class MenuFragment implements Fragment{ public void build(){ - if(!android){ - //menu table - new table(){{ - + new table(){{ + visible(() -> state.is(State.menu)); + + if(!android){ new table(){{ PressGroup group = new PressGroup(); @@ -53,37 +53,32 @@ public class MenuFragment implements Fragment{ } get().margin(16); }}.end(); - - visible(() -> state.is(State.menu)); - }}.end(); - }else{ - new table(){{ - new table(){{ + + }else { + new table() {{ defaults().size(120f).pad(5); - float isize = 14f*4; - + float isize = 14f * 4; + new imagebutton("icon-play-2", isize, ui.levels::show).text("$text.play").padTop(4f); - + new imagebutton("icon-tutorial", isize, () -> control.playMap(world.maps().getMap("tutorial"))).text("$text.tutorial").padTop(4f); - + new imagebutton("icon-load", isize, ui.load::show).text("$text.load").padTop(4f); new imagebutton("icon-add", isize, ui.join::show).text("$text.joingame").padTop(4f); - + row(); new imagebutton("icon-editor", isize, ui.editor::show).text("$text.editor").padTop(4f); - + new imagebutton("icon-tools", isize, ui.settings::show).text("$text.settings").padTop(4f); new imagebutton("icon-info", isize, ui.about::show).text("$text.about.button").padTop(4f); new imagebutton("icon-donate", isize, Platform.instance::openDonations).text("$text.donate").padTop(4f); - - visible(() -> state.is(State.menu)); }}.end(); - }}.end(); - } + } + }}.end(); //extra icons in top right new table(){{ diff --git a/kryonet/src/io/anuke/kryonet/KryoClient.java b/kryonet/src/io/anuke/kryonet/KryoClient.java index 0940f4e517..4a946541f3 100644 --- a/kryonet/src/io/anuke/kryonet/KryoClient.java +++ b/kryonet/src/io/anuke/kryonet/KryoClient.java @@ -13,6 +13,7 @@ import io.anuke.mindustry.net.Net.SendMode; import io.anuke.mindustry.net.Packets.Connect; import io.anuke.mindustry.net.Packets.Disconnect; import io.anuke.ucore.function.Consumer; +import io.anuke.ucore.util.Strings; import java.io.IOException; import java.net.DatagramPacket; @@ -140,7 +141,7 @@ public class KryoClient implements ClientProvider{ } @Override - public void pingHost(String address, int port, Consumer valid, Consumer invalid){ + public void pingHost(String address, int port, Consumer valid, Consumer invalid){ runAsync(() -> { try { DatagramSocket socket = new DatagramSocket(); @@ -162,7 +163,7 @@ public class KryoClient implements ClientProvider{ } else { Gdx.app.postRunnable(() -> invalid.accept(new IOException("Outdated server."))); } - } catch (IOException e) { + } catch (Exception e) { Gdx.app.postRunnable(() -> invalid.accept(e)); } }); @@ -209,7 +210,7 @@ public class KryoClient implements ClientProvider{ if(e instanceof KryoNetException){ Gdx.app.postRunnable(() -> Net.showError("$text.server.mismatch")); }else{ - //TODO better exception handling. + Net.showError(Strings.parseException(e, true)); disconnect(); } } diff --git a/server/src/io/anuke/mindustry/server/ServerControl.java b/server/src/io/anuke/mindustry/server/ServerControl.java index ab51272464..6c54e11028 100644 --- a/server/src/io/anuke/mindustry/server/ServerControl.java +++ b/server/src/io/anuke/mindustry/server/ServerControl.java @@ -99,7 +99,7 @@ public class ServerControl extends Module { handler.register("help", "Displays this command list.", arg -> { info("Commands:"); for(Command command : handler.getCommandList()){ - print(" &y" + command.text + (command.params.isEmpty() ? "" : " ") + command.params + " - &lm" + command.description); + print(" &y" + command.text + (command.paramText.isEmpty() ? "" : " ") + command.paramText + " - &lm" + command.description); } }); @@ -184,7 +184,7 @@ public class ServerControl extends Module { } }); - handler.register("say", "", "Send a message to all players.", arg -> { + handler.register("say", "", "Send a message to all players.", arg -> { if(!state.is(State.playing)) { err("Not hosting. Host a game first."); return; @@ -192,7 +192,7 @@ public class ServerControl extends Module { netCommon.sendMessage("[GRAY][[Server]:[] " + arg[0]); info("&lyServer: &lb{0}", arg[0]); - }).mergeArgs(); + }); handler.register("difficulty", "", "Set game difficulty.", arg -> { try{ @@ -355,8 +355,10 @@ public class ServerControl extends Module { if (response.type == ResponseType.unknownCommand) { err("Invalid command. Type 'help' for help."); - } else if (response.type == ResponseType.invalidArguments) { - err("Invalid command arguments. Usage: " + response.command.text + " " + response.command.params); + }else if (response.type == ResponseType.fewArguments) { + err("Too few command arguments. Usage: " + response.command.text + " " + response.command.paramText); + }else if (response.type == ResponseType.manyArguments) { + err("Too many command arguments. Usage: " + response.command.text + " " + response.command.paramText); } }); } From 9f5f6ae38231e4724da452f88001e27b24910143 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 25 Feb 2018 22:32:12 -0500 Subject: [PATCH 08/18] Security changes: placement verification, banning, unfinished admins --- .../sprites/ui/icons/icon-admin.png | Bin 0 -> 257 bytes core/assets-raw/sprites/ui/icons/icon-ban.png | Bin 0 -> 276 bytes core/assets/bundles/bundle.properties | 9 + core/assets/sprites/sprites.atlas | 498 +++++++++--------- core/assets/sprites/sprites.png | Bin 83116 -> 83232 bytes core/assets/version.properties | 4 +- .../io/anuke/mindustry/core/NetClient.java | 15 + .../io/anuke/mindustry/core/NetCommon.java | 20 - .../io/anuke/mindustry/core/NetServer.java | 57 +- .../src/io/anuke/mindustry/core/Renderer.java | 1 + .../anuke/mindustry/core/ThreadHandler.java | 5 +- core/src/io/anuke/mindustry/core/UI.java | 4 + core/src/io/anuke/mindustry/core/World.java | 38 +- .../io/anuke/mindustry/entities/Player.java | 4 +- .../anuke/mindustry/input/InputHandler.java | 164 +----- core/src/io/anuke/mindustry/io/Maps.java | 13 +- .../anuke/mindustry/net/Administration.java | 114 ++++ core/src/io/anuke/mindustry/net/Host.java | 6 +- .../src/io/anuke/mindustry/net/NetEvents.java | 3 - core/src/io/anuke/mindustry/net/Packets.java | 20 +- .../io/anuke/mindustry/net/Registrator.java | 3 +- .../mindustry/ui/dialogs/AdminsDialog.java | 53 ++ .../mindustry/ui/dialogs/BansDialog.java | 53 ++ .../mindustry/ui/dialogs/HostDialog.java | 4 +- .../mindustry/ui/dialogs/JoinDialog.java | 12 +- .../ui/fragments/PlayerListFragment.java | 63 ++- .../io/anuke/mindustry/world/Placement.java | 164 ++++++ .../mindustry/client/WebsocketClient.java | 4 +- kryonet/src/io/anuke/kryonet/KryoClient.java | 2 +- .../src/io/anuke/kryonet/KryoRegistrator.java | 40 +- kryonet/src/io/anuke/kryonet/KryoServer.java | 33 +- mindustry-maps/maps.json | 1 + .../anuke/mindustry/server/ServerControl.java | 151 +++++- 33 files changed, 1038 insertions(+), 520 deletions(-) create mode 100644 core/assets-raw/sprites/ui/icons/icon-admin.png create mode 100644 core/assets-raw/sprites/ui/icons/icon-ban.png create mode 100644 core/src/io/anuke/mindustry/net/Administration.java create mode 100644 core/src/io/anuke/mindustry/ui/dialogs/AdminsDialog.java create mode 100644 core/src/io/anuke/mindustry/ui/dialogs/BansDialog.java create mode 100644 core/src/io/anuke/mindustry/world/Placement.java create mode 100644 mindustry-maps/maps.json diff --git a/core/assets-raw/sprites/ui/icons/icon-admin.png b/core/assets-raw/sprites/ui/icons/icon-admin.png new file mode 100644 index 0000000000000000000000000000000000000000..3d3811462ab316b35df4e1935305517a60964d3f GIT binary patch literal 257 zcmeAS@N?(olHy`uVBq!ia0y~yVBiB`4mJh`26+$Niwq15Y)RhkE)4%caKYZ?lNlHo zI14-?iy0WWg+Z8+Vb&Z81_lQ95>H=O_D4)o%mT_5_cc#2FfjCax;TbtobR1@khj@@ z$Mt@D&c)P-h2k$#-Z<#5acEy@#kym;iz1gre3!`0%5VK^Yo$A@bo}>Sp7n13&!Zn_ zGQ4OvSAToEW9HQ5A`YjRTZ$!nb}6lq;NUypn%LUS{%KB$`GlvkQ4aUlM~a@=y&^3% zNUE>v$=wYh(e9rMLiA2eR#7!bwu$)IKR0=!>GgH?jjw#Tw@#10z`(%3;OXk;vd$@? F2>_bWU4Z}q literal 0 HcmV?d00001 diff --git a/core/assets-raw/sprites/ui/icons/icon-ban.png b/core/assets-raw/sprites/ui/icons/icon-ban.png new file mode 100644 index 0000000000000000000000000000000000000000..f8df32c20c44cd4711463212fc85688d5dd58a4a GIT binary patch literal 276 zcmeAS@N?(olHy`uVBq!ia0y~yVBiB`4mJh`26+$Niwq15Y)RhkE)4%caKYZ?lNlHo zI14-?iy0WWg+Z8+Vb&Z81_lQ95>H=O_D4)oOez|pPcs`B7#J3Mx;TbtoS!@KHgA)I zfb01Mt`lzb=>A~d=HR@|;lpvU4HC(s6@L#XZrH8!%2RFT%)8bz+j(nSi(mNJyt@6w zUOzqVyHvy7kEfazuAg8Md2`DY-)^@FE#luTH2>U~^Fnrkg4@m;XC^sKR6Et~lq~ym zPWIY5RlOgwGjD2qiOxOq^7O{FPa_uPcFXuqj}`frdg6c8y`n{t7dOOydm?i1;$f!x bk8DMA$|_Uu-S=Q%U|{fc^>bP0l+XkKUmI?Y literal 0 HcmV?d00001 diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index eb860705bf..cd22419d6a 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -25,6 +25,7 @@ text.server.kicked.kick=You have been kicked from the server! text.server.kicked.invalidPassword=Invalid password! text.server.kicked.clientOutdated=Outdated client! Update your game! text.server.kicked.serverOutdated=Outdated server! Ask the host to update! +text.server.kicked.banned=You are banned on this server. text.server.connected={0} has joined. text.server.disconnected={0} has disconnected. text.nohost=Can't host server on a custom map! @@ -37,10 +38,18 @@ text.server.refreshing=Refreshing server text.hosts.none=[lightgray]No LAN games found! text.host.invalid=[scarlet]Can't connect to host. text.server.friendlyfire=Friendly Fire +text.server.bans=Bans +text.server.bans.none=No banned players found! +text.server.admins=Admins +text.server.admins.none=No admins found! text.server.add=Add Server text.server.delete=Are you sure you want to delete this server? text.server.hostname=Host: {0} text.server.edit=Edit Server +text.confirmban=Are you sure you want to ban this player? +text.confirmunban=Are you sure you want to unban this player? +text.confirmadmin=Are you sure you want to make this player an admin? +text.confirmunadmin=Are you sure you want to remove admin status from this player? text.joingame.byip=Join by IP... text.joingame.title=Join Game text.joingame.ip=IP: diff --git a/core/assets/sprites/sprites.atlas b/core/assets/sprites/sprites.atlas index 40c8ead303..77a8a23490 100644 --- a/core/assets/sprites/sprites.atlas +++ b/core/assets/sprites/sprites.atlas @@ -27,49 +27,49 @@ blocks/blackrock1 index: -1 blocks/blackrockshadow1 rotate: false - xy: 214, 87 + xy: 732, 381 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/blackstone1 rotate: false - xy: 224, 87 + xy: 736, 371 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/blackstone2 rotate: false - xy: 732, 381 + xy: 736, 361 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/blackstone3 rotate: false - xy: 234, 87 + xy: 736, 351 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/blackstoneblock1 rotate: false - xy: 736, 371 + xy: 540, 110 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/blackstoneblock2 rotate: false - xy: 736, 361 + xy: 659, 282 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/blackstoneblock3 rotate: false - xy: 736, 351 + xy: 669, 282 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -83,7 +83,7 @@ blocks/blackstoneedge index: -1 blocks/block rotate: false - xy: 264, 91 + xy: 250, 91 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -104,7 +104,7 @@ blocks/block-3x3 index: -1 blocks/block-middle rotate: false - xy: 274, 91 + xy: 260, 91 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -125,112 +125,112 @@ blocks/chainturret-icon index: -1 blocks/coal1 rotate: false - xy: 314, 95 + xy: 300, 95 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/coal2 rotate: false - xy: 324, 95 + xy: 310, 95 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/coal3 rotate: false - xy: 334, 95 + xy: 320, 95 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/coaldrill rotate: false - xy: 344, 95 + xy: 330, 95 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/coalgenerator rotate: false - xy: 354, 95 + xy: 340, 95 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/coalgenerator-top rotate: false - xy: 364, 95 + xy: 350, 95 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/coalpurifier rotate: false - xy: 374, 95 + xy: 360, 95 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/combustiongenerator rotate: false - xy: 384, 95 + xy: 370, 95 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/compositewall rotate: false - xy: 394, 95 + xy: 380, 95 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/conduit rotate: false - xy: 404, 95 + xy: 390, 95 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/conduitbottom rotate: false - xy: 414, 95 + xy: 400, 95 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/conduitliquid rotate: false - xy: 424, 95 + xy: 410, 95 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/conduittop rotate: false - xy: 434, 95 + xy: 420, 95 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/conveyor rotate: false - xy: 444, 95 + xy: 430, 95 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/conveyormove rotate: false - xy: 454, 95 + xy: 440, 95 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/conveyortunnel rotate: false - xy: 464, 95 + xy: 450, 95 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -244,56 +244,56 @@ blocks/core index: -1 blocks/cross rotate: false - xy: 669, 282 + xy: 460, 95 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/crucible rotate: false - xy: 679, 282 + xy: 470, 95 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/deepwater rotate: false - xy: 591, 187 + xy: 601, 187 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/dirt1 rotate: false - xy: 624, 233 + xy: 611, 187 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/dirt2 rotate: false - xy: 624, 223 + xy: 621, 189 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/dirt3 rotate: false - xy: 624, 213 + xy: 114, 80 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/dirtedge rotate: false - xy: 521, 164 + xy: 535, 211 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 blocks/door rotate: false - xy: 634, 235 + xy: 113, 70 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -307,7 +307,7 @@ blocks/door-large index: -1 blocks/door-large-icon rotate: false - xy: 634, 225 + xy: 113, 60 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -321,7 +321,7 @@ blocks/door-large-open index: -1 blocks/door-open rotate: false - xy: 634, 215 + xy: 113, 50 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -335,7 +335,7 @@ blocks/doubleturret index: -1 blocks/duriumwall rotate: false - xy: 114, 80 + xy: 117, 40 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -349,14 +349,14 @@ blocks/duriumwall-large index: -1 blocks/duriumwall-large-icon rotate: false - xy: 113, 70 + xy: 117, 30 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/enemyspawn rotate: false - xy: 113, 60 + xy: 117, 20 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -370,245 +370,245 @@ blocks/flameturret index: -1 blocks/fluxpump rotate: false - xy: 113, 50 + xy: 117, 10 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/grass1 rotate: false - xy: 117, 40 + xy: 865, 417 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/grass2 rotate: false - xy: 117, 30 + xy: 624, 233 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/grass3 rotate: false - xy: 117, 20 + xy: 624, 223 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/grassblock1 rotate: false - xy: 117, 10 + xy: 624, 213 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/grassblock2 rotate: false - xy: 865, 417 + xy: 634, 235 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/grassedge rotate: false - xy: 521, 150 + xy: 535, 197 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 blocks/ice1 rotate: false - xy: 178, 75 + xy: 634, 225 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/ice2 rotate: false - xy: 188, 75 + xy: 634, 215 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/ice3 rotate: false - xy: 198, 75 + xy: 178, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/iceedge rotate: false - xy: 521, 136 + xy: 549, 213 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 blocks/icerock1 rotate: false - xy: 208, 75 + xy: 188, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/icerock2 rotate: false - xy: 218, 77 + xy: 198, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/icerockshadow1 rotate: false - xy: 228, 77 + xy: 208, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/rockshadow1 rotate: false - xy: 228, 77 + xy: 208, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/icerockshadow2 rotate: false - xy: 238, 77 + xy: 218, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/rockshadow2 rotate: false - xy: 238, 77 + xy: 218, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/iron1 rotate: false - xy: 328, 85 + xy: 248, 71 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/iron2 rotate: false - xy: 338, 85 + xy: 258, 71 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/iron3 rotate: false - xy: 348, 85 + xy: 268, 71 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/irondrill rotate: false - xy: 358, 85 + xy: 278, 71 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/ironwall rotate: false - xy: 368, 85 + xy: 288, 71 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/junction rotate: false - xy: 378, 85 + xy: 537, 140 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/laserturret rotate: false - xy: 728, 333 + xy: 853, 415 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 blocks/lava rotate: false - xy: 388, 85 + xy: 300, 85 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/lavaedge rotate: false - xy: 518, 122 + xy: 563, 213 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 blocks/lavasmelter rotate: false - xy: 398, 85 + xy: 310, 85 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/liquiditemjunction rotate: false - xy: 408, 85 + xy: 320, 85 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/liquidjunction rotate: false - xy: 418, 85 + xy: 330, 85 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/liquidrouter rotate: false - xy: 428, 85 + xy: 340, 85 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/machineturret rotate: false - xy: 728, 321 + xy: 619, 199 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 blocks/megarepairturret rotate: false - xy: 728, 309 + xy: 142, 81 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 blocks/mortarturret rotate: false - xy: 731, 297 + xy: 154, 81 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 blocks/mossblock rotate: false - xy: 438, 85 + xy: 350, 85 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/mossstone rotate: false - xy: 438, 85 + xy: 350, 85 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -629,7 +629,7 @@ blocks/nuclearreactor-center index: -1 blocks/nuclearreactor-icon rotate: false - xy: 448, 85 + xy: 360, 85 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -650,336 +650,336 @@ blocks/nuclearreactor-small index: -1 blocks/oil rotate: false - xy: 458, 85 + xy: 370, 85 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/oiledge rotate: false - xy: 535, 197 + xy: 577, 207 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 blocks/oilrefinery rotate: false - xy: 468, 85 + xy: 380, 85 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/omnidrill rotate: false - xy: 601, 187 + xy: 390, 85 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/plasmaturret rotate: false - xy: 731, 285 + xy: 166, 81 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 blocks/playerspawn rotate: false - xy: 611, 189 + xy: 400, 85 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/powerbooster rotate: false - xy: 621, 189 + xy: 410, 85 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/poweredconveyor rotate: false - xy: 875, 417 + xy: 420, 85 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/poweredconveyormove rotate: false - xy: 885, 421 + xy: 430, 85 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/powerlaser rotate: false - xy: 895, 421 + xy: 440, 85 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/powerlasercorner rotate: false - xy: 905, 421 + xy: 450, 85 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/powerlaserrouter rotate: false - xy: 915, 421 + xy: 460, 85 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/pulseconduit rotate: false - xy: 925, 421 + xy: 470, 85 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/pulseconduitbottom rotate: false - xy: 935, 421 + xy: 480, 87 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/pulseconduittop rotate: false - xy: 945, 421 + xy: 298, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/pump rotate: false - xy: 955, 421 + xy: 308, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/repairturret rotate: false - xy: 853, 415 + xy: 178, 85 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 blocks/rock1 rotate: false - xy: 965, 421 + xy: 318, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/rock2 rotate: false - xy: 975, 421 + xy: 328, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/router rotate: false - xy: 985, 421 + xy: 338, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/rtgenerator rotate: false - xy: 995, 421 + xy: 348, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/rtgenerator-top rotate: false - xy: 248, 71 + xy: 358, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/sand1 rotate: false - xy: 258, 71 + xy: 368, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/sand2 rotate: false - xy: 268, 71 + xy: 378, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/sand3 rotate: false - xy: 278, 71 + xy: 388, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/sandblock1 rotate: false - xy: 288, 71 + xy: 398, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/sandblock2 rotate: false - xy: 298, 71 + xy: 408, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/sandblock3 rotate: false - xy: 308, 75 + xy: 418, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/sandedge rotate: false - xy: 549, 213 + xy: 577, 193 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 blocks/shadow rotate: false - xy: 142, 81 + xy: 190, 85 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 blocks/shieldgenerator rotate: false - xy: 328, 75 + xy: 438, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/shotgunturret rotate: false - xy: 154, 81 + xy: 202, 85 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 blocks/shrub rotate: false - xy: 378, 75 + xy: 551, 168 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/shrubshadow rotate: false - xy: 388, 75 + xy: 551, 158 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/smelter rotate: false - xy: 398, 75 + xy: 551, 148 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/smelter-middle rotate: false - xy: 408, 75 + xy: 875, 417 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/sniperturret rotate: false - xy: 166, 81 + xy: 214, 85 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 blocks/snow1 rotate: false - xy: 418, 75 + xy: 885, 421 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/snow2 rotate: false - xy: 428, 75 + xy: 895, 421 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/snow3 rotate: false - xy: 438, 75 + xy: 905, 421 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/snowblock1 rotate: false - xy: 448, 75 + xy: 915, 421 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/snowblock2 rotate: false - xy: 458, 75 + xy: 925, 421 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/snowblock3 rotate: false - xy: 468, 75 + xy: 935, 421 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/snowedge rotate: false - xy: 549, 199 + xy: 605, 197 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 blocks/sorter rotate: false - xy: 478, 87 + xy: 945, 421 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/steelconveyor rotate: false - xy: 488, 87 + xy: 955, 421 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/steelconveyormove rotate: false - xy: 478, 77 + xy: 965, 421 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/steelwall rotate: false - xy: 488, 77 + xy: 975, 421 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -993,98 +993,98 @@ blocks/steelwall-large index: -1 blocks/steelwall-large-icon rotate: false - xy: 498, 80 + xy: 985, 421 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/stone1 rotate: false - xy: 508, 80 + xy: 995, 421 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/stone2 rotate: false - xy: 885, 411 + xy: 298, 65 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/stone3 rotate: false - xy: 895, 411 + xy: 308, 65 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/stoneblock1 rotate: false - xy: 905, 411 + xy: 318, 65 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/stoneblock2 rotate: false - xy: 915, 411 + xy: 328, 65 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/stoneblock3 rotate: false - xy: 925, 411 + xy: 338, 65 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/stonedrill rotate: false - xy: 935, 411 + xy: 348, 65 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/stoneedge rotate: false - xy: 577, 193 + xy: 537, 150 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 blocks/stoneformer rotate: false - xy: 945, 411 + xy: 358, 65 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/stonewall rotate: false - xy: 955, 411 + xy: 368, 65 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/teleporter rotate: false - xy: 965, 411 + xy: 378, 65 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/teleporter-top rotate: false - xy: 975, 411 + xy: 388, 65 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/thermalgenerator rotate: false - xy: 985, 411 + xy: 398, 65 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -1098,56 +1098,56 @@ blocks/titancannon index: -1 blocks/titancannon-icon rotate: false - xy: 178, 85 + xy: 226, 85 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 blocks/titanium1 rotate: false - xy: 995, 411 + xy: 408, 65 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/titanium2 rotate: false - xy: 308, 65 + xy: 418, 65 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/titanium3 rotate: false - xy: 318, 65 + xy: 428, 65 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/titaniumdrill rotate: false - xy: 328, 65 + xy: 438, 65 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/titaniumpurifier rotate: false - xy: 338, 65 + xy: 448, 65 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/titaniumshieldwall rotate: false - xy: 348, 65 + xy: 458, 65 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/titaniumwall rotate: false - xy: 358, 65 + xy: 468, 65 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -1161,63 +1161,63 @@ blocks/titaniumwall-large index: -1 blocks/titaniumwall-large-icon rotate: false - xy: 368, 65 + xy: 557, 178 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/turret rotate: false - xy: 190, 85 + xy: 528, 108 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 blocks/uranium1 rotate: false - xy: 408, 65 + xy: 561, 168 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/uranium2 rotate: false - xy: 418, 65 + xy: 561, 158 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/uranium3 rotate: false - xy: 428, 65 + xy: 561, 148 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/uraniumdrill rotate: false - xy: 438, 65 + xy: 571, 169 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/water rotate: false - xy: 468, 65 + xy: 547, 138 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 blocks/wateredge rotate: false - xy: 591, 197 + xy: 521, 132 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 blocks/waveturret rotate: false - xy: 202, 85 + xy: 533, 120 size: 10, 10 orig: 10, 10 offset: 0, 0 @@ -1231,21 +1231,21 @@ blocks/weaponfactory index: -1 blocks/weaponfactory-icon rotate: false - xy: 478, 67 + xy: 557, 138 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 bullet rotate: false - xy: 284, 91 + xy: 270, 91 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 chainbullet rotate: false - xy: 659, 283 + xy: 591, 188 size: 8, 7 orig: 8, 7 offset: 0, 0 @@ -1392,91 +1392,91 @@ enemies/healerenemy-t3 index: -1 enemies/mortarenemy-t1 rotate: false - xy: 965, 447 + xy: 981, 447 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 enemies/mortarenemy-t2 rotate: false - xy: 965, 431 + xy: 981, 431 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 enemies/mortarenemy-t3 rotate: false - xy: 981, 447 + xy: 997, 447 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 enemies/rapidenemy-t1 rotate: false - xy: 981, 431 + xy: 997, 431 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 enemies/rapidenemy-t2 rotate: false - xy: 997, 447 + xy: 592, 211 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 enemies/rapidenemy-t3 rotate: false - xy: 997, 431 + xy: 608, 211 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 enemies/standardenemy-t1 rotate: false - xy: 592, 211 + xy: 519, 208 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 enemies/targetenemy-t1 rotate: false - xy: 592, 211 + xy: 519, 208 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 enemies/standardenemy-t2 rotate: false - xy: 563, 199 + xy: 533, 178 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 enemies/standardenemy-t3 rotate: false - xy: 577, 207 + xy: 537, 164 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 enemies/tankenemy-t1 rotate: false - xy: 608, 211 + xy: 519, 192 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 enemies/tankenemy-t2 rotate: false - xy: 519, 208 + xy: 521, 162 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 enemies/tankenemy-t3 rotate: false - xy: 519, 192 + xy: 521, 146 size: 14, 14 orig: 14, 14 offset: 0, 0 @@ -1511,63 +1511,63 @@ enemyarrow index: -1 icon-coal rotate: false - xy: 248, 81 + xy: 228, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 icon-dirium rotate: false - xy: 258, 81 + xy: 238, 81 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 icon-iron rotate: false - xy: 268, 81 + xy: 248, 81 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 icon-sand rotate: false - xy: 278, 81 + xy: 258, 81 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 icon-steel rotate: false - xy: 288, 81 + xy: 268, 81 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 icon-stone rotate: false - xy: 298, 81 + xy: 278, 81 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 icon-titanium rotate: false - xy: 308, 85 + xy: 288, 81 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 icon-uranium rotate: false - xy: 318, 85 + xy: 238, 71 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 laser rotate: false - xy: 533, 178 + xy: 518, 126 size: 1, 12 orig: 1, 12 offset: 0, 0 @@ -1588,49 +1588,49 @@ laserfull index: -1 mechs/mech-standard rotate: false - xy: 516, 108 + xy: 549, 199 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 mechs/mech-standard-icon rotate: false - xy: 535, 211 + xy: 563, 199 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 mechs/ship-standard rotate: false - xy: 563, 213 + xy: 591, 197 size: 12, 12 orig: 12, 12 offset: 0, 0 index: -1 shell rotate: false - xy: 318, 75 + xy: 428, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 shot rotate: false - xy: 358, 75 + xy: 468, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 shot-long rotate: false - xy: 368, 75 + xy: 547, 178 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 titanshell rotate: false - xy: 378, 65 + xy: 567, 189 size: 8, 8 orig: 8, 8 offset: 0, 0 @@ -1762,6 +1762,13 @@ ui/icons/icon-add orig: 14, 14 offset: 0, 0 index: -1 +ui/icons/icon-admin + rotate: false + xy: 977, 463 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 ui/icons/icon-areaDelete rotate: false xy: 93, 2 @@ -1771,7 +1778,7 @@ ui/icons/icon-areaDelete index: -1 ui/icons/icon-arrow rotate: false - xy: 977, 463 + xy: 993, 479 size: 14, 14 orig: 14, 14 offset: 0, 0 @@ -1811,23 +1818,30 @@ ui/icons/icon-back orig: 16, 16 offset: 0, 0 index: -1 +ui/icons/icon-ban + rotate: false + xy: 1009, 479 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 ui/icons/icon-cancel rotate: false - xy: 993, 479 + xy: 993, 463 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 ui/icons/icon-chat rotate: false - xy: 605, 199 + xy: 142, 93 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 ui/icons/icon-check rotate: false - xy: 1009, 479 + xy: 1009, 463 size: 14, 14 orig: 14, 14 offset: 0, 0 @@ -1855,63 +1869,63 @@ ui/icons/icon-close-over index: -1 ui/icons/icon-crafting rotate: false - xy: 617, 199 + xy: 154, 93 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 ui/icons/icon-cursor rotate: false - xy: 142, 93 + xy: 166, 93 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 ui/icons/icon-defense rotate: false - xy: 154, 93 + xy: 521, 120 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 ui/icons/icon-discord rotate: false - xy: 993, 463 + xy: 592, 227 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 ui/icons/icon-distribution rotate: false - xy: 166, 93 + xy: 516, 108 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 ui/icons/icon-donate rotate: false - xy: 1009, 463 + xy: 608, 227 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 ui/icons/icon-dots rotate: false - xy: 592, 227 + xy: 500, 106 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 ui/icons/icon-editor rotate: false - xy: 608, 227 + xy: 482, 97 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 ui/icons/icon-file-text rotate: false - xy: 500, 106 + xy: 498, 90 size: 14, 14 orig: 14, 14 offset: 0, 0 @@ -1925,21 +1939,21 @@ ui/icons/icon-fill index: -1 ui/icons/icon-floppy rotate: false - xy: 482, 97 + xy: 628, 245 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 ui/icons/icon-folder rotate: false - xy: 498, 90 + xy: 837, 438 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 ui/icons/icon-folder-parent rotate: false - xy: 628, 245 + xy: 837, 422 size: 14, 14 orig: 14, 14 offset: 0, 0 @@ -1953,35 +1967,35 @@ ui/icons/icon-grid index: -1 ui/icons/icon-hold rotate: false - xy: 536, 185 + xy: 722, 415 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 ui/icons/icon-holdDelete rotate: false - xy: 536, 173 + xy: 722, 403 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 ui/icons/icon-home rotate: false - xy: 837, 438 + xy: 853, 443 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 ui/icons/icon-host rotate: false - xy: 837, 422 + xy: 853, 427 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 ui/icons/icon-info rotate: false - xy: 535, 161 + xy: 722, 391 size: 10, 10 orig: 10, 10 offset: 0, 0 @@ -1995,7 +2009,7 @@ ui/icons/icon-line index: -1 ui/icons/icon-load rotate: false - xy: 853, 443 + xy: 869, 446 size: 14, 14 orig: 14, 14 offset: 0, 0 @@ -2023,21 +2037,21 @@ ui/icons/icon-loading index: -1 ui/icons/icon-menu rotate: false - xy: 535, 149 + xy: 734, 416 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 ui/icons/icon-none rotate: false - xy: 535, 137 + xy: 734, 404 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 ui/icons/icon-pause rotate: false - xy: 722, 415 + xy: 734, 392 size: 10, 10 orig: 10, 10 offset: 0, 0 @@ -2051,7 +2065,7 @@ ui/icons/icon-pencil index: -1 ui/icons/icon-pencil-small rotate: false - xy: 853, 427 + xy: 869, 430 size: 14, 14 orig: 14, 14 offset: 0, 0 @@ -2065,42 +2079,42 @@ ui/icons/icon-pick index: -1 ui/icons/icon-play rotate: false - xy: 722, 403 + xy: 724, 369 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 ui/icons/icon-play-2 rotate: false - xy: 869, 446 + xy: 885, 447 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 ui/icons/icon-players rotate: false - xy: 722, 391 + xy: 724, 357 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 ui/icons/icon-power rotate: false - xy: 734, 416 + xy: 724, 345 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 ui/icons/icon-production rotate: false - xy: 734, 404 + xy: 728, 333 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 ui/icons/icon-quit rotate: false - xy: 869, 430 + xy: 885, 431 size: 14, 14 orig: 14, 14 offset: 0, 0 @@ -2114,14 +2128,14 @@ ui/icons/icon-redo index: -1 ui/icons/icon-refresh rotate: false - xy: 885, 447 + xy: 901, 447 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 ui/icons/icon-rename rotate: false - xy: 885, 431 + xy: 901, 431 size: 14, 14 orig: 14, 14 offset: 0, 0 @@ -2135,35 +2149,35 @@ ui/icons/icon-resize index: -1 ui/icons/icon-rotate rotate: false - xy: 901, 447 + xy: 917, 447 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 ui/icons/icon-rotate-arrow rotate: false - xy: 901, 431 + xy: 917, 431 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 ui/icons/icon-rotate-left rotate: false - xy: 917, 447 + xy: 933, 447 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 ui/icons/icon-rotate-right rotate: false - xy: 917, 431 + xy: 933, 431 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 ui/icons/icon-save rotate: false - xy: 933, 447 + xy: 949, 447 size: 14, 14 orig: 14, 14 offset: 0, 0 @@ -2184,7 +2198,7 @@ ui/icons/icon-save-map index: -1 ui/icons/icon-settings rotate: false - xy: 734, 392 + xy: 728, 321 size: 10, 10 orig: 10, 10 offset: 0, 0 @@ -2198,28 +2212,28 @@ ui/icons/icon-terrain index: -1 ui/icons/icon-tools rotate: false - xy: 933, 431 + xy: 949, 431 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 ui/icons/icon-touch rotate: false - xy: 724, 369 + xy: 728, 309 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 ui/icons/icon-touchDelete rotate: false - xy: 724, 357 + xy: 731, 297 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 ui/icons/icon-trash rotate: false - xy: 949, 447 + xy: 965, 447 size: 14, 14 orig: 14, 14 offset: 0, 0 @@ -2233,7 +2247,7 @@ ui/icons/icon-trash-16 index: -1 ui/icons/icon-tutorial rotate: false - xy: 949, 431 + xy: 965, 431 size: 14, 14 orig: 14, 14 offset: 0, 0 @@ -2247,7 +2261,7 @@ ui/icons/icon-undo index: -1 ui/icons/icon-weapon rotate: false - xy: 724, 345 + xy: 731, 285 size: 10, 10 orig: 10, 10 offset: 0, 0 @@ -2332,7 +2346,7 @@ ui/selection index: -1 ui/slider rotate: false - xy: 474, 95 + xy: 634, 277 size: 1, 8 orig: 1, 8 offset: 0, 0 @@ -2441,70 +2455,70 @@ weapons/beam-equip index: -1 weapons/blaster rotate: false - xy: 244, 91 + xy: 679, 282 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 weapons/blaster-equip rotate: false - xy: 254, 91 + xy: 240, 91 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 weapons/clustergun rotate: false - xy: 294, 91 + xy: 280, 91 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 weapons/clustergun-equip rotate: false - xy: 304, 95 + xy: 290, 91 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 weapons/shockgun rotate: false - xy: 338, 75 + xy: 448, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 weapons/shockgun-equip rotate: false - xy: 348, 75 + xy: 458, 75 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 weapons/triblaster rotate: false - xy: 388, 65 + xy: 567, 179 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 weapons/triblaster-equip rotate: false - xy: 398, 65 + xy: 577, 183 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 weapons/vulcan rotate: false - xy: 448, 65 + xy: 571, 159 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 weapons/vulcan-equip rotate: false - xy: 458, 65 + xy: 571, 149 size: 8, 8 orig: 8, 8 offset: 0, 0 diff --git a/core/assets/sprites/sprites.png b/core/assets/sprites/sprites.png index 6193c11acd4aed3ea4a5f793b397c0d8872e84bb..05ff91f4a12caf7375b0a8867e1d43a4c329db42 100644 GIT binary patch delta 82438 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