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;