diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 13405ba012..08422736a2 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -14,6 +14,7 @@ android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:isGame="true" + android:theme="@style/ArcTheme" android:usesCleartextTraffic="true" android:appCategory="game" android:label="@string/app_name" diff --git a/android/build.gradle b/android/build.gradle index 672dfc81f4..5f355a0ec7 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -100,6 +100,9 @@ android{ all{ minifyEnabled = true shrinkResources = true + //this is the ONLY WAY I could find to force r8 to keep its filthy hands off of my default interfaces. + //may have undesirable side effects + debuggable = true proguardFiles("proguard-rules.pro") } } diff --git a/android/res/values-v21/styles.xml b/android/res/values-v21/styles.xml new file mode 100644 index 0000000000..9ddd5ffb6c --- /dev/null +++ b/android/res/values-v21/styles.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/android/res/values/styles.xml b/android/res/values/styles.xml new file mode 100644 index 0000000000..ac57c806dd --- /dev/null +++ b/android/res/values/styles.xml @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/annotations/src/main/java/mindustry/annotations/util/AnnotationProxyMaker.java b/annotations/src/main/java/mindustry/annotations/util/AnnotationProxyMaker.java index c3398f3ae8..64d86a4346 100644 --- a/annotations/src/main/java/mindustry/annotations/util/AnnotationProxyMaker.java +++ b/annotations/src/main/java/mindustry/annotations/util/AnnotationProxyMaker.java @@ -7,6 +7,7 @@ import com.sun.tools.javac.code.Attribute.Enum; import com.sun.tools.javac.code.Attribute.Error; import com.sun.tools.javac.code.Attribute.Visitor; import com.sun.tools.javac.code.Attribute.*; +import com.sun.tools.javac.code.Scope.*; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.ArrayType; @@ -64,36 +65,13 @@ public class AnnotationProxyMaker{ LinkedHashMap map = new LinkedHashMap(); ClassSymbol cl = (ClassSymbol)this.anno.type.tsym; - //try to use Java 8 API for this if possible - try{ - Class entryClass = Class.forName("com.sun.tools.javac.code.Scope$Entry"); - Object members = cl.members(); - Field field = members.getClass().getField("elems"); - Object elems = field.get(members); - Field siblingField = entryClass.getField("sibling"); - Field symField = entryClass.getField("sym"); - for(Object currEntry = elems; currEntry != null; currEntry = siblingField.get(currEntry)){ - handleSymbol((Symbol)symField.get(currEntry), map); - } - - }catch(Throwable e){ - //otherwise try other API - - try{ - Class lookupClass = Class.forName("com.sun.tools.javac.code.Scope$LookupKind"); - Field nonRecField = lookupClass.getField("NON_RECURSIVE"); - Object nonRec = nonRecField.get(null); - Scope scope = cl.members(); - Method getSyms = scope.getClass().getMethod("getSymbols", lookupClass); - Iterable it = (Iterable)getSyms.invoke(scope, nonRec); - Iterator i = it.iterator(); - while(i.hasNext()){ - handleSymbol(i.next(), map); + for(Symbol s : cl.members().getSymbols(LookupKind.NON_RECURSIVE)){ + if(s.getKind() == ElementKind.METHOD){ + MethodSymbol var4 = (MethodSymbol)s; + Attribute var5 = var4.getDefaultValue(); + if(var5 != null){ + map.put(var4, var5); } - - }catch(Throwable death){ - //I tried - throw new RuntimeException(death); } } @@ -104,17 +82,6 @@ public class AnnotationProxyMaker{ return map; } - private void handleSymbol(Symbol sym, LinkedHashMap map){ - - if(sym.getKind() == ElementKind.METHOD){ - MethodSymbol var4 = (MethodSymbol)sym; - Attribute var5 = var4.getDefaultValue(); - if(var5 != null){ - map.put(var4, var5); - } - } - } - private Object generateValue(MethodSymbol var1, Attribute var2){ AnnotationProxyMaker.ValueVisitor var3 = new AnnotationProxyMaker.ValueVisitor(var1); return var3.getValue(var2); diff --git a/annotations/src/main/java/mindustry/annotations/util/Selement.java b/annotations/src/main/java/mindustry/annotations/util/Selement.java index ca7a9ce5ad..c416f83b0a 100644 --- a/annotations/src/main/java/mindustry/annotations/util/Selement.java +++ b/annotations/src/main/java/mindustry/annotations/util/Selement.java @@ -12,6 +12,10 @@ import java.lang.Class; import java.lang.annotation.*; import java.lang.reflect.*; +/** + * Wrapper over Element with added utility functions. + * I would have preferred to use extension methods for this, but Java doesn't have any. + * */ public class Selement{ public final T e; diff --git a/build.gradle b/build.gradle index a20b848221..95b6c068ad 100644 --- a/build.gradle +++ b/build.gradle @@ -57,7 +57,7 @@ allprojects{ if(!project.hasProperty("versionType")) versionType = 'official' appName = 'Mindustry' steamworksVersion = '0b86023401880bb5e586bc404bedbaae9b1f1c94' - rhinoVersion = '55bf0dac1cfa7770672fd26112512c733ca9d5dc' + rhinoVersion = '0601de1f37d55b25d2a6e647acba336f40cdefe4' loadVersionProps = { return new Properties().with{p -> p.load(file('../core/assets/version.properties').newReader()); return p } diff --git a/core/assets-raw/sprites/ui/slider-back.9.png b/core/assets-raw/sprites/ui/slider-back.9.png new file mode 100644 index 0000000000..71762a2163 Binary files /dev/null and b/core/assets-raw/sprites/ui/slider-back.9.png differ diff --git a/core/assets-raw/sprites/ui/slider-knob-down.png b/core/assets-raw/sprites/ui/slider-knob-down.png index 7eac1c0f51..72ff323d0b 100644 Binary files a/core/assets-raw/sprites/ui/slider-knob-down.png and b/core/assets-raw/sprites/ui/slider-knob-down.png differ diff --git a/core/assets-raw/sprites/ui/slider-knob-over.png b/core/assets-raw/sprites/ui/slider-knob-over.png index a4bb61170b..d7ca8fb4ea 100644 Binary files a/core/assets-raw/sprites/ui/slider-knob-over.png and b/core/assets-raw/sprites/ui/slider-knob-over.png differ diff --git a/core/assets-raw/sprites/ui/slider-knob.png b/core/assets-raw/sprites/ui/slider-knob.png index 6e643e0dc6..7c4e35233e 100644 Binary files a/core/assets-raw/sprites/ui/slider-knob.png and b/core/assets-raw/sprites/ui/slider-knob.png differ diff --git a/core/assets-raw/sprites/ui/slider-vertical.png b/core/assets-raw/sprites/ui/slider-vertical.png deleted file mode 100644 index 91d7c16e1f..0000000000 Binary files a/core/assets-raw/sprites/ui/slider-vertical.png and /dev/null differ diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index c3b05aeac9..4b001b5830 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -101,6 +101,7 @@ customgame = Custom Game newgame = New Game none = none.found = [lightgray] +none.inmap = [lightgray] minimap = Minimap position = Position close = Close @@ -1596,7 +1597,7 @@ lst.set = Set a variable. lst.operation = Perform an operation on 1-2 variables. lst.end = Jump to the top of the instruction stack. lst.wait = Wait a certain number of seconds. -lst.lookup = Look up a item/liquid/unit/block type by ID.\nTotal counts of each type can be accessed with:\n[accent]@unitCount[] / [accent]@itemCount[] / [accent]@liquidCount[] / [accent]@blockCount[] +lst.lookup = Look up an item/liquid/unit/block type by ID.\nTotal counts of each type can be accessed with:\n[accent]@unitCount[] / [accent]@itemCount[] / [accent]@liquidCount[] / [accent]@blockCount[] lst.jump = Conditionally jump to another statement. lst.unitbind = Bind to the next unit of a type, and store it in [accent]@unit[]. lst.unitcontrol = Control the currently bound unit. diff --git a/core/assets/bundles/bundle_es.properties b/core/assets/bundles/bundle_es.properties index e9d0f796e3..8701bc0531 100644 --- a/core/assets/bundles/bundle_es.properties +++ b/core/assets/bundles/bundle_es.properties @@ -41,11 +41,13 @@ be.ignore = Ignorar be.noupdates = No se encontraron actualizaciones. be.check = Buscar actualizaciones -mod.featured.title = Explorador de mods -mod.featured.dialog.title = Explorador de Mods +mods.browser = Explorador de Mods mods.browser.selected = Mod seleccionado -mods.browser.add = Installar Mod -mods.github.open = Abrir en Github +mods.browser.add = Instalar +mods.browser.reinstall = Reinstalar +mods.github.open = Repositorio +mods.browser.sortdate = Más recientes +mods.browser.sortstars = Mejor valorados schematic = Plantilla schematic.add = Guardar plantilla... @@ -55,16 +57,24 @@ schematic.exists = Ya existe una plantilla con ese nombre. schematic.import = Importar plantilla... schematic.exportfile = Exportar archivo schematic.importfile = Importar archivo -schematic.browseworkshop = Buscar en el Steam Workshop +schematic.browseworkshop = Buscar en Steam Workshop schematic.copy = Copiar al portapapeles. schematic.copy.import = Importar desde el portapapeles. -schematic.shareworkshop = Compartir en el Steam Workshop +schematic.shareworkshop = Compartir en Steam Workshop schematic.flip = [accent][[{0}][]/[accent][[{1}][]: Girar plantilla schematic.saved = Plantilla guardada. schematic.delete.confirm = Se borrará ésta plantilla. schematic.rename = Renombrar plantilla schematic.info = {0}x{1}, {2} bloques schematic.disabled = [scarlet]Plantillas desactivadas.[]\nNo puedes usar plantillas en este [accent]mapa[] o [accent]servidor. +schematic.tags = Etiquetas: +schematic.edittags = Editar Etiquetas +schematic.addtag = Añadir Etiqueta +schematic.texttag = Texto de Etiqueta +schematic.icontag = Icono de Etiqueta +schematic.renametag = Renombrar Etiqueta +schematic.tagdelconfirm = ¿Eliminar ésta etiqueta? +schematic.tagexists = Esa etiqueta ya existe. stats = Estadísticas stat.wave = Oleadas Derrotadas:[accent] {0} @@ -77,12 +87,12 @@ stat.playtime = Tiempo jugado:[accent] {0} stat.rank = Rango final: [accent]{0} globalitems = [accent]Recursos Totales -map.delete = ¿Estás seguro de que quieres borrar el mapa "[accent]{0}[]"? +map.delete = ¿Quieres borrar el mapa "[accent]{0}[]"? level.highscore = Puntuación más alta: [accent]{0} -level.select = Selección de nivel +level.select = Selección de Nivel level.mode = Modo de juego: coreattack = < ¡El núcleo está bajo ataque! > -nearpoint = [[ [scarlet]ABANDONA EL PUNTO DE APARICIÓN INMEDIATAMENTE[] ]\nRiesgo de aniquilación inminente +nearpoint = [[ [scarlet]ABANDONA EL PUNTO DE ATERRIZAJE INMEDIATAMENTE[] ]\nRiesgo de aniquilación inminente database = Base de datos savegame = Guardar Partida loadgame = Cargar Partida @@ -90,6 +100,7 @@ joingame = Unirse a Partida customgame = Crear Partida newgame = Nueva Partida none = +none.found = [lightgray] minimap = Minimapa position = Posición close = Cerrar @@ -110,17 +121,20 @@ committingchanges = Confirmando Cambios done = Hecho feature.unsupported = Tu dispositivo no es compatible con esta función. -mods.alphainfo = Ten en cuenta que los mods estan en fase Alpha, y[scarlet] pueden tener varios errores[].\nReporta cualquier error que encuentres en la página de GitHub de Mindustry. +mods.initfailed = [red]⚠[] La anterior ejecución de Mindustry encontró un fallo al inicializarse. Seguramente fue causado por algún mod erróneo.\n\nPara evitar un bucle de erroes al iniciar el juego, [red]se han desactivado todos los mods.[]\n\nPuedes desactivar ésta medida de seguridad desde [accent]Opciones->Juego->Desactivar mods si el juego encuentra un error al iniciarse.[]. mods = Mods mods.none = [lightgray]¡No se encontraron Mods! -mods.guide = Guía de Modding +mods.guide = Guía sobre Mods mods.report = Reportar Error mods.openfolder = Abrir carpeta de mods +mods.viewcontent = Ver Contenido mods.reload = Recargar mods.reloadexit = A continuación se cerrará el juego para recargar los mods. +mod.installed = [[Instalado] mod.display = [gray]Mod:[orange] {0} mod.enabled = [lightgray]Activado mod.disabled = [scarlet]Desactivado +mod.multiplayer.compatible = [gray]Compatible con Multijugador mod.disable = Desactivar mod.content = Contenido: mod.delete.error = No se pudo elminar el mod. Tal vez esté en uso por el juego. @@ -130,20 +144,20 @@ mod.missingdependencies = [scarlet]Dependencias faltantes: {0} mod.erroredcontent = [scarlet]Contenido erróneo mod.errors = Ha ocurrido un fallo al cargar el contenido. mod.noerrorplay = [scarlet]Se están ejecutando algunos mods con fallos.[]Deshabilítalos o arregla los errores antes de jugar. -mod.nowdisabled = [scarlet]Al/Los Mod/s '{0}'le esta/n faltando dependencias:[accent] {1}\n[lightgray]Estos mods necesitan descargarse primero.\nEste mod será automaticamente desactivado. +mod.nowdisabled = [scarlet]El mod '{0}' necesita ejecutarse junto a otros mods de los que depende:[accent] {1}\n[lightgray]Es necesario descargar primero estos mods.\nEste mod será automaticamente desactivado. mod.enable = Activar mod.requiresrestart = El juego se cerrará para aplicar los mods. -mod.reloadrequired = [scarlet]Se requiere volver a cargar +mod.reloadrequired = [scarlet]Es necesario Reiniciar mod.import = Importar mod mod.import.file = Importar archivo -mod.import.github = Importar Mod de Github +mod.import.github = Importar desde Github mod.jarwarn = [scarlet]Los mods JAR pueden no ser seguros.[]\n¡Asegúrate de haberlos descargado de una fuente en la que confíes! mod.item.remove = Este objeto es parte del[accent] '{0}'[] mod. Para eliminarlo, desinstala ese mod. mod.remove.confirm = Este mod va a ser eliminado.\n¿Quieres continuar? mod.author = [lightgray]Autor:[] {0} mod.missing = Esta partida guardada usa mods que has actualizado recientemente o que no tienes instalados. Se puede corromper la partida guardada. ¿Quieres cargarla a pesar de ello?\n[lightgray]Mods:\n{0} -mod.preview.missing = Antes de publicar este mod en el Steam Workshop, debe añadir una imagen de vista previa.\nAñada una imagen con nombre[accent] preview.png[] en la carpeta del mod e intente nuevamente. -mod.folder.missing = Solo los mods en forma de carpeta se pueden publicar en el Steam Workshop.\nPara convertir cualquier mod en una carpeta, simplemente descomprima su archivo a una carpeta y elimine el zip anterior, luego reinicie su juego o vuelva a cargar sus mods. +mod.preview.missing = Antes de publicar este mod en Steam Workshop, debes añadir una imagen de vista previa.\nAñade una imagen llamada[accent] preview.png[] en la carpeta del mod e inténtalo de nuevo. +mod.folder.missing = Sólo los mods en forma de carpeta se pueden publicar en Steam Workshop.\nPara convertir cualquier mod en una carpeta, descomprime su archivo a una carpeta y elimina el zip anterior, luego reinicia el juego o vuelve a cargar tus mods. mod.scripts.disable = Tu dispositivo no es compatible con mods con scripts. Debes deshabilitar esos mods para jugar. about.button = Acerca de... @@ -214,6 +228,8 @@ trace.ip = IP: [accent]{0} trace.id = ID Única: [accent]{0} trace.mobile = Cliente de móvil: [accent]{0} trace.modclient = Cliente Personalizado: [accent]{0} +trace.times.joined = Se ha unido [accent]{0} []veces +trace.times.kicked = Fue expulsado [accent]{0} []veces invalidid = ¡ID de cliente inválida! Por favor, envía un informe del error. server.bans = Expulsiones server.bans.none = No se ha baneado a ningún usuario aún @@ -222,16 +238,16 @@ server.admins.none = ¡No hay ningún administrador! server.add = Agregar Servidor server.delete = ¿Estás seguro de querer borrar este servidor? server.edit = Editar Servidor -server.outdated = [crimson]¡Servidor desactualizado![] -server.outdated.client = [crimson]¡Cliente desactualizado![] -server.version = [lightgray]Versión: {0} -server.custombuild = [accent]Versión personalizada -confirmban = ¿Quieres banear a este jugador? -confirmkick = ¿Estás seguro de querer expulsar este jugador? -confirmvotekick = ¿Estás de acuerdo en expulsar este jugador? +server.outdated = [scarlet]¡Servidor Desactualizado![] +server.outdated.client = [scarlet]¡Cliente Desactualizado![] +server.version = [gray]v{0} {1} +server.custombuild = [accent]Versión Personalizada +confirmban = ¿Quieres banear a "{0}[white]"? +confirmkick = ¿Quieres expulsar a "{0}[white]"? +confirmvotekick = ¿Estás a favor de expulsar a "{0}[white]"? confirmunban = ¿Quieres desbanear a este jugador? -confirmadmin = ¿Quieres hacer administrador a este jugador? -confirmunadmin = ¿Quieres quitar los permisos de administrador a este jugador? +confirmadmin = ¿Quieres hacer administrador a "{0}[white]"? +confirmunadmin = ¿Quieres quitarle los permisos de administrador a "{0}[white]"? joingame.title = Unirse a Partida joingame.ip = IP: disconnect = Desconectado. @@ -287,6 +303,7 @@ cancel = Cancelar openlink = Abrir Enlace copylink = Copiar Enlace back = Atrás +max = Máximo crash.export = Exportar Registros de errores crash.none = No se encontraron Registros de errores. crash.exported = Registros de errores exportados. @@ -361,7 +378,6 @@ editor.center = Centrar workshop = Steam Workshop waves.title = Oleadas waves.remove = Borrar -waves.never = waves.every = cada waves.waves = oleada(s) waves.perspawn = por lugar de aparición @@ -444,6 +460,7 @@ toolmode.drawteams = Dibujar Equipos toolmode.drawteams.description = Dibuja equipos en lugar de bloques. filters.empty = [lightgray]¡No hay filtros! Añade uno con el botón de abajo. + filter.distort = Distorsionar filter.noise = Ruido filter.enemyspawn = Punto de aparición enemigo @@ -460,19 +477,22 @@ filter.clear = Despejar filter.option.ignore = Ignorar filter.scatter = Dispersar filter.terrain = Terreno + filter.option.scale = Escala filter.option.chance = Probabilidad filter.option.mag = Magnitud filter.option.threshold = Umbral filter.option.circle-scale = Escala del círculo filter.option.octaves = Continuidad -filter.option.falloff = Aterrizaje +filter.option.falloff = Caída filter.option.angle = Ángulo +filter.option.rotate = Rotación filter.option.amount = Cantidad filter.option.block = Bloque filter.option.floor = Suelo filter.option.flooronto = Suelo objetivo -filter.option.target = Target +filter.option.target = Objetivo +filter.option.replacement = Reemplazo filter.option.wall = Muro filter.option.ore = Veta filter.option.floor2 = Terreno secundario @@ -484,11 +504,12 @@ width = Ancho: height = Alto: menu = Menú play = Jugar -campaign = Continuar Campaña +campaign = Campaña load = Cargar save = Guardar fps = FPS: {0} -ping = Ping: {0} ms +ping = Ping: {0}ms +tps = TPS: {0} memory = Mem: {0}mb memory2 = Mem:\n {0}mb +\n {1}mb language.restart = Reinicia el juego para que los cambios en el idioma tengan efecto. @@ -565,6 +586,7 @@ sector.attacked = Sector [accent]{0}[white] bajo ataque[]! sector.lost = ¡Sector [accent]{0}[white] perdido[]! #nota: el espacio en blanco en la línea siguiente es intencionado sector.captured = ¡Sector [accent]{0}[white] capturado[]! +sector.changeicon = Cambiar Icono threat.low = Baja threat.medium = Media @@ -611,6 +633,20 @@ sector.extractionOutpost.description = Una base remota, construida por el enemig sector.impact0078.description = Aquí yacen las ruinas de la primera estación de transporte interestelar en estar operativa del sistema.\n\nRecupera todo lo posible de los escombros. Investiga cualquier tecnología intacta. sector.planetaryTerminal.description = El objetivo final.\n\nÉsta base costera alberga una estructura capaz de lanzar Núcleos a planeteas locales. Está extremadamente bien protegida.\n\nProduce unidades navales. Acaba con el enemigo lo antes posible. Analiza la estructura de lanzamiento. +status.burning.name = En llamas +status.freezing.name = Congelado +status.wet.name = Húmedo +status.muddy.name = Fangoso +status.melting.name = Fundido +status.sapped.name = Debilitado +status.electrified.name = Electrificado +status.spore-slowed.name = Ralentizado +status.tarred.name = Alquitranado +status.overclock.name = Sobrecargado +status.shocked.name = Aturdido +status.blasted.name = Explotado +status.unmoving.name = Inmóvil + settings.language = Idioma settings.data = Datos del Juego settings.reset = Reiniciar a los valores por defecto @@ -632,6 +668,7 @@ settings.clearcampaignsaves.confirm = ¿Quieres borrar tus partidas guardadas en paused = [accent] < Pausado > clear = Vaciar banned = [scarlet]Baneado +unsupported.environment = [scarlet]Entorno no válido yes = Sí no = No info.title = Información @@ -641,12 +678,14 @@ unit.nobuild = [scarlet]Esta unidad no puede construir lastaccessed = [lightgray]Último usado: {0} block.unknown = [lightgray]??? +stat.showinmap = stat.description = Objetivo stat.input = Entrada stat.output = Salida stat.booster = Potenciador stat.tiles = Terreno requerido stat.affinities = Afinidades +stat.opposites = Opuestos stat.powercapacity = Capacidad de Energía stat.powershot = Energía/Disparo stat.damage = Daño @@ -669,6 +708,7 @@ stat.memorycapacity = Capacidad de memoria stat.basepowergeneration = Generación de energía stat.productiontime = Tiempo de producción stat.repairtime = Tiempo para Reparar Bloque Completamente +stat.repairspeed = Velocidad de Reparación stat.weapons = Armas stat.bullet = Proyectil stat.speedincrease = Aumento de Velocidad @@ -705,15 +745,24 @@ stat.minetier = Nivel de taladro stat.payloadcapacity = Capacidad de carga stat.commandlimit = Límite de comando stat.abilities = Habilidades -stat.canboost = Tiene Propulsores +stat.canboost = Potenciador stat.flying = Aéreo +stat.ammouse = Usa Munición +stat.damagemultiplier = Multiplicador de Daño +stat.healthmultiplier = Multiplicador de Vida +stat.speedmultiplier = Multiplicador de Velocidad +stat.reloadmultiplier = Multiplicador de Recarga +stat.buildspeedmultiplier = Multiplicador de Velocidad de Construcción +stat.reactive = Reacciona +stat.healing = Sanador -ability.forcefield = Campo de Fuerza +ability.forcefield = Campo de Escudo ability.repairfield = Campo de Reparación -ability.statusfield = Campo de Estado -ability.unitspawn = {0} Fábrica de Drones -ability.shieldregenfield = Campo de Regeneración de Escudos +ability.statusfield = {0} Campo de aceleración +ability.unitspawn = {0} Fábrica +ability.shieldregenfield = Regeneración de Armaduras ability.movelightning = Movimiento Relámpago +ability.energyfield = Campo de Energía: [accent]{0}[] daño ~ [accent]{1}[] bloques / [accent]{2}[] objetivos bar.drilltierreq = Requiere un taladro mejor bar.noresources = Recursos insuficientes @@ -736,29 +785,28 @@ bar.power = Energía bar.progress = Progreso de construcción bar.input = Entrada bar.output = Salida +bar.strength = [stat]{0}[lightgray]x fuerza units.processorcontrol = [lightgray]Controlado por Procesador bullet.damage = [stat]{0}[lightgray] Daño -bullet.splashdamage = [stat]{0}[lightgray] daño de área ~[stat] {1}[lightgray] casillas +bullet.splashdamage = [stat]{0}[lightgray] área daño ~[stat] {1}[lightgray] bloques bullet.incendiary = [stat]Incendiaria -bullet.sapping = [stat]Oxidante bullet.homing = [stat]Rastreadora -bullet.shock = [stat]Electrizante bullet.frag = [stat]De fragmentación -bullet.buildingdamage = [stat]{0}%[lightgray]daño a estructuras -bullet.knockback = [stat]{0}[lightgray] Empuje -bullet.pierce = [stat]{0}[lightgray]x penetración -bullet.infinitepierce = [stat]Penetrante +bullet.lightning = [stat]{0}[lightgray]x rayo ~ [stat]{1}[lightgray] daño +bullet.buildingdamage = [stat]{0}%[lightgray] daño a estructuras +bullet.knockback = [stat]{0}[lightgray] empuje +bullet.pierce = [stat]{0}[lightgray]x perforación +bullet.infinitepierce = [stat]Perforante bullet.healpercent = [stat]{0}[lightgray]% reparación -bullet.freezing = [stat]Congelación -bullet.tarred = [stat]Ralentizado bullet.multiplier = [stat]{0}[lightgray]x multiplicador de munición bullet.reload = [stat]{0}[lightgray]x cadencia de fuego unit.blocks = bloques unit.blockssquared = bloques² unit.powersecond = unidades de energía/segundo +unit.tilessecond = bloques/segundo unit.liquidsecond = unidades de líquido/segundo unit.itemssecond = objetos/segundo unit.liquidunits = unidades de líquido @@ -775,6 +823,7 @@ unit.items = objetos unit.thousands = k unit.millions = M unit.billions = b +unit.pershot = /disparo category.purpose = Objetivo category.general = General category.power = Energía @@ -788,10 +837,13 @@ setting.shadows.name = Sombras setting.blockreplace.name = Sugerir bloques al construir setting.linear.name = Filtrado Lineal setting.hints.name = Consejos +setting.logichints.name = Consejos sobre "Bloques Lógicos" setting.flow.name = Mostrar tasa de flujo de recursos setting.backgroundpause.name = Pausar en segundo plano setting.buildautopause.name = Auto-pausar construcción -setting.animatedwater.name = Animaciones de Terreno +setting.doubletapmine.name = Doble-Click para Extraer minerales +setting.modcrashdisable.name = Desactivar Mods si se cuelga el juego +setting.animatedwater.name = Animación de Terreno setting.animatedshields.name = Animación de Escudos setting.antialias.name = Antialias[lightgray] (necesita un reinicio)[] setting.playerindicators.name = Indicadores de Jugadores @@ -844,6 +896,7 @@ setting.bridgeopacity.name = Opacidad de Puentes Transportadores setting.playerchat.name = Mostrar el chat de burbuja setting.showweather.name = Efectos visuales climáticos public.confirm = ¿Quieres hacer pública tu partida?\n[lightgray]Esto se puede cambiar más tarde en "Configuración->Juego->Visibilidad pública de la partida". +public.confirm.really = ¡Si quieres jugar con amigos, usa [green]Invitar a Amigos[] en lugar de un [scarlet]Servidor Público[]!\n¿De verdad quieres hacer [scarlet]pública[] tu partida? public.beta = Recuerda que no puedes crear partidas públicas en las versiones beta del juego. uiscale.reset = La escala de la interfaz ha sido modificada.\nPulsa "OK" para conservar esta escala.\n[scarlet]Se desharán los cambios automáticamente en [accent] {0}[] segundos... uiscale.cancel = Cancelar y Salir @@ -908,7 +961,8 @@ keybind.pause.name = Pausa keybind.pause_building.name = Pausar/Reanudar construcción keybind.minimap.name = Minimapa keybind.planet_map.name = Mapa del Planeta -keybind.research.name = Investigaciones +keybind.research.name = Investigar +keybind.block_info.name = Información del Bloque keybind.chat.name = Chat keybind.player_list.name = Lista de jugadores keybind.console.name = Consola @@ -935,18 +989,23 @@ mode.custom = Normas personalizadas rules.infiniteresources = Recursos infinitos rules.reactorexplosions = Los reactores pueden explotar +rules.coreincinerates = Núcleos inceran exceso de recursos rules.schematic = Permitir Plantillas rules.wavetimer = Temporizador de Oleadas rules.waves = Oleadas -rules.attack = Ataque -rules.buildai = La IA enemiga puede construir -rules.enemyCheat = La IA enemiga tiene recursos infinitos -rules.blockhealthmultiplier = Multiplicador de salud de bloque -rules.blockdamagemultiplier = Multiplicador de daño de bloque +rules.attack = Asalto +rules.buildai = Contrucción de IA +rules.corecapture = Capturar Núcleo al Destruirlo +rules.polygoncoreprotection = Protección de Núcleo Poligonal +rules.enemyCheat = La IA (Equipo Rojo) tiene recursos infinitos +rules.blockhealthmultiplier = Multiplicador de Salud de Bloque +rules.blockdamagemultiplier = Multiplicador de Daño de Bloque rules.unitbuildspeedmultiplier = Multiplicador de velocidad de creación de unidades -rules.unithealthmultiplier = Multiplicador de la vida de las unidades -rules.unitdamagemultiplier = Multiplicador del daño de unidades -rules.enemycorebuildradius = Radio de No-Construcción del Núcleo Enemigo:[lightgray] (casillas) +rules.unithealthmultiplier = Multiplicador de Vida de Unidades +rules.unitdamagemultiplier = Multiplicador de Daño de Unidades +rules.unitcapvariable = Núcleos alteran el Límite de Unidades +rules.unitcap = Límite Base de Unidades +rules.enemycorebuildradius = Radio de No-Construcción del Núcleo Enemigo:[lightgray] (bloques) rules.wavespacing = Tiempo entre oleadas:[lightgray] (seg) rules.buildcostmultiplier = Multiplicador de coste de construcción rules.buildspeedmultiplier = Multiplicador de velocidad de construcción @@ -967,12 +1026,14 @@ rules.explosions = Daño de explosiones de Bloques/Unidades rules.ambientlight = Iluminación ambiental rules.weather = Clima rules.weather.frequency = Frequencia: +rules.weather.always = Siempre rules.weather.duration = Duracion: content.item.name = Objetos content.liquid.name = Líquidos content.unit.name = Unidades content.block.name = Bloques +content.status.name = Alteraciones de Estado content.sector.name = Sectores item.copper.name = Cobre @@ -983,7 +1044,7 @@ item.titanium.name = Titanio item.thorium.name = Torio item.silicon.name = Silicio item.plastanium.name = Plastanio -item.phase-fabric.name = Tejido de fase +item.phase-fabric.name = Tejido de Fase item.surge-alloy.name = Aleación Eléctrica item.spore-pod.name = Vaina de Esporas item.sand.name = Arena @@ -991,11 +1052,12 @@ item.blast-compound.name = Compuesto Explosivo item.pyratite.name = Pirotita item.metaglass.name = Metacristal item.scrap.name = Chatarra + liquid.water.name = Agua liquid.slag.name = Magma liquid.oil.name = Petróleo liquid.cryofluid.name = Líquido criogénico -#Names of Units and Turrets look better untranslated, since they are propper/own names +#Names of Units and Turrets looks better untranslated, since they are propper/own names unit.dagger.name = Dagger unit.mace.name = Mace unit.fortress.name = Fortress @@ -1022,6 +1084,11 @@ unit.minke.name = Minke unit.bryde.name = Bryde unit.sei.name = Sei unit.omura.name = Omura +unit.retusa.name = Retusa +unit.oxynoe.name = Oxynoe +unit.cyerce.name = Cyerce +unit.aegires.name = Aegires +unit.navanax.name = Navanax unit.alpha.name = Alpha unit.beta.name = Beta unit.gamma.name = Gamma @@ -1082,23 +1149,25 @@ block.sand-water.name = Agua con arena block.darksand-water.name = Agua con arena oscura block.char.name = Cenizas block.dacite.name = Dacita -block.dacite-wall.name = Bloque de dacita -block.dacite-boulder.name = Roca de dacita +block.rhyolite.name = Riolita +block.dacite-wall.name = Bloque de Dacita +block.dacite-boulder.name = Roca de Dacita block.ice-snow.name = Hielo-Nieve -block.stone-wall.name = Bloque de piedra -block.ice-wall.name = Bloque de hielo -block.snow-wall.name = Bloque de nieve -block.dune-wall.name = Bloque de arena +block.stone-wall.name = Bloque de Piedra +block.ice-wall.name = Bloque de Hielo +block.snow-wall.name = Bloque de Nieve +block.dune-wall.name = Bloque de Arena block.pine.name = Pino block.dirt.name = Tierra block.dirt-wall.name = Bloque de tierra block.mud.name = Lodo block.white-tree-dead.name = Árbol Blanco Muerto block.white-tree.name = Árbol Blanco -block.spore-cluster.name = Concentración de Esporas -block.metal-floor.name = Suelo de Metal +block.spore-cluster.name = Esporas +block.metal-floor.name = Suelo de Metal 1 block.metal-floor-2.name = Suelo de Metal 2 block.metal-floor-3.name = Suelo de Metal 3 +block.metal-floor-4.name = Suelo de Metal 4 block.metal-floor-5.name = Suelo de Metal 5 block.metal-floor-damaged.name = Suelo de Metal dañado block.dark-panel-1.name = Panel Oscuro 1 @@ -1189,6 +1258,7 @@ block.solar-panel.name = Panel Solar block.solar-panel-large.name = Panel Solar Grande block.oil-extractor.name = Extractor de Petróleo block.repair-point.name = Punto de Reparación de Unidades +block.repair-turret.name = Torreta Reparadora block.pulse-conduit.name = Conducto de Pulso block.plated-conduit.name = Conducto Acorazado block.phase-conduit.name = Conducto de Fase @@ -1221,16 +1291,22 @@ block.container.name = Contenedor block.launch-pad.name = Plataforma de Lanzamiento block.launch-pad-large.name = Plataforma de Lanzamiento Grande block.segment.name = Segment -block.command-center.name = Centro de comando -block.ground-factory.name = Fábrica terrestre -block.air-factory.name = Fábrica aérea +block.command-center.name = Centro de Comando +block.ground-factory.name = Fábrica Terrestre +block.air-factory.name = Fábrica Aérea block.naval-factory.name = Fábrica naval -block.additive-reconstructor.name = Reconstructor aditivo -block.multiplicative-reconstructor.name = Reconstructor multiplicativo -block.exponential-reconstructor.name = Reconstructor exponencial -block.tetrative-reconstructor.name = Reconstructor tetrativo -block.payload-conveyor.name = Transportador de carga -block.payload-router.name = Enrutador de carga +block.additive-reconstructor.name = Reconstructor Aditivo +block.multiplicative-reconstructor.name = Reconstructor Multiplicativo +block.exponential-reconstructor.name = Reconstructor Exponencial +block.tetrative-reconstructor.name = Reconstructor Tetrativo +block.payload-conveyor.name = Cinta Transportadora de Carga +block.payload-router.name = Enrutador de Carga +block.duct.name = Túnel +block.duct-router.name = Túnel Enrutador +block.duct-bridge.name = Túnel Puente +block.payload-propulsion-tower.name = Torre de Propulsión de Bloques +block.payload-void.name = Vacío de Bloques +block.payload-source.name = Fuente de Bloques block.disassembler.name = Desensamblador block.silicon-crucible.name = Crisol de silicio block.overdrive-dome.name = Campo de Aceleración @@ -1252,7 +1328,6 @@ block.memory-bank.name = Servidor de memoria team.blue.name = azul team.crux.name = crux team.sharded.name = sharded -team.orange.name = naranja team.derelict.name = delerict team.green.name = verde team.purple.name = morado @@ -1273,6 +1348,7 @@ hint.placeConveyor.mobile = Las cintas transportadoras pueden mover objetos de l hint.placeTurret = Construye \uf861 [accent]Torretas[] para defender tu base de los enemigos.\n\nLas torretas necesitan munición - en este caso, \uf838cobre.\nUsa cintas transportadoras y taladros para abastecerlas con cobre. hint.breaking = Pulsa [accent]Clic-derecho[] y arrastra para destruir bloques. hint.breaking.mobile = Activa el botón con el \ue817 [accent]martillo[] situado abajo a la derecha y selecciona bloques para eliminarlos.\n\nMantén el dedo un segundo y arrastra para eliminar bloques directamente en esa selección. +hint.blockInfo = Puedes visualizar información de un bloque seleccionándolo en el [accent]menú de construcción[], mediante el botón [accent][[?][] en la derecha. hint.research = Usa el botón \ue875 [accent]Investigación[] para acceder al menú de descubrimientos tecnológicos. hint.research.mobile = Usa el botón \ue875 [accent]Investigación[] para acceder al menú de descubrimientos tecnológicos. hint.unitControl = Mantén [accent][[L-ctrl][] y [accent]haz clic[] sobre unidades o torretas aliadas para controlarlas manualmente. @@ -1319,7 +1395,7 @@ item.spore-pod.details = Esporas. Es algo parecido a una forma de vida sintétic item.blast-compound.description = Usado en bombas y munición explosiva. item.pyratite.description = Usado en armas incendiarias y generadores de combustión. -liquid.water.description = Usada comúnmente para enfriar máquinas y para procesar residuos. +liquid.water.description = Usada para enfriar máquinas y para procesar residuos. liquid.slag.description = Diferentes tipos de metales fundidos mezclados. Puede ser separado en sus minerales constituyentes, o disparado a unidades enemigas como arma. liquid.oil.description = Se utiliza en producción de materiales avanzados, y en munición incendiaria. liquid.cryofluid.description = Usado como refrigerante para reactores, torretas, y fábricas. @@ -1502,3 +1578,155 @@ unit.omura.description = Dispara rayos contínuos perforantes. Construye unidade unit.alpha.description = Defiende el núcleo Shard de los enemigos. Construye estructuras. unit.beta.description = Defiende el núcleo Foundation de los enemigos. Construye estructuras. unit.gamma.description = Defiende el núcleo Nucleus de los enemigos. Construye estructuras. + +lst.read = Lee un número desde una unidad de memoria conectada. +lst.write = Escribe un número en una unidad de memoria conectada. +lst.print = Añade texto a la cola para impresión.\nNo mostrará nada hasta que se use [accent]Ejecutar Imprimir[]. +lst.draw = Añade una operación a la cola de gráfico.\nNo mostrará nada hasta que se use [accent]Ejecutar Gráfico[]. +lst.drawflush = Ejecución en cola de operaciones [accent]Gráfico[] a un monitor gráfico. +lst.printflush = Ejecución en cola de operaciones [accent]Imprimir[] a un bloque de mensaje. +lst.getlink = Obtiene el número de enlace de procesador. Inicia en 0. +lst.control = Controla el estado de un bloque. +lst.radar = Localiza unidades alrededor de un bloque con rango. +lst.sensor = Recopila datos de un bloque o unidad. +lst.set = Establece una variable. +lst.operation = Realiza una operación sobre 1-2 variables. +lst.end = Salta al inicio de la lista de instrucciones. +lst.wait = Espera unos segundos. +lst.lookup = Busca un objeto/líquido/unidad/tipo de bloque por ID.\nSe puede acceder al número total de cada tipo con:\n[accent]@unitCount[] / [accent]@itemCount[] / [accent]@liquidCount[] / [accent]@blockCount[] +lst.jump = Salta a otra instrucción. +lst.unitbind = Se enlaza a la siguiente unidad de un tipo, y la almacena en [accent]@unit[]. +lst.unitcontrol = Controla la unidad actualmente enlazada. +lst.unitradar = Localiza unidades alrededor de la unidad actualmente enlazada. +lst.unitlocate = Localiza un tipo específico de posición/bloque en cualquier lugar del mapa.\nRequiere una unidad enlazada. + +logic.nounitbuild = [red]No se permite la construcción de bloques de categoría lógica. + +lenum.type = El tipo de bloque/unidad\nEjemplo: "para cualquier enrutador", devolverá [accent]@router[].\nNo es una cadena de texto. +lenum.shoot = Dispara a una posición. +lenum.shootp = Dispara a una unidad/bloque con predicción de velocidad. +lenum.config = Configuración de bloque, por ejemplo: clasificador. +lenum.enabled = Si el bloque está activado o no. + +laccess.color = Color del iluminador. +laccess.controller = Controlador de unidad. Si se controla mediante un procesador, devuelve dicho procesador.\nSi está en formación, devuelve su líder.\nDe otra forma, devuelve la misma unidad. +laccess.dead = Si una unidad/bloque es destruída o inválida. +laccess.controlled = Devuelve:\n[accent]@ctrlProcessor[] si el control de la unidad lo tiene un procesador\n[accent]@ctrlPlayer[] si el control de la unidad/bloque lo tiene un jugador\n[accent]@ctrlFormation[] si la unidad está en formación\nDe otra forma, devuelve 0. +laccess.commanded = [red]En desuso. ¡Será eliminado![]\nUsa [accent]controlado[] en su lugar. +laccess.progress = Progreso de una acción, 0 a 1.\nDevuelve de una producción, recarga de una torreta o progreso de una construcción. + +graphicstype.clear = Llena el monitor con un color. +graphicstype.color = Establece el color para próximas operaciones de gráficos. +graphicstype.stroke = Establece el ancho de la línea. +graphicstype.line = Segmento de la línea del gráfico. +graphicstype.rect = Rellena un rectángulo. +graphicstype.linerect = Dibuja las aristas de un rectángulo. +graphicstype.poly = Rellena un polígono regular. +graphicstype.linepoly = Dibuja las aristas de un polígono regular. +graphicstype.triangle = Rellena un triángulo. +graphicstype.image = Dibuja una imágen de un contenido.\nEjemplo: [accent]@router[] o [accent]@dagger[]. + +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.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.or = Comprobación bit a bit OR. +lenum.land = Comprobación lógica AND. +lenum.and = Comprobación bit a bit AND. +lenum.not = Comprobación bit a bit invertida. +lenum.xor = Comprobación bit a bit XOR. + +lenum.min = Mínimo de dos números. +lenum.max = Máximo de dos números. +lenum.angle = Ángulo del vector en grados. +lenum.len = Longitud del vector. + +lenum.sin = Seno, en grados. +lenum.cos = Coseno, en grados. +lenum.tan = Tangente, en grados. + +lenum.asin = Arco seno, en grados. +lenum.acos = Arco coseno, en grados. +lenum.atan = Arco tangente, en grados. + +#not a typo, look up 'range notation' +lenum.rand = Número decimal aleatorio en un rango [0, valor). +lenum.log = Logaritmo natural (ln). +lenum.log10 = Logaritmo en base 10. +lenum.noise = Ruido simplex 2D. +lenum.abs = Valor absoluto. +lenum.sqrt = Raíz cuadrada. + +lenum.any = Cualquier unidad. +lenum.ally = Unidad aliada. +lenum.attacker = Unidad con un arma. +lenum.enemy = Unidad enemiga. +lenum.boss = Unidad guardián (Jefe). +lenum.flying = Unidad aérea. +lenum.ground = Unidad terrestre. +lenum.player = Unidad controlada por un jugador. + +lenum.ore = Depósito mineral. +lenum.damaged = Bloque aliado dañado. +lenum.spawn = Punto de aterrizaje enemigo.\nPuede ser un núcleo o una posición. +lenum.building = Un bloque de una categoría específica. + +lenum.core = Cualquier núcleo. +lenum.storage = Bloque de almacenamiento, ejemplo: Contenedor. +lenum.generator = Bloques que generan energía. +lenum.factory = Bloques que transforman recursos. +lenum.repair = Puntos de reparación. +lenum.rally = Centro de comando. +lenum.battery = Cualquier batería. +lenum.resupply = Puntos de reabastecimiento.\nSólo es relevante cuando [accent]"Unidades necesitan munición"[] está activada. +lenum.reactor = Reactor de Impacto/Torio. +lenum.turret = Cualquier torreta. + +sensor.in = El bloque/unidad a detectar. + +radar.from = Bloque del que detectar.\nEl rango del sensor está limitado por el rango de dicha construcción. +radar.target = Filtro de unidades a detectar. +radar.and = Filtros adicionales. +radar.order = Orden para ordenar. 0 para invertir. +radar.sort = Métrica a usar al ordenar resultados. +radar.output = Variable en la que escribir la salida de una unidad. + +unitradar.target = Filtro para detectar unidades. +unitradar.and = Filtros adicionales. +unitradar.order = Orden para ordenar. 0 para invertir. +unitradar.sort = Métrica a usar al ordenar resultados. +unitradar.output = Variable en la que escribir la salida de una unidad. + +control.of = Bloque a controlar. +control.unit = Unidad/bloque al que apuntar. +control.shoot = Cuándo disparar. + +unitlocate.enemy = Cuándo localizar construcciones enemigas. +unitlocate.found = Cuándo el objeto es encontrado. +unitlocate.building = Variable de salida para contrucciones localizadas. +unitlocate.outx = Coordenada X devuelta. +unitlocate.outy = Coordenada Y devuelta. +unitlocate.group = Grupo de bloque a buscar. + +lenum.idle = No se mueve, pero seguirá construyendo/extrayendo minerales.\nEs el estado por defecto. +lenum.stop = Deja de moverse/extraer minerales/contruir. +lenum.move = Moverse a una posición exacta. +lenum.approach = Aproximarse a una posición con un radio. +lenum.pathfind = Establece una ruta hasta el punto de aterrizaje enemigo. +lenum.target = Dispara a una posición. +lenum.targetp = Dispara a un objetivo con predicción de velocidad. +lenum.itemdrop = Suelta un objeto. +lenum.itemtake = Recoge un objeto de una construcción. +lenum.paydrop = Suelta la carga actual. +lenum.paytake = Recoge bloques o unidades en la posición actual como carga a trasnportar. +lenum.flag = Etiqueta numérica de la unidad. +lenum.mine = Extrae minerales de una posición. +lenum.build = Construye una estructura. +lenum.getblock = Obtiene la construcción y su categoría en unas coordenadas específicas.\nLa unidad debe estar en el rango de su posición.\nLos bloques no-construcciones tendrán el tipo [accent]@solid[]. +lenum.within = Comprueba si una unidad se encuentra cerca de una posición. +lenum.boost = Inicia/Detiene potenciación. diff --git a/core/assets/bundles/bundle_fr.properties b/core/assets/bundles/bundle_fr.properties index d89400769f..942ae5c750 100644 --- a/core/assets/bundles/bundle_fr.properties +++ b/core/assets/bundles/bundle_fr.properties @@ -807,6 +807,7 @@ bullet.reload = [stat]{0}[lightgray]x vitesse de tir unit.blocks = blocs unit.blockssquared = blocs² unit.powersecond = unités d'énergie/seconde +unit.tilessecond = tuiles/seconde unit.liquidsecond = unités de liquide/seconde unit.itemssecond = objets/seconde unit.liquidunits = unités de liquide @@ -1601,6 +1602,8 @@ lst.sensor = Récupère des données depuis un bâtiment ou une unité. lst.set = Définit une variable. lst.operation = Effectue une opération sur 1 ou 2 variables. lst.end = Saute au sommet de la série d’instructions. +lst.wait = Attendre un certain nombre de secondes. +lst.lookup = Recherche d'un type d'objet/liquide/unité/bloc par ID.\nLe nombre total de chaque type peut être consulté avec:\n[accent]@unitCount[] / [accent]@itemCount[] / [accent]@liquidCount[] / [accent]@blockCount[] lst.jump = Saute conditionnellement vers une autre instruction. lst.unitbind = Se lie à une unité du type donné et la stocke dans [accent]@unit[]. lst.unitcontrol = Contrôle l'unité actuellement liée. diff --git a/core/assets/bundles/bundle_ko.properties b/core/assets/bundles/bundle_ko.properties index 917ef699f4..ef57409e9d 100644 --- a/core/assets/bundles/bundle_ko.properties +++ b/core/assets/bundles/bundle_ko.properties @@ -806,6 +806,7 @@ bullet.reload = [stat]{0}[lightgray]배 발사 속도 unit.blocks = 블록 unit.blockssquared = 블록² unit.powersecond = 전력/초 +unit.tilessecond = 타일/초 unit.liquidsecond = 액체/초 unit.itemssecond = 자원/초 unit.liquidunits = 액체 diff --git a/core/assets/bundles/bundle_ru.properties b/core/assets/bundles/bundle_ru.properties index 6162508307..8a8c1924de 100644 --- a/core/assets/bundles/bundle_ru.properties +++ b/core/assets/bundles/bundle_ru.properties @@ -806,6 +806,7 @@ bullet.reload = [stat]{0}[lightgray]x скорость стрельбы unit.blocks = блоков unit.blockssquared = блоков² unit.powersecond = единиц энергии/секунду +unit.tilessecond = плиток/секунду unit.liquidsecond = жидкостных единиц/секунду unit.itemssecond = предметов/секунду unit.liquidunits = жидкостных единиц @@ -1570,7 +1571,7 @@ unit.mega.description = Автоматически ремонтирует пов unit.quad.description = Сбрасывает большие бомбы на наземные цели, восстанавливая союзные постройки и повреждая врагов. Может переносить единицы среднего размера. unit.oct.description = Защищает союзников поблизости при помощи своего восстанавливающегося щита. Может переносить большинство наземных единиц. unit.risso.description = Стреляет залпами ракет и пуль по всем врагам поблизости. -unit.minke.description = Стреляет зажигательными снарядами и стандартными пулями по наземным целям. +unit.minke.description = Стреляет артиллерийскими снарядами и стандартными пулями по наземным целям. unit.bryde.description = Стреляет дальнобойными артиллерийскими снарядами и ракетами по врагам. unit.sei.description = Стреляет залпами ракет и бронебойных пуль по врагам. unit.omura.description = Стреляет дальнобойным пробивающим снарядом из рельсотрона по врагам. Производит единицы «Вспышка». @@ -1591,6 +1592,8 @@ lst.sensor = Получает данные из постройки или еди lst.set = Устанавливает переменную. lst.operation = Совершает операцию над 1-2 переменными. lst.end = Переходит к началу стека операций. +lst.wait = Ждёт определённое количество секунд. +lst.lookup = Находит тип предмета/жидкости/единицы/блока по ID.\nОбщее количество каждого типа может быть получено при помощи:\n[accent]@unitCount[] / [accent]@itemCount[] / [accent]@liquidCount[] / [accent]@blockCount[] lst.jump = Условно переходит к другой операции. lst.unitbind = Привязывается к единице определённого типа и сохраняет её в [accent]@unit[]. lst.unitcontrol = Управляет привязанной в данный момент единицей. diff --git a/core/assets/sounds/mineDeploy.ogg b/core/assets/sounds/mineDeploy.ogg new file mode 100644 index 0000000000..69fb5d2f98 Binary files /dev/null and b/core/assets/sounds/mineDeploy.ogg differ diff --git a/core/assets/sounds/plantBreak.ogg b/core/assets/sounds/plantBreak.ogg new file mode 100644 index 0000000000..08d911b3e7 Binary files /dev/null and b/core/assets/sounds/plantBreak.ogg differ diff --git a/core/assets/sounds/rockBreak.ogg b/core/assets/sounds/rockBreak.ogg new file mode 100644 index 0000000000..6a17a5edc2 Binary files /dev/null and b/core/assets/sounds/rockBreak.ogg differ diff --git a/core/src/mindustry/Vars.java b/core/src/mindustry/Vars.java index 2f61b463c7..224f8ec96e 100644 --- a/core/src/mindustry/Vars.java +++ b/core/src/mindustry/Vars.java @@ -24,10 +24,8 @@ import mindustry.logic.*; import mindustry.maps.Map; import mindustry.maps.*; import mindustry.mod.*; -import mindustry.net.Net; import mindustry.net.*; import mindustry.service.*; -import mindustry.world.*; import java.io.*; import java.nio.charset.*; @@ -113,8 +111,6 @@ public class Vars implements Loadable{ public static final float tilePayload = tilesize * tilesize; /** icon sizes for UI */ public static final float iconXLarge = 8*6f, iconLarge = 8*5f, iconMed = 8*4f, iconSmall = 8*3f; - /** tile used in certain situations, instead of null */ - public static Tile emptyTile; /** for map generator dialog */ public static boolean updateEditorOnChange = false; /** all choosable player colors in join/host dialog */ @@ -278,7 +274,6 @@ public class Vars implements Loadable{ schematicDirectory = dataDirectory.child("schematics/"); bebuildDirectory = dataDirectory.child("be_builds/"); emptyMap = new Map(new StringMap()); - emptyTile = null; if(tree == null) tree = new FileTree(); if(mods == null) mods = new Mods(); diff --git a/core/src/mindustry/ai/BlockIndexer.java b/core/src/mindustry/ai/BlockIndexer.java index 2fb2467437..430630f5d3 100644 --- a/core/src/mindustry/ai/BlockIndexer.java +++ b/core/src/mindustry/ai/BlockIndexer.java @@ -106,7 +106,7 @@ public class BlockIndexer{ public void removeIndex(Tile tile){ var team = tile.team(); - if(team != Team.derelict && tile.isCenter()){ + if(tile.build != null && tile.isCenter()){ var flags = tile.block().flags; var data = team.data(); diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 1f41ed08d5..d263b4a56a 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -245,7 +245,6 @@ public class Blocks implements ContentList{ magmarock = new Floor("magmarock"){{ attributes.set(Attribute.heat, 0.75f); attributes.set(Attribute.water, -0.75f); - updateEffect = Fx.magmasmoke; blendGroup = basalt; emitLight = true; @@ -452,6 +451,7 @@ public class Blocks implements ContentList{ sporeCluster = new Prop("spore-cluster"){{ variants = 3; + breakSound = Sounds.plantBreak; }}; redweed = new Seaweed("redweed"){{ diff --git a/core/src/mindustry/content/StatusEffects.java b/core/src/mindustry/content/StatusEffects.java index 2ea8af6c9d..bc0a7e4864 100644 --- a/core/src/mindustry/content/StatusEffects.java +++ b/core/src/mindustry/content/StatusEffects.java @@ -47,7 +47,6 @@ public class StatusEffects implements ContentList{ affinity(blasted, ((unit, result, time) -> { unit.damagePierce(transitionDamage); - result.set(freezing, time); })); }); }}; @@ -75,7 +74,6 @@ public class StatusEffects implements ContentList{ if(unit.team == state.rules.waveTeam){ Events.fire(Trigger.shock); } - result.set(wet, time); })); opposite(burning, melting); }); diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index b6a8d995d6..8cfaa3f989 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -1780,6 +1780,7 @@ public class UnitTypes implements ContentList{ shots = 3; shotDelay = 7f; x = y = shootX = shootY = 0f; + shootSound = Sounds.mineDeploy; bullet = new BasicBulletType(){{ sprite = "mine-bullet"; @@ -2047,7 +2048,6 @@ public class UnitTypes implements ContentList{ buildSpeed = 3f; abilities.add(new EnergyFieldAbility(35f, 65f, 180f){{ - repair = 35f; statusDuration = 60f * 6f; maxTargets = 25; }}); @@ -2151,6 +2151,8 @@ public class UnitTypes implements ContentList{ shootY = 7f; recoil = 4f; cooldownTime = reload - 10f; + //TODO better sound + shootSound = Sounds.laser; bullet = new EmpBulletType(){{ float rad = 100f; @@ -2183,6 +2185,7 @@ public class UnitTypes implements ContentList{ hitShake = 4f; trailRotation = true; status = StatusEffects.electrified; + hitSound = Sounds.plasmaboom; trailEffect = new Effect(16f, e -> { color(Pal.heal); diff --git a/core/src/mindustry/core/NetServer.java b/core/src/mindustry/core/NetServer.java index 905425f1c9..64cd73c4ad 100644 --- a/core/src/mindustry/core/NetServer.java +++ b/core/src/mindustry/core/NetServer.java @@ -344,8 +344,7 @@ public class NetServer implements ApplicationListener{ boolean checkPass(){ if(votes >= votesRequired()){ Call.sendMessage(Strings.format("[orange]Vote passed.[scarlet] @[orange] will be banned from the server for @ minutes.", target.name, (kickDuration / 60))); - target.getInfo().lastKicked = Time.millis() + kickDuration * 1000; - Groups.player.each(p -> p.uuid().equals(target.uuid()), p -> p.kick(KickReason.vote)); + Groups.player.each(p -> p.uuid().equals(target.uuid()), p -> p.kick(KickReason.vote, kickDuration * 1000)); map[0] = null; task.cancel(); return true; diff --git a/core/src/mindustry/entities/abilities/EnergyFieldAbility.java b/core/src/mindustry/entities/abilities/EnergyFieldAbility.java index 587fff2bdc..8681e37843 100644 --- a/core/src/mindustry/entities/abilities/EnergyFieldAbility.java +++ b/core/src/mindustry/entities/abilities/EnergyFieldAbility.java @@ -1,6 +1,7 @@ package mindustry.entities.abilities; import arc.*; +import arc.audio.*; import arc.graphics.*; import arc.graphics.g2d.*; import arc.math.*; @@ -16,14 +17,15 @@ import mindustry.type.*; public class EnergyFieldAbility extends Ability{ private static final Seq all = new Seq<>(); - public float damage = 1, repair = 20f, reload = 100, range = 60; + public float damage = 1, reload = 100, range = 60; public Effect healEffect = Fx.heal, hitEffect = Fx.hitLaserBlast, damageEffect = Fx.chainLightning; public StatusEffect status = StatusEffects.electrified; + public Sound shootSound = Sounds.spark; public float statusDuration = 60f * 6f; public float x, y; public boolean hitBuildings = true; public int maxTargets = 25; - public float healPercent = 3f; + public float healPercent = 2.5f; public float layer = Layer.bullet - 0.001f, blinkScl = 20f; public float effectRadius = 5f, sectorRad = 0.14f, rotateSpeed = 0.5f; @@ -139,6 +141,10 @@ public class EnergyFieldAbility extends Ability{ } } + if(anyNearby){ + shootSound.at(unit); + } + timer = 0f; } } diff --git a/core/src/mindustry/entities/bullet/BulletType.java b/core/src/mindustry/entities/bullet/BulletType.java index ebe84d0f24..4a1df75e62 100644 --- a/core/src/mindustry/entities/bullet/BulletType.java +++ b/core/src/mindustry/entities/bullet/BulletType.java @@ -232,8 +232,8 @@ public class BulletType extends Content implements Cloneable{ } if(entity instanceof Unit unit){ - Tmp.v3.set(unit).sub(b.x, b.y).nor().scl(knockback * 80f); - if(impact) Tmp.v3.setAngle(b.rotation()); + Tmp.v3.set(unit).sub(b).nor().scl(knockback * 80f); + if(impact) Tmp.v3.setAngle(b.rotation() + (knockback < 0 ? 180f : 0f)); unit.impulse(Tmp.v3); unit.apply(status, statusDuration); } diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index 83c20b40ab..3ccc414500 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -106,7 +106,6 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, /** Sets up all the necessary variables, but does not add this entity anywhere. */ public Building create(Block block, Team team){ - this.tile = emptyTile; this.block = block; this.team = team; @@ -1443,7 +1442,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, @Override public void killed(){ Events.fire(new BlockDestroyEvent(tile)); - block.breakSound.at(tile); + block.destroySound.at(tile); onDestroyed(); tile.remove(); remove(); diff --git a/core/src/mindustry/entities/comp/PhysicsComp.java b/core/src/mindustry/entities/comp/PhysicsComp.java index 1924de8eb9..a3009fe2a8 100644 --- a/core/src/mindustry/entities/comp/PhysicsComp.java +++ b/core/src/mindustry/entities/comp/PhysicsComp.java @@ -2,6 +2,7 @@ package mindustry.entities.comp; import arc.math.*; import arc.math.geom.*; +import arc.util.*; import mindustry.annotations.Annotations.*; import mindustry.async.PhysicsProcess.*; import mindustry.gen.*; diff --git a/core/src/mindustry/entities/comp/PlayerComp.java b/core/src/mindustry/entities/comp/PlayerComp.java index 14cb71c10f..057687ada8 100644 --- a/core/src/mindustry/entities/comp/PlayerComp.java +++ b/core/src/mindustry/entities/comp/PlayerComp.java @@ -238,6 +238,10 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra con.kick(reason); } + void kick(KickReason reason, long duration){ + con.kick(reason, duration); + } + void kick(String reason){ con.kick(reason); } diff --git a/core/src/mindustry/logic/LExecutor.java b/core/src/mindustry/logic/LExecutor.java index 73a83c00b2..c2b3fac347 100644 --- a/core/src/mindustry/logic/LExecutor.java +++ b/core/src/mindustry/logic/LExecutor.java @@ -363,6 +363,9 @@ public class LExecutor{ float x1 = World.unconv(exec.numf(p1)), y1 = World.unconv(exec.numf(p2)), d1 = World.unconv(exec.numf(p3)); switch(type){ + case idle -> { + ai.control = type; + } case move, stop, approach -> { ai.control = type; ai.moveX = x1; diff --git a/core/src/mindustry/maps/filters/FilterOption.java b/core/src/mindustry/maps/filters/FilterOption.java index ea97157abf..6b2e3aa1f1 100644 --- a/core/src/mindustry/maps/filters/FilterOption.java +++ b/core/src/mindustry/maps/filters/FilterOption.java @@ -3,12 +3,15 @@ package mindustry.maps.filters; import arc.*; import arc.func.*; +import arc.scene.event.*; import arc.scene.style.*; import arc.scene.ui.*; import arc.scene.ui.layout.*; +import arc.util.*; import mindustry.*; import mindustry.content.*; import mindustry.gen.*; +import mindustry.ui.*; import mindustry.ui.dialogs.*; import mindustry.world.*; import mindustry.world.blocks.environment.*; @@ -35,7 +38,7 @@ public abstract class FilterOption{ final Floatc setter; final float min, max, step; - boolean display; + boolean display = true; SliderOption(String name, Floatp getter, Floatc setter, float min, float max){ this(name, getter, setter, min, max, (max - min) / 200); @@ -57,19 +60,27 @@ public abstract class FilterOption{ @Override public void build(Table table){ + Label label; if(!display){ - table.add("@filter.option." + name); + label = new Label("@filter.option." + name); }else{ - table.label(() -> Core.bundle.get("filter.option." + name) + ": " + (int)getter.get()); + label = new Label(() -> Core.bundle.get("filter.option." + name) + ": " + Strings.autoFixed(getter.get(), 2)); } - table.row(); - Slider slider = table.slider(min, max, step, setter).growX().get(); + label.setWrap(true); + label.setAlignment(Align.center); + label.touchable = Touchable.disabled; + label.setStyle(Styles.outlineLabel); + + Slider slider = new Slider(min, max, step, false); + slider.moved(setter); slider.setValue(getter.get()); if(updateEditorOnChange){ slider.changed(changed); }else{ slider.released(changed); } + + table.stack(slider, label).colspan(2).pad(3).growX().row(); } } diff --git a/core/src/mindustry/mod/Mods.java b/core/src/mindustry/mod/Mods.java index 1380251730..693ac2222a 100644 --- a/core/src/mindustry/mod/Mods.java +++ b/core/src/mindustry/mod/Mods.java @@ -86,7 +86,8 @@ public class Mods implements Loadable{ /** Imports an external mod file. Folders are not supported here. */ public LoadedMod importMod(Fi file) throws IOException{ - String baseName = file.nameWithoutExtension(); + //for some reason, android likes to add colons to file names, e.g. primary:ExampleJavaMod.jar, which breaks dexing + String baseName = file.nameWithoutExtension().replace(':', '_').replace(' ', '_'); String finalName = baseName; //find a name to prevent any name conflicts int count = 1; @@ -300,12 +301,12 @@ public class Mods implements Loadable{ } private PageType getPage(Fi file){ - String parent = file.parent().name(); + String path = file.path(); return - parent.equals("environment") ? PageType.environment : - parent.equals("editor") ? PageType.editor : - parent.equals("rubble") ? PageType.editor : - parent.equals("ui") || file.parent().parent().name().equals("ui") ? PageType.ui : + path.contains("sprites/blocks/environment") ? PageType.environment : + path.contains("sprites/editor") ? PageType.editor : + path.contains("sprites/rubble") ? PageType.editor : + path.contains("sprites/ui") ? PageType.ui : PageType.main; } diff --git a/core/src/mindustry/net/NetConnection.java b/core/src/mindustry/net/NetConnection.java index a7bcc9b7fd..87eedd6675 100644 --- a/core/src/mindustry/net/NetConnection.java +++ b/core/src/mindustry/net/NetConnection.java @@ -4,7 +4,6 @@ import arc.struct.*; import arc.util.*; import mindustry.entities.units.*; import mindustry.gen.*; -import mindustry.net.Administration.*; import mindustry.net.Packets.*; import java.io.*; @@ -37,38 +36,39 @@ public abstract class NetConnection{ /** Kick with a special, localized reason. Use this if possible. */ public void kick(KickReason reason){ - if(kicked) return; + kick(reason, (reason == KickReason.kick || reason == KickReason.banned || reason == KickReason.vote) ? 30 * 1000 : 0); + } - Log.info("Kicking connection @ / @; Reason: @", address, uuid, reason.name()); - - if((reason == KickReason.kick || reason == KickReason.banned || reason == KickReason.vote)){ - PlayerInfo info = netServer.admins.getInfo(uuid); - info.timesKicked++; - info.lastKicked = Math.max(Time.millis() + 30 * 1000, info.lastKicked); - } - - Call.kick(this, reason); - - close(); - - netServer.admins.save(); - kicked = true; + /** Kick with a special, localized reason. Use this if possible. */ + public void kick(KickReason reason, long kickDuration){ + kick(null, reason, kickDuration); } /** Kick with an arbitrary reason. */ public void kick(String reason){ - kick(reason, 30 * 1000); + kick(reason, null, 30 * 1000); + } + + /** Kick with an arbitrary reason. */ + public void kick(String reason, long duration){ + kick(reason, null, duration); } /** Kick with an arbitrary reason, and a kick duration in milliseconds. */ - public void kick(String reason, long kickDuration){ + private void kick(String reason, KickReason kickType, long kickDuration){ if(kicked) return; - Log.info("Kicking connection @ / @; Reason: @", address, uuid, reason.replace("\n", " ")); + Log.info("Kicking connection @ / @; Reason: @", address, uuid, reason == null ? kickType.name() : reason.replace("\n", " ")); - netServer.admins.handleKicked(uuid, address, kickDuration); + if(kickDuration > 0){ + netServer.admins.handleKicked(uuid, address, kickDuration); + } - Call.kick(this, reason); + if(reason == null){ + Call.kick(this, kickType); + }else{ + Call.kick(this, reason); + } close(); diff --git a/core/src/mindustry/type/Weapon.java b/core/src/mindustry/type/Weapon.java index 7df7a4cece..ddc49cf8d2 100644 --- a/core/src/mindustry/type/Weapon.java +++ b/core/src/mindustry/type/Weapon.java @@ -249,7 +249,7 @@ public class Weapon implements Cloneable{ unit.vel.add(Tmp.v1.trns(unit.rotation + 180f, mount.bullet.type.recoil)); if(shootSound != Sounds.none && !headless){ if(mount.sound == null) mount.sound = new SoundLoop(shootSound, 1f); - mount.sound.update(x, y, true); + mount.sound.update(bulletX, bulletY, true); } } }else{ @@ -285,8 +285,7 @@ public class Weapon implements Cloneable{ can && //must be able to shoot (!useAmmo || unit.ammo > 0 || !state.rules.unitAmmo || unit.team.rules().infiniteAmmo) && //check ammo (!alternate || mount.side == flipSprite) && - //TODO checking for velocity this way isn't entirely correct - (unit.vel.len() >= mount.weapon.minShootVelocity || (net.active() && !unit.isLocal())) && //check velocity requirements + unit.vel.len() >= mount.weapon.minShootVelocity && //check velocity requirements mount.reload <= 0.0001f && //reload has to be 0 Angles.within(rotate ? mount.rotation : unit.rotation, mount.targetRotation, mount.weapon.shootCone) //has to be within the cone ){ @@ -324,6 +323,9 @@ public class Weapon implements Cloneable{ Time.run(sequenceNum * shotDelay + firstShotDelay, () -> { if(!unit.isAdded()) return; mount.bullet = bullet(unit, shootX + unit.x - baseX, shootY + unit.y - baseY, f + Mathf.range(inaccuracy), lifeScl); + if(!continuous){ + shootSound.at(shootX, shootY, Mathf.random(soundPitchMin, soundPitchMax)); + } }); sequenceNum++; }); diff --git a/core/src/mindustry/ui/Fonts.java b/core/src/mindustry/ui/Fonts.java index 3c6c1b175c..7beff27396 100644 --- a/core/src/mindustry/ui/Fonts.java +++ b/core/src/mindustry/ui/Fonts.java @@ -203,7 +203,7 @@ public class Fonts{ /** Merges the UI and font atlas together for better performance. */ public static void mergeFontAtlas(TextureAtlas atlas){ - //grab all textures from the ui page, remove all the regions assigned to it, then copy them over to Fonts.packer and replace the texture in this atlas. + //grab all textures from the ui page, remove all the regions assigned to it, then copy them over to UI.packer and replace the texture in this atlas. //grab old UI texture and regions... Texture texture = atlas.find("logo").texture; @@ -236,8 +236,12 @@ public class Fonts{ } public static TextureRegionDrawable getGlyph(Font font, char glyph){ - Glyph g = font.getData().getGlyph(glyph); - if(g == null) throw new IllegalArgumentException("No glyph: " + glyph + " (" + (int)glyph + ")"); + Glyph found = font.getData().getGlyph(glyph); + if(found == null){ + Log.warn("No icon found for glyph: @ (@)", glyph, (int)glyph); + found = font.getData().getGlyph('F'); + } + Glyph g = found; float size = Math.max(g.width, g.height); TextureRegionDrawable draw = new TextureRegionDrawable(new TextureRegion(font.getRegion().texture, g.u, g.v2, g.u2, g.v)){ diff --git a/core/src/mindustry/ui/Styles.java b/core/src/mindustry/ui/Styles.java index 4e7042fe80..36a3ace7d2 100644 --- a/core/src/mindustry/ui/Styles.java +++ b/core/src/mindustry/ui/Styles.java @@ -31,7 +31,7 @@ public class Styles{ public static ImageButtonStyle defaulti, nodei, righti, emptyi, emptytogglei, selecti, logici, geni, colori, accenti, cleari, clearFulli, clearPartiali, clearPartial2i, clearTogglei, clearTransi, clearToggleTransi, clearTogglePartiali; public static ScrollPaneStyle defaultPane, horizontalPane, smallPane, nonePane; public static KeybindDialog.KeybindDialogStyle defaultKeybindDialog; - public static SliderStyle defaultSlider, vSlider; + public static SliderStyle defaultSlider; public static LabelStyle defaultLabel, outlineLabel, techLabel; public static TextFieldStyle defaultField, nodeField, areaField, nodeArea; public static CheckBoxStyle defaultCheck; @@ -320,13 +320,7 @@ public class Styles{ }}; defaultSlider = new SliderStyle(){{ - background = slider; - knob = sliderKnob; - knobOver = sliderKnobOver; - knobDown = sliderKnobDown; - }}; - vSlider = new SliderStyle(){{ - background = sliderVertical; + background = sliderBack; knob = sliderKnob; knobOver = sliderKnobOver; knobDown = sliderKnobDown; diff --git a/core/src/mindustry/ui/WarningBar.java b/core/src/mindustry/ui/WarningBar.java index efa124f8ab..c528c308a5 100644 --- a/core/src/mindustry/ui/WarningBar.java +++ b/core/src/mindustry/ui/WarningBar.java @@ -2,6 +2,7 @@ package mindustry.ui; import arc.graphics.g2d.*; import arc.scene.*; +import arc.scene.ui.layout.*; import mindustry.graphics.*; public class WarningBar extends Element{ @@ -27,7 +28,7 @@ public class WarningBar extends Element{ rx + barWidth, y ); } - Lines.stroke(3f); + Lines.stroke(Scl.scl(3f)); Lines.line(x, y, x + width, y); Lines.line(x, y + height, x + width, y + height); diff --git a/core/src/mindustry/ui/dialogs/ModsDialog.java b/core/src/mindustry/ui/dialogs/ModsDialog.java index 944995a20c..abad12a00a 100644 --- a/core/src/mindustry/ui/dialogs/ModsDialog.java +++ b/core/src/mindustry/ui/dialogs/ModsDialog.java @@ -80,9 +80,7 @@ public class ModsDialog extends BaseDialog{ } shown(this::setup); - if(mobile){ - onResize(this::setup); - } + onResize(this::setup); Events.on(ResizeEvent.class, event -> { if(currentContent != null){ @@ -144,10 +142,10 @@ public class ModsDialog extends BaseDialog{ void setup(){ float h = 110f; - float w = Math.min(Core.graphics.getWidth() / 1.1f, 520f); + float w = Math.min(Core.graphics.getWidth() / Scl.scl(1.05f), 520f); cont.clear(); - cont.defaults().width(Math.min(Core.graphics.getWidth() / 1.2f, 556f)).pad(4); + cont.defaults().width(Math.min(Core.graphics.getWidth() / Scl.scl(1.05f), 556f)).pad(4); cont.add("@mod.reloadrequired").visible(mods::requiresReload).center().get().setAlignment(Align.center); cont.row(); diff --git a/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java b/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java index 168ae4b451..7c6ed01a38 100644 --- a/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java +++ b/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java @@ -6,6 +6,7 @@ import arc.func.*; import arc.graphics.*; import arc.graphics.Texture.*; import arc.input.*; +import arc.scene.event.*; import arc.scene.ui.*; import arc.scene.ui.TextButton.*; import arc.scene.ui.layout.*; @@ -286,7 +287,8 @@ public class SettingsMenuDialog extends Dialog{ sound.sliderPref("sfxvol", bundle.get("setting.sfxvol.name", "SFX Volume"), 100, 0, 100, 1, i -> i + "%"); sound.sliderPref("ambientvol", bundle.get("setting.ambientvol.name", "Ambient Volume"), 100, 0, 100, 1, i -> i + "%"); - game.screenshakePref(); + game.sliderPref("saveinterval", 60, 10, 5 * 120, 10, i -> Core.bundle.format("setting.seconds", i)); + if(mobile){ game.checkPref("autotarget", true); game.checkPref("keyboard", false, val -> { @@ -307,7 +309,6 @@ public class SettingsMenuDialog extends Dialog{ control.setInput(new MobileInput()); } }*/ - game.sliderPref("saveinterval", 60, 10, 5 * 120, 10, i -> Core.bundle.format("setting.seconds", i)); if(!mobile){ game.checkPref("crashreport", true); @@ -350,6 +351,8 @@ public class SettingsMenuDialog extends Dialog{ Core.settings.put("uiscalechanged", s != lastUiScale[0]); return s + "%"; }); + + graphics.sliderPref("screenshake", 4, 0, 8, i -> (i / 4f) + "x"); graphics.sliderPref("fpscap", 240, 15, 245, 5, s -> (s > 240 ? Core.bundle.get("setting.fpscap.none") : Core.bundle.format("setting.fpscap.text", s))); graphics.sliderPref("chatopacity", 100, 0, 100, 5, s -> s + "%"); graphics.sliderPref("lasersopacity", 100, 0, 100, 5, s -> { @@ -559,10 +562,6 @@ public class SettingsMenuDialog extends Dialog{ rebuild(); } - public void screenshakePref(){ - sliderPref("screenshake", bundle.get("setting.screenshake.name", "Screen Shake"), 4, 0, 8, i -> (i / 4f) + "x"); - } - public SliderSetting sliderPref(String name, String title, int def, int min, int max, StringProcessor s){ return sliderPref(name, title, def, min, max, 1, s); } @@ -686,23 +685,21 @@ public class SettingsMenuDialog extends Dialog{ slider.setValue(settings.getInt(name)); - Label label = new Label(title); + Label value = new Label(""); + value.setStyle(Styles.outlineLabel); + value.touchable = Touchable.disabled; + slider.changed(() -> { settings.put(name, (int)slider.getValue()); - label.setText(title + ": " + sp.get((int)slider.getValue())); + value.setText(title + ": " + sp.get((int)slider.getValue())); }); + value.setAlignment(Align.center); + value.setWrap(true); + slider.change(); - table.table(t -> { - t.left().defaults().left(); - t.add(label).minWidth(label.getPrefWidth() / Scl.scl(1f) + 50); - if(Core.graphics.isPortrait()){ - t.row(); - } - t.add(slider).width(180); - }).left().padTop(3); - + table.stack(slider, value).width(Math.min(Core.graphics.getWidth() / 1.2f, 460f)).left().padTop(4); table.row(); } } diff --git a/core/src/mindustry/ui/fragments/BlockInventoryFragment.java b/core/src/mindustry/ui/fragments/BlockInventoryFragment.java index e63acaac4e..ecad1514fa 100644 --- a/core/src/mindustry/ui/fragments/BlockInventoryFragment.java +++ b/core/src/mindustry/ui/fragments/BlockInventoryFragment.java @@ -14,6 +14,7 @@ import arc.scene.ui.layout.Stack; import arc.scene.ui.layout.*; import arc.struct.*; import arc.util.*; +import mindustry.core.*; import mindustry.game.EventType.*; import mindustry.gen.*; import mindustry.type.*; @@ -200,9 +201,9 @@ public class BlockInventoryFragment extends Fragment{ private String round(float f){ f = (int)f; if(f >= 1000000){ - return (int)(f / 1000000f) + "[gray]" + Core.bundle.getOrNull("unit.millions") + "[]"; + return (int)(f / 1000000f) + "[gray]" + UI.millions; }else if(f >= 1000){ - return (int)(f / 1000) + Core.bundle.getOrNull("unit.thousands"); + return (int)(f / 1000) + UI.thousands; }else{ return (int)f + ""; } diff --git a/core/src/mindustry/ui/fragments/PlayerListFragment.java b/core/src/mindustry/ui/fragments/PlayerListFragment.java index 7be7e6d090..67b101c6ab 100644 --- a/core/src/mindustry/ui/fragments/PlayerListFragment.java +++ b/core/src/mindustry/ui/fragments/PlayerListFragment.java @@ -83,13 +83,15 @@ public class PlayerListFragment extends Fragment{ Groups.player.copy(players); players.sort(Structs.comps(Structs.comparing(Player::team), Structs.comparingBool(p -> !p.admin))); + if(sField.getText().length() > 0){ + players.filter(p -> Strings.stripColors(p.name().toLowerCase()).contains(sField.getText().toLowerCase())); + } for(var user : players){ found = true; NetConnection connection = user.con; if(connection == null && net.server() && !user.isLocal()) return; - if(sField.getText().length() > 0 && !user.name().toLowerCase().contains(sField.getText().toLowerCase()) && !Strings.stripColors(user.name().toLowerCase()).contains(sField.getText().toLowerCase())) return; Table button = new Table(); button.left(); diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java index a4a17257a7..391f6255ca 100644 --- a/core/src/mindustry/world/Block.java +++ b/core/src/mindustry/world/Block.java @@ -193,8 +193,10 @@ public class Block extends UnlockableContent{ public int outlinedIcon = -1; /** Whether this block has a shadow under it. */ public boolean hasShadow = true; - /** Sounds made when this block breaks.*/ - public Sound breakSound = Sounds.boom; + /** Sounds made when this block is destroyed.*/ + public Sound destroySound = Sounds.boom; + /** Sound made when this block is deconstructed. */ + public Sound breakSound = Sounds.breaks; /** How reflective this block is. */ public float albedo = 0f; /** Environmental passive light color. */ diff --git a/core/src/mindustry/world/blocks/ConstructBlock.java b/core/src/mindustry/world/blocks/ConstructBlock.java index 4c2fc98b1c..a3a66b1280 100644 --- a/core/src/mindustry/world/blocks/ConstructBlock.java +++ b/core/src/mindustry/world/blocks/ConstructBlock.java @@ -47,7 +47,7 @@ public class ConstructBlock extends Block{ /** Returns a ConstructBlock by size. */ public static ConstructBlock get(int size){ - if(size > maxBlockSize) throw new IllegalArgumentException("No. Don't place ConstructBlock of size greater than " + maxBlockSize); + if(size > maxBlockSize) throw new IllegalArgumentException("No. Don't place ConstructBlocks of size greater than " + maxBlockSize); return consBlocks[size - 1]; } @@ -57,7 +57,7 @@ public class ConstructBlock extends Block{ block.breakEffect.at(tile.drawx(), tile.drawy(), block.size, block.mapColor); Events.fire(new BlockBuildEndEvent(tile, builder, team, true, null)); tile.remove(); - if(shouldPlay()) Sounds.breaks.at(tile, calcPitch(false)); + if(shouldPlay()) block.breakSound.at(tile, calcPitch(false)); } @Remote(called = Loc.server) diff --git a/core/src/mindustry/world/blocks/campaign/LaunchPad.java b/core/src/mindustry/world/blocks/campaign/LaunchPad.java index fe50676d0b..c36b5a7a91 100644 --- a/core/src/mindustry/world/blocks/campaign/LaunchPad.java +++ b/core/src/mindustry/world/blocks/campaign/LaunchPad.java @@ -129,8 +129,8 @@ public class LaunchPad extends Block{ public void updateTile(){ if(!state.isCampaign()) return; - //launch when full and base conditions are met - if(items.total() >= itemCapacity && efficiency() >= 1f && (launchCounter += edelta()) >= launchTime){ + //increment launchCounter then launch when full and base conditions are met + if((launchCounter += edelta()) >= launchTime && items.total() >= itemCapacity){ launchSound.at(x, y); LaunchPayload entity = LaunchPayload.create(); items.each((item, amount) -> entity.stacks.add(new ItemStack(item, amount))); diff --git a/core/src/mindustry/world/blocks/distribution/Conveyor.java b/core/src/mindustry/world/blocks/distribution/Conveyor.java index 22811f3326..1714e038df 100644 --- a/core/src/mindustry/world/blocks/distribution/Conveyor.java +++ b/core/src/mindustry/world/blocks/distribution/Conveyor.java @@ -246,7 +246,7 @@ public class Conveyor extends Block implements Autotiler{ if(ys[i] > nextMax) ys[i] = nextMax; if(ys[i] > 0.5 && i > 0) mid = i - 1; - xs[i] = Mathf.approachDelta(xs[i], 0, speed*2); + xs[i] = Mathf.approach(xs[i], 0, moved*2); if(ys[i] >= 1f && pass(ids[i])){ //align X position if passing forwards @@ -262,7 +262,7 @@ public class Conveyor extends Block implements Autotiler{ } if(minitem < itemSpace + (blendbits == 1 ? 0.3f : 0f)){ - clogHeat = Mathf.lerpDelta(clogHeat, 1f, 0.02f); + clogHeat = Mathf.approachDelta(clogHeat, 1f, 1f / 60f); }else{ clogHeat = 0f; } diff --git a/core/src/mindustry/world/blocks/environment/Floor.java b/core/src/mindustry/world/blocks/environment/Floor.java index 14ec094818..5865a00fb2 100644 --- a/core/src/mindustry/world/blocks/environment/Floor.java +++ b/core/src/mindustry/world/blocks/environment/Floor.java @@ -51,8 +51,6 @@ public class Floor extends Block{ public boolean playerUnmineable = false; /** Group of blocks that this block does not draw edges on. */ public Block blendGroup = this; - /** Effect displayed when randomly updated. */ - public Effect updateEffect = Fx.none; /** Whether this ore generates in maps by default. */ public boolean oreDefault = false; /** Ore generation params. */ diff --git a/core/src/mindustry/world/blocks/environment/Prop.java b/core/src/mindustry/world/blocks/environment/Prop.java index 45da9aae88..0e7807acdd 100644 --- a/core/src/mindustry/world/blocks/environment/Prop.java +++ b/core/src/mindustry/world/blocks/environment/Prop.java @@ -4,15 +4,18 @@ import arc.*; import arc.graphics.g2d.*; import arc.math.*; import mindustry.content.*; +import mindustry.gen.*; import mindustry.world.*; public class Prop extends Block{ + public Prop(String name){ super(name); breakable = true; alwaysReplace = true; instantDeconstruct = true; breakEffect = Fx.breakProp; + breakSound = Sounds.rockBreak; } @Override diff --git a/core/src/mindustry/world/blocks/payloads/Payload.java b/core/src/mindustry/world/blocks/payloads/Payload.java index 33271cec70..4be19f66bf 100644 --- a/core/src/mindustry/world/blocks/payloads/Payload.java +++ b/core/src/mindustry/world/blocks/payloads/Payload.java @@ -6,6 +6,7 @@ import arc.util.*; import arc.util.io.*; import mindustry.game.*; import mindustry.gen.*; +import mindustry.ui.*; import mindustry.type.*; import mindustry.world.*; @@ -56,6 +57,12 @@ public interface Payload extends Position{ /** @return icon describing the contents. */ TextureRegion icon(); + /** @deprecated use icon() instead. */ + @Deprecated + default TextureRegion icon(Cicon icon){ + return icon(); + } + @Override default float getX(){ return x(); diff --git a/core/src/mindustry/world/blocks/payloads/PayloadMassDriver.java b/core/src/mindustry/world/blocks/payloads/PayloadMassDriver.java index 71a1aa1f23..5e04456ac3 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadMassDriver.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadMassDriver.java @@ -456,6 +456,7 @@ public class PayloadMassDriver extends PayloadBlock{ @Override public Point2 config(){ + if(tile == null) return null; return Point2.unpack(link).sub(tile.x, tile.y); } diff --git a/core/src/mindustry/world/blocks/production/GenericCrafter.java b/core/src/mindustry/world/blocks/production/GenericCrafter.java index bd684fcf8a..31e3093140 100644 --- a/core/src/mindustry/world/blocks/production/GenericCrafter.java +++ b/core/src/mindustry/world/blocks/production/GenericCrafter.java @@ -15,7 +15,10 @@ import mindustry.world.draw.*; import mindustry.world.meta.*; public class GenericCrafter extends Block{ + /** Written to outputItems as a single-element array if outputItems is null. */ public @Nullable ItemStack outputItem; + /** Overwrites outputItem if not null. */ + public @Nullable ItemStack[] outputItems; public @Nullable LiquidStack outputLiquid; public float craftTime = 80; @@ -45,8 +48,8 @@ public class GenericCrafter extends Block{ super.setStats(); stats.add(Stat.productionTime, craftTime / 60f, StatUnit.seconds); - if(outputItem != null){ - stats.add(Stat.output, StatValues.items(craftTime, outputItem)); + if(outputItems != null){ + stats.add(Stat.output, StatValues.items(craftTime, outputItems)); } if(outputLiquid != null){ @@ -64,6 +67,9 @@ public class GenericCrafter extends Block{ @Override public void init(){ outputsLiquid = outputLiquid != null; + if(outputItems == null && outputItem != null){ + outputItems = new ItemStack[]{outputItem}; + } super.init(); } @@ -74,7 +80,7 @@ public class GenericCrafter extends Block{ @Override public boolean outputsItems(){ - return outputItem != null; + return outputItems != null; } public class GenericCrafterBuild extends Building{ @@ -95,8 +101,12 @@ public class GenericCrafter extends Block{ @Override public boolean shouldConsume(){ - if(outputItem != null && items.get(outputItem.item) + outputItem.amount > itemCapacity){ - return false; + if(outputItems != null){ + for(ItemStack output : outputItems){ + if(items.get(output.item) + output.amount > itemCapacity){ + return false; + } + } } return (outputLiquid == null || !(liquids.get(outputLiquid.liquid) >= liquidCapacity - 0.001f)) && enabled; } @@ -119,9 +129,11 @@ public class GenericCrafter extends Block{ if(progress >= 1f){ consume(); - if(outputItem != null){ - for(int i = 0; i < outputItem.amount; i++){ - offload(outputItem.item); + if(outputItems != null){ + for(ItemStack output : outputItems){ + for(int i = 0; i < output.amount; i++){ + offload(output.item); + } } } @@ -133,8 +145,10 @@ public class GenericCrafter extends Block{ progress %= 1f; } - if(outputItem != null && timer(timerDump, dumpTime / timeScale)){ - dump(outputItem.item); + if(outputItems != null && timer(timerDump, dumpTime / timeScale)){ + for(ItemStack output : outputItems){ + dump(output.item); + } } if(outputLiquid != null){ @@ -174,4 +188,4 @@ public class GenericCrafter extends Block{ if(legacyReadWarmup) read.f(); } } -} +} \ No newline at end of file diff --git a/core/src/mindustry/world/blocks/storage/CoreBlock.java b/core/src/mindustry/world/blocks/storage/CoreBlock.java index ae49d49f70..2c78debb6d 100644 --- a/core/src/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/mindustry/world/blocks/storage/CoreBlock.java @@ -281,7 +281,7 @@ public class CoreBlock extends StorageBlock{ @Override public void afterDestroyed(){ if(state.rules.coreCapture){ - tile.setBlock(block, lastDamage); + tile.setNet(block, lastDamage, 0); //core is invincible for several seconds to prevent recapture ((CoreBuild)tile.build).iframes = captureInvicibility; } diff --git a/core/src/mindustry/world/meta/StatValues.java b/core/src/mindustry/world/meta/StatValues.java index 83f65ebc22..a64f40b8c3 100644 --- a/core/src/mindustry/world/meta/StatValues.java +++ b/core/src/mindustry/world/meta/StatValues.java @@ -147,7 +147,7 @@ public class StatValues{ } } }else{ - c.add("@none.found"); + c.add("@none.inmap"); } }else{ c.add("@stat.showinmap"); diff --git a/desktop/build.gradle b/desktop/build.gradle index 347ffeee07..dfcc365f79 100644 --- a/desktop/build.gradle +++ b/desktop/build.gradle @@ -119,13 +119,14 @@ platforms.each{ platform -> "--removelibs", "$rootDir/desktop/build/packr/desktop.jar".toString() ] + args += "--vmargs" + if(platform == "MacOS"){ - args += ["--vmargs", "XstartOnFirstThread"] as String[] - }else{ - //TODO unneeded for windows? - args += ["--vmargs", "Dhttps.protocols=TLSv1.2,TLSv1.1,TLSv1"] + args += "XstartOnFirstThread" } + args += "Dhttps.protocols=TLSv1.2,TLSv1.1,TLSv1" + exec{ commandLine args.toList() standardOutput = System.out diff --git a/gradle.properties b/gradle.properties index da2c038cd7..642357fb9e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,4 +10,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=b8db131172548e1f10ba86392e09819c34296711 +archash=fbdfa0307101b881e208f53666c1f4b7ebf0fe90 diff --git a/servers_v6.json b/servers_v6.json index 1be97e5f26..6d1bad5a2a 100644 --- a/servers_v6.json +++ b/servers_v6.json @@ -7,10 +7,6 @@ "name": "SMokeOfAnarchy.duckdns.org", "address": ["smokeofanarchy.duckdns.org:6853"] }, - { - "name": "mindustry.pl", - "address": ["mindustry.pl:6000", "mindustry.pl:6666", "mindustry.pl", "mindustry.pl:6966"] - }, { "name": "{AA}", "address": ["aamindustry.play.ai", "aamindustry.play.ai:6571", "aamindustry.play.ai:6572", "aamindustry.play.ai:6573", "aamindustry.play.ai:6574"] @@ -23,17 +19,13 @@ "name": "C.A.M.S.", "address": ["baseduser.eu.org:6568", "nikochio.ddns.net", "play.thedimas.pp.ua"] }, - { - "name": "BE6.RUN", - "address": ["be6.run", "mindustrycn.top"] - }, { "name": "ECAN", "address": ["mindustry.ecansol.com:6597", "mindustry.ecansol.com:6499", "mindustry.ecansol.com:6599"] }, { "name": "Chaotic Neutral", - "address": ["Chaotic-Neutral.ddns.net:1111", "Chaotic-Neutral.ddns.net:2222", "Chaotic-Neutral.ddns.net:5555", "Chaotic-Neutral.ddns.net:6666", "Chaotic-Neutral.ddns.net:7777"] + "address": ["Chaotic-Neutral.ddns.net:1111", "Chaotic-Neutral.ddns.net:2222", "Chaotic-Neutral.ddns.net:7777"] }, { "name": "Ranked", @@ -53,7 +45,7 @@ }, { "name": "ALEX", - "address": ["alexmindustryhub.ddns.net:6568", "alexmindustry.ddns.net:6568", "alexmindustry.ddns.net:6569", "alexmindustryattac.ddns.net:25800","alexmindustryturbo.ddns.net:25854","alexmindustryhex.ddns.net:25587"] + "address": ["alexmindustryhub.ddns.net:6568", "alexmindustry.ddns.net:25586", "alexmindustry.ddns.net:25587", "alexmindustryattac.ddns.net:25800","alexmindustryturbo.ddns.net:25581","alexmindustryhex.ddns.net:25583"] }, { "name": "Minty [subzero]", @@ -61,11 +53,7 @@ }, { "name": "Korea", - "address": ["mindustry.kr", "mindustry.initd.kr"] - }, - { - "name": "hexpvp.ml", - "address": ["hexpvp.ml"] + "address": ["mindustry.initd.kr"] }, { "name": "Omega", @@ -73,7 +61,7 @@ }, { "name": "md.obvilionnetwork.ru", - "address": ["obvilionnetwork.ru", "obvilionnetwork.ru:7001", "obvilionnetwork.ru:7002", "obvilionnetwork.ru:7003"] + "address": ["obvilionnetwork.ru", "obvilionnetwork.ru:7001", "obvilionnetwork.ru:7002"] }, { "name": "Mindustry PLAY", @@ -83,10 +71,6 @@ "name": "Nydus", "address": ["v6.mindustry.nydus.app:6566"] }, - { - "name": "MD Community", - "address": ["mindurka.tk", "mindurka.tk:4000"] - }, { "name": "Mindustry.Party", "address": ["game.mindustry.party"] diff --git a/servers_v7.json b/servers_v7.json index 6342cdb659..9dc02e7370 100644 --- a/servers_v7.json +++ b/servers_v7.json @@ -9,7 +9,7 @@ { "name": "C.A.M.S.", "address": ["baseduser.eu.org:6569", "v7.thedimas.pp.ua"] - } + }, { "name": "hexpvp.ml", "address": "hexpvp.ml" @@ -20,7 +20,7 @@ }, { "name": "Omega", - "address": "157.90.180.53:25777" + "address": ["157.90.180.53:25777", "redstonneur1256.ml", "185.86.230.61:25571"] }, { "name": "MeowLand", @@ -45,5 +45,9 @@ { "name": "io", "address": ["mindustry.io.community", "mindustry.io.community:1000", "mindustry.io.community:2000", "mindustry.io.community:3000"] + }, + { + "name": "Korea", + "address": ["mindustry.kr"] } ] diff --git a/tests/src/test/java/ApplicationTests.java b/tests/src/test/java/ApplicationTests.java index ab16bf6597..01dce8947e 100644 --- a/tests/src/test/java/ApplicationTests.java +++ b/tests/src/test/java/ApplicationTests.java @@ -20,7 +20,8 @@ import mindustry.io.SaveIO.*; import mindustry.maps.*; import mindustry.mod.*; import mindustry.mod.Mods.*; -import mindustry.net.Net; +import mindustry.net.*; +import mindustry.net.Packets.*; import mindustry.type.*; import mindustry.world.*; import mindustry.world.blocks.storage.*; @@ -28,6 +29,7 @@ import org.junit.jupiter.api.*; import org.junit.jupiter.params.*; import org.junit.jupiter.params.provider.*; +import java.io.*; import java.nio.*; import static mindustry.Vars.*; @@ -133,14 +135,56 @@ public class ApplicationTests{ @ParameterizedTest @NullSource @ValueSource(strings = { + "a", "asd asd asd asd asdagagasasjakbgeah;jwrej 23424234", - "这个服务器可以用自己的语言说话" + "这个服务器可以用自己的语言说话", + "\uD83D\uDEA3" }) void writeStringTest(String string){ ByteBuffer buffer = ByteBuffer.allocate(500); TypeIO.writeString(buffer, string); buffer.position(0); assertEquals(TypeIO.readString(buffer), string); + + ByteArrayOutputStream ba = new ByteArrayOutputStream(); + + TypeIO.writeString(new Writes(new DataOutputStream(ba)), string); + assertEquals(TypeIO.readString(new Reads(new DataInputStream(new ByteArrayInputStream(ba.toByteArray())))), string); + + SendChatMessageCallPacket pack = new SendChatMessageCallPacket(); + pack.message = string; + + buffer.position(0); + pack.write(new Writes(new ByteBufferOutput(buffer))); + int len = buffer.position(); + buffer.position(0); + pack.message = "INVALID"; + pack.read(new Reads(new ByteBufferInput(buffer)), len); + pack.handled(); + + assertEquals(string, pack.message); + + buffer.position(0); + Writes writes = new Writes(new ByteBufferOutput(buffer)); + TypeIO.writeString(writes, string); + + buffer.position(0); + + assertEquals(string, TypeIO.readString(new Reads(new ByteBufferInput(buffer)))); + + buffer.position(0); + ConnectPacket con = new ConnectPacket(); + con.name = string; + con.uuid = "AAAAAAAA"; + con.usid = "AAAAAAAA"; + con.mods = new Seq<>(); + con.write(new Writes(new ByteBufferOutput(buffer))); + + con.name = "INVALID"; + buffer.position(0); + con.read(new Reads(new ByteBufferInput(buffer))); + + assertEquals(string, con.name); } @Test diff --git a/tests/src/test/java/GenericModTest.java b/tests/src/test/java/GenericModTest.java index 46843116f7..10b75c1d24 100644 --- a/tests/src/test/java/GenericModTest.java +++ b/tests/src/test/java/GenericModTest.java @@ -13,7 +13,7 @@ public class GenericModTest{ static void grabMod(String url){ //clear older mods ApplicationTests.testDataFolder.deleteDirectory(); - Http.get(url).error(Assertions::fail).block(httpResponse -> { + Http.get(url).error(Assertions::fail).timeout(20000).block(httpResponse -> { try{ ApplicationTests.testDataFolder.child("mods").child("test_mod." + (url.endsWith("jar") ? "jar" : "zip")).writeBytes(Streams.copyBytes(httpResponse.getResultAsStream())); }catch(IOException e){ diff --git a/tools/src/mindustry/tools/Generators.java b/tools/src/mindustry/tools/Generators.java index 2c188946b3..c78e7dbb5f 100644 --- a/tools/src/mindustry/tools/Generators.java +++ b/tools/src/mindustry/tools/Generators.java @@ -598,7 +598,7 @@ public class Generators{ }); } - /** Generates a scorch pixmap based on parameters. Thread safe, unless multiple scorch generators are running in parallel. */ + /** Generates a scorch pixmap based on parameters. Thread safe. */ public static class ScorchGenerator{ public int size = 80, seed = 0, color = Color.whiteRgba; public double scale = 18, pow = 2, octaves = 4, pers = 0.4, add = 2, nscl = 4.5f;