Merge branch 'master' into balancing-payload_system

This commit is contained in:
SomeonesShade
2025-06-30 18:15:08 +08:00
committed by GitHub
138 changed files with 1357 additions and 471 deletions
+5 -1
View File
@@ -793,6 +793,7 @@ sectors.wave = Wave:
sectors.stored = Stored:
sectors.resume = Resume
sectors.launch = Launch
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Select
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]none (sun)
@@ -2448,7 +2449,7 @@ unit.collaris.description = Fires long-range fragmenting artillery at enemy targ
unit.elude.description = Fires pairs of homing bullets at enemy targets. Can float over bodies of liquid.
unit.avert.description = Fires twisting pairs of bullets at enemy targets.
unit.obviate.description = Fires twisting pairs of lightning orbs at enemy targets.
unit.quell.description = Fires long-range homing missiles at enemy targets. Suppresses enemy structure repair blocks. Only attacks ground targets.
unit.quell.description = Fires long-range homing missiles with unstable plasma shielding at enemy targets. Suppresses enemy structure repair blocks. Only attacks ground targets.
unit.disrupt.description = Fires long-range homing suppression missiles at enemy targets. Suppresses enemy structure repair blocks. Only attacks ground targets.
unit.evoke.description = Builds structures to defend the Bastion core. Repairs structures with a beam. Capable of carrying 2x2 structures.
unit.incite.description = Builds structures to defend the Citadel core. Repairs structures with a beam. Capable of carrying 2x2 structures.
@@ -2566,6 +2567,7 @@ laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Unknown
lcategory.unknown.description = Uncategorized instructions.
@@ -2599,11 +2601,13 @@ lenum.always = Always true.
lenum.idiv = Integer division.
lenum.div = Division.\nReturns [accent]null[] on divide-by-zero.
lenum.mod = Modulo.
lenum.emod = True modulo, result is always positive.
lenum.equal = Equal. Coerces types.\nNon-null objects compared with numbers become 1, otherwise 0.
lenum.notequal = Not equal. Coerces types.
lenum.strictequal = Strict equality. Does not coerce types.\nCan be used to check for [accent]null[].
lenum.shl = Bit-shift left.
lenum.shr = Bit-shift right.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Bitwise OR.
lenum.land = Logical AND.
lenum.and = Bitwise AND.
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = Хваля:
sectors.stored = Захавана:
sectors.resume = Працягнуць
sectors.launch = Запусціць
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Выбраць
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]нічога (sun)
@@ -2566,6 +2567,7 @@ laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Unknown
lcategory.unknown.description = Uncategorized instructions.
@@ -2599,11 +2601,13 @@ lenum.always = Always true.
lenum.idiv = Integer division.
lenum.div = Division.\nReturns [accent]null[] on divide-by-zero.
lenum.mod = Modulo.
lenum.emod = True modulo, result is always positive.
lenum.equal = Equal. Coerces types.\nNon-null objects compared with numbers become 1, otherwise 0.
lenum.notequal = Not equal. Coerces types.
lenum.strictequal = Strict equality. Does not coerce types.\nCan be used to check for [accent]null[].
lenum.shl = Bit-shift left.
lenum.shr = Bit-shift right.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Bitwise OR.
lenum.land = Logical AND.
lenum.and = Bitwise AND.
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = Вълна:
sectors.stored = Съхранени:
sectors.resume = Продължи
sectors.launch = Изстреляй
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Избери
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]няма (Слънцето)
@@ -2566,6 +2567,7 @@ laccess.id = ID на единица/блок/предмет/течност.\nТ
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Неизвестно
lcategory.unknown.description = Некатегоризирани указания.
@@ -2599,11 +2601,13 @@ lenum.always = Винаги вярно
lenum.idiv = Деление с цели числа.
lenum.div = Деление.\nВръща [accent]null[] при делене на 0.
lenum.mod = Модул.
lenum.emod = True modulo, result is always positive.
lenum.equal = Равенство. Конвертира променливите в еднакъв тип.\nНе-null обекти стават 1, null обекти стават 0.
lenum.notequal = Неравенство. Конвертира променливите в еднакъв тип.
lenum.strictequal = Стриктно равенство. Отрицателно при различни типове променливи.\nМоже да се използва за проверка на [accent]null[].
lenum.shl = Побитово изместване наляво.
lenum.shr = Побитово изместване надясно.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Побитово ИЛИ.
lenum.land = Логическо И.
lenum.and = Побитово И.
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = Onada:
sectors.stored = Emmagatzemat:
sectors.resume = Continua
sectors.launch = Llança
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Selecciona
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]cap (sol)
@@ -2566,6 +2567,7 @@ laccess.id = Identificador dunitat/bloc/element/líquid.\nÉs linvers de l
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Desconegut
lcategory.unknown.description = Instruccions sense categoria.
@@ -2599,11 +2601,13 @@ lenum.always = Sempre cert.
lenum.idiv = Divisió entera.
lenum.div = Divisió.\nRetorna [accent]null[] si es divideix per zero.
lenum.mod = Mòdul (residu de la divisió entera).
lenum.emod = True modulo, result is always positive.
lenum.equal = Igual. Força els tipus.\nCompara objectes no nuls amb nombres. Si són iguals, retorna 1. Si no, retorna 0.
lenum.notequal = No igual. Força els tipus.
lenum.strictequal = Igualtat estricta sense forçar el tipus.\nEs pot fer servir amb objectes nuls.
lenum.shl = Desplaça els bits a lesquerra.
lenum.shr = Desplaça els bits a la dreta.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Operació lògica OR bit a bit.
lenum.land = Operació lògica AND bit a bit.
lenum.and = Operació lògica AND bit a bit.
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = Vlna:
sectors.stored = Uskladněno:
sectors.resume = Pokračovat
sectors.launch = Vyslat
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Vybrat
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]bez (slunce)[]
@@ -2566,6 +2567,7 @@ laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup
laccess.displaywidth = Šířka displeje v pixelech.
laccess.displayheight = Výška displeje v pixelech.
laccess.bufferusage = Počet nezpracovaných příkazů ve vyrovnávací paměti displeje.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Neznámé
lcategory.unknown.description = Nezařazené instrukce.
@@ -2599,11 +2601,13 @@ lenum.always = Vždy pravda.
lenum.idiv = Číselné dělení.
lenum.div = Dělení.\nVrací [accent]null[], pokud je děleno nulou.
lenum.mod = Modulo (Vydělí 2 hodnoty a vrací zbytek).
lenum.emod = True modulo, result is always positive.
lenum.equal = Stejné. Vynucuje typy.\nNon-null objekty porovnané s čísly se stanou 1, jinak 0.
lenum.notequal = Není stejné. Vynucuje typy.
lenum.strictequal = Přísná rovnost. Nevynucuje typy.\nMůže být použít, jestli je [accent]null[].
lenum.shl = Bitový posun vlevo.
lenum.shr = Bitový posun vpravo.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Bitový OR.
lenum.land = Logický AND.
lenum.and = Bitový AND.
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = Wave:
sectors.stored = Stored:
sectors.resume = Genoptag
sectors.launch = Affyr
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Vælg
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]ingen (solen)
@@ -2566,6 +2567,7 @@ laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Unknown
lcategory.unknown.description = Uncategorized instructions.
@@ -2599,11 +2601,13 @@ lenum.always = Always true.
lenum.idiv = Integer division.
lenum.div = Division.\nReturns [accent]null[] on divide-by-zero.
lenum.mod = Modulo.
lenum.emod = True modulo, result is always positive.
lenum.equal = Equal. Coerces types.\nNon-null objects compared with numbers become 1, otherwise 0.
lenum.notequal = Not equal. Coerces types.
lenum.strictequal = Strict equality. Does not coerce types.\nCan be used to check for [accent]null[].
lenum.shl = Bit-shift left.
lenum.shr = Bit-shift right.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Bitwise OR.
lenum.land = Logical AND.
lenum.and = Bitwise AND.
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = Welle:
sectors.stored = Gelagert:
sectors.resume = Weiterspielen
sectors.launch = Start
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Auswählen
sectors.launchselect = Ziel auswählen
sectors.nonelaunch = [lightgray]keiner (Sonne)
@@ -2566,6 +2567,7 @@ laccess.id = ID einer Einheit/eines Blocks/eines Materials/einer Flüssigkeit\nT
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Unbekannt
lcategory.unknown.description = Unbekannte Anweisungen
@@ -2599,11 +2601,13 @@ lenum.always = Immer.
lenum.idiv = Division mit ganzen Zahlen.
lenum.div = Division.\nGibt bei Teilung durch null [accent]null[] zurück.
lenum.mod = Modulo.
lenum.emod = True modulo, result is always positive.
lenum.equal = Prüft Gleichheit.\nNicht-null Objekte, die mit Zahlen verglichen werden, werden 1.
lenum.notequal = Prüft Ungleichheit.
lenum.strictequal = Prüft strenge Gleichheit.\nKann verwendet werden, um [accent]null[] zu finden.
lenum.shl = Bit-Shift nacht links.
lenum.shr = Bit-Shift nach rechts.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Bitwise ODER.
lenum.land = Logisches AND.
lenum.and = Bitweises UND.
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = Oleada:
sectors.stored = Almacenado:
sectors.resume = Reanudar
sectors.launch = Lanzar
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Seleccionar
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]Ninguno (sol)
@@ -2566,6 +2567,7 @@ laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Desconocido
lcategory.unknown.description = Instrucciones no clasificadas.
@@ -2599,11 +2601,13 @@ lenum.always = Siempre "true".
lenum.idiv = División de un número entero.
lenum.div = División.\nDevuelve [accent]null[] al dividir entre cero.
lenum.mod = Modulo.
lenum.emod = True modulo, result is always positive.
lenum.equal = Igual. Coacciona tipos.\nObjetos no-nulos coaccionados con números pasan a 1, si no coinciden pasan a 0.
lenum.notequal = No igual. Coacciona tipos.
lenum.strictequal = Igualdad estricta. No coacciona tipos.\nSe puede usar para comprobar si un resultado es [accent]null[].
lenum.shl = Cambia bits a izquierda.
lenum.shr = Cambia bits a derecha.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Comprobación bit a bit OR.
lenum.land = Comprobación lógica AND.
lenum.and = Comprobación bit a bit AND.
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = Wave:
sectors.stored = Stored:
sectors.resume = Resume
sectors.launch = Launch
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Select
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]none (sun)
@@ -2566,6 +2567,7 @@ laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Unknown
lcategory.unknown.description = Uncategorized instructions.
@@ -2599,11 +2601,13 @@ lenum.always = Always true.
lenum.idiv = Integer division.
lenum.div = Division.\nReturns [accent]null[] on divide-by-zero.
lenum.mod = Modulo.
lenum.emod = True modulo, result is always positive.
lenum.equal = Equal. Coerces types.\nNon-null objects compared with numbers become 1, otherwise 0.
lenum.notequal = Not equal. Coerces types.
lenum.strictequal = Strict equality. Does not coerce types.\nCan be used to check for [accent]null[].
lenum.shl = Bit-shift left.
lenum.shr = Bit-shift right.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Bitwise OR.
lenum.land = Logical AND.
lenum.and = Bitwise AND.
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = Wave:
sectors.stored = Stored:
sectors.resume = Resume
sectors.launch = Launch
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Select
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]none (sun)
@@ -2566,6 +2567,7 @@ laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Unknown
lcategory.unknown.description = Uncategorized instructions.
@@ -2599,11 +2601,13 @@ lenum.always = Always true.
lenum.idiv = Integer division.
lenum.div = Division.\nReturns [accent]null[] on divide-by-zero.
lenum.mod = Modulo.
lenum.emod = True modulo, result is always positive.
lenum.equal = Equal. Coerces types.\nNon-null objects compared with numbers become 1, otherwise 0.
lenum.notequal = Not equal. Coerces types.
lenum.strictequal = Strict equality. Does not coerce types.\nCan be used to check for [accent]null[].
lenum.shl = Bit-shift left.
lenum.shr = Bit-shift right.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Bitwise OR.
lenum.land = Logical AND.
lenum.and = Bitwise AND.
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = Taso:
sectors.stored = Säilötty:
sectors.resume = Jatka
sectors.launch = Laukaise
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Valitse
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]ei mitään (sun)
@@ -2566,6 +2567,7 @@ laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Tuntematon
lcategory.unknown.description = Luokittelemattomat ohjeet.
@@ -2599,11 +2601,13 @@ lenum.always = Aina tosi.
lenum.idiv = Kokonaislukujen osamäärä.
lenum.div = Osamäärä.\nPalauttaa arvon [accent]null[] jaettaessa nollalla.
lenum.mod = Lukuun ottamatta.
lenum.emod = True modulo, result is always positive.
lenum.equal = Yhtä suuri. Pakottaa tyypit.\nMuut kohteet kuin null palauttavat arvon 1 verrattaessa numeroihin, muussa tapauksessa palautus on 0.
lenum.notequal = Erisuuri. Pakottaa tyypit.
lenum.strictequal = Tarkka yhtäsuuruus. Ei pakota tyyppejä.\nVoidaan käyttää tarkistamaan arvon [accent]null[] varalta.
lenum.shl = Siirrä bittejä vasemmalle.
lenum.shr = Siirrä bittejä oikealle.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Binäärinen OR.
lenum.land = Looginen AND.
lenum.and = Binäärinen AND.
@@ -793,6 +793,7 @@ sectors.wave = Mga Waves:
sectors.stored = Stored:
sectors.resume = Resume
sectors.launch = I-Launch
sectors.viewsubmission = \ue80d View Submissions
sectors.select = I-Select
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]none (sun)
@@ -2566,6 +2567,7 @@ laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Unknown
lcategory.unknown.description = Uncategorized instructions.
@@ -2599,11 +2601,13 @@ lenum.always = Always true.
lenum.idiv = Integer division.
lenum.div = Division.\nReturns [accent]null[] on divide-by-zero.
lenum.mod = Modulo.
lenum.emod = True modulo, result is always positive.
lenum.equal = Equal. Coerces types.\nNon-null objects compared with numbers become 1, otherwise 0.
lenum.notequal = Not equal. Coerces types.
lenum.strictequal = Strict equality. Does not coerce types.\nCan be used to check for [accent]null[].
lenum.shl = Bit-shift left.
lenum.shr = Bit-shift right.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Bitwise OR.
lenum.land = Logical AND.
lenum.and = Bitwise AND.
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = Vague :
sectors.stored = Stockage :
sectors.resume = Reprendre
sectors.launch = Décoller
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Sélectionner
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]Vide (soleil)
@@ -2566,6 +2567,7 @@ laccess.id = L'ID d'une unité/bloc/ressource/liquide.\nCeci est l'inverse de l'
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Inconnu
lcategory.unknown.description = Instructions sans catégorie.
@@ -2599,11 +2601,13 @@ lenum.always = Toujours [accent]true[].
lenum.idiv = Division entière.
lenum.div = Division.\nRetourne [accent]null[] lors d'une division par zéro.
lenum.mod = Modulo.
lenum.emod = True modulo, result is always positive.
lenum.equal = Égalité. Conversion des types.\nLes objets non-nuls comparés avec des nombres deviennent 1, sinon 0.
lenum.notequal = Inégalité. Conversion des types.
lenum.strictequal = Égalité stricte. Ne convertit pas les types.\nPeut être utilisé pour vérifier les valeurs [accent]null[].
lenum.shl = Décalage de bits vers la gauche.
lenum.shr = Décalage de bits vers la droite.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Opération binaire OR.
lenum.land = Opération logique AND.
lenum.and = Opération binaire AND.
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = Hullám:
sectors.stored = Tárolt nyersanyagok:
sectors.resume = Folytatás
sectors.launch = Kilövés
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Kiválasztás
sectors.launchselect = Célállomás kiválasztása
sectors.nonelaunch = [lightgray]semmi (nap)
@@ -2566,6 +2567,7 @@ laccess.id = Egy egység/blokk/nyersanyag/folyadék azonosítója.\nEz a keresé
laccess.displaywidth = Egy kijelzőblokk szélessége pixelben.
laccess.displayheight = Egy kijelzőblokk magassága pixelben.
laccess.bufferusage = A kijelző grafikus pufferében lévő feldolgozatlan parancsok száma.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Ismeretlen
lcategory.unknown.description = Nem kategorizált utasítások.
@@ -2599,11 +2601,13 @@ lenum.always = Mindig igaz.
lenum.idiv = Egész osztás.
lenum.div = Osztás.\nNullával való osztáskor a visszatérési érték [accent]null[].
lenum.mod = Modulo.
lenum.emod = True modulo, result is always positive.
lenum.equal = Egyenlő. Kényszeríti a típusokat.\nA nem null értékű objektumok értéke 1 lesz, egyébként 0.
lenum.notequal = Nem egyenlő. Kényszeríti a típusokat.
lenum.strictequal = Szigorúan egyenlőség. Nem kényszeríti a típusokat.\nA [accent]null[] ellenőrzésére is használható.
lenum.shl = Biteltolás balra.
lenum.shr = Biteltolás jobbra.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Bitenkénti VAGY.
lenum.land = Logikai ÉS.
lenum.and = Bitenkénti ÉS.
@@ -793,6 +793,7 @@ sectors.wave = Gelombang:
sectors.stored = Terisi:
sectors.resume = Lanjutkan
sectors.launch = Luncurkan
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Pilih
sectors.launchselect = Pilih Destinasi Peluncuran
sectors.nonelaunch = [lightgray]tidak ada (matahari)
@@ -2566,6 +2567,7 @@ laccess.id = ID suatu unit/blok/bahan/cairan.\nIni adalah kebalikan dari operasi
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Tak Diketahui
lcategory.unknown.description = Instruksi tanpa kategori.
@@ -2599,11 +2601,13 @@ lenum.always = Selalu benar.
lenum.idiv = Pembagian integer.
lenum.div = Pembagian.\nMengembalikan [accent]null[] pada pembagian dengan nol.
lenum.mod = Modulus.
lenum.emod = True modulo, result is always positive.
lenum.equal = Kesetaraan. Mengonversikan tipe.\nObjek bukan nol dibandingkan dengan angka menjadi 1, jika tidak 0.
lenum.notequal = Kesetaraan tanpa jenis pemaksaan. Mengonversikan tipe.
lenum.strictequal = Kesetaraan dengan jenis pemaksaan. Tidak mengonversikan tipe.\nDapat digunakan untuk memeriksa [accent]null[].
lenum.shl = Bit-shift kiri.
lenum.shr = Bit-shift kanan.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Bitwise OR.
lenum.land = Logika AND.
lenum.and = Bitwise AND.
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = Ondata:
sectors.stored = Immagazzinato:
sectors.resume = Riprendi
sectors.launch = Lancia
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Seleziona
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]nessuno (sole)
@@ -2566,6 +2567,7 @@ laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Unknown
lcategory.unknown.description = Uncategorized instructions.
@@ -2599,11 +2601,13 @@ lenum.always = Always true.
lenum.idiv = Integer division.
lenum.div = Division.\nReturns [accent]null[] on divide-by-zero.
lenum.mod = Modulo.
lenum.emod = True modulo, result is always positive.
lenum.equal = Equal. Coerces types.\nNon-null objects compared with numbers become 1, otherwise 0.
lenum.notequal = Not equal. Coerces types.
lenum.strictequal = Strict equality. Does not coerce types.\nCan be used to check for [accent]null[].
lenum.shl = Bit-shift left.
lenum.shr = Bit-shift right.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Bitwise OR.
lenum.land = Logical AND.
lenum.and = Bitwise AND.
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = ウェーブ:
sectors.stored = コアの資源:
sectors.resume = 再開
sectors.launch = 打ち上げ
sectors.viewsubmission = \ue80d View Submissions
sectors.select = 選択
sectors.launchselect = 発射先
sectors.nonelaunch = [lightgray]無し (sun)
@@ -2566,6 +2567,7 @@ laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = 不明
lcategory.unknown.description = 未分類の指示です。
@@ -2599,11 +2601,13 @@ lenum.always = 常にtrueを返します。
lenum.idiv = 整数の割り算をします。
lenum.div = 割り算をします。\nゼロ除算で [accent]null[] を返します。
lenum.mod = 割ったあまりを返します。
lenum.emod = True modulo, result is always positive.
lenum.equal = 等しいかどうかを比較します。型を強制します。\n数値と比較される非NULLオブジェクトは1になり、そうでない場合は0になる。
lenum.notequal = 等しくないかどうかを比較します。型を強制します。
lenum.strictequal = より厳密な比較をします。型の強制はしません。\n [accent]null[] のチェックに使用することができます。
lenum.shl = ビットを左にシフトします。
lenum.shr = ビットを右にシフトします。
lenum.ushr = Unsigned bit-shift right.
lenum.or = ビット単位でのOR演算をします。
lenum.land = 論理的なAND演算をします。
lenum.and = ビット単位でのAND演算をします。
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = 단계:
sectors.stored = 저장량:
sectors.resume = 재개
sectors.launch = 출격
sectors.viewsubmission = \ue80d View Submissions
sectors.select = 선택
sectors.launchselect = 발사 대상 선택
sectors.nonelaunch = [lightgray]없음 (태양)[]
@@ -2566,6 +2567,7 @@ laccess.id = 유닛/블록/아이템/액체의 ID.\n이것은 조회 작업의
laccess.displaywidth = 디스플레이 블록의 픽셀 단위 너비.
laccess.displayheight = 디스플레이 블록의 픽셀 단위 높이.
laccess.bufferusage = 디스플레이의 그래픽 버퍼에 있는 처리되지 않은 명령의 수.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = 알 수 없음
lcategory.unknown.description = 분류되지 않은 설명
@@ -2599,11 +2601,13 @@ lenum.always = 항상 참
lenum.idiv = 정수 나누기
lenum.div = 나누기\n0으로 나누면 [accent]null[]을 반환합니다.
lenum.mod = 나머지
lenum.emod = True modulo, result is always positive.
lenum.equal = 동치 비교. 형변환 가능\nNull이 아닌 객체가 숫자와 비교하려면 1이 되고, 아니면 0이 됩니다.
lenum.notequal = 동치 부정. 형변환 가능
lenum.strictequal = 엄격한 동치 비교. 형변환 불가능\n[accent]null[]을 확인할 때 쓸 수 있습니다.
lenum.shl = 왼쪽으로 비트 이동
lenum.shr = 오른쪽으로 비트 이동
lenum.ushr = Unsigned bit-shift right.
lenum.or = 비트연산자 OR
lenum.land = 논리연산자 AND
lenum.and = 비트연산자 AND
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = Wave:
sectors.stored = Stored:
sectors.resume = Resume
sectors.launch = Launch
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Select
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]none (sun)
@@ -2566,6 +2567,7 @@ laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Unknown
lcategory.unknown.description = Uncategorized instructions.
@@ -2599,11 +2601,13 @@ lenum.always = Always true.
lenum.idiv = Integer division.
lenum.div = Division.\nReturns [accent]null[] on divide-by-zero.
lenum.mod = Modulo.
lenum.emod = True modulo, result is always positive.
lenum.equal = Equal. Coerces types.\nNon-null objects compared with numbers become 1, otherwise 0.
lenum.notequal = Not equal. Coerces types.
lenum.strictequal = Strict equality. Does not coerce types.\nCan be used to check for [accent]null[].
lenum.shl = Bit-shift left.
lenum.shr = Bit-shift right.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Bitwise OR.
lenum.land = Logical AND.
lenum.and = Bitwise AND.
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = Golf:
sectors.stored = Opgeslagen:
sectors.resume = Doorgaan
sectors.launch = Lanceer
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Selecteer
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]geen (sun)
@@ -2566,6 +2567,7 @@ laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Unknown
lcategory.unknown.description = Uncategorized instructions.
@@ -2599,11 +2601,13 @@ lenum.always = Always true.
lenum.idiv = Integer division.
lenum.div = Division.\nReturns [accent]null[] on divide-by-zero.
lenum.mod = Modulo.
lenum.emod = True modulo, result is always positive.
lenum.equal = Equal. Coerces types.\nNon-null objects compared with numbers become 1, otherwise 0.
lenum.notequal = Not equal. Coerces types.
lenum.strictequal = Strict equality. Does not coerce types.\nCan be used to check for [accent]null[].
lenum.shl = Bit-shift left.
lenum.shr = Bit-shift right.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Bitwise OR.
lenum.land = Logical AND.
lenum.and = Bitwise AND.
@@ -793,6 +793,7 @@ sectors.wave = Wave:
sectors.stored = Stored:
sectors.resume = Resume
sectors.launch = Launch
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Select
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]none (sun)
@@ -2566,6 +2567,7 @@ laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Unknown
lcategory.unknown.description = Uncategorized instructions.
@@ -2599,11 +2601,13 @@ lenum.always = Always true.
lenum.idiv = Integer division.
lenum.div = Division.\nReturns [accent]null[] on divide-by-zero.
lenum.mod = Modulo.
lenum.emod = True modulo, result is always positive.
lenum.equal = Equal. Coerces types.\nNon-null objects compared with numbers become 1, otherwise 0.
lenum.notequal = Not equal. Coerces types.
lenum.strictequal = Strict equality. Does not coerce types.\nCan be used to check for [accent]null[].
lenum.shl = Bit-shift left.
lenum.shr = Bit-shift right.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Bitwise OR.
lenum.land = Logical AND.
lenum.and = Bitwise AND.
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = Fala:
sectors.stored = Zmagazynowane:
sectors.resume = Kontynuuj
sectors.launch = Wystrzel
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Wybierz
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]Żaden (Słońce)
@@ -2566,6 +2567,7 @@ laccess.id = ID jednostki/bloku/przedmiotu/płynu.\nOdwrotnośc operacji wyszuki
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Inne
lcategory.unknown.description = Niezkategoryzowane instrukcje.
@@ -2599,11 +2601,13 @@ lenum.always = Zawsze prawda.
lenum.idiv = Dzielenie liczb całkowitych.
lenum.div = Dzielenie.\nZwraca [accent]null[] w trakcie dzielenia przez zero.
lenum.mod = Modulo.
lenum.emod = True modulo, result is always positive.
lenum.equal = Równość. Wymusza typ.\nNiezerowe objekty połączone z liczbami stają się 1, w innym wypadku 0.
lenum.notequal = Nierówność. Wymusza typ.
lenum.strictequal = Ścisła równość. Nie wymusza typów.\nMoże być użyte do wykrycia [accent]null[].
lenum.shl = Przesunięcie bitowe w lewo.
lenum.shr = Przesunięcie bitowe w prawo.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Bitowe OR (lub).
lenum.land = Logiczne AND (i).
lenum.and = Bitowe AND (i).
@@ -793,6 +793,7 @@ sectors.wave = Horda:
sectors.stored = Armazenado:
sectors.resume = Continuar
sectors.launch = Lançar
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Selecionar
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]nenhum (sun)
@@ -2566,6 +2567,7 @@ laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Desconhecido
lcategory.unknown.description = Instruções não categorizadas.
@@ -2599,11 +2601,13 @@ lenum.always = Sempre verdade.
lenum.idiv = Divisão inteira.
lenum.div = Divisão.\nRetorna [accent]null[] na divisão por zero.
lenum.mod = Modulo.
lenum.emod = True modulo, result is always positive.
lenum.equal = Igual. Coage tipos.\nObjetos não nulos comparados com números tornam-se 1, caso contrário, 0.
lenum.notequal = Não igual. Tipos de coerção.
lenum.strictequal = Igualdade estrita. Não coage tipos.Pode ser usado para verificar [accent]null[].
lenum.shl = Deslocamento de bit para a esquerda.
lenum.shr = Deslocamento de bits para a direita.
lenum.ushr = Unsigned bit-shift right.
lenum.or = OU bit a bit.
lenum.land = Lógico E.
lenum.and = E bit a bit.
@@ -793,6 +793,7 @@ sectors.wave = Horda:
sectors.stored = Armazenado:
sectors.resume = Continuar
sectors.launch = Lançar
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Selecionar
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]nenhum (sun)
@@ -2566,6 +2567,7 @@ laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Desconhecido
lcategory.unknown.description = Instruções não categorizadas.
@@ -2599,11 +2601,13 @@ lenum.always = Sempre verdade.
lenum.idiv = Divisão inteira.
lenum.div = Divisão.\nRetorna [accent]null[] na divisão por zero.
lenum.mod = Modulo.
lenum.emod = True modulo, result is always positive.
lenum.equal = Igual. Coage tipos.\nObjetos não nulos comparados com números tornam-se 1, caso contrário, 0.
lenum.notequal = Não igual. Tipos de coerção.
lenum.strictequal = Igualdade estrita. Não coage tipos.Pode ser usado para verificar [accent]null[].
lenum.shl = Deslocamento de bit para a esquerda.
lenum.shr = Deslocamento de bits para a direita.
lenum.ushr = Unsigned bit-shift right.
lenum.or = OU bit a bit.
lenum.land = Lógico E.
lenum.and = E bit a bit.
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = Valul:
sectors.stored = Stocat:
sectors.resume = Revino
sectors.launch = Lansare
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Selectează
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]nimic (soarele)
@@ -2566,6 +2567,7 @@ laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Unknown
lcategory.unknown.description = Uncategorized instructions.
@@ -2599,11 +2601,13 @@ lenum.always = Mereu adevărat.
lenum.idiv = Împărțirea naturală a numerelor (int).
lenum.div = Împărțirea.\nReturnează [accent]null[] dacă împarți la 0.
lenum.mod = Modulo (restul împărțirii).
lenum.emod = True modulo, result is always positive.
lenum.equal = Egal. Convertește tipurile variabilelor.\nObiectele nenule comparate cu numere devin 1, cele nule devin 0.
lenum.notequal = Nu e egal. Convertește tipurile variabilelor.
lenum.strictequal = Egalitate strictă. Nu convertește tipurile variabilelor.\nPoate fi folosit pt a verifica dacă ceva este [accent]null[].
lenum.shl = Shift left pe biți.
lenum.shr = Shift right pe biți.
lenum.ushr = Unsigned bit-shift right.
lenum.or = OR/SAU. Ține cont de biți.
lenum.land = Logical AND/ȘI logic. Nu ține cont de biți.
lenum.and = AND/ȘI. Ține cont de biți.
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = Волна:
sectors.stored = Накоплено:
sectors.resume = Продолжить
sectors.launch = Высадка
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Выбор
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]нет (солнце)
@@ -2566,6 +2567,7 @@ laccess.id = Идентификатор единицы/блока/предмет
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Неизвестно
lcategory.unknown.description = Нет категории.
@@ -2599,11 +2601,13 @@ lenum.always = Всегда истина.
lenum.idiv = Целочисленное деление.
lenum.div = Деление.\nВозвращает [accent]null[] при делении на ноль.
lenum.mod = Остаток от деления.
lenum.emod = True modulo, result is always positive.
lenum.equal = Равно. Приводит типы.\nНе-null объекты, по сравнению с числами, становятся 1, иначе — 0.
lenum.notequal = Не равно. Приводит типы.
lenum.strictequal = Строгое равенство. Не приводит типы.\nМожет быть использовано для проверки на [accent]null[].
lenum.shl = Побитовый сдвиг влево.
lenum.shr = Побитовый сдвиг вправо.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Побитовое ИЛИ.
lenum.land = Булевое И.
lenum.and = Побитовое И.
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = Talas:
sectors.stored = Skladišćeno:
sectors.resume = Nastavi
sectors.launch = Lansiraj
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Izaberi
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]nema (sunce)
@@ -2566,6 +2567,7 @@ laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Nepoznato
lcategory.unknown.description = Uncategorized instructions.
@@ -2599,11 +2601,13 @@ lenum.always = Uvek Tačno.
lenum.idiv = Integer division.
lenum.div = Deljenje.Šalje [accent]null[] kada se deli sa nulom.
lenum.mod = Modulo.
lenum.emod = True modulo, result is always positive.
lenum.equal = Jednakost. Primorava vrste.\nObjekti koji nisu [accent]null[] poređeni sa brojevima postaju 1, u suprotnom 0.
lenum.notequal = Nejednakost. Primorava vrste.
lenum.strictequal = Zacrtana jednakost. Ne primorava vrste.\nMože se koristiti radi provere [accent]null[]-a.
lenum.shl = Bit-shift left.
lenum.shr = Bit-shift right.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Bitwise OR.
lenum.land = Logical AND.
lenum.and = Bitwise AND.
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = Wave:
sectors.stored = Lagrade:
sectors.resume = Återuppta
sectors.launch = Skjuta upp
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Select
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]none (sun)
@@ -2566,6 +2567,7 @@ laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Unknown
lcategory.unknown.description = Uncategorized instructions.
@@ -2599,11 +2601,13 @@ lenum.always = Always true.
lenum.idiv = Integer division.
lenum.div = Division.\nReturns [accent]null[] on divide-by-zero.
lenum.mod = Modulo.
lenum.emod = True modulo, result is always positive.
lenum.equal = Equal. Coerces types.\nNon-null objects compared with numbers become 1, otherwise 0.
lenum.notequal = Not equal. Coerces types.
lenum.strictequal = Strict equality. Does not coerce types.\nCan be used to check for [accent]null[].
lenum.shl = Bit-shift left.
lenum.shr = Bit-shift right.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Bitwise OR.
lenum.land = Logical AND.
lenum.and = Bitwise AND.
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = คลื่น:
sectors.stored = คลังไอเท็ม:
sectors.resume = ไปต่อ
sectors.launch = ลงจอด
sectors.viewsubmission = \ue80d View Submissions
sectors.select = เลือก
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]ไม่มี (ดวงอาทิตย์)
@@ -2566,6 +2567,7 @@ laccess.id = ID ของยูนิต/บล็อก/ไอเท็ม/ข
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = ไม่ทราบ
lcategory.unknown.description = คำสั่งที่ไม่อยู่ในหมวดหมู่ใดๆเลย
@@ -2599,11 +2601,13 @@ lenum.always = เป็นจริงเสมอ
lenum.idiv = หารจำนวนเต็ม
lenum.div = หาร\nจะส่งกลับ[accent]ค่าว่าง[] หากหารศูนย์
lenum.mod = โมดูโล่ (หารหาเศษ)
lenum.emod = True modulo, result is always positive.
lenum.equal = เท่ากับ แบบบังคับประเภท\nสิ่งที่ไม่ใช่ค่าว่างเมื่อเทียบกับตัวเลขจะส่งกลับค่า 1 นอกนั้นจะส่งกลับค่า 0
lenum.notequal = ไม่เท่ากับ บังคับประเภท
lenum.strictequal = เท่ากับที่เข้มงวด ไม่บังคับประเภท\nสามารถใช้ตรวจสอบหา[accent]ค่าว่าง[]ได้
lenum.shl = เลื่อนบิตไปทางซ้าย
lenum.shr = เลื่อนบิตไปทางขวา
lenum.ushr = Unsigned bit-shift right.
lenum.or = หรือ แบบบิต
lenum.land = และ เชิงตรรกะ
lenum.and = และ แบบบิต
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = Wave:
sectors.stored = Stored:
sectors.resume = Resume
sectors.launch = Launch
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Select
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]none (sun)
@@ -2566,6 +2567,7 @@ laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Unknown
lcategory.unknown.description = Uncategorized instructions.
@@ -2599,11 +2601,13 @@ lenum.always = Always true.
lenum.idiv = Integer division.
lenum.div = Division.\nReturns [accent]null[] on divide-by-zero.
lenum.mod = Modulo.
lenum.emod = True modulo, result is always positive.
lenum.equal = Equal. Coerces types.\nNon-null objects compared with numbers become 1, otherwise 0.
lenum.notequal = Not equal. Coerces types.
lenum.strictequal = Strict equality. Does not coerce types.\nCan be used to check for [accent]null[].
lenum.shl = Bit-shift left.
lenum.shr = Bit-shift right.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Bitwise OR.
lenum.land = Logical AND.
lenum.and = Bitwise AND.
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = Dalga:
sectors.stored = Depolanan:
sectors.resume = Devam Et
sectors.launch = Fırlat
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Seç
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]yok (güneş)
@@ -2566,6 +2567,7 @@ laccess.id = Bir birim/blok/eşya/sıvı kimliği. \nBu arama operasyonun zıtt
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = ???
lcategory.unknown.description = Kategorize edilmemiş talimatlar
@@ -2599,11 +2601,13 @@ lenum.always = Her Zaman Doğru
lenum.idiv = Tamsayı Bölme
lenum.div = Bölme
lenum.mod = Mod
lenum.emod = True modulo, result is always positive.
lenum.equal = Eşit
lenum.notequal = Eşit Değil
lenum.strictequal = Aynı
lenum.shl = Shift Sol
lenum.shr = Shift Sağ
lenum.ushr = Unsigned bit-shift right.
lenum.or = Veya
lenum.land = Çapraz Ve
lenum.and = Ve
@@ -793,6 +793,7 @@ sectors.wave = Хвиля:
sectors.stored = Зберігає:
sectors.resume = Продовжити
sectors.launch = Запустити
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Вибрати
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]нічого (сонце)
@@ -2566,6 +2567,7 @@ laccess.id = Ідентифікатор одиниці/блоку/предмет
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Невідома категорія
lcategory.unknown.description = Команди без категорії.
@@ -2599,11 +2601,13 @@ lenum.always = Завжди істинне.
lenum.idiv = Ціле ділення.
lenum.div = Ділення.\nПовертає [accent]null[] при діленні на нуль.
lenum.mod = Залишок від ділення.
lenum.emod = True modulo, result is always positive.
lenum.equal = Рівно. Примусове приведення типів.\nНе-null об’єкти у порівнянні з числами стають 1, інакше — 0.
lenum.notequal = Не рівно. Примусове приведення типів.
lenum.strictequal = Сувора рівність. Примусового приведення типів немає.\nМожна використати для перевірки на [accent]null[].
lenum.shl = Зсув бітів ліворуч.
lenum.shr = Зсув бітів праворуч.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Побітове АБО (OR).
lenum.land = Побітове логічне І.
lenum.and = Побітове І.
+4
View File
@@ -793,6 +793,7 @@ sectors.wave = Đợt:
sectors.stored = Lưu trữ:
sectors.resume = Tiếp tục
sectors.launch = Phóng
sectors.viewsubmission = \ue80d View Submissions
sectors.select = Chọn
sectors.launchselect = Chọn đích phóng
sectors.nonelaunch = [lightgray]không có (mặt trời)
@@ -2566,6 +2567,7 @@ laccess.id = Định danh của một đơn vị/khối/vật phẩm/chất lỏ
laccess.displaywidth = Độ rộng của một khối hiển thị tính bằng pixel.
laccess.displayheight = Độ cao của một khối hiển thị tính bằng pixel.
laccess.bufferusage = Số lệnh chưa xử lý trong bộ đệm đồ họa của một hiển thị.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = Không xác định
lcategory.unknown.description = Chỉ lệnh không được phân loại.
@@ -2599,11 +2601,13 @@ lenum.always = Luôn đúng.
lenum.idiv = Chia lấy phần nguyên.
lenum.div = Phép chia.\nTrả về [accent]rỗng (null)[] khi chia cho 0.
lenum.mod = Chia lấy phần dư.
lenum.emod = True modulo, result is always positive.
lenum.equal = Bằng nhau. Ép kiểu.\nĐối tượng không-rỗng (non-null) so sánh với số sẽ thành 1, ngược lại là 0.
lenum.notequal = Không bằng nhau. Ép kiểu.
lenum.strictequal = Bằng nhau ràng buộc. Không ép kiểu.\nCó thể dùng để kiểm tra [accent]rỗng (null)[].
lenum.shl = Nhảy bit sang trái.
lenum.shr = Nhảy bit sang phải.
lenum.ushr = Unsigned bit-shift right.
lenum.or = Phép toán bit OR.
lenum.land = Phép toán logic AND.
lenum.and = Phép toán bit AND.
@@ -793,6 +793,7 @@ sectors.wave = 波次:
sectors.stored = 贮存:
sectors.resume = 继续
sectors.launch = 发射
sectors.viewsubmission = \ue80d View Submissions
sectors.select = 选择
sectors.launchselect = 选择发射目的地
sectors.nonelaunch = [lightgray]无(自动销毁)
@@ -2566,6 +2567,7 @@ laccess.id = 单位/块/物品/液体的 ID。\n这是 Lookup 的反向操作。
laccess.displaywidth = 显示屏的宽度(以像素为单位)。
laccess.displayheight = 显示屏的高度(以像素为单位)。
laccess.bufferusage = 显示器图形缓冲区中未处理的命令数。
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = 未知
lcategory.unknown.description = 未分类的指令
@@ -2599,11 +2601,13 @@ lenum.always = 无条件跳转
lenum.idiv = 整数除法,返回不带小数的商
lenum.div = 除法,除以 0 时返回 [accent]null[]
lenum.mod = 求除法的余数
lenum.emod = True modulo, result is always positive.
lenum.equal = 相等。转换参数类型后进行比较\n与数字进行比较时,null 转换为 0 ,非 null 对象转换为 1
lenum.notequal = 不相等。转换参数类型后进行比较
lenum.strictequal = 严格相等。不转换参数类型\n可用于准确检查 [accent]null[] 对象
lenum.shl = 左移位
lenum.shr = 右移位
lenum.ushr = Unsigned bit-shift right.
lenum.or = 按位或
lenum.land = 逻辑与
lenum.and = 按位与
@@ -793,6 +793,7 @@ sectors.wave = 波次:
sectors.stored = 儲存:
sectors.resume = 繼續
sectors.launch = 發射
sectors.viewsubmission = \ue80d View Submissions
sectors.select = 選取
sectors.launchselect = Select Launch Destination
sectors.nonelaunch = [lightgray]無(太陽)
@@ -2566,6 +2567,7 @@ laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup
laccess.displaywidth = Width of a display block in pixels.
laccess.displayheight = Height of a display block in pixels.
laccess.bufferusage = Number of unprocessed commands in the graphics buffer of a display.
laccess.operations = Number of operations performed on the block.\nFor displays, returns the number of drawflush operations.
lcategory.unknown = 未知
lcategory.unknown.description = Uncategorized instructions.
@@ -2599,11 +2601,13 @@ lenum.always = 永遠 true (直接跳).
lenum.idiv = 整數除法,無條件捨去.
lenum.div = 除法.\n除以零時回傳 [accent]null[]
lenum.mod = Modulo,求餘數
lenum.emod = True modulo, result is always positive.
lenum.equal = 是否相等,不管資料型態。\n非null 物件和數值相比時回傳1
lenum.notequal = 是否不相等,不管資料型態.
lenum.strictequal = 嚴格檢查是否相等,會比照資料型態。\n可用來檢查[accent]null[]
lenum.shl = 左移n位元
lenum.shr = 右移n位元
lenum.ushr = Unsigned bit-shift right.
lenum.or = 位元 OR
lenum.land = 邏輯 AND
lenum.and = 位元 AND
+2
View File
@@ -181,4 +181,6 @@ IchMagSchokolade
MonoChronos
RushieWashie
ITY
Iniquit
DSFdsfWxp
Someone's Shadow
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
{presets:{windsweptIslands:97,stainedMountains:223,weatheredChannels:166,craters:219,extractionOutpost:213,coastline:164,navalFortress:165,frontier:86,groundZero:170,mycelialBastion:143,facility32m:65,atolls:75,overgrowth:142,testingGrounds:169,frozenForest:64,saltFlats:98,taintedWoods:145,infestedCanyons:85,desolateRift:271,nuclearComplex:228,ruinousShores:41,planetaryTerminal:217,impact0078:266,seaPort:214,geothermalStronghold:264,cruxscape:54,fungalPass:221,tarFields:99,biomassFacility:23},attackSectors:[0,2,5,6,10,11,12,13,16,19,24,25,27,28,30,33,36,47,48,49,51,57,59,60,66,67,68,70,71,76,78,82,90,104,106,110,114,115,121,127,128,129,133,138,148,149,154,158,172,180,182,200,202,204,210,224,225,233,234,235,241,243,248,254,255,257,259,265]}
{presets:{windsweptIslands:97,stainedMountains:223,weatheredChannels:166,craters:219,extractionOutpost:213,coastline:164,navalFortress:165,frontier:86,groundZero:170,mycelialBastion:143,facility32m:65,atolls:75,overgrowth:142,testingGrounds:169,frozenForest:64,saltFlats:98,taintedWoods:145,infestedCanyons:85,desolateRift:271,nuclearComplex:228,ruinousShores:41,planetaryTerminal:217,impact0078:266,seaPort:214,geothermalStronghold:264,cruxscape:54,fungalPass:221,tarFields:99,biomassFacility:23},attackSectors:[0,6,13,16,19,20,24,27,30,47,55,66,67,69,76,92,94,103,111,116,127,133,138,150,157,161,162,176,180,185,191,192,197,200,204,207,225,230,237,242,243,244,245,246,247,248,251,254,259,263,265]}
+9 -2
View File
@@ -1,6 +1,7 @@
attribute vec4 a_position;
attribute vec3 a_normal;
attribute vec4 a_color;
attribute vec4 a_emissive;
uniform mat4 u_proj;
uniform mat4 u_trans;
@@ -8,6 +9,7 @@ uniform vec3 u_lightdir;
uniform vec3 u_camdir;
uniform vec3 u_campos;
uniform vec3 u_ambientColor;
uniform float u_emissive;
varying vec4 v_col;
@@ -19,13 +21,18 @@ void main(){
//TODO this calculation is probably wrong
vec3 lightReflect = normalize(reflect(a_normal, u_lightdir));
vec3 vertexEye = normalize(u_campos - (u_trans * a_position).xyz);
float albedo = 1.0 - a_color.a;
float specularFactor = dot(vertexEye, lightReflect);
if(specularFactor > 0.0){
specular = vec3(1.0 * pow(specularFactor, 40.0)) * (1.0-a_color.a);
specular = vec3(1.0 * pow(specularFactor, 40.0)) * albedo;
}
vec3 norc = (u_ambientColor + specular) * (diffuse + vec3(clamp((dot(a_normal, u_lightdir) + 1.0) / 2.0, 0.0, 1.0)));
v_col = vec4(a_color.rgb, 1.0) * vec4(norc, 1.0);
float emissive = a_emissive.a * u_emissive * min(pow(max(0.0, (1.0 - norc.r) * 1.2), 3.0), 1.1);
v_col = vec4(mix(a_color.rgb, a_emissive.rgb, emissive), 1.0) * vec4(mix(norc, vec3(1.0), emissive), 1.0);
gl_Position = u_proj * u_trans * a_position;
}
+2
View File
@@ -51,6 +51,8 @@ public class Vars implements Loadable{
public static final int minModGameVersion = 136;
/** Min game version for java mods specifically - this is higher, as Java mods have more breaking changes. */
public static final int minJavaModGameVersion = 147;
/** If true, a button to view sector submission threads is shown. */
public static boolean showSectorSubmissions = true;
/** If true, the BE server list is always used. */
public static boolean forceBeServers = false;
/** If true, mod code and scripts do not run. For internal testing only. This WILL break mods if enabled. */
+1 -1
View File
@@ -540,7 +540,7 @@ public class Pathfinder implements Runnable{
if(!targets.isEmpty()){
boolean any = false;
for(Building other : targets){
if((other.items != null && other.items.any()) || other.status() != BlockStatus.noInput){
if(((other.items != null && other.items.any()) || other.status() != BlockStatus.noInput) && other.block.targetable){
out.add(other.tile.array());
any = true;
}
+12 -5
View File
@@ -141,6 +141,8 @@ public class RtsAI{
boolean handleSquad(Seq<Unit> units, boolean noDefenders){
if(units.isEmpty()) return false;
boolean naval = units.first() instanceof WaterMovec;
float health = 0f, dps = 0f;
float ax = 0f, ay = 0f;
boolean targetAir = true, targetGround = true;
@@ -165,7 +167,7 @@ public class RtsAI{
boolean defendingCore = false;
//there is something to defend, see if it's worth the time
if(damaged.size > 0){
if(damaged.size > 0 && !naval){
//TODO do the weights matter at all?
//for(var build : damaged){
//float w = estimateStats(ax, ay, dps, health);
@@ -251,7 +253,7 @@ public class RtsAI{
}
}
var build = anyDefend ? null : findTarget(ax, ay, units.size, dps, health, units.first().flag == 0, units.first().isFlying());
var build = anyDefend ? null : findTarget(ax, ay, units.size, dps, health, units.first().flag == 0, units.first().isFlying(), naval);
if(build != null || anyDefend){
for(var unit : units){
@@ -274,7 +276,7 @@ public class RtsAI{
return anyDefend;
}
@Nullable Building findTarget(float x, float y, int total, float dps, float health, boolean checkWeight, boolean air){
@Nullable Building findTarget(float x, float y, int total, float dps, float health, boolean checkWeight, boolean air, boolean naval){
if(total < data.team.rules().rtsMinSquad) return null;
//flag priority?
@@ -282,8 +284,13 @@ public class RtsAI{
//2. factory
//3. core
targets.clear();
for(var flag : flags){
targets.addAll(Vars.indexer.getEnemy(data.team, flag));
if(naval){
//naval units can only target enemy cores, because those are assumed to always be reachable. other blocks may not be!
targets.addAll(Vars.indexer.getEnemy(data.team, BlockFlag.core));
}else{
for(var flag : flags){
targets.addAll(Vars.indexer.getEnemy(data.team, flag));
}
}
targets.removeAll(b -> assignedTargets.contains(b.id) || invalidTarget.contains(b.pos()));
+1 -1
View File
@@ -158,7 +158,7 @@ public class UnitGroup{
}
private void updateRaycast(int index, Vec2 dest, Vec2 v1){
if(collisionLayer != PhysicsProcess.layerFlying){
if(collisionLayer != PhysicsProcess.layerFlying && originalPositions != null && positions != null){
//coordinates in world space
float
+1 -1
View File
@@ -41,7 +41,7 @@ public class FlyingAI extends AIController{
Building closest = null;
float cdist = 0f;
for(Building t : list){
if((t.items != null && t.items.any()) || t.status() != BlockStatus.noInput){
if(((t.items != null && t.items.any()) || t.status() != BlockStatus.noInput) && t.block.targetable){
float dst = t.dst2(x, y);
if(closest == null || dst < cdist){
closest = t;
+1 -5
View File
@@ -3437,7 +3437,6 @@ public class Blocks{
hitEffect = Fx.hitLancer;
despawnEffect = Fx.none;
status = StatusEffects.shocked;
statusDuration = 10f;
hittable = false;
lightColor = Color.white;
collidesAir = false;
@@ -3489,7 +3488,6 @@ public class Blocks{
despawnEffect = Fx.blastExplosion;
status = StatusEffects.blasted;
statusDuration = 60f;
hitColor = backColor = trailColor = Pal.blastAmmoBack;
frontColor = Pal.blastAmmoFront;
@@ -3915,7 +3913,6 @@ public class Blocks{
collidesGround = true;
status = StatusEffects.blasted;
statusDuration = 60f;
backColor = hitColor = trailColor = Pal.blastAmmoBack;
frontColor = Pal.blastAmmoFront;
@@ -4385,6 +4382,7 @@ public class Blocks{
targetInterval = 5f;
newTargetInterval = 30f;
targetUnderBlocks = false;
shootY = 8f;
float r = range = 130f;
@@ -4421,7 +4419,6 @@ public class Blocks{
);
scaledHealth = 210;
shootY = 7f;
size = 3;
researchCost = with(Items.tungsten, 400, Items.silicon, 400, Items.oxide, 80, Items.beryllium, 800);
@@ -5455,7 +5452,6 @@ public class Blocks{
hitEffect = Fx.hitLancer;
despawnEffect = Fx.none;
status = StatusEffects.shocked;
statusDuration = 10f;
hittable = false;
lightColor = Color.white;
buildingDamageMultiplier = 0.25f;
@@ -111,7 +111,7 @@ public class SectorPresets{
}};
fungalPass = new SectorPreset("fungalPass", serpulo, 21){{
difficulty = 4;
difficulty = 2;
}};
infestedCanyons = new SectorPreset("infestedCanyons", serpulo, 210){{
+50 -23
View File
@@ -3829,8 +3829,10 @@ public class UnitTypes{
engineSize = 4.8f;
engineOffset = 61 / 4f;
range = 4.3f * 60f * 1.4f;
abilities.add(new SuppressionFieldAbility(){{
reload = 60f * 8f;
orbRadius = 5.3f;
y = 1f;
}});
@@ -3846,36 +3848,59 @@ public class UnitTypes{
recoil = 1f;
rotationLimit = 60f;
bullet = new BulletType(){{
bullet = new BasicBulletType(4.3f, 70f, "missile-large"){{
shootEffect = Fx.shootBig;
smokeEffect = Fx.shootBigSmoke2;
shake = 1f;
speed = 0f;
lifetime = 60 * 0.496f;
rangeOverride = 361.2f;
followAimSpeed = 5f;
width = 12f;
height = 22f;
hitSize = 7f;
hitColor = backColor = trailColor = Pal.sapBulletBack;
trailWidth = 3f;
trailLength = 12;
hitEffect = despawnEffect = Fx.hitBulletColor;
keepVelocity = false;
collidesGround = true;
collidesAir = false;
spawnUnit = new MissileUnitType("quell-missile"){{
targetAir = false;
speed = 4.3f;
maxRange = 6f;
lifetime = 60f * 1.4f;
outlineColor = Pal.darkOutline;
engineColor = trailColor = Pal.sapBulletBack;
engineLayer = Layer.effect;
health = 45;
loopSoundVolume = 0.1f;
//workaround to get the missile to behave like in spawnUnit while still spawning on death
fragRandomSpread = 0;
fragBullets = 1;
fragVelocityMin = 1f;
fragOffsetMax = 1f;
weapons.add(new Weapon(){{
shootSound = Sounds.none;
shootCone = 360f;
mirror = false;
reload = 1f;
shootOnDeath = true;
bullet = new ExplosionBulletType(110f, 25f){{
shootEffect = Fx.massiveExplosion;
collidesAir = false;
}};
}});
fragBullet = new BulletType(){{
speed = 0f;
keepVelocity = false;
collidesAir = false;
spawnUnit = new MissileUnitType("quell-missile"){{
targetAir = false;
speed = 4.3f;
maxRange = 6f;
lifetime = 60f * (1.4f - 0.496f);
outlineColor = Pal.darkOutline;
engineColor = trailColor = Pal.sapBulletBack;
engineLayer = Layer.effect;
health = 45;
loopSoundVolume = 0.1f;
weapons.add(new Weapon() {{
shootSound = Sounds.none;
shootCone = 360f;
mirror = false;
reload = 1f;
shootOnDeath = true;
bullet = new ExplosionBulletType(110f, 25f) {{
shootEffect = Fx.massiveExplosion;
collidesAir = false;
}};
}});
}};
}};
}};
}});
@@ -3909,6 +3934,8 @@ public class UnitTypes{
int parts = 10;
abilities.add(new SuppressionFieldAbility(){{
reload = 60 * 15f;
range = 320f;
orbRadius = orbRad;
particleSize = partRad;
y = 10f;
+11 -1
View File
@@ -156,6 +156,16 @@ public class Logic implements ApplicationListener{
if(!net.client() && e.sector == state.getSector() && e.sector.isBeingPlayed()){
state.rules.waveTeam.data().destroyToDerelict();
}
if(!net.client() && e.sector.planet.generator != null){
e.sector.planet.generator.onSectorCaptured(e.sector);
}
});
Events.on(SectorLoseEvent.class, e -> {
if(!net.client() && e.sector.planet.generator != null){
e.sector.planet.generator.onSectorLost(e.sector);
}
});
Events.on(BlockDestroyEvent.class, e -> {
@@ -462,7 +472,7 @@ public class Logic implements ApplicationListener{
if(rules.fillItems && data.cores.size > 0){
var core = data.cores.first();
content.items().each(i -> {
if(i.isOnPlanet(Vars.state.getPlanet())){
if(i.isOnPlanet(Vars.state.getPlanet()) && !i.isHidden()){
core.items.set(i, core.getMaximumAccepted(i));
}
});
@@ -64,6 +64,9 @@ public class DrawOperation{
Block block = content.block(to);
tile.setBlock(block, tile.team(), tile.build == null ? 0 : tile.build.rotation);
if(tile.build != null){
tile.build.enabled = true;
}
tile.getLinkedTiles(t -> editor.renderer.updatePoint(t.x, t.y));
}else if(type == OpType.rotation.ordinal()){
+11 -9
View File
@@ -222,38 +222,38 @@ public class Damage{
public static float collideLaser(Bullet b, float length, boolean large, boolean laser, int pierceCap){
float resultLength = findPierceLength(b, pierceCap, laser, length);
collideLine(b, b.team, b.type.hitEffect, b.x, b.y, b.rotation(), resultLength, large, laser, pierceCap);
collideLine(b, b.team, b.x, b.y, b.rotation(), resultLength, large, laser, pierceCap);
b.fdata = resultLength;
return resultLength;
}
public static void collideLine(Bullet hitter, Team team, Effect effect, float x, float y, float angle, float length){
collideLine(hitter, team, effect, x, y, angle, length, false);
public static void collideLine(Bullet hitter, Team team, float x, float y, float angle, float length){
collideLine(hitter, team, x, y, angle, length, false);
}
/**
* Damages entities in a line.
* Only enemies of the specified team are damaged.
*/
public static void collideLine(Bullet hitter, Team team, Effect effect, float x, float y, float angle, float length, boolean large){
collideLine(hitter, team, effect, x, y, angle, length, large, true);
public static void collideLine(Bullet hitter, Team team, float x, float y, float angle, float length, boolean large){
collideLine(hitter, team, x, y, angle, length, large, true);
}
/**
* Damages entities in a line.
* Only enemies of the specified team are damaged.
*/
public static void collideLine(Bullet hitter, Team team, Effect effect, float x, float y, float angle, float length, boolean large, boolean laser){
collideLine(hitter, team, effect, x, y, angle, length, large, laser, -1);
public static void collideLine(Bullet hitter, Team team, float x, float y, float angle, float length, boolean large, boolean laser){
collideLine(hitter, team, x, y, angle, length, large, laser, -1);
}
/**
* Damages entities in a line.
* Only enemies of the specified team are damaged.
*/
public static void collideLine(Bullet hitter, Team team, Effect effect, float x, float y, float angle, float length, boolean large, boolean laser, int pierceCap){
public static void collideLine(Bullet hitter, Team team, float x, float y, float angle, float length, boolean large, boolean laser, int pierceCap){
length = findLength(hitter, length, laser, pierceCap);
hitter.fdata = length;
@@ -545,8 +545,10 @@ public class Damage{
tileDamage(team, x, y, baseRadius, damage, null);
}
public static void tileDamage(Team team, int x, int y, float baseRadius, float damage, @Nullable Bullet source){
public static void tileDamage(Team team, int tx, int ty, float baseRadius, float damage, @Nullable Bullet source){
Time.run(0f, () -> {
int x = Mathf.clamp(tx, -100, world.width() + 100), y = Mathf.clamp(ty, -100, world.height() + 100);
var in = world.build(x, y);
//spawned inside a multiblock. this means that damage needs to be dealt directly.
//why? because otherwise the building would absorb everything in one cell, which means much less damage than a nearby explosion.
@@ -17,6 +17,7 @@ public class SuppressionFieldAbility extends Ability{
protected static Rand rand = new Rand();
public float reload = 60f * 1.5f;
public float maxDelay = 60f * 1.5f;
public float range = 200f;
public float orbRadius = 4.1f, orbMidScl = 0.33f, orbSinScl = 8f, orbSinMag = 1f;
@@ -55,9 +56,9 @@ public class SuppressionFieldAbility extends Ability{
public void update(Unit unit){
if(!active) return;
if((timer += Time.delta) >= reload){
if((timer += Time.delta) >= maxDelay){
Tmp.v1.set(x, y).rotate(unit.rotation - 90f).add(unit);
Damage.applySuppression(unit.team, Tmp.v1.x, Tmp.v1.y, range, reload, reload, applyParticleChance, unit, effectColor);
Damage.applySuppression(unit.team, Tmp.v1.x, Tmp.v1.y, range, reload, maxDelay, applyParticleChance, unit, effectColor);
timer = 0f;
}
}
@@ -85,7 +85,7 @@ public class ContinuousBulletType extends BulletType{
if(timescaleDamage && b.owner instanceof Building build){
b.damage *= build.timeScale();
}
Damage.collideLine(b, b.team, hitEffect, b.x, b.y, b.rotation(), currentLength(b), largeHit, laserAbsorb, pierceCap);
Damage.collideLine(b, b.team, b.x, b.y, b.rotation(), currentLength(b), largeHit, laserAbsorb, pierceCap);
b.damage = damage;
}
@@ -55,13 +55,13 @@ public class ContinuousLaserBulletType extends ContinuousBulletType{
float ellipseLenScl = Mathf.lerp(1 - i / (float)(colors.length), 1f, pointyScaling);
Lines.stroke(stroke);
Lines.lineAngle(b.x, b.y, rot, realLength - frontLength, false);
Lines.lineAngle(b.x, b.y, rot, Math.max(0, realLength - frontLength), false);
//back ellipse
Drawf.flameFront(b.x, b.y, divisions, rot + 180f, backLength, stroke / 2f);
//front ellipse
Tmp.v1.trnsExact(rot, realLength - frontLength);
Tmp.v1.trnsExact(rot, Math.max(0, realLength - frontLength));
Drawf.flameFront(b.x + Tmp.v1.x, b.y + Tmp.v1.y, divisions, rot, frontLength * ellipseLenScl, stroke / 2f);
}
@@ -4,8 +4,10 @@ import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.math.*;
import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.world.blocks.distribution.MassDriver.*;
import static mindustry.Vars.*;
@@ -89,5 +91,17 @@ public class MassDriverBolt extends BasicBulletType{
public void hit(Bullet b, float hitx, float hity){
super.hit(b, hitx, hity);
despawned(b);
if(b.data() instanceof DriverBulletData data){
float explosiveness = 0f;
float flammability = 0f;
float power = 0f;
for(int i = 0; i < data.items.length; i++){
Item item = content.item(i);
explosiveness += item.explosiveness * data.items[i];
flammability += item.flammability * data.items[i];
power += item.charge * Mathf.pow(data.items[i], 1.1f) * 25f;
}
Damage.dynamicExplosion(b.x, b.y, flammability / 10f, explosiveness / 10f, power, 1f, state.rules.damageExplosions);
}
}
}
@@ -59,7 +59,7 @@ public class RailBulletType extends BulletType{
super.init(b);
b.fdata = length;
Damage.collideLine(b, b.team, b.type.hitEffect, b.x, b.y, b.rotation(), length, false, false, pierceCap);
Damage.collideLine(b, b.team, b.x, b.y, b.rotation(), length, false, false, pierceCap);
float resultLen = b.fdata;
Vec2 nor = Tmp.v1.trns(b.rotation(), 1f).nor();
@@ -35,7 +35,7 @@ import static mindustry.logic.GlobalVars.*;
@Component(base = true)
abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, Itemsc, Rotc, Unitc, Weaponsc, Drawc, Syncc, Shieldc, Displayable, Ranged, Minerc, Builderc, Senseable, Settable{
private static final Vec2 tmp1 = new Vec2(), tmp2 = new Vec2();
static final float warpDst = 20f;
static final float warpDst = 8f;
@Import boolean dead, disarmed;
@Import float x, y, rotation, maxHealth, drag, armor, hitSize, health, shield, ammo, dragMultiplier, armorOverride, speedMultiplier;
@@ -643,11 +643,11 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
//repel unit out of bounds
if(x < left) dx += (-(x - left)/warpDst);
if(y < bot) dy += (-(y - bot)/warpDst);
if(x > right) dx -= (x - right)/warpDst;
if(y > top) dy -= (y - top)/warpDst;
if(x > right - tilesize) dx -= (x - (right - tilesize))/warpDst;
if(y > top - tilesize) dy -= (y - (top - tilesize))/warpDst;
velAddNet(dx * Time.delta, dy * Time.delta);
float margin = tilesize * 2f;
float margin = tilesize * 1f;
x = Mathf.clamp(x, left - margin, right - tilesize + margin);
y = Mathf.clamp(y, bot - margin, top - tilesize + margin);
}
@@ -21,8 +21,6 @@ public class BuildPlan implements Position, QuadTreeObject{
public boolean breaking;
/** Config int. Not used unless hasConfig is true.*/
public Object config;
/** Original position, only used in schematics.*/
public int originalX, originalY, originalWidth, originalHeight;
/** Last progress.*/
public float progress;
@@ -65,6 +63,7 @@ public class BuildPlan implements Position, QuadTreeObject{
public BuildPlan(){
}
public boolean placeable(Team team){
return Build.validPlace(block, team, x, y, rotation);
}
@@ -111,22 +110,12 @@ public class BuildPlan implements Position, QuadTreeObject{
copy.block = block;
copy.breaking = breaking;
copy.config = config;
copy.originalX = originalX;
copy.originalY = originalY;
copy.progress = progress;
copy.initialized = initialized;
copy.animScale = animScale;
return copy;
}
public BuildPlan original(int x, int y, int originalWidth, int originalHeight){
originalX = x;
originalY = y;
this.originalWidth = originalWidth;
this.originalHeight = originalHeight;
return this;
}
public Rect bounds(Rect rect){
if(breaking){
return rect.set(-100f, -100f, 0f, 0f);
+1 -2
View File
@@ -119,8 +119,7 @@ public final class FogControl implements CustomChunk{
var data = data(team);
if(data == null) return false;
if(x < 0 || y < 0 || x >= ww || y >= wh) return false;
return data.read.get(x + y * ww);
return data.read.get(Mathf.clamp(x, 0, ww - 1) + Mathf.clamp(y, 0, wh - 1) * ww);
}
public void resetFog(){
+31 -44
View File
@@ -3,6 +3,7 @@ package mindustry.game;
import arc.*;
import arc.func.*;
import arc.graphics.*;
import arc.graphics.Texture.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.math.geom.*;
@@ -98,7 +99,7 @@ public class MapObjectives implements Iterable<MapObjective>, Eachable<MapObject
}
}
public static void registerLegacyMarker(String name, Prov<? extends ObjectiveMarker> prov) {
public static void registerLegacyMarker(String name, Prov<? extends ObjectiveMarker> prov){
Class<?> type = prov.get().getClass();
markerNameToType.put(name, prov);
@@ -663,7 +664,7 @@ public class MapObjectives implements Iterable<MapObjective>, Eachable<MapObject
}
}
/** Marker used for drawing various content to indicate something along with an objective. Mostly used as UI overlay. */
/** Marker used for drawing various content to indicate something along with an objective. Mostly used as UI overlay. */
public static abstract class ObjectiveMarker{
/** Internal use only! Do not access. */
public transient int arrayIndex;
@@ -714,7 +715,7 @@ public class MapObjectives implements Iterable<MapObjective>, Eachable<MapObject
state.mapLocales.getProperty(key + ".mobile") :
state.mapLocales.containsProperty(key) ?
state.mapLocales.getProperty(key) :
Core.bundle.get(key);
Core.bundle.get(key + ".mobile", Core.bundle.get(key));
}else{
out =
state.mapLocales.containsProperty(key) ?
@@ -822,13 +823,8 @@ public class MapObjectives implements Iterable<MapObjective>, Eachable<MapObject
switch(type){
case fontSize -> fontSize = (float)p1;
case textHeight -> textHeight = (float)p1;
case labelFlags -> {
if(!Mathf.equal((float)p1, 0f)){
flags |= WorldLabel.flagBackground;
}else{
flags &= ~WorldLabel.flagBackground;
}
}
case outline -> flags = (byte)Pack.bitmask(flags, WorldLabel.flagOutline, !Mathf.equal((float)p1, 0f));
case labelFlags -> flags = (byte)Pack.bitmask(flags, WorldLabel.flagBackground, !Mathf.equal((float)p1, 0f));
case radius -> radius = (float)p1;
case rotation -> rotation = (float)p1;
case color -> color.fromDouble(p1);
@@ -838,13 +834,7 @@ public class MapObjectives implements Iterable<MapObjective>, Eachable<MapObject
if(!Double.isNaN(p2)){
switch(type){
case labelFlags -> {
if(!Mathf.equal((float)p2, 0f)){
flags |= WorldLabel.flagOutline;
}else{
flags &= ~WorldLabel.flagOutline;
}
}
case labelFlags -> flags = (byte)Pack.bitmask(flags, WorldLabel.flagOutline, !Mathf.equal((float)p2, 0f));
}
}
}
@@ -944,7 +934,7 @@ public class MapObjectives implements Iterable<MapObjective>, Eachable<MapObject
Lines.poly(pos.x, pos.y, sides, (radius + 1f) * scaleFactor, rotation + startAngle, rotation + endAngle);
}else{
Draw.color(color);
if (startAngle < endAngle){
if(startAngle < endAngle){
Fill.arc(pos.x, pos.y, radius * scaleFactor, (endAngle - startAngle) / 360f, rotation + startAngle, sides);
}else{
Fill.arc(pos.x, pos.y, radius * scaleFactor, (startAngle - endAngle) / 360f, rotation + endAngle, sides);
@@ -962,6 +952,7 @@ public class MapObjectives implements Iterable<MapObjective>, Eachable<MapObject
switch(type){
case radius -> radius = (float)p1;
case stroke -> stroke = (float)p1;
case outline -> outline = !Mathf.equal((float)p1, 0f);
case rotation -> rotation = (float)p1;
case color -> color.fromDouble(p1);
case shape -> sides = (int)p1;
@@ -1025,25 +1016,14 @@ public class MapObjectives implements Iterable<MapObjective>, Eachable<MapObject
if(!Double.isNaN(p1)){
switch(type){
case fontSize -> fontSize = (float)p1;
case labelFlags -> {
if(!Mathf.equal((float)p1, 0f)){
flags |= WorldLabel.flagBackground;
}else{
flags &= ~WorldLabel.flagBackground;
}
}
case outline -> flags = (byte)Pack.bitmask(flags, WorldLabel.flagOutline, !Mathf.equal((float)p1, 0f));
case labelFlags -> flags = (byte)Pack.bitmask(flags, WorldLabel.flagBackground, !Mathf.equal((float)p1, 0f));
}
}
if(!Double.isNaN(p2)){
switch(type){
case labelFlags -> {
if(!Mathf.equal((float)p2, 0f)){
flags |= WorldLabel.flagOutline;
}else{
flags &= ~WorldLabel.flagOutline;
}
}
case labelFlags -> flags = (byte)Pack.bitmask(flags, WorldLabel.flagOutline, !Mathf.equal((float)p2, 0f));
}
}
}
@@ -1101,6 +1081,7 @@ public class MapObjectives implements Iterable<MapObjective>, Eachable<MapObject
case endPos -> endPos.x = (float)p1 * tilesize;
case stroke -> stroke = (float)p1;
case color -> color1.set(color2.fromDouble(p1));
case outline -> outline = !Mathf.equal((float)p1, 0f);
}
}
@@ -1111,7 +1092,7 @@ public class MapObjectives implements Iterable<MapObjective>, Eachable<MapObject
}
if(!Double.isNaN(p1) && !Double.isNaN(p2)){
switch (type){
switch(type){
case posi -> ((int)p1 == 0 ? pos : (int)p1 == 1 ? endPos : Tmp.v1).x = (float)p2 * tilesize;
case colori -> ((int)p1 == 0 ? color1 : (int)p1 == 1 ? color2 : Tmp.c1).fromDouble(p2);
}
@@ -1199,7 +1180,7 @@ public class MapObjectives implements Iterable<MapObjective>, Eachable<MapObject
private transient TextureRegion fetchedRegion;
public QuadMarker() {
public QuadMarker(){
for(int i = 0; i < 4; i++){
vertices[i * 6 + 2] = Color.white.toFloatBits();
vertices[i * 6 + 5] = Color.clearFloatBits;
@@ -1250,7 +1231,7 @@ public class MapObjectives implements Iterable<MapObjective>, Eachable<MapObject
boolean firstUpdate = fetchedRegion == null;
if(fetchedRegion == null) fetchedRegion = new TextureRegion();
if(firstUpdate) fetchedRegion = new TextureRegion();
Tmp.tr1.set(fetchedRegion);
lookupRegion(textureName, fetchedRegion);
@@ -1258,21 +1239,22 @@ public class MapObjectives implements Iterable<MapObjective>, Eachable<MapObject
if(firstUpdate){
if(mapRegion){
mapRegion = false;
// possibly from the editor, we need to clamp the values
for(int i = 0; i < 4; i++){
vertices[i * 6 + 3] = Mathf.map(Mathf.clamp(vertices[i * 6 + 3]), fetchedRegion.u, fetchedRegion.u2);
vertices[i * 6 + 4] = Mathf.map(1 - Mathf.clamp(vertices[i * 6 + 4]), fetchedRegion.v, fetchedRegion.v2);
setUv(i, vertices[i * 6 + 3], vertices[i * 6 + 4]);
}
}
}else{
for(int i = 0; i < 4; i++){
vertices[i * 6 + 3] = Mathf.map(vertices[i * 6 + 3], Tmp.tr1.u, Tmp.tr1.u2, fetchedRegion.u, fetchedRegion.u2);
vertices[i * 6 + 4] = Mathf.map(vertices[i * 6 + 4], Tmp.tr1.v, Tmp.tr1.v2, fetchedRegion.v, fetchedRegion.v2);
setUv(i, unmap(vertices[i * 6 + 3], Tmp.tr1.u, Tmp.tr1.u2), 1 - unmap(vertices[i * 6 + 4], Tmp.tr1.v, Tmp.tr1.v2));
}
}
}
private static float unmap(float x, float from, float to){
if(Mathf.equal(from, to)) return x;
return (x - from) / (to - from);
}
private void setPos(int i, double x, double y){
if(i >= 0 && i < 4){
if(!Double.isNaN(x)) vertices[i * 6] = (float)x * tilesize;
@@ -1290,11 +1272,16 @@ public class MapObjectives implements Iterable<MapObjective>, Eachable<MapObject
if(i >= 0 && i < 4){
if(fetchedRegion == null) setTexture(textureName);
if(!Double.isNaN(u)) vertices[i * 6 + 3] = Mathf.map(Mathf.clamp((float)u), fetchedRegion.u, fetchedRegion.u2);
if(!Double.isNaN(v)) vertices[i * 6 + 4] = Mathf.map(1 - Mathf.clamp((float)v), fetchedRegion.v, fetchedRegion.v2);
if(!Double.isNaN(u)){
boolean clampU = fetchedRegion.texture.getUWrap() != TextureWrap.mirroredRepeat && fetchedRegion.texture.getUWrap() != TextureWrap.repeat;
vertices[i * 6 + 3] = Mathf.map(clampU ? Mathf.clamp((float)u) : (float)u, fetchedRegion.u, fetchedRegion.u2);
}
if(!Double.isNaN(v)){
boolean clampV = fetchedRegion.texture.getVWrap() != TextureWrap.mirroredRepeat && fetchedRegion.texture.getVWrap() != TextureWrap.repeat;
vertices[i * 6 + 4] = Mathf.map(clampV ? 1 - Mathf.clamp((float)v) : 1 - (float)v, fetchedRegion.v, fetchedRegion.v2);
}
}
}
}
private static void lookupRegion(String name, TextureRegion out){
+54 -20
View File
@@ -72,7 +72,32 @@ public class Saves{
lastSectorSave = saves.find(s -> s.isSector() && s.getName().equals(Core.settings.getString("last-sector-save", "<none>")));
ObjectSet<Sector> infoToClear = new ObjectSet<>(), remapped = new ObjectSet<>();
class Remap{
//file in the temp folder
Fi sourceFile;
//slot of source sector to move file for
SaveSlot slot;
Sector sourceSector;
//sector info from source sector to move into
SectorInfo sourceInfo;
//file to copy to
Fi destFile;
//destination sector to move to
Sector destSector;
Remap(SaveSlot slot, Fi sourceFile, Sector sourceSector, SectorInfo sourceInfo, Fi destFile, Sector destSector){
this.slot = slot;
this.sourceFile = sourceFile;
this.sourceSector = sourceSector;
this.sourceInfo = sourceInfo;
this.destFile = destFile;
this.destSector = destSector;
}
}
Seq<Remap> remaps = new Seq<>();
ObjectSet<Sector> remapped = new ObjectSet<>();
//automatically assign sector save slots
for(SaveSlot slot : saves){
@@ -102,22 +127,13 @@ public class Saves{
if(!slot.file.equals(getSectorFile(remapTarget))){
Log.info("Remapping sector: @ -> @ (@)", sector.id, remapTarget.id, remapTarget.preset);
sector.loadInfo();
//overwrite the target sector's info with the save's info
Core.settings.putJson(remapTarget.planet.name + "-s-" + remapTarget.id + "-info", sector.info);
remapTarget.loadInfo();
//queue a clear of the sector that had its data moved
infoToClear.add(sector);
//add to the remapped list (if it was remapped, don't clear it!)
remapped.add(remapTarget);
remapTarget.save = slot;
try{
Fi target = getSectorFile(remapTarget);
//move over save file
slot.file.moveTo(target);
slot.file = target;
SectorInfo info = Core.settings.getJson(sector.planet.name + "-s-" + sector.id + "-info", SectorInfo.class, SectorInfo::new);
Fi tmpRemapFile = saveDirectory.child("remap_" + sector.planet.name + "_" + sector.id + "." + saveExtension);
slot.file.moveTo(tmpRemapFile);
remaps.add(new Remap(slot, tmpRemapFile, sector, info, getSectorFile(remapTarget), remapTarget));
remapped.add(remapTarget);
}catch(Exception e){
Log.err("Failed to move sector files when remapping: " + sector.id + " -> " + remapTarget.id, e);
}
@@ -125,6 +141,7 @@ public class Saves{
remapTarget.save = slot;
slot.meta.rules.sector = remapTarget;
}else{
if(sector.save != null){
Log.warn("Sector @ has two corresponding saves: @ and @", sector, sector.save.file, slot.file);
@@ -134,10 +151,27 @@ public class Saves{
}
}
for(var sector : infoToClear){
if(!remapped.contains(sector)){
sector.clearInfo();
}
//process remaps later to allow swaps of sectors
for(var remap : remaps){
var remapTarget = remap.destSector;
//overwrite the target sector's info with the save's info
Core.settings.putJson(remapTarget.planet.name + "-s-" + remapTarget.id + "-info", remap.sourceInfo);
remapTarget.loadInfo();
remapTarget.save = remap.slot;
try{
//move file from tmp directory back into the correct location
remap.sourceFile.moveTo(remap.destFile);
remap.slot.file = remap.destFile;
}catch(Exception e){
Log.err("Failed to move back sector files when remapping: " + remap.sourceSector.id + " -> " + remapTarget.id, e);
}
//clear the info, assuming it wasn't a sector that got mapped to
if(!remapped.contains(remap.sourceSector)){
remap.sourceSector.clearInfo();
}
}
}
+2 -2
View File
@@ -97,7 +97,7 @@ public class Schematics implements Loadable{
all.sort();
if(shadowBuffer == null){
if(shadowBuffer == null && !headless){
Core.app.post(() -> shadowBuffer = new FrameBuffer(maxSchematicSize + padding + 8, maxSchematicSize + padding + 8));
}
}
@@ -275,7 +275,7 @@ public class Schematics implements Loadable{
/** Creates an array of build plans from a schematic's data, centered on the provided x+y coordinates. */
public Seq<BuildPlan> toPlans(Schematic schem, int x, int y){
return schem.tiles.map(t -> new BuildPlan(t.x + x - schem.width/2, t.y + y - schem.height/2, t.rotation, t.block, t.config).original(t.x, t.y, schem.width, schem.height))
return schem.tiles.map(t -> new BuildPlan(t.x + x - schem.width/2, t.y + y - schem.height/2, t.rotation, t.block, t.config))
.removeAll(s -> (!s.block.isVisible() && !(s.block instanceof CoreBlock)) || !s.block.unlockedNow()).sort(Structs.comparingInt(s -> -s.block.schematicPriority));
}
+15
View File
@@ -73,6 +73,8 @@ public class SectorInfo{
public float secondsPassed;
/** How many minutes this sector has been captured. */
public float minutesCaptured;
/** Light coverage in terms of radius. */
public float lightCoverage;
/** Display name. */
public @Nullable String name;
/** Displayed icon. */
@@ -225,6 +227,15 @@ public class SectorInfo{
damage = 0;
hasSpawns = spawner.countSpawns() > 0;
lightCoverage = 0f;
for(var build : state.rules.defaultTeam.data().buildings){
if(build.block.emitLight){
lightCoverage += build.block.lightRadius * build.efficiency;
}
}
lightCoverage += state.rules.defaultTeam.data().units.sumf(u -> u.type.lightRadius/2f);
//cap production at raw production.
production.each((item, stat) -> {
stat.mean = Math.min(stat.mean, rawProduction.get(item, ExportStat::new).mean);
@@ -242,6 +253,10 @@ public class SectorInfo{
if(sector.planet.allowWaveSimulation){
SectorDamage.writeParameters(sector);
}
if(sector.planet.generator != null){
sector.planet.generator.beforeSaveWrite(sector);
}
}
/** Update averages of various stats, updates some special sector logic.
+7
View File
@@ -322,6 +322,13 @@ public class Universe{
return net.client() ? netSeconds : seconds;
}
public void setSeconds(float seconds){
this.seconds = (int)seconds;
this.secondCounter = seconds - this.seconds;
save();
}
public float secondsf(){
return seconds() + secondCounter;
}
@@ -32,7 +32,7 @@ public class LoadRenderer implements Disposable{
private float testprogress = 0f;
private StringBuilder assetText = new StringBuilder();
private Bar[] bars;
private Mesh mesh = MeshBuilder.buildHex(colorRed, 2, true, 1f);
private Mesh mesh = MeshBuilder.buildPlanetGrid(PlanetGrid.create(2), colorRed, 1f);
private Camera3D cam = new Camera3D();
private int lastLength = -1;
private FxProcessor fx;
+2
View File
@@ -109,6 +109,7 @@ public class Shaders{
public Color ambientColor = Color.white.cpy();
public Vec3 camDir = new Vec3();
public Vec3 camPos = new Vec3();
public boolean emissive;
public Planet planet;
public PlanetShader(){
@@ -123,6 +124,7 @@ public class Shaders{
setUniformf("u_ambientColor", ambientColor.r, ambientColor.g, ambientColor.b);
setUniformf("u_camdir", camDir);
setUniformf("u_campos", renderer.planets.cam.position);
setUniformf("u_emissive", emissive ? 1f : 0f);
}
}
@@ -1,7 +1,8 @@
package mindustry.graphics.g3d;
import arc.math.geom.*;
import arc.util.*;
public interface GenericMesh{
public interface GenericMesh extends Disposable{
void render(PlanetParams params, Mat3D projection, Mat3D transform);
}
+3 -2
View File
@@ -8,11 +8,11 @@ import mindustry.type.*;
public class HexMesh extends PlanetMesh{
public HexMesh(Planet planet, int divisions){
super(planet, MeshBuilder.buildHex(planet.generator, divisions, false, planet.radius, 0.2f), Shaders.planet);
super(planet, MeshBuilder.buildHex(planet.generator, divisions, planet.radius, 0.2f), Shaders.planet);
}
public HexMesh(Planet planet, HexMesher mesher, int divisions, Shader shader){
super(planet, MeshBuilder.buildHex(mesher, divisions, false, planet.radius, 0.2f), shader);
super(planet, MeshBuilder.buildHex(mesher, divisions, planet.radius, 0.2f), shader);
}
public HexMesh(){
@@ -21,6 +21,7 @@ public class HexMesh extends PlanetMesh{
@Override
public void preRender(PlanetParams params){
Shaders.planet.planet = planet;
Shaders.planet.emissive = planet.generator != null && planet.generator.isEmissive();
Shaders.planet.lightDir.set(planet.solarSystem.position).sub(planet.position).rotate(Vec3.Y, planet.getRotation()).nor();
Shaders.planet.ambientColor.set(planet.solarSystem.lightColor);
}
+17 -2
View File
@@ -5,8 +5,23 @@ import arc.math.geom.*;
/** Defines color and height for a planet mesh. */
public interface HexMesher{
float getHeight(Vec3 position);
Color getColor(Vec3 position);
default float getHeight(Vec3 position){
return 0f;
}
default void getColor(Vec3 position, Color out){
}
default void getEmissiveColor(Vec3 position, Color out){
}
default boolean isEmissive(){
return false;
}
default boolean skip(Vec3 position){
return false;
}
@@ -21,15 +21,15 @@ public class HexSkyMesh extends PlanetMesh{
}
@Override
public Color getColor(Vec3 position){
return color;
public void getColor(Vec3 position, Color out){
out.set(color);
}
@Override
public boolean skip(Vec3 position){
return Simplex.noise3d(7 + seed, octaves, persistence, scl, position.x, position.y * 3f, position.z) >= thresh;
}
}, divisions, false, planet.radius, radius), Shaders.clouds);
}, divisions, planet.radius, radius), Shaders.clouds);
this.speed = speed;
}
@@ -19,4 +19,9 @@ public class MatMesh implements GenericMesh{
public void render(PlanetParams params, Mat3D projection, Mat3D transform){
mesh.render(params, projection, tmp.set(transform).mul(mat));
}
@Override
public void dispose(){
mesh.dispose();
}
}
+198 -82
View File
@@ -1,56 +1,72 @@
package mindustry.graphics.g3d;
import arc.*;
import arc.graphics.*;
import arc.math.geom.*;
import arc.struct.*;
import mindustry.graphics.g3d.PlanetGrid.*;
import mindustry.maps.generators.*;
public class MeshBuilder{
private static final Vec3 v1 = new Vec3(), v2 = new Vec3(), v3 = new Vec3(), v4 = new Vec3();
private static final float[] floats = new float[3 + 3 + 1];
private static Mesh mesh;
public static Mesh buildIcosphere(int divisions, float radius, Color color){
begin(20 * (2 << (2 * divisions - 1)) * 3);
private static final boolean gl30 = Core.gl30 != null;
private static volatile float[] tmpHeights = new float[14580]; //highest amount of corners in vanilla
/** Note that the resulting icosphere does not have normals or a color. */
public static Mesh buildIcosphere(int divisions, float radius){
MeshResult result = Icosphere.create(divisions);
for(int i = 0; i < result.indices.size; i+= 3){
v1.set(result.vertices.items, result.indices.items[i] * 3).setLength(radius);
v2.set(result.vertices.items, result.indices.items[i + 1] * 3).setLength(radius);
v3.set(result.vertices.items, result.indices.items[i + 2] * 3).setLength(radius);
verts(v1, v3, v2, normal(v1, v2, v3).scl(-1f), color);
Mesh mesh = begin(result.vertices.size / 3, result.indices.size, false, false);
if(result.vertices.size >= 65535) throw new RuntimeException("Due to index size limits, only meshes with a maximum of 65535 vertices are supported. If you want more than that, make your own non-indexed mesh builder.");
float[] items = result.vertices.items;
for(int i = 0; i < result.vertices.size; i ++){
items[i] *= radius;
}
return end();
}
mesh.getVerticesBuffer().put(items, 0, result.vertices.size);
public static Mesh buildIcosphere(int divisions, float radius){
return buildIcosphere(divisions, radius, Color.white);
short[] indices = new short[result.indices.size];
for(int i = 0; i < result.indices.size; i++){
indices[i] = (short)result.indices.items[i];
}
mesh.getIndicesBuffer().put(indices);
return end(mesh);
}
public static Mesh buildPlanetGrid(PlanetGrid grid, Color color, float scale){
int total = 0;
for(Ptile tile : grid.tiles){
total += tile.corners.length * 2;
}
Mesh mesh = begin(grid.tiles.length * 12, 0, false, false);
float col = color.toFloatBits();
float[] floats = new float[8];
begin(total);
for(Ptile tile : grid.tiles){
Corner[] c = tile.corners;
for(int i = 0; i < c.length; i++){
Vec3 a = v1.set(c[i].v).scl(scale);
Vec3 b = v2.set(c[(i + 1) % c.length].v).scl(scale);
vert(a, Vec3.Z, color);
vert(b, Vec3.Z, color);
for(int i = 0; i < c.length; i++){
Vec3 v1 = c[i].v;
Vec3 v2 = c[(i + 1) % c.length].v;
floats[0] = v1.x * scale;
floats[1] = v1.y * scale;
floats[2] = v1.z * scale;
floats[3] = col;
floats[4] = v2.x * scale;
floats[5] = v2.y * scale;
floats[6] = v2.z * scale;
floats[7] = col;
mesh.getVerticesBuffer().put(floats);
}
}
return end();
return end(mesh);
}
public static Mesh buildHex(Color color, int divisions, boolean lines, float radius){
public static Mesh buildHex(Color color, int divisions, float radius){
return buildHex(new HexMesher(){
@Override
public float getHeight(Vec3 position){
@@ -58,20 +74,46 @@ public class MeshBuilder{
}
@Override
public Color getColor(Vec3 position){
return color;
public void getColor(Vec3 position, Color out){
out.set(color);
}
}, divisions, lines, radius, 0);
}, divisions, radius, 0);
}
public static Mesh buildHex(HexMesher mesher, int divisions, boolean lines, float radius, float intensity){
//TODO: in principle this should not be synchronized, but I would rather not realloc tmpHeights every time, and it is unlikely that two planets will be reloading at the same time
public static synchronized Mesh buildHex(HexMesher mesher, int divisions, float radius, float intensity){
PlanetGrid grid = PlanetGrid.create(divisions);
//TODO: this is NOT thread safe, but in practice, it should never cause a problem
if(mesher instanceof PlanetGenerator generator){
generator.seed = generator.baseSeed;
}
begin(grid.tiles.length * 12);
boolean emit = mesher.isEmissive();
if(grid.tiles.length * 6 >= 65535) throw new RuntimeException("Due to index size limits, only meshes with a maximum of 65535 vertices are supported. If you want more than that, make your own non-indexed mesh builder.");
Mesh mesh = begin(grid.tiles.length * 6, grid.tiles.length * 4 * 3, true, emit);
float[] heights;
if(tmpHeights == null || tmpHeights.length < grid.corners.length){
heights = tmpHeights = new float[grid.corners.length];
}else{
heights = tmpHeights;
}
//cache heights in an array to prevent redundant calls to getHeight
for(int i = 0; i < grid.corners.length; i++){
heights[i] = (1f + mesher.getHeight(grid.corners[i].v) * intensity) * radius;
}
int position = 0;
short[] shorts = new short[12];
float[] floats = new float[3 + (gl30 ? 1 : 3) + 1 + (emit ? 1 : 0)];
Vec3 nor = new Vec3();
Color tmpCol = new Color();
for(Ptile tile : grid.tiles){
if(mesher.skip(tile.v)){
@@ -80,81 +122,155 @@ public class MeshBuilder{
Corner[] c = tile.corners;
for(Corner corner : c){
corner.v.setLength((1f + mesher.getHeight(v2.set(corner.v)) * intensity) * radius);
float
h1 = heights[c[0].id],
h2 = heights[c[2].id],
h3 = heights[c[4].id];
Vec3
v1 = c[0].v,
v2 = c[2].v,
v3 = c[4].v;
normal(
v1.x * h1, v1.y * h1, v1.z * h1,
v2.x * h2, v2.y * h2, v2.z * h2,
v3.x * h3, v3.y * h3, v3.z * h3,
nor);
tmpCol.set(1f, 1f, 1f, 1f);
mesher.getColor(tile.v, tmpCol);
float color = tmpCol.toFloatBits();
float emissive = 0f;
if(emit){
tmpCol.set(0f, 0f, 0f, 0f);
mesher.getEmissiveColor(tile.v, tmpCol);
emissive = tmpCol.toFloatBits();
}
Vec3 nor = normal(c[0].v, c[2].v, c[4].v);
Color color = mesher.getColor(v2.set(tile.v));
for(var corner : c){
float height = heights[corner.id];
if(lines){
nor.set(1f, 1f, 1f);
for(int i = 0; i < c.length; i++){
Vec3 v1 = c[i].v;
Vec3 v2 = c[(i + 1) % c.length].v;
vert(v1, nor, color);
vert(v2, nor, color);
}
}else{
verts(c[0].v, c[1].v, c[2].v, nor, color);
verts(c[0].v, c[2].v, c[3].v, nor, color);
verts(c[0].v, c[3].v, c[4].v, nor, color);
if(c.length > 5){
verts(c[0].v, c[4].v, c[5].v, nor, color);
}
vert(mesh, floats, corner.v.x * height, corner.v.y * height, corner.v.z * height, nor, color, emissive);
}
//restore mutated corners
for(Corner corner : c){
corner.v.nor();
shorts[0] = (short)(position);
shorts[1] = (short)(position + 1);
shorts[2] = (short)(position + 2);
shorts[3] = (short)(position);
shorts[4] = (short)(position + 2);
shorts[5] = (short)(position + 3);
shorts[6] = (short)(position);
shorts[7] = (short)(position + 3);
shorts[8] = (short)(position + 4);
if(c.length > 5){
shorts[9] = (short)(position);
shorts[10] = (short)(position + 4);
shorts[11] = (short)(position + 5);
}
mesh.getIndicesBuffer().put(shorts, 0, c.length > 5 ? 12 : 9);
position += c.length;
}
return end();
return end(mesh);
}
private static void begin(int count){
mesh = new Mesh(true, count, 0,
VertexAttribute.position3,
VertexAttribute.normal,
VertexAttribute.color
private static Mesh begin(int vertices, int indices, boolean normal, boolean emissive){
Seq<VertexAttribute> attributes = Seq.with(
VertexAttribute.position3
);
if(normal){
//only GL30 supports GL_INT_2_10_10_10_REV
attributes.add(gl30 ? VertexAttribute.packedNormal : VertexAttribute.normal);
}
attributes.add(VertexAttribute.color);
if(emissive){
attributes.add(new VertexAttribute(4, GL20.GL_UNSIGNED_BYTE, true, "a_emissive"));
}
Mesh mesh = new Mesh(true, vertices, indices, attributes.toArray(VertexAttribute.class));
mesh.getVerticesBuffer().limit(mesh.getVerticesBuffer().capacity());
mesh.getVerticesBuffer().position(0);
if(indices > 0){
mesh.getIndicesBuffer().limit(mesh.getIndicesBuffer().capacity());
mesh.getIndicesBuffer().position(0);
}
return mesh;
}
private static Mesh end(){
Mesh last = mesh;
last.getVerticesBuffer().limit(last.getVerticesBuffer().position());
mesh = null;
return last;
private static Mesh end(Mesh mesh){
mesh.getVerticesBuffer().limit(mesh.getVerticesBuffer().position());
if(mesh.getNumIndices() > 0){
mesh.getIndicesBuffer().limit(mesh.getIndicesBuffer().position());
}
return mesh;
}
private static Vec3 normal(Vec3 v1, Vec3 v2, Vec3 v3){
return v4.set(v2).sub(v1).crs(v3.x - v1.x, v3.y - v1.y, v3.z - v1.z).nor();
private static Vec3 normal(Vec3 v1, Vec3 v2, Vec3 v3, Vec3 out){
return out.set(v2).sub(v1).crs(v3.x - v1.x, v3.y - v1.y, v3.z - v1.z).nor();
}
private static void verts(Vec3 a, Vec3 b, Vec3 c, Vec3 normal, Color color){
vert(a, normal, color);
vert(b, normal, color);
vert(c, normal, color);
private static void normal(float v1x, float v1y, float v1z, float v2x, float v2y, float v2z, float v3x, float v3y, float v3z, Vec3 out){
float
x = v2x - v1x,
y = v2y - v1y,
z = v2z - v1z,
vx = v3x - v1x,
vy = v3y - v1y,
vz = v3z - v1z;
float
cx = y * vz - z * vy,
cy = z * vx - x * vz,
cz = x * vy - y * vx;
out.set(cx, cy, cz).nor();
}
private static void vert(Vec3 a, Vec3 normal, Color color){
floats[0] = a.x;
floats[1] = a.y;
floats[2] = a.z;
private static void vert(Mesh mesh, float[] floats, float x, float y, float z, Vec3 normal, float color, float emissive){
floats[0] = x;
floats[1] = y;
floats[2] = z;
floats[3] = normal.x;
floats[4] = normal.y;
floats[5] = normal.z;
if(gl30){
floats[3] = packNormals(normal.x, normal.y, normal.z);
floats[4] = color;
if(floats.length > 5) floats[5] = emissive;
}else{
floats[3] = normal.x;
floats[4] = normal.x;
floats[5] = normal.x;
floats[6] = color;
if(floats.length > 7) floats[7] = emissive;
}
floats[6] = color.toFloatBits();
mesh.getVerticesBuffer().put(floats);
}
private static float packNormals(float x, float y, float z){
int xs = x < -1f/512f ? 1 : 0;
int ys = y < -1f/512f ? 1 : 0;
int zs = z < -1f/512f ? 1 : 0;
int vi =
zs << 29 | ((int)(z * 511 + (zs << 9)) & 511) << 20 |
ys << 19 | ((int)(y * 511 + (ys << 9)) & 511) << 10 |
xs << 9 | ((int)(x * 511 + (xs << 9)) & 511);
return Float.intBitsToFloat(vi);
}
}
@@ -15,4 +15,11 @@ public class MultiMesh implements GenericMesh{
v.render(params, projection, transform);
}
}
@Override
public void dispose(){
for(var mesh : meshes){
mesh.dispose();
}
}
}
@@ -18,10 +18,10 @@ public class NoiseMesh extends HexMesh{
}
@Override
public Color getColor(Vec3 position){
return color;
public void getColor(Vec3 position, Color out){
out.set(color);
}
}, divisions, false, radius, 0.2f);
}, divisions, radius, 0.2f);
}
/** Two-color variant. */
@@ -35,9 +35,9 @@ public class NoiseMesh extends HexMesh{
}
@Override
public Color getColor(Vec3 position){
return Simplex.noise3d(8 + seed, coct, cper, cscl, 5f + position.x, 5f + position.y, 5f + position.z) > cthresh ? color2 : color1;
public void getColor(Vec3 position, Color out){
out.set(Simplex.noise3d(8 + seed, coct, cper, cscl, 5f + position.x, 5f + position.y, 5f + position.z) > cthresh ? color2 : color1);
}
}, divisions, false, radius, 0.2f);
}, divisions, radius, 0.2f);
}
}
@@ -47,7 +47,7 @@ public class PlanetGrid{
}
}
public static PlanetGrid create(int size){
public static synchronized PlanetGrid create(int size){
//cache grids between calls, since only ~5 different grids total are needed
if(size < cache.length && cache[size] != null){
return cache[size];
@@ -240,6 +240,14 @@ public class PlanetGrid{
corners = new Corner[edgeCount];
edges = new Edge[edgeCount];
}
@Override
public String toString(){
return "Ptile{" +
"id=" + id +
" " + v +
'}';
}
}
public static class Corner{
@@ -26,6 +26,8 @@ public abstract class PlanetMesh implements GenericMesh{
@Override
public void render(PlanetParams params, Mat3D projection, Mat3D transform){
if(mesh.isDisposed()) return;
preRender(params);
shader.bind();
shader.setUniformMatrix4("u_proj", projection.val);
@@ -33,4 +35,9 @@ public abstract class PlanetMesh implements GenericMesh{
shader.apply();
mesh.render(shader, Gl.triangles);
}
@Override
public void dispose(){
mesh.dispose();
}
}
@@ -31,7 +31,7 @@ public class PlanetRenderer implements Disposable{
setThreshold(0.8f);
blurPasses = 6;
}};
public final Mesh atmosphere = MeshBuilder.buildHex(Color.white, 2, false, 1.5f);
public final Mesh atmosphere = MeshBuilder.buildHex(Color.white, 2, 1.5f);
//seed: 8kmfuix03fw
public final CubemapMesh skybox = new CubemapMesh(new Cubemap("cubemaps/stars/"));
+2 -3
View File
@@ -3,7 +3,6 @@ package mindustry.graphics.g3d;
import arc.graphics.*;
import arc.math.*;
import arc.math.geom.*;
import arc.util.*;
import arc.util.noise.*;
import mindustry.graphics.*;
import mindustry.type.*;
@@ -19,9 +18,9 @@ public class SunMesh extends HexMesh{
}
@Override
public Color getColor(Vec3 position){
public void getColor(Vec3 position, Color out){
double height = Math.pow(Simplex.noise3d(0, octaves, persistence, scl, position.x, position.y, position.z), pow) * mag;
return Tmp.c1.set(colors[Mathf.clamp((int)(height * colors.length), 0, colors.length - 1)]).mul(colorScale);
out.set(colors[Mathf.clamp((int)(height * colors.length), 0, colors.length - 1)]).mul(colorScale);
}
}, divisions, Shaders.unlit);
}
+26 -4
View File
@@ -56,6 +56,11 @@ public class DesktopInput extends InputHandler{
/** Time of most recent control group selection */
public long lastCtrlGroupSelectMillis;
/** Time of most recent payload pickup/drop key press*/
public long lastPayloadKeyTapMillis;
/** Time of most recent payload pickup/drop key hold*/
public long lastPayloadKeyHoldMillis;
private float buildPlanMouseOffsetX, buildPlanMouseOffsetY;
private boolean changedCursor;
@@ -425,10 +430,6 @@ public class DesktopInput extends InputHandler{
}
}
if(Core.input.keyRelease(Binding.select)){
player.shooting = false;
}
if(state.isGame() && !scene.hasDialog() && !scene.hasField()){
if(Core.input.keyTap(Binding.minimap)) ui.minimapfrag.toggle();
if(Core.input.keyTap(Binding.planetMap) && state.isCampaign()) ui.planet.toggle();
@@ -555,6 +556,10 @@ public class DesktopInput extends InputHandler{
changedCursor = false;
}
}
if(Core.input.keyRelease(Binding.select)){
player.shooting = false;
}
}
@Override
@@ -728,6 +733,7 @@ public class DesktopInput extends InputHandler{
mode = none;
}else if(!selectPlans.isEmpty()){
flushPlans(selectPlans);
movedPlan = true;
}else if(isPlacing()){
selectX = cursorX;
selectY = cursorY;
@@ -970,10 +976,26 @@ public class DesktopInput extends InputHandler{
if(unit instanceof Payloadc){
if(Core.input.keyTap(Binding.pickupCargo)){
tryPickupPayload();
lastPayloadKeyTapMillis = Time.millis();
}
if(Core.input.keyDown(Binding.pickupCargo)
&& Time.timeSinceMillis(lastPayloadKeyHoldMillis) > 20
&& Time.timeSinceMillis(lastPayloadKeyTapMillis) > 200){
tryPickupPayload();
lastPayloadKeyHoldMillis = Time.millis();
}
if(Core.input.keyTap(Binding.dropCargo)){
tryDropPayload();
lastPayloadKeyTapMillis = Time.millis();
}
if(Core.input.keyDown(Binding.dropCargo)
&& Time.timeSinceMillis(lastPayloadKeyHoldMillis) > 20
&& Time.timeSinceMillis(lastPayloadKeyTapMillis) > 200){
tryDropPayload();
lastPayloadKeyHoldMillis = Time.millis();
}
}
}
+9 -9
View File
@@ -1331,9 +1331,11 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
plans.each(plan -> {
if(plan.breaking) return;
float off = plan.block.size % 2 == 0 ? -0.5f : 0f;
plan.pointConfig(p -> {
int cx = p.x, cy = p.y;
int lx = cx;
float cx = p.x + off, cy = p.y + off;
float lx = cx;
if(direction >= 0){
cx = -cy;
@@ -1342,7 +1344,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
cx = cy;
cy = -lx;
}
p.set(cx, cy);
p.set(Mathf.floor(cx - off), Mathf.floor(cy - off));
});
//rotate actual plan, centered on its multiblock position
@@ -1376,14 +1378,12 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
}
plan.pointConfig(p -> {
int corigin = x ? plan.originalWidth/2 : plan.originalHeight/2;
int nvalue = -(x ? p.x : p.y);
if(x){
plan.originalX = -(plan.originalX - corigin) + corigin;
p.x = nvalue;
if(plan.block.size % 2 == 0) p.x --;
p.x = -p.x;
}else{
plan.originalY = -(plan.originalY - corigin) + corigin;
p.y = nvalue;
if(plan.block.size % 2 == 0) p.y --;
p.y = -p.y;
}
});
+2 -2
View File
@@ -98,7 +98,7 @@ public class MobileInput extends InputHandler implements GestureListener{
}else{
Building tile = world.buildWorld(x, y);
if((tile != null && player.team() != tile.team && (tile.team != Team.derelict || state.rules.coreCapture)) || (tile != null && player.unit().type.canHeal && tile.team == player.team() && tile.damaged())){
if((tile != null && (player.team() != tile.team && (tile.team != Team.derelict || state.rules.coreCapture)) && player.unit().type.canAttack) || (tile != null && player.unit().type.canHeal && tile.team == player.team() && tile.damaged())){
player.unit().mineTile = null;
target = tile;
}
@@ -1078,7 +1078,7 @@ public class MobileInput extends InputHandler implements GestureListener{
//this may be a bad idea, aiming for a point far in front could work better, test it out
unit.aim(Core.input.mouseWorldX(), Core.input.mouseWorldY());
}else{
Vec2 intercept = Predict.intercept(unit, target, bulletSpeed);
Vec2 intercept = player.unit().type.weapons.contains(w -> w.predictTarget) ? Predict.intercept(unit, target, bulletSpeed) : Tmp.v1.set(target);
player.mouseX = intercept.x;
player.mouseY = intercept.y;
+4 -2
View File
@@ -172,7 +172,7 @@ public class MapIO{
for(Tile tile : tiles){
//while synthetic blocks are possible, most of their data is lost, so in order to avoid questions like
//"why is there air under my drill" and "why are all my conveyors facing right", they are disabled
int color = tile.block().hasColor && !tile.block().synthetic() ? tile.block().mapColor.rgba() : tile.floor().mapColor.rgba();
int color = tile.block().hasColor && !tile.block().hasBuilding() ? tile.block().mapColor.rgba() : tile.floor().mapColor.rgba();
pix.set(tile.x, tiles.height - 1 - tile.y, color);
}
return pix;
@@ -183,6 +183,9 @@ public class MapIO{
int color = pixmap.get(tile.x, pixmap.height - 1 - tile.y);
Block block = ColorMapper.get(color);
//ignore buildings; reading images is only intended for environment tiles
if(block.hasBuilding()) continue;
if(block.isOverlay()){
tile.setOverlay(block.asFloor());
}else if(block.isFloor()){
@@ -194,7 +197,6 @@ public class MapIO{
}
}
//guess at floors by grabbing a random adjacent floor
for(Tile tile : tiles){
//default to stone floor
if(tile.floor() == Blocks.air){
+1 -1
View File
@@ -1104,7 +1104,7 @@ public class TypeIO{
}
}
/** Represents a unit that has not been resolved yet. TODO unimplemented / unused*/
/** Represents a unit that has not been resolved yet. */
public static class UnitBox implements Boxed<Unit>{
public int id;
+1
View File
@@ -41,6 +41,7 @@ public enum LAccess{
displayWidth,
displayHeight,
bufferUsage,
operations,
size,
solid,
dead,
+5
View File
@@ -25,6 +25,7 @@ import mindustry.ui.*;
import mindustry.world.*;
import mindustry.world.blocks.environment.*;
import mindustry.world.blocks.logic.*;
import mindustry.world.blocks.logic.CanvasBlock.*;
import mindustry.world.blocks.logic.LogicBlock.*;
import mindustry.world.blocks.logic.LogicDisplay.*;
import mindustry.world.blocks.logic.MemoryBlock.*;
@@ -581,6 +582,8 @@ public class LExecutor{
}
}else if(target.isobj && target.objval instanceof CharSequence str){
output.setnum(address < 0 || address >= str.length() ? Double.NaN : (int)str.charAt(address));
}else if(from instanceof CanvasBuild canvas && (exec.privileged || (from.team == exec.team))){
output.setnum(canvas.getPixel(address));
}
}
}
@@ -611,6 +614,8 @@ public class LExecutor{
toVar.numval = value.numval;
toVar.isobj = value.isobj;
}
}else if(from instanceof CanvasBuild canvas && (exec.privileged || (from.team == exec.team))){
canvas.setPixel(address, value.numi());
}
}
}
@@ -11,6 +11,7 @@ public enum LMarkerControl{
color("color"),
radius("radius"),
stroke("stroke"),
outline("outline"),
rotation("rotation"),
shape("sides", "fill", "outline"),
arc("start", "end"),
+1 -1
View File
@@ -221,7 +221,7 @@ public class LogicDialog extends BaseDialog{
update(() -> setColor(typeColor(s, color)));
}}, new Label(() -> " " + typeName(s) + " "){{
setStyle(Styles.outlineLabel);
}});
}}).minWidth(120f);
t.row();
+2
View File
@@ -11,6 +11,7 @@ public enum LogicOp{
div("/", (a, b) -> a / b),
idiv("//", (a, b) -> Math.floor(a / b)),
mod("%", (a, b) -> a % b),
emod("%%", (a, b) -> ((a % b) + b) % b),
pow("^", Math::pow),
equal("==", (a, b) -> Math.abs(a - b) < 0.000001 ? 1 : 0, (a, b) -> Structs.eq(a, b) ? 1 : 0),
@@ -24,6 +25,7 @@ public enum LogicOp{
shl("<<", (a, b) -> (long)a << (long)b),
shr(">>", (a, b) -> (long)a >> (long)b),
ushr(">>>", (a, b) -> (long)a >>> (long)b),
or("or", (a, b) -> (long)a | (long)b),
and("b-and", (a, b) -> (long)a & (long)b),
xor("xor", (a, b) -> (long)a ^ (long)b),
@@ -0,0 +1,73 @@
package mindustry.maps;
import arc.struct.*;
import arc.util.*;
import mindustry.type.*;
/** Class for temporarily (?) storing links to map submissions on Discord. */
public class SectorSubmissions{
private static IntMap<String> hiddenMap = new IntMap<>();
static{
//autogenerated
hiddenMap.put(0, "https://discord.com/channels/391020510269669376/1379926780860698784");
hiddenMap.put(6, "https://discord.com/channels/391020510269669376/1379926782966497322");
hiddenMap.put(13, "https://discord.com/channels/391020510269669376/1379926785164312810");
hiddenMap.put(16, "https://discord.com/channels/391020510269669376/1379926788280680579");
hiddenMap.put(19, "https://discord.com/channels/391020510269669376/1379926792479183019");
hiddenMap.put(20, "https://discord.com/channels/391020510269669376/1379926794114961634");
hiddenMap.put(24, "https://discord.com/channels/391020510269669376/1379926797042581716");
hiddenMap.put(27, "https://discord.com/channels/391020510269669376/1379926798833287289");
hiddenMap.put(30, "https://discord.com/channels/391020510269669376/1379926800854945823");
hiddenMap.put(47, "https://discord.com/channels/391020510269669376/1379926802591645820");
hiddenMap.put(55, "https://discord.com/channels/391020510269669376/1379926823277695189");
hiddenMap.put(66, "https://discord.com/channels/391020510269669376/1379926825941078128");
hiddenMap.put(67, "https://discord.com/channels/391020510269669376/1379926828696866898");
hiddenMap.put(69, "https://discord.com/channels/391020510269669376/1379926831326822610");
hiddenMap.put(76, "https://discord.com/channels/391020510269669376/1379926833411391580");
hiddenMap.put(92, "https://discord.com/channels/391020510269669376/1379926835621527615");
hiddenMap.put(94, "https://discord.com/channels/391020510269669376/1379926838079393802");
hiddenMap.put(103, "https://discord.com/channels/391020510269669376/1379926839559979030");
hiddenMap.put(111, "https://discord.com/channels/391020510269669376/1379926842659569864");
hiddenMap.put(116, "https://discord.com/channels/391020510269669376/1379926845058711734");
hiddenMap.put(127, "https://discord.com/channels/391020510269669376/1379926869465632829");
hiddenMap.put(133, "https://discord.com/channels/391020510269669376/1379926871227240770");
hiddenMap.put(138, "https://discord.com/channels/391020510269669376/1379926873152164004");
hiddenMap.put(150, "https://discord.com/channels/391020510269669376/1379926876457537547");
hiddenMap.put(157, "https://discord.com/channels/391020510269669376/1379926879502598155");
hiddenMap.put(161, "https://discord.com/channels/391020510269669376/1379926882203730024");
hiddenMap.put(162, "https://discord.com/channels/391020510269669376/1379926884606808247");
hiddenMap.put(176, "https://discord.com/channels/391020510269669376/1379926887203213353");
hiddenMap.put(180, "https://discord.com/channels/391020510269669376/1379926889648619580");
hiddenMap.put(185, "https://discord.com/channels/391020510269669376/1379926892181983283");
hiddenMap.put(191, "https://discord.com/channels/391020510269669376/1379926912004001914");
hiddenMap.put(192, "https://discord.com/channels/391020510269669376/1379926914122256449");
hiddenMap.put(197, "https://discord.com/channels/391020510269669376/1379926916911599676");
hiddenMap.put(200, "https://discord.com/channels/391020510269669376/1379926918429806755");
hiddenMap.put(204, "https://discord.com/channels/391020510269669376/1379926921130807447");
hiddenMap.put(207, "https://discord.com/channels/391020510269669376/1379926923370827827");
hiddenMap.put(225, "https://discord.com/channels/391020510269669376/1379926925719376152");
hiddenMap.put(230, "https://discord.com/channels/391020510269669376/1379926927585841163");
hiddenMap.put(237, "https://discord.com/channels/391020510269669376/1379926929636851812");
hiddenMap.put(242, "https://discord.com/channels/391020510269669376/1379926931923013843");
hiddenMap.put(243, "https://discord.com/channels/391020510269669376/1379926955423694978");
hiddenMap.put(244, "https://discord.com/channels/391020510269669376/1379926957738954762");
hiddenMap.put(245, "https://discord.com/channels/391020510269669376/1379926971286290584");
hiddenMap.put(246, "https://discord.com/channels/391020510269669376/1379926973454745600");
hiddenMap.put(247, "https://discord.com/channels/391020510269669376/1379926976361533752");
hiddenMap.put(248, "https://discord.com/channels/391020510269669376/1379926979129774151");
hiddenMap.put(251, "https://discord.com/channels/391020510269669376/1379928042637361382");
hiddenMap.put(254, "https://discord.com/channels/391020510269669376/1379928045577703424");
hiddenMap.put(259, "https://discord.com/channels/391020510269669376/1379928048245280871");
hiddenMap.put(263, "https://discord.com/channels/391020510269669376/1379928050010951694");
hiddenMap.put(265, "https://discord.com/channels/391020510269669376/1379928052921929891");
}
/** @return the link to the Discord discussion thread of the specified hidden sector submission. */
public static @Nullable String getSectorThread(Sector sector){
if(sector.generateEnemyBase){
return hiddenMap.get(sector.id);
}
return null;
}
}
@@ -1,7 +1,5 @@
package mindustry.maps.generators;
import arc.graphics.*;
import arc.math.geom.*;
import mindustry.game.*;
import mindustry.type.*;
import mindustry.world.*;
@@ -9,16 +7,6 @@ import mindustry.world.*;
/** A planet generator that provides no weather, height, color or bases. Override generate().*/
public class BlankPlanetGenerator extends PlanetGenerator{
@Override
public float getHeight(Vec3 position){
return 0;
}
@Override
public Color getColor(Vec3 position){
return Color.white;
}
@Override
public void addWeather(Sector sector, Rules rules){
@@ -25,11 +25,22 @@ public abstract class PlanetGenerator extends BasicGenerator implements HexMeshe
protected @Nullable Sector sector;
/** Should generate sector bases for a planet. */
public void generateSector(Sector sector){
}
public void onSectorCaptured(Sector sector){
}
public void onSectorLost(Sector sector){
}
public void beforeSaveWrite(Sector sector){
}
public void getLockedText(Sector hovered, StringBuilder out){
out.append("[gray]").append(Iconc.lock).append(" ").append(Core.bundle.get("locked"));
}
@@ -39,20 +39,17 @@ public class ErekirPlanetGenerator extends PlanetGenerator{
}
@Override
public Color getColor(Vec3 position){
public void getColor(Vec3 position, Color out){
Block block = getBlock(position);
//more obvious color
if(block == Blocks.crystallineStone) block = Blocks.crystalFloor;
//TODO this might be too green
//if(block == Blocks.beryllicStone) block = Blocks.arkyicStone;
return Tmp.c1.set(block.mapColor).a(1f - block.albedo);
out.set(block.mapColor).a(1f - block.albedo);
}
@Override
public float getSizeScl(){
//TODO should sectors be 600, or 500 blocks?
return 2000 * 1.07f * 6f / 5f;
}
@@ -65,17 +62,17 @@ public class ErekirPlanetGenerator extends PlanetGenerator{
}
Block getBlock(Vec3 position){
float ice = rawTemp(position);
Tmp.v32.set(position);
float px = position.x, py = position.y, pz = position.z;
float ice = rawTemp(position);
float height = rawHeight(position);
Tmp.v31.set(position);
height *= 1.2f;
height = Mathf.clamp(height);
Block result = terrain[Mathf.clamp((int)(height * terrain.length), 0, terrain.length - 1)];
if(ice < 0.3 + Math.abs(Ridged.noise3d(seed + crystalSeed, position.x + 4f, position.y + 8f, position.z + 1f, crystalOct, crystalScl)) * crystalMag){
if(ice < 0.3 + Math.abs(Ridged.noise3d(seed + crystalSeed, px + 4f, py + 8f, pz + 1f, crystalOct, crystalScl)) * crystalMag){
return Blocks.crystallineStone;
}
@@ -86,11 +83,9 @@ public class ErekirPlanetGenerator extends PlanetGenerator{
}
}
position = Tmp.v32;
//TODO tweak this to make it more natural
//TODO edge distortion?
if(ice < redThresh - noArkThresh && Ridged.noise3d(seed + arkSeed, position.x + 2f, position.y + 8f, position.z + 1f, arkOct, arkScl) > arkThresh){
if(ice < redThresh - noArkThresh && Ridged.noise3d(seed + arkSeed, px + 2f, py + 8f, pz + 1f, arkOct, arkScl) > arkThresh){
//TODO arkyic in middle
result = Blocks.beryllicStone;
}
@@ -20,13 +20,16 @@ import mindustry.world.blocks.environment.*;
import static mindustry.Vars.*;
public class SerpuloPlanetGenerator extends PlanetGenerator{
//alternate, less direct generation (wip)
public static boolean alt = false;
//alternate, less direct generation
public static boolean indirectPaths = false;
//random water patches
public static boolean genLakes = false;
BaseGenerator basegen = new BaseGenerator();
float heightYOffset = 42.7f;
float scl = 5f;
float waterOffset = 0.05f;
boolean genLakes = false;
float waterOffset = 0.04f;
float heightScl = 1.01f;
Block[][] arr =
{
@@ -58,10 +61,30 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
);
float water = 2f / arr[0].length;
Vec3 basePos = new Vec3(0.9341721, 0.0, 0.3568221);
float rawHeight(Vec3 position){
position = Tmp.v33.set(position).scl(scl);
return (Mathf.pow(Simplex.noise3d(seed, 7, 0.5f, 1f/3f, position.x, position.y, position.z), 2.3f) + waterOffset) / (1f + waterOffset);
return (Mathf.pow(Simplex.noise3d(seed, 7, 0.5f, 1f/3f, position.x * scl, position.y * scl + heightYOffset, position.z * scl) * heightScl, 2.3f) + waterOffset) / (1f + waterOffset);
}
@Override
public void onSectorCaptured(Sector sector){
sector.planet.reloadMeshAsync();
}
@Override
public void onSectorLost(Sector sector){
sector.planet.reloadMeshAsync();
}
@Override
public void beforeSaveWrite(Sector sector){
sector.planet.reloadMeshAsync();
}
@Override
public boolean isEmissive(){
return true;
}
@Override
@@ -86,16 +109,57 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
}
@Override
public Color getColor(Vec3 position){
public void getColor(Vec3 position, Color out){
Block block = getBlock(position);
//replace salt with sand color
if(block == Blocks.salt) return Blocks.sand.mapColor;
return Tmp.c1.set(block.mapColor).a(1f - block.albedo);
if(block == Blocks.salt) block = Blocks.sand;
out.set(block.mapColor).a(1f - block.albedo);
}
@Override
public void getEmissiveColor(Vec3 position, Color out){
float dst = 999f, captureDst = 999f, lightScl = 0f;
Object[] sectors = Planets.serpulo.sectors.items;
int size = Planets.serpulo.sectors.size;
for(int i = 0; i < size; i ++){
var sector = (Sector)sectors[i];
if(sector.hasEnemyBase() && !sector.isCaptured()){
dst = Math.min(dst, position.dst(sector.tile.v) - (sector.preset != null ? sector.preset.difficulty/10f * 0.03f - 0.03f : 0f));
}else if(sector.hasBase()){
float cdst = position.dst(sector.tile.v);
if(cdst < captureDst){
captureDst = cdst;
lightScl = sector.info.lightCoverage;
}
}
}
lightScl = Math.min(lightScl / 50000f, 1.3f);
if(lightScl < 1f) lightScl = Interp.pow5Out.apply(lightScl);
float freq = 0.05f;
if(position.dst(basePos) < 0.55f ?
dst*metalDstScl + Simplex.noise3d(seed + 1, 3, 0.4, 5.5f, position.x, position.y + 200f, position.z)*0.08f + ((basePos.dst(position) + 0.00f) % freq < freq/2f ? 1f : 0f) * 0.07f < 0.08f/* || dst <= 0.0001f*/ :
dst*metalDstScl + Simplex.noise3d(seed, 3, 0.4, 9f, position.x, position.y + 370f, position.z)*0.06f < 0.045){
out.set(Team.crux.color)
.mul(0.8f + Simplex.noise3d(seed, 1, 1, 9f, position.x, position.y + 99f, position.z) * 0.4f)
.lerp(Team.sharded.color, 0.2f*Simplex.noise3d(seed, 1, 1, 9f, position.x, position.y + 999f, position.z)).toFloatBits();
}else if(captureDst*metalDstScl + Simplex.noise3d(seed, 3, 0.4, 9f, position.x, position.y + 600f, position.z)*0.07f < 0.05 * lightScl){
out.set(Team.sharded.color).mul(0.7f + Simplex.noise3d(seed, 1, 1, 9f, position.x, position.y + 99f, position.z) * 0.4f)
.lerp(Team.crux.color, 0.3f*Simplex.noise3d(seed, 1, 1, 9f, position.x, position.y + 999f, position.z)).toFloatBits();
}
}
@Override
public void genTile(Vec3 position, TileGen tile){
tile.floor = getBlock(position);
if(tile.floor == Blocks.darkPanel6) tile.floor = Blocks.darkPanel3;
tile.block = tile.floor.asFloor().wall;
if(Ridged.noise3d(seed + 1, position.x, position.y, position.z, 2, 22) > 0.31){
@@ -103,23 +167,46 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
}
}
static double metalDstScl = 0.25;
Block getBlock(Vec3 position){
float height = rawHeight(position);
Tmp.v31.set(position);
position = Tmp.v33.set(position).scl(scl);
float px = position.x * scl, py = position.y * scl, pz = position.z * scl;
float rad = scl;
float temp = Mathf.clamp(Math.abs(position.y * 2f) / (rad));
float tnoise = Simplex.noise3d(seed, 7, 0.56, 1f/3f, position.x, position.y + 999f, position.z);
float temp = Mathf.clamp(Math.abs(py * 2f) / (rad));
float tnoise = Simplex.noise3d(seed, 7, 0.56, 1f/3f, px, py + 999f - 0.1f, pz);
temp = Mathf.lerp(temp, tnoise, 0.5f);
height *= 1.2f;
height = Mathf.clamp(height);
float tar = Simplex.noise3d(seed, 4, 0.55f, 1f/2f, position.x, position.y + 999f, position.z) * 0.3f + Tmp.v31.dst(0, 0, 1f) * 0.2f;
float tar = Simplex.noise3d(seed, 4, 0.55f, 1f/2f, px, py + 999f, pz) * 0.3f + position.dst(0, 0, 1f) * 0.2f;
Block res = arr[Mathf.clamp((int)(temp * arr.length), 0, arr[0].length - 1)][Mathf.clamp((int)(height * arr[0].length), 0, arr[0].length - 1)];
if(tar > 0.5f){
return tars.get(res, res);
}else{
if(position.within(basePos, 0.65f)){
float dst = 999f;
Object[] sectors = Planets.serpulo.sectors.items;
int size = Planets.serpulo.sectors.size;
for(int i = 0; i < size; i ++){
var sector = (Sector)sectors[i];
if(sector.hasEnemyBase()){
dst = Math.min(dst, position.dst(sector.tile.v));
}
}
float freq = 0.05f, freq2 = 0.07f;
if(dst*0.85f + Simplex.noise3d(seed, 3, 0.4, 5.5f, position.x, position.y + 200f, position.z)*0.015f + ((basePos.dst(position) + 0.00f) % freq < freq/2f ? 1f : 0f) * 0.07f < 0.15f){
return ((basePos.dst(position) + 0.01f) % freq2 < freq2*0.65f) ? Blocks.metalFloor : Blocks.darkPanel6;
}
}
return res;
}
}
@@ -156,7 +243,7 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
Vec2 midpoint = Tmp.v1.set(to.x, to.y).add(x, y).scl(0.5f);
rand.nextFloat();
if(alt){
if(indirectPaths){
midpoint.add(Tmp.v2.set(1, 0f).setAngle(Angles.angle(to.x, to.y, x, y) + 90f * (rand.chance(0.5) ? 1f : -1f)).scl(Tmp.v1.dst(x, y) * 2f));
}else{
//add randomized offset to avoid straight lines
@@ -14,7 +14,7 @@ import mindustry.world.*;
import static mindustry.Vars.*;
public class TantrosPlanetGenerator extends PlanetGenerator{
Color c1 = Color.valueOf("5057a6"), c2 = Color.valueOf("272766"), out = new Color();
Color c1 = Color.valueOf("5057a6"), c2 = Color.valueOf("272766");
Block[][] arr = {
{Blocks.redmat, Blocks.redmat, Blocks.darksand, Blocks.bluemat, Blocks.bluemat}
@@ -30,9 +30,9 @@ public class TantrosPlanetGenerator extends PlanetGenerator{
}
@Override
public Color getColor(Vec3 position){
public void getColor(Vec3 position, Color out){
float depth = Simplex.noise3d(seed, 2, 0.56, 1.7f, position.x, position.y, position.z) / 2f;
return c1.write(out).lerp(c2, Mathf.clamp(Mathf.round(depth, 0.15f))).a(0.2f);
out.set(c1).lerp(c2, Mathf.clamp(Mathf.round(depth, 0.15f))).a(1f - 0.2f).toFloatBits();
}
@Override
+22 -6
View File
@@ -413,11 +413,22 @@ public class Mods implements Loadable{
/** Removes a mod file and marks it for requiring a restart. */
public void removeMod(LoadedMod mod){
if(!android && mod.loader != null){
try{
ClassLoaderCloser.close(mod.loader);
}catch(Exception e){
Log.err(e);
boolean deleted = true;
if(mod.loader != null){
if(android){
//Try to remove cache for Android 14 security problem
Fi cacheDir = new Fi(Core.files.getCachePath()).child("mods");
Fi modCacheDir = cacheDir.child(mod.file.nameWithoutExtension());
if(modCacheDir.exists()){
deleted = modCacheDir.deleteDirectory();
}
}else{
try{
ClassLoaderCloser.close(mod.loader);
}catch(Exception e){
Log.err(e);
}
}
}
@@ -425,7 +436,7 @@ public class Mods implements Loadable{
mod.root.delete();
}
boolean deleted = mod.file.isDirectory() ? mod.file.deleteDirectory() : mod.file.delete();
deleted &= mod.file.isDirectory() ? mod.file.deleteDirectory() : mod.file.delete();
if(!deleted){
ui.showErrorMessage("@mod.delete.error");
@@ -1112,6 +1123,11 @@ public class Mods implements Loadable{
//close the classloader for jar mods
if(!android){
ClassLoaderCloser.close(other.loader);
}else if(other.loader != null){
//Try to remove cache for Android 14 security problem
Fi cacheDir = new Fi(Core.files.getCachePath()).child("mods");
Fi modCacheDir = cacheDir.child(other.file.nameWithoutExtension());
modCacheDir.deleteDirectory();
}
//close zip file
@@ -91,6 +91,10 @@ public class Administration{
dosBlacklist.add(address);
}
public synchronized void unBlacklistDos(String address){
dosBlacklist.remove(address);
}
public synchronized boolean isDosBlacklisted(String address){
return dosBlacklist.contains(address);
}
@@ -113,6 +113,8 @@ public class ArcNetProvider implements NetProvider{
//kill connections above the limit to prevent spam
if((playerLimitCache > 0 && server.getConnections().length > playerLimitCache) || netServer.admins.isDosBlacklisted(ip)){
Log.info("Closing connection @ - IP marked as a potential DOS attack.", ip);
connection.close(DcReason.closed);
return;
}
+3 -1
View File
@@ -28,6 +28,8 @@ public class CrashHandler{
report += "Report this at " + Vars.reportIssueURL + "\n\n";
}
var enabledMods = mods == null ? null : mods.list().select(m -> m.shouldBeEnabled() && m.isSupported());
return report
+ "Version: " + Version.combined() + (Version.buildDate.equals("unknown") ? "" : " (Built " + Version.buildDate + ")") + (Vars.headless ? " (Server)" : "") + "\n"
+ "Date: " + new SimpleDateFormat("MMMM d, yyyy HH:mm:ss a", Locale.getDefault()).format(new Date()) + "\n"
@@ -37,7 +39,7 @@ public class CrashHandler{
+ "Runtime Available Memory: " + (Runtime.getRuntime().maxMemory() / 1024 / 1024) + "mb\n"
+ "Cores: " + OS.cores + "\n"
+ (cause == null ? "" : "Likely Cause: " + cause.meta.displayName + " (" + cause.name + " v" + cause.meta.version + ")\n")
+ (mods == null ? "<no mod init>" : "Mods: " + (!mods.list().contains(LoadedMod::shouldBeEnabled) ? "none (vanilla)" : mods.list().select(LoadedMod::shouldBeEnabled).toString(", ", mod -> mod.name + ":" + mod.meta.version)))
+ (enabledMods == null ? "<no mod init>" : "Mods: " + (enabledMods.isEmpty() ? "none (vanilla)" : enabledMods.toString(", ", mod -> mod.name + ":" + mod.meta.version)))
+ "\n\n" + error;
}
@@ -67,6 +67,7 @@ public enum Achievement{
have10mItems(SStat.totalCampaignItems, 10_000_000),
killEclipseDuo,
killMassDriver,
completeErekir,
completeSerpulo,

Some files were not shown because too many files have changed in this diff Show More