Compare commits

...
86 Commits
Author SHA1 Message Date
BalaM314 beaa1da276 Allow closing the console after you've disabled it (#12737)
* Allow closing the console after you've disabled it

* Close the console immediately when disabled
2026-10-03 12:35:04 -04:00
Anuken a378c35fb6 Contribution guidelines & AI policy update 2026-10-03 11:07:11 -04:00
Anuken 69ed90bb9d Directional unloader read fix 2026-09-30 18:02:13 -04:00
Anuken e337452d46 Reverted #12722 on master branch (will be back on v9)
This reverts commit 9f70386466.
2026-09-30 17:59:01 -04:00
Twcash 9f70386466 fix Copper ore color to match item color (#12722) 2026-09-30 17:56:38 -04:00
Cardillan e7de4e1a10 Fix empty statement fields shifting the remaining parameters (#12715)
* Fix empty statement fields shifting remaining parameters

* Fixed unit tests
2026-09-30 17:55:18 -04:00
WayZer 4cc15b84f6 Do not let content JSON set Effect#initialized (#12724) 2026-09-29 14:29:43 -04:00
Anuken f3bfa418a5 Fixed rare physics crash 2026-09-27 18:45:23 -04:00
Anuken 663b0b8737 Backported patch loading in mods from v9 for future compatibility 2026-09-25 16:47:42 -04:00
Anuken 3a54813513 Fixed some schema generation bugs 2026-09-20 18:40:01 -04:00
Anuken 3e43d88374 WIP re-generation of regions on server 2026-09-20 17:27:51 -04:00
Anuken 580f8f5217 Fixed #12697 2026-09-20 13:55:06 -04:00
Github Actions 067c720a88 Automatic bundle update 2026-09-20 13:22:06 +00:00
Kevin Vilyan 2541682bee Update Bundle ID (#12693) 2026-09-20 09:21:29 -04:00
Vector 78921a064e Update bundle_es.properties (#12672)
* Update bundle_es.properties

* Update bundle_es.properties

* Update bundle_es.properties

* sensor descriptions

* Update bundle_es.properties

* Update bundle_es.properties

* Update bundle_es.properties

* Update bundle_es.properties
2026-09-20 09:21:19 -04:00
Sunky.MP3G 92d53b01fc More RU translations (#12639)
* New RU translations and proper processor ones

* Finished

* Typo
2026-09-20 09:21:11 -04:00
Anuken 8f1a4c5541 Merge remote-tracking branch 'origin/master' 2026-09-20 09:21:00 -04:00
Anuken e2ccb6ea96 Fixed #12691 2026-09-20 09:20:54 -04:00
EggleEgg 2f3a3979a4 Bugfix lightning chain distance (again) (#12695) 2026-09-20 09:19:40 -04:00
Anuken 9f065cea59 Do not add liquid bars to blocks with 0 liquid capacity 2026-09-19 23:24:54 -04:00
Anuken d2c5e09413 Fixed popups not respecting hidden UI state 2026-09-19 11:43:05 -04:00
Anuken 1cc5d54fde Fixed #12690 2026-09-19 10:53:14 -04:00
Anuken 4ef2a6d81e CADisableMinimumFrameDurationOnPhone on iOS 2026-09-18 18:04:25 -04:00
Anuken be14e4173e Null check for displayFlow 2026-09-18 13:58:24 -04:00
Anuken c58aac5f67 Version-specific release fetching for mods 2026-09-18 12:47:14 -04:00
Anuken cada4b2543 Logic parsing tests 2026-09-18 11:11:56 -04:00
summoner ccc5bebc3b Translation: Update bundle_hu.properties (#12679)
Follow the changes of the english bundle
Minor fixes
2026-09-18 10:47:37 -04:00
Anuken 8b80186320 Merge remote-tracking branch 'origin/master' 2026-09-18 10:47:15 -04:00
Anuken 1e8317fbac Fixed #12683 2026-09-18 10:47:09 -04:00
Cardillan 6500b5b6de Improve hex and binary literal parses (#12678)
* Improve hex and binary literal parses

* Moved the specialized unsigned long parsing routine from Strings directly to LAssembler
2026-09-18 10:46:33 -04:00
Anuken eff677e112 Merge remote-tracking branch 'origin/master' 2026-09-18 10:17:56 -04:00
Anuken 543dae701c Updated PR template 2026-09-18 10:17:43 -04:00
Anuken ec2bc54339 Fixed #12677 2026-09-18 10:17:43 -04:00
EggleEgg ca2c51896d Bugfix: scaled crafters unable to dump fast enough (#12669) 2026-09-17 11:10:16 -04:00
Anuken c640ae21ad Merge remote-tracking branch 'origin/master' 2026-09-17 10:54:56 -04:00
Anuken b8f392a116 Fixed #12674 2026-09-17 10:54:49 -04:00
EggleEgg bfa31bf184 Bugfix: attributecrafter yield string format (#12675)
* Bugfix: attributecrafter yield string format

* imports
2026-09-17 10:51:59 -04:00
Anuken 088486c1ad Fixed #12673 2026-09-17 10:51:38 -04:00
Anuken acf891e419 Mod matching release WIP 2026-09-16 15:40:41 -04:00
Anuken ca90af5f56 Updated steamworks 2026-09-16 12:42:44 -04:00
Anuken 45b82b9fa2 Merge remote-tracking branch 'origin/master' 2026-09-16 10:18:06 -04:00
Anuken 22cf431170 Fixed incorrect texture removal 2026-09-16 10:17:59 -04:00
Acts1631 b513d92456 Deduplicate requested assets during handshake (#12667)
* Deduplicate requested assets during handshake

* Use Bits for asset request deduplication
2026-09-15 20:34:09 -04:00
Anuken b3be63437e Better player name wrapping in player list 2026-09-15 12:13:12 -04:00
Anuken c801b625ac Merge remote-tracking branch 'origin/master' 2026-09-15 00:39:53 -04:00
Anuken 0bbc4c6777 Fixed #12660 2026-09-15 00:39:46 -04:00
sora54 4eed142ccc Fix cluster array dimension to use costTypes size (#12658) 2026-09-15 00:19:59 -04:00
EggleEgg 42ec5c9685 Bugfix: cap lightning distance (#12659) 2026-09-15 00:03:44 -04:00
summoner ca9876544e Translation: Update bundle_hu.properties (#12661)
* Translation: Update bundle_hu.properties

Fixing sentences
Fixing wording

* Translation: Update bundle_hu.properties

More fixes
2026-09-15 00:03:23 -04:00
Cardillan 73d5865908 Fix processor text/graphics buffer holding old content on restart (#12663) 2026-09-15 00:03:16 -04:00
NiTiSonandNiTiSon f474eab926 fix: Renderer update cause blocks to lose their extra and floor data (#12664)
Co-authored-by: NiTiSon <NiTiSon@users.noreply.github.com>
2026-09-15 00:03:02 -04:00
Anuken b76147ec50 Antialias + linear filter bleed on data patch images 2026-09-14 10:48:08 -04:00
Anuken 22ca0ce33f Avoidance radius clamp 2026-09-13 22:53:38 -04:00
Anuken 4368c6e60e Fixed #12657 2026-09-13 21:20:47 -04:00
Anuken 7591c51b60 More dummy validation + Pathfinder fixes 2026-09-13 21:15:29 -04:00
Anuken 93c88fea8c Merge remote-tracking branch 'origin/master' 2026-09-13 09:15:04 -04:00
Anuken 9de4deed37 Fixed redundant mod browser mod icons being cached 2026-09-13 09:14:58 -04:00
Thinker8832 254fd3e28d Fix typo in split.container description (#12651) 2026-09-12 23:46:25 -04:00
EggleEgg 9a886aa582 Bugfix: overdriable dummy sddeq3e (#12653) 2026-09-12 23:46:09 -04:00
Anuken a51047a80d Merge remote-tracking branch 'origin/master' 2026-09-12 23:45:59 -04:00
Anuken 55dba0c156 Fixed #12650 2026-09-12 23:45:53 -04:00
WMF a98a7ba227 yet another requiredPlanets fix (#12649) 2026-09-12 23:28:09 -04:00
Anuken 56348b3e31 Fixed #12652 2026-09-12 23:21:40 -04:00
Anuken 89527f879b Fixed #12632 2026-09-12 12:41:42 -04:00
Anuken 78646f512e Made small data patch sounds load as one-shot wavs instead of streams 2026-09-12 11:50:15 -04:00
Anuken fd4eac0f81 Merge remote-tracking branch 'origin/master' 2026-09-12 11:00:55 -04:00
Anuken 60cc6a1839 Fixed #12647 2026-09-12 11:00:48 -04:00
summoner 3d56fefb51 Translation: Update bundle_hu.properties (#12637)
Translate new strings
Follow the changes of the english bundle
2026-09-12 10:55:02 -04:00
Anuken a5c178ae5a Merge remote-tracking branch 'origin/master' 2026-09-12 10:49:51 -04:00
Anuken 06163708bd Fixed misleading build UI for team-specific infinite resources 2026-09-12 10:49:45 -04:00
Github Actions 137c6201c0 Automatic bundle update 2026-09-12 14:37:17 +00:00
redloong a341cff83f Refine Chinese translations in bundle_zh_CN.properties (#12631)
* Refine Chinese translations in bundle_zh_CN.properties

Updated various translations in the properties file for improved clarity and accuracy.

* Update Chinese localization for various labels

* Rename animated water settings to dynamic effects

Updated animated water settings to reflect dynamic effects.

* Update Chinese translations in bundle_zh_CN.properties
2026-09-12 10:36:26 -04:00
Anuken 7501697f02 Fixed #12644 2026-09-12 10:36:11 -04:00
Anuken 776214f7bb Merge remote-tracking branch 'origin/master' 2026-09-12 10:04:50 -04:00
Anuken 6df25c8308 Reverted fix for #12223 2026-09-12 10:04:44 -04:00
Cardillan ab51304dd6 Fixes #12640: Unset keybinding not saved (#12641) 2026-09-12 10:01:41 -04:00
Anuken e751e240db Fixed #12636 2026-09-12 09:59:07 -04:00
Anuken e675535cb7 Fixed fetch instruction layout 2026-09-11 03:02:08 -04:00
Anuken 84cdf2bbfe Fixed heal beam discontinuity 2026-09-11 02:40:28 -04:00
Anuken 6f4914d5cb arc 2026-09-11 01:56:19 -04:00
Anuken c7945610ee More dummy value validation 2026-09-11 01:50:09 -04:00
Anuken c6512c0b00 Fixed #12626 (by disallowing dummies in payloads) 2026-09-11 01:38:27 -04:00
Anuken cc5a63109a SoundControl crash fix 2026-09-11 00:56:38 -04:00
Anuken 43aa0d95f5 Closes Anuken/Mindustry-Suggestions/issues/6541 2026-09-11 00:49:24 -04:00
Anuken 42ad617bbd Temporary workaround for some mods crashing 2026-09-11 00:45:34 -04:00
Anuken e433d5f334 Fixed #11477 causing particle effects to be twice as big 2026-09-11 00:41:00 -04:00
74 changed files with 1069 additions and 670 deletions
+3 -3
View File
@@ -1,5 +1,5 @@
If your pull request is **not** translation or serverlist-related, read the list of requirements below and check each box:
If your pull request is **not** translation-related, read the list of requirements below and check each box:
- [ ] I have read the [contribution guidelines](https://github.com/Anuken/Mindustry/blob/master/CONTRIBUTING.md).
- [ ] I have ensured that my code compiles, if applicable.
- [ ] I have ensured that any new features in this PR function correctly in-game, if applicable.
- [ ] I have ensured that any new features or fixes in this PR function correctly in-game, if applicable.
- [ ] I affirm that this code follows Mindustry's [AI policy](https://github.com/Anuken/Mindustry/blob/master/CONTRIBUTING.md#ai-policy).
+17 -9
View File
@@ -4,9 +4,6 @@ This is for code contributions. For translations, see [TRANSLATING](TRANSLATING.
## Basic Guidelines
### Use an IDE.
Specifically, IntelliJ IDEA. Download the (free) Community Edition of it [here](https://www.jetbrains.com/idea/download/). Some people use other tools, like VS Code, but I would personally not recommend them for Java development.
### Always test your changes.
Do not submit something without at least running the game to see if it compiles.
If you are submitting a new block, make sure it has a name and description, and that it works correctly in-game. If you are changing existing block mechanics, test them out first.
@@ -20,11 +17,19 @@ Yes, there are occurrences of trailing spaces, extra newlines, empty indents, an
I **especially** do not want to see PRs that apply any kind of automated analysis to the source code to "optimize" anything - my IDE can do that already. If the PR doesn't actually change anything useful, I'm not going to review or merge it.
### Do not make AI "contributions".
## AI Policy
If I see a PR with significant amounts of code that's obviously written by AI, I will reject your PR, and you will be blocked. Don't waste my time with slop.
Mindustry's AI contribution policies are similar to that of [the Rust language](https://forge.rust-lang.org/policies/llm-usage.html), which are summarized as follows:
Asking AI questions, and using that information to help you write code? Fine. Using it to actually write code? No.
- ✔️ You **are** allowed use AI to review your own code, summarize, inform, and answer questions.
- ✔️ You **are** allowed to use AI to translate your *human-written* messages into English, if necessary.
- ❌ You are **not** allowed to submit PRs that are generated by AI.
- ❌ You are **not** allowed to use AI to *generate* any text posted (PRs, issues, commit messages, etc.)
- ⚠️ If you post *anything* that is based on AI output (potential solution to a bug, crash diagnosis...), it must be clearly marked as being sourced from AI.
Repeated (or particularly egregious) violations of these rules will get you banned from this repository.
## Style Guidelines
@@ -67,7 +72,6 @@ What you'll usually need to change:
### Avoid boxed types (Integer, Boolean)
Never create variables or collections with boxed types `Seq<Integer>` or `ObjectMap<Integer, ...>`. Use the collections specialized for this task, e.g. `IntSeq` and `IntMap`.
### Do not allocate anything if possible.
Never allocate `new` objects in the main loop. If you absolutely require new objects, use `Pools` to obtain and free object instances.
Otherwise, use the `Tmp` variables for things like vector/shape operations, or create `static` variables for re-use.
@@ -77,9 +81,13 @@ If using a list, make it a static variable and clear it every time it is used. R
This is situational, but in essence, what it means is to avoid using any sort of getters and setters unless absolutely necessary. Public or protected fields should suffice for most things.
If something needs to be encapsulated in the future, IntelliJ can handle it with a few clicks.
### Do not create methods unless necessary.
Unless a block of code is very large or used in more than 1-2 places, don't split it up into a separate method. Making unnecessary methods only creates confusion, and may slightly decrease performance.
## Other Notes
If you would like your name to appear in the game's credits, add it to the [list of contributors](https://github.com/Anuken/Mindustry/blob/master/core/assets/contributors) as part of your PR.
- If you would like your name to appear in the game's credits, add it to the [list of contributors](https://github.com/Anuken/Mindustry/blob/master/core/assets/contributors) as part of your PR.
- Using an IDE is highly recommended, but not required.
- I use IntelliJ; download it [here](https://www.jetbrains.com/idea/download/).
- Some people use other tools, like VS Code, but I haven't used them for Java myself, and cannot guarantee that they will work well for this codebase.
-3
View File
@@ -1,3 +0,0 @@
# Note: The v7 server list is frozen. No new servers will be accepted. All v8 server PRs should be made [here](https://github.com/Anuken/MindustryServerList).
*PRs to edit addresses of existing servers will still be accepted, although very infrequently.*
@@ -211,10 +211,7 @@ public abstract class BaseProcessor extends AbstractProcessor{
if(round++ >= rounds) return false; //only process 1 round
if(rootDirectory == null){
try{
String path = Fi.get(filer.getResource(StandardLocation.CLASS_OUTPUT, "no", "no")
.toUri().toURL().toString().substring(OS.isWindows ? 6 : "file:".length()))
.parent().parent().parent().parent().parent().parent().parent().toString().replace("%20", " ");
rootDirectory = Fi.get(path).parent();
rootDirectory = new Fi(new File(filer.getResource(StandardLocation.CLASS_OUTPUT, "no", "no").toUri())).parent().parent().parent().parent().parent().parent().parent().parent();
}catch(IOException e){
throw new RuntimeException(e);
}
+1 -1
View File
@@ -42,7 +42,7 @@ allprojects{
if(!project.hasProperty("versionModifier")) versionModifier = 'release'
if(!project.hasProperty("versionType")) versionType = 'official'
appName = 'Mindustry'
steamworksVersion = 'da41c05b7a2a44c8625ca0ba7d6ca1a2e73f621a'
steamworksVersion = '185e76cfe630a6f0e1dd7b9bf57be41f6064a1f2'
rhinoVersion = '32395f942976a6d1d21ec9877664554cd5762306'
loadVersionProps = {
+2 -2
View File
@@ -1304,7 +1304,7 @@ bar.cargounitcap = Cargo Unit Cap Reached
bar.drillspeed = Drill Speed: {0}/s
bar.pumpspeed = Pump Speed: {0}/s
bar.efficiency = Efficiency: {0}%
bar.yield = Yield: +{0}%
bar.yield = Yield: {0}%
bar.boost = Boost: +{0}%
bar.powerbuffer = Batteries: {0}/{1}
bar.powerbalance = Power: {0}/s
@@ -3396,7 +3396,7 @@ logicrule.label.wavetimer = wave timer?
logicrule.label.waves = waves
logicrule.label.wave = wave
logicrule.label.wavespacing = wave spacing
logicrule.label.wavesending = waves ending?
logicrule.label.wavesending = waves sending?
logicrule.label.attackmode = attack mode?
logicrule.label.enemycorebuildradius = enemy core build radius
logicrule.label.dropzoneradius = drop zone radius
+179 -179
View File
@@ -838,7 +838,7 @@ objective.destroyblock.name = Destruir bloque
objective.destroyblocks.name = Destruir bloques
objective.destroycore.name = Destruir núcleo
objective.commandmode.name = Modo comando
objective.flag.name = Etiqueta
objective.flag.name = Flag
marker.shapetext.name = Forma del texto
marker.point.name = Punto
@@ -1238,7 +1238,7 @@ stat.reactive = Reacciona con
stat.immunities = Inmune a
stat.healing = Curación
stat.status = Efecto de estado
stat.efficiency = [stat]{0}% Eficiencia
stat.efficiency = {0}% Eficiencia
stat.chance = [stat]{0}%[lightgray] probabilidad de [white]
stat.hitsize = Tamaño de Unidad
stat.resettime = Tiempo de Reinicio
@@ -1299,7 +1299,7 @@ bar.cargounitcap = Se alcanzó el límite de carga de unidades
bar.drillspeed = Velocidad del taladro: {0}/s
bar.pumpspeed = Velocidad de bombeado: {0}/s
bar.efficiency = Eficiencia: {0}%
bar.yield = Yield: +{0}%
bar.yield = Producción: {0}%
bar.boost = Aceleración: +{0}%
bar.powerbuffer = Poder en baterías: {0}/{1}
bar.powerbalance = Energía: {0}/s
@@ -1319,7 +1319,7 @@ bar.nevermelts = nunca hace fusión
bar.heatamount = Calor: {0}
bar.heatpercent = Calor: {0} ({1}%)
bar.power = Energía
bar.progress = Construyendo...
bar.progress = {0}% Construido
bar.loadprogress = Progreso
bar.launchcooldown = Recarga de lanzamiento
bar.input = Entrada
@@ -1990,8 +1990,8 @@ block.metal-tiles-13.name = Casilla de metal 13
block.metal-wall-1.name = Muro de metal 1
block.metal-wall-2.name = Muro de metal 2
block.metal-wall-3.name = Muro de metal 3
block.colored-floor.name = Piso coloreado
block.colored-wall.name = Muro coloreado
block.colored-floor.name = Suelo de Color
block.colored-wall.name = Muro de Color
block.character-overlay.name = Caracter
block.character-overlay-white.name = Caracter (Blanco)
block.rune-overlay.name = Runa
@@ -2757,7 +2757,7 @@ block.ship-refabricator.description = Mejora al segundo nivel la nave selecciona
block.mech-refabricator.description = Mejora al segundo nivel el mech seleccionado.
block.prime-refabricator.description = Mejora al tercer nivel las unidades entrantes.
block.basic-assembler-module.description = Incrementa el nivel del ensamblador si se coloca junto a un área de construcción. Requiere energía. Se puede usar como entrada de un cargador.
block.small-deconstructor.description = Deconstruye las estructuras y unidades entrantes. Devuelve el 100% de su coste de construcción.
block.small-deconstructor.description = Deconstruye las estructuras y unidades entrantes. Devuelve el 100% de su coste de construcción. Guarda los objetos en diferentes capacidades de objetos.
block.reinforced-payload-conveyor.description = Mueve los lotes de carga en una dirección.
block.reinforced-payload-router.description = Distribuye las cargas a los bloques adyacentes. Funcionará como un clasificador si se le establece un filtro.
block.payload-mass-driver.description = Estructura de transporte de carga de largo alcance. Dispara las cargas entrantes a otras catapultas enlazadas.
@@ -2945,63 +2945,63 @@ laccess.displayheight = Alto de un bloque de pantalla, en pixeles.
laccess.buffersize = Número de comandos sin ejecutar en el buffer gráfico de una pantalla.
laccess.operations = Número de operaciones ejecutadas en el bloque.\nPara pantallas, retorna el número de operaciones drawflush.
laccess.maxunits = Unidades máximas que un equipo puede tener.\nSolo puede ser obtenido de los núcleos.
laccess.totalitems = Total number of items contained.
laccess.firstitem = First item contained, or null if empty.
laccess.totalliquids = Total amount of liquid contained.
laccess.totalpower = For blocks with a buffered power store, the amount of power stored; for other blocks, buffer fullness from 0 to 1.
laccess.itemcapacity = Maximum number of items this building can hold.
laccess.liquidcapacity = Maximum amount of liquid this building can hold.
laccess.powercapacity = Maximum amount of power this building can store.
laccess.powernetstored = Total power stored in the connected power grid.
laccess.powernetcapacity = Total power storage capacity of the connected power grid.
laccess.powernetin = Power entering the connected power grid, per second.
laccess.powernetout = Power leaving the connected power grid, per second.
laccess.ammo = Current ammo count of a turret.
laccess.ammocapacity = Maximum ammo count of a turret.
laccess.health = Current health.\nFor bullets, their damage.
laccess.maxhealth = Maximum health.\nFor bullets, the base damage.
laccess.heat = Current heat of a turret that consumes heat, 0 to 1.
laccess.shield = Current shield amount of a unit.
laccess.armor = Armor value; flat damage reduction per hit.
laccess.efficiency = Operating efficiency of a building, where 1 is nominal.
laccess.timescale = Time scale multiplier affecting a building, where 1 is normal speed.
laccess.rotation = Facing angle of a unit or turret, in degrees.\nFor most other buildings, the 0 to 3 orientation.
laccess.x = X position, in tiles.
laccess.y = Y position, in tiles.
laccess.velocityx = X velocity of a unit, in tiles/sec.
laccess.velocityy = Y velocity of a unit, in tiles/sec.
laccess.shootx = X coordinate a unit or turret is aiming at.
laccess.shooty = Y coordinate a unit or turret is aiming at.
laccess.camerax = X position of the controlling player's camera.
laccess.cameray = Y position of the controlling player's camera.
laccess.camerawidth = Width of the controlling player's view, in tiles.
laccess.cameraheight = Height of the controlling player's view, in tiles.
laccess.solid = Whether this building blocks movement.
laccess.range = Range of a unit or turret, in tiles.
laccess.shooting = Whether a unit or turret is currently shooting.
laccess.boosting = Whether a unit is currently boosting or flying over terrain.
laccess.minex = X tile coordinate a unit is mining, or -1 if not mining.
laccess.miney = Y tile coordinate a unit is mining, or -1 if not mining.
laccess.mining = Whether a unit is currently mining.
laccess.buildx = X tile coordinate a unit is building at, or -1 if not building.
laccess.buildy = Y tile coordinate a unit is building at, or -1 if not building.
laccess.pingx = X coordinate a player is pinging, or null if not pinging.
laccess.pingy = Y coordinate a player is pinging, or null if not pinging.
laccess.pingtext = Text of a player's current ping, or null if not pinging.
laccess.building = Building a unit is currently constructing, or null.
laccess.breaking = Building a unit is currently deconstructing, or null.
laccess.team = Team ID of a unit or building.
laccess.flag = Numeric flag value stored on a unit.
laccess.flying = Whether a unit is currently airborne.
laccess.name = Name of the player controlling this unit, or null.
laccess.payloadcount = Number of payloads currently held.
laccess.payloadtype = Type of the last payload picked up, or null.
laccess.totalpayload = Combined size of all held payloads.
laccess.payloadcapacity = Maximum combined payload size a unit or building can carry.
laccess.selectedblock = Block currently selected by the controlling player, or null.
laccess.selectedrotation = Build rotation currently selected by the controlling player, 0 to 3.
laccess.bulletlifetime = Total lifetime of a bullet, in ticks.
laccess.bullettime = Time a bullet has existed, in ticks.
laccess.totalitems = Número total de items dentro.
laccess.firstitem = Primer item dentro, Devuelve null si se encuentra vacío.
laccess.totalliquids = Cantidad total de líquido contenido.
laccess.totalpower = Para bloques con la capacidad de almacenar energía, la cantidad de energía almacenada; para otros bloques, de 0 a 1.
laccess.itemcapacity = Número total de items que esta construcción o unidad puede almacenar.
laccess.liquidcapacity = Tamaño máximo de liquido que esta construcción puede almacenar.
laccess.powercapacity = Cantidad máxima de energía que esta construcción puede almacenar.
laccess.powernetstored = Total de energía almacenada en la red de energía conectada.
laccess.powernetcapacity = Capacidad de almacenamiento total en la red de energía conectada.
laccess.powernetin = Energía que entra en la red de energía conectada, por segundo.
laccess.powernetout = Energía que abandona la red de energía conectada, por segundo.
laccess.ammo = Cantidad de munición actual de una torreta.
laccess.ammocapacity = Cantidad de munición máxima de una torreta.
laccess.health = Salud actual.\nPara balas, su daño.
laccess.maxhealth = Salud máxima.\nPara balas, su daño base.
laccess.heat = Calor actual de una torreta que puede usarlo, 0 a 1.
laccess.shield = Cantidad de escudo actual de una unidad.
laccess.armor = Valor de armadura; reducción plana de daño por golpe.
laccess.efficiency = Eficiencia operativa de la construcción, donde 1 es el valor nominal.
laccess.timescale = Multiplicador de escala de tiempo afectando a la construcción, donde 1 es la velocidad normal.
laccess.rotation = El ángulo al que está mirando una unidad o torreta, en grados.\nPara muchas de las otras construcciones, la orientación de 0 a 3.
laccess.x = Posición X, en casillas.
laccess.y = Posición Y, en casillas.
laccess.velocityx = Velocidad horizontal de una unidad, en casillas/segundo.
laccess.velocityy = Velocidad vertical de una unidad, en casillas/segundo.
laccess.shootx = Coordenada X a la cual una unidad o torreta está apuntando.
laccess.shooty = Coordenada Y a la cual una unidad o torreta está apuntando.
laccess.camerax = Posición X de la camara del jugador que está controlando.
laccess.cameray = Posición Y de la camara del jugador que está controlando.
laccess.camerawidth = Ancho de la vista del jugador que está controlando, en casillas.
laccess.cameraheight = Largo de la vista del jugador que está controlando, en casillas.
laccess.solid = Si una construcción bloquea el movimiento sobre de ella.
laccess.range = Rango de una unidad o torreta, en casillas.
laccess.shooting = Si una unidad o torreta se encuentra disparando.
laccess.boosting = Si una unidad está volando sobrevolando o volando sobre el terreno.
laccess.minex = Coordenada X de la casilla en la cual una unidad está minando, o -1 si no está minando.
laccess.miney = Coordenada Y de la casilla en la cual una unidad está minando, o -1 si no está minando.
laccess.mining = Si una unidad se encuentra minando.
laccess.buildx = Coordenada X de la casilla en la cual una unidad está construyendo, o -1 si no está construyendo.
laccess.buildy = Coordenada Y de la casilla en la cual una unidad está construyendo, o -1 si no está construyendo.
laccess.pingx = Coordenada X en la cual un jugador esta pingeando, o null si no está pingeando.
laccess.pingy = Coordenada Y en la cual un jugador está pingeando, o null si no está pingeando.
laccess.pingtext = Texto del ping actual de un jugador, o null si no está pingeando.
laccess.building = Construcción que la unidad está construyendo actualmente, o null.
laccess.breaking = Construcción que la unidad está deconstruyendo actualmente, o null.
laccess.team = Identificador de equipo de una unidad o construcción.
laccess.flag = Valor numérico o flag almacenada en una unidad.
laccess.flying = Si la unidad se encuentra volando.
laccess.name = Nombre del jugador controlando esta unidad, o null.
laccess.payloadcount = Numero de carga que se lleva actualmente.
laccess.payloadtype = Tipo de la última carga recogida, o null.
laccess.totalpayload = Tamaño combinado de toda la carga llevada.
laccess.payloadcapacity = Tamaño máximo combinado que una unidad o construcción pueden cargar.
laccess.selectedblock = Bloque seleccionado actualmente por el jugador que está controlando, o null.
laccess.selectedrotation = Rotación del bloque actualmente seleccionado por el jugador que está controland, de 0 a 3.
laccess.bulletlifetime = Tiempo de vida total de una bala, en ticks.
laccess.bullettime = Tiempo que una bala ha existido, en ticks.
lcategory.unknown = Desconocido
lcategory.unknown.description = Instrucciones no clasificadas.
@@ -3186,8 +3186,8 @@ instruction.print = Agregar texto
instruction.printchar = Agregar Carácter
instruction.format = Reemplazar Formato
instruction.drawflush = Dibujar Gráficos
instruction.printflush = Imprimir
instruction.getlink = Obtener Enlazados
instruction.printflush = Imprimir Texto
instruction.getlink = Obtener Enlazado
instruction.control = Controlar
instruction.radar = Radar
instruction.sensor = Sensor
@@ -3195,9 +3195,9 @@ instruction.set = Asignar
instruction.operation = Operación
instruction.select = Seleccionar
instruction.wait = Esperar
instruction.stop = Detener
instruction.stop = Detener Ejecución
instruction.lookup = Buscar
instruction.jump = Salto Condicional
instruction.jump = Jump
instruction.end = Terminar
instruction.unitbind = Vincular Unidad
instruction.unitcontrol = Controlar Unidad
@@ -3206,31 +3206,31 @@ instruction.unitlocate = Localizar con Unidad
instruction.query = Query
instruction.getblock = Obtener Bloque
instruction.setblock = Crear Bloque
instruction.spawnunit = Aparecer Unidad
instruction.spawnbullet = Aparecer Bala
instruction.spawnunit = Crear Unidad
instruction.spawnbullet = Crear Bala
instruction.applystatus = Aplicar Estado
instruction.weathersense = Detectar Clima
instruction.weathersense = Obtener Clima
instruction.weatherset = Establecer Clima
instruction.spawnwave = Aparecer Oleada
instruction.spawnwave = Generar Oleada
instruction.setrule = Cambiar Regla
instruction.flushmessage = Flush Message
instruction.flushmessage = Mostrar Mensaje
instruction.cutscene = Cinematica
instruction.effect = Efecto
instruction.explosion = Explosion
instruction.setrate = Set Rate
instruction.setrate = Establecer Velocidad
instruction.fetch = Buscar
instruction.sync = Sincronizar
instruction.clientdata = Datos del Cliente
instruction.getflag = Get Flag
instruction.setflag = Set Flag
instruction.setprop = Set Prop
instruction.getflag = Obtener Flag Global
instruction.setflag = Asignar Flag Global
instruction.setprop = Asignar Propiedad
instruction.playsound = Reproducir Sonido
instruction.playmusic = Reproducir Musica
instruction.setmarker = Set Marker
instruction.makemarker = Make Marker
instruction.localeprint = Locale Print
instruction.packcolor = Desagrupar Color
instruction.unpackcolor = Agrupar Color
instruction.packcolor = Agrupar Color
instruction.unpackcolor = Desagrupar Color
instruction.invalid = Instrucción Invalida
# Implemented via the enumText() method
blockflag.label.core = núcleos
@@ -3263,22 +3263,22 @@ fetchtype.label.unitcount = cantidad de unidades
fetchtype.label.playercount = cantidad de jugadores
fetchtype.label.corecount = cantidad de núcleos
fetchtype.label.buildcount = cantidad de construcciones
graphicstype.label.clear = clear
graphicstype.label.clear = llenar
graphicstype.label.color = color
graphicstype.label.col = col
graphicstype.label.stroke = stroke
graphicstype.label.line = line
graphicstype.label.rect = rect
graphicstype.label.linerect = line rect
graphicstype.label.poly = poly
graphicstype.label.linepoly = line poly
graphicstype.label.triangle = triangle
graphicstype.label.image = image
graphicstype.label.print = print
graphicstype.label.stroke = ancho
graphicstype.label.line = linea
graphicstype.label.rect = rectangulo
graphicstype.label.linerect = lineas rect
graphicstype.label.poly = poligono
graphicstype.label.linepoly = lineas poly
graphicstype.label.triangle = triangulo
graphicstype.label.image = imágen
graphicstype.label.print = texto
graphicstype.label.translate = translate
graphicstype.label.scale = scale
graphicstype.label.rotate = rotate
graphicstype.label.reset = reset
graphicstype.label.scale = escalar
graphicstype.label.rotate = rotar
graphicstype.label.reset = reiniciar
laccess.label.totalitems = total de objetos
laccess.label.firstitem = primer objeto
laccess.label.totalliquids = liquido total
@@ -3318,27 +3318,27 @@ laccess.label.displayheight = largo de pantalla
laccess.label.buffersize = tamaño de buffer
laccess.label.operations = operaciones
laccess.label.size = tamaño
laccess.label.solid = ¿solido?
laccess.label.dead = ¿muerto?
laccess.label.solid = solido?
laccess.label.dead = muerto?
laccess.label.range = rango
laccess.label.shooting = ¿disparando?
laccess.label.boosting = ¿sobrevolando?
laccess.label.shooting = disparando?
laccess.label.boosting = sobrevolando?
laccess.label.minex = minando x
laccess.label.miney = minando y
laccess.label.mining = ¿minando?
laccess.label.mining = minando?
laccess.label.buildx = construyendo x
laccess.label.buildy = construyendo y
laccess.label.pingx = ping x
laccess.label.pingy = ping y
laccess.label.pingtext = texto en ping
laccess.label.building = ¿construyendo?
laccess.label.breaking = ¿deconstruyendo?
laccess.label.building = construyendo?
laccess.label.breaking = deconstruyendo?
laccess.label.speed = velocidad
laccess.label.team = equipo
laccess.label.type = tipo
laccess.label.flag = flag
laccess.label.flying = ¿puede volar?
laccess.label.controlled = ¿controlada?
laccess.label.flying = puede volar?
laccess.label.controlled = controlada?
laccess.label.controller = controlador
laccess.label.name = nombre
laccess.label.payloadcount = conteo de carga
@@ -3351,7 +3351,7 @@ laccess.label.selectedblock = bloque seleccionado
laccess.label.selectedrotation = rotación seleccionada
laccess.label.bulletlifetime = tiempo de vida de la bala
laccess.label.bullettime = tiempo de bala
laccess.label.enabled = ¿activado?
laccess.label.enabled = activado?
laccess.label.shoot = disparo
laccess.label.shootp = disparo con predicción
laccess.label.config = configuración
@@ -3387,17 +3387,17 @@ lmarkercontrol.label.posi = posi
lmarkercontrol.label.uvi = uvi
lmarkercontrol.label.colori = colori
logicrule.label.currentwavetime = tiempo restante oleada actual
logicrule.label.wavetimer = ¿temporizador de oleada?
logicrule.label.waves = ¿oleadas activas?
logicrule.label.wavetimer = temporizador de oleada?
logicrule.label.waves = oleadas activas?
logicrule.label.wave = oleada
logicrule.label.wavespacing = tiempo entre oleadas
logicrule.label.wavesending = ¿adelantar oleada?
logicrule.label.attackmode = ¿modo de juego ataque?
logicrule.label.wavesending = enviar oleadas?
logicrule.label.attackmode = modo de juego ataque?
logicrule.label.enemycorebuildradius = radio de construccion de núcleo enemiga
logicrule.label.dropzoneradius = radio de zona de aparición
logicrule.label.unitcap = capacidad de unidades
logicrule.label.maparea = area del mapa
logicrule.label.lighting = ¿iluminación?
logicrule.label.lighting = iluminación?
logicrule.label.cangameover = se puede perder
logicrule.label.ambientlight = iluminación ambiental
logicrule.label.unitlight = iluminación de unidad
@@ -3405,7 +3405,7 @@ logicrule.label.solarmultiplier = multiplicador solar
logicrule.label.dragmultiplier = multiplicador de arrastre
logicrule.label.ban = banear
logicrule.label.unban = desbanear
logicrule.label.pausedisabled = ¿desactivar pausa?
logicrule.label.pausedisabled = desactivar pausa?
logicrule.label.musicvolume = volumen de la música
logicrule.label.buildspeed = velocidad de construcción
logicrule.label.unithealth = salud de unidad
@@ -3421,29 +3421,29 @@ lunitcontrol.label.idle = inactiva
lunitcontrol.label.stop = detenerse
lunitcontrol.label.unbind = desvincular
lunitcontrol.label.move = mover
lunitcontrol.label.approach = aproximar
lunitcontrol.label.pathfind = encontrarRuta
lunitcontrol.label.autopathfind = encontrarRuta auto
lunitcontrol.label.target = target
lunitcontrol.label.targetp = target predict
lunitcontrol.label.approach = acercar
lunitcontrol.label.pathfind = seguir ruta
lunitcontrol.label.autopathfind = auto-seguir ruta
lunitcontrol.label.target = disparar
lunitcontrol.label.targetp = disparar con predicción
lunitcontrol.label.itemdrop = soltar objeto
lunitcontrol.label.itemtake = tomar objeto
lunitcontrol.label.paydrop = soltar carga
lunitcontrol.label.paytake = tomar carga
lunitcontrol.label.payenter = entrar como carga
lunitcontrol.label.flag = etiqueta
lunitcontrol.label.flag = flag
lunitcontrol.label.mine = minar
lunitcontrol.label.build = construir bloque
lunitcontrol.label.getblock = obtener bloque
lunitcontrol.label.deconstruct = deconstruir
lunitcontrol.label.within = ¿dentro de?
lunitcontrol.label.boost = ¿potenciar?
lunitcontrol.label.within = dentro de?
lunitcontrol.label.boost = sobrevolar?
messagetype.label.notify = notify
messagetype.label.announce = announce
messagetype.label.toast = toast
messagetype.label.mission = mission
querytype.label.unit = unit
querytype.label.building = building
querytype.label.unit = unidad
querytype.label.building = construcción
radarsort.label.distance = distancia
radarsort.label.health = salud
radarsort.label.maxhealth = salud máxima
@@ -3457,40 +3457,40 @@ radartarget.label.attacker = unidad armada
radartarget.label.flying = unidad aérea
radartarget.label.ground = unidad terrestre
radartarget.label.boss = boss
tilelayer.label.floor = floor
tilelayer.label.ore = ore
tilelayer.label.block = block
tilelayer.label.building = building
tilelayer.label.floor = suelo
tilelayer.label.ore = mineral
tilelayer.label.block = bloque
tilelayer.label.building = construcción
name.token.color = color
name.token.width = width
name.token.height = height
name.token.sides = sides
name.token.radius = radius
name.token.rotation = rotation
name.token.image = image
name.token.size = size
name.token.align = align
name.token.set = crear
name.token.of = of
name.token.width = ancho
name.token.height = largo
name.token.sides = lados
name.token.radius = radio
name.token.rotation = rotación
name.token.image = imagen
name.token.size = tamaño
name.token.align = alinear
name.token.set = asigna
name.token.of = de
name.token.to = a
name.token.at = en
name.token.in = en
name.token.damage = daño
name.token.velocityScl = velocity scale
name.token.lifeScl = life scale
name.token.aimX = aim X
name.token.aimY = aim Y
name.token.read = read
name.token.write = write
name.token.from = from
name.token.char = char
name.token.velocityScl = escala de velocidad
name.token.lifeScl = escala de salud
name.token.aimX = apuntar X
name.token.aimY = apuntar Y
name.token.read = lee
name.token.write = escribe
name.token.from = de
name.token.char = carácter
name.token.linknum = link#
name.token.draw = draw
name.token.clear = clear
name.token.apply = apply
name.token.circle = circle
name.token.rect = rect
name.token.draw = dibujar
name.token.clear = limpiar
name.token.apply = aplicar
name.token.circle = circulo
name.token.rect = recta
name.token.positional = posicional
name.token.global = global
name.token.target = objetivo
@@ -3507,43 +3507,43 @@ name.token.then = then
name.token.else = else
name.token.find = localizar
name.token.group = grupo
name.token.enemy = ¿enemigo?
name.token.enemy = enemigo?
name.token.ore = mineral
name.token.outX = X obtenida
name.token.outY = Y obtenida
name.token.owner = owner
name.token.found = ¿encontrado?
name.token.found = encontrado?
name.token.building = construcción
name.token.always = always
name.token.not = not
name.token.pack = pack
name.token.unpack = unpack
name.token.-lookup = = lookup
name.token.type = type
name.token.pack = agrupar
name.token.unpack = desagrupar
name.token.-lookup = = bucar
name.token.type = tipo
name.token.get = get
name.token.team = team
name.token.angle = angle
name.token.spawn = spawn
name.token.-bullet = = bullet
name.token.unit = unit
name.token.weather = weather
name.token.state = state
name.token.team = equipo
name.token.angle = ángulo
name.token.spawn = crear
name.token.-bullet = = bala
name.token.unit = unidad
name.token.weather = clima
name.token.state = estado
name.token.natural = natural
name.token.speed = speed
name.token.level = level
name.token.duration = duration
name.token.seconds = seconds
name.token.duration = duración
name.token.seconds = segundos
name.token.shown = shown
name.token.data = data
name.token.effect = effect
name.token.pierce = pierce
name.token.ground = ground
name.token.effect = efecto
name.token.pierce = atraviesa
name.token.ground = terrestre
name.token.air = air
name.token.flag = flag
name.token.volume = volume
name.token.volume = volumen
name.token.pitch = pitch
name.token.pan = pan
name.token.limit = limit
name.token.limit = limite
name.token.id = id #
name.token.replace = replace?
name.token.for = for
@@ -3562,13 +3562,13 @@ name.token.name = name
name.token.index = index
name.token.block-unit = block/unit
name.token.enable = enable
name.token.amount = amount
name.token.amount = cantidad
name.token.item = item
name.token.takeUnits = take units
name.token.takeUnits = tomar unidades?
name.token.value = value
name.token.floor = floor
name.token.result = resultado
name.token.config = config
name.token.config = configuración
name.token.shapeText = shape text
name.token.point = point
name.token.shape = shape
@@ -3577,12 +3577,12 @@ name.token.line = line
name.token.texture = texture
name.token.quad = quad
name.token.light = light
name.token.snowing = snowing
name.token.rain = rain
name.token.sandstorm = sand storm
name.token.sporestorm = spore storm
name.token.fog = fog
name.token.suspend-particles = suspended particles
name.token.snowing = nevando
name.token.rain = lloviendo
name.token.sandstorm = tormenta de arena
name.token.sporestorm = tormenta de esporas
name.token.fog = neblina
name.token.suspend-particles = particulas suspendidas
name.token.topLeft = top left
name.token.top = top
name.token.topRight = top right
@@ -3626,15 +3626,15 @@ name.token.sparkExplosion = explosión con chispas
name.token.crossExplosion = explosión con cruz
name.token.wave = oleada
name.token.bubble = burbuja
name.token.music = music
name.token.interrupt = interrupt
name.token.music = musica
name.token.interrupt = interrumpe
name.token.all = Todos
name.token.beams = Rayos
name.token.block = Bloques
name.token.block = bloque
name.token.charge = Carga
name.token.environment = Clima
name.token.explosions = Explosiones
name.token.loops = Bucles
name.token.movement = Movimiento
name.token.shoot = Disparos
name.token.ui = Interfaz Usuario
name.token.shoot = disparar
name.token.ui = Interfaz de Usuario
+72 -72
View File
@@ -1019,7 +1019,7 @@ sector.crateredBattleground.description = Víz gyűlt össze ebben a kráterben,
sector.ruinousShores.description = A pusztaság mögött a partvonal húzódik. Valaha ezen a helyen egy partvédelmi rendszer állt. Nem sok minden maradt belőle. Csak a legalapvetőbb védelmi szerkezetek maradtak érintetlenül, minden más csak törmelék lett.\nFolytasd a terjeszkedést. Fedezd fel újra a technológiát.
sector.stainedMountains.description = Mélyebben a szárazföldön fekszenek a hegyek, a spóráktól még érintetlenül.\nTermeld ki a bőséges titán készleteket a körzetben. Tanuld meg felhasználni.\n\nAz ellenség itt nagyobb létszámban van jelen. Ne hagyj nekik időt, hogy a legerősebb egységeiket hadba állíthassák.
sector.overgrowth.description = Ez a terület közelebb esik a spórák forrásához, a spórák már kinőtték.\nAz ellenség egy helyőrséget létesített itt. Építs Mace egységeket. Pusztítsd el a bázist.
sector.tarFields.description = Egy olajtermelő övezet peremvidéke a hegyek és a sivatag határán. Egy azon kevés szektorok közül, ahol még hasznosítható kátránykészletek találhatók.\nBár a terület elhagyatott, veszélyes ellenséges erők fészkelnek a közelben. Ne becsüld alá őket.\n\n[lightgray]Fedezd fel az olajfeldolgozási lehetőségeket, ha tudod.
sector.tarFields.description = Egy olajtermelő övezet peremvidéke a hegyek és a sivatag határán. Azon kevés szektorok egyike, ahol még hasznosítható kátránykészletek találhatók.\nBár a terület elhagyatott, veszélyes ellenséges erők fészkelnek a közelben. Ne becsüld alá őket.\n\n[lightgray]Fedezd fel az olajfeldolgozási lehetőségeket, ha tudod.
sector.desolateRift.description = Ez egy rendkívül veszélyes zóna. Bár nyersanyagokban gazdag, kevés hely áll rendelkezésre. Magas a kockázat. Építs szárazföldi és légvédelmet, amint csak tudsz. Ne tévesszen meg a hosszú szünet az ellenség támadásai között.
sector.nuclearComplex.description = Egy néhai tóriumkitermelő és feldolgozó létesítmény, romokban.\n[lightgray]Fedezd fel a tóriumot és a sokrétű felhasználását.\n\nAz ellenség nagy létszámban van jelen, és folyamatosan megfigyelés alatt tartják a környéket.
sector.fungalPass.description = Átmeneti terület a magas hegyek és a mélyebben fekvő, spórák uralta lapály között. Egy kisebb ellenséges megfigyelő állomás található itt.\nSemmisítsd meg.\nHasználj Dagger egységeket. Pusztítsd el a támaszpontot.
@@ -1299,7 +1299,7 @@ bar.cargounitcap = Az egység raktere megtelt
bar.drillspeed = Termelés: {0}/mp
bar.pumpspeed = Termelés: {0}/mp
bar.efficiency = Hatásfok: {0}%
bar.yield = Hozam: +{0}%
bar.yield = Hozam: {0}%
bar.boost = Erősítés: +{0}%
bar.powerbuffer = Akkumulátorok: {0}/{1}
bar.powerbalance = Áram: {0}/mp
@@ -1414,8 +1414,8 @@ category.function = Funkció
category.optional = Lehetséges fejlesztések
setting.alwaysmusic.name = Folyamatos zenelejátszás
setting.alwaysmusic.description = Amikor engedélyezve van, akkor a zene folyamatosan szól a játékban.\nHa ki van kapcsolva, akkor csak véletlenszerű időközönként szólal meg.
setting.skipcoreanimation.name = Támaszpont animációjának kihagyása kilövéskor és leszálláskor
setting.skipcoreanimation.description = Ha engedélyezve van, akkor a támaszpont fel- és leszállásának\nanimációja nem lesz megjelenítve.
setting.skipcoreanimation.name = Támaszpont animációinak kihagyása
setting.skipcoreanimation.description = Ha engedélyezve van, akkor a támaszpont fel- és leszállási\nanimációja nem lesz megjelenítve.
setting.landscape.name = Fekvő mód zárolása
setting.landscape.description = Ha engedélyezve van, akkor a képernyő tájolása fekvő módban lesz rögzítve.
setting.blockreplace.name = Automatikus blokkjavaslatok
@@ -1468,8 +1468,8 @@ setting.destroyedblocks.name = Lerombolt építmények megjelenítése
setting.destroyedblocks.description = Ha engedélyezve van, akkor a megsemmisített blokkok\ntörmeléket hagynak maguk után.
setting.blockstatus.name = Blokkok állapotának megjelenítése
setting.blockstatus.description = A blokkok felett színes állapotikonok jelennek meg.
setting.conveyorpathfinding.name = Szállítószalag nyomvonalkeresése építéskor
setting.conveyorpathfinding.description = Ha engedélyezve van, akkor a szállítószalagok elhelyezésekor a rendszer\nautomatikusan megpróbálja megtalálni az útvonalat a célállomásig.
setting.conveyorpathfinding.name = Nyomvonalkeresés szállítószalag-építéskor
setting.conveyorpathfinding.description = Ha engedélyezve van, akkor a szállítószalagok elhelyezésekor a rendszer\nautomatikusan megpróbálja megtalálni azok nyomvonalát a célállomásig.
setting.sensitivity.name = Játékvezérlők érzékenysége
setting.sensitivity.description = A játékvezérlők (joystick) érzékenységét lehet vele finomhangolni.
setting.saveinterval.name = Mentési időköz
@@ -1478,7 +1478,7 @@ setting.seconds = {0} másodperc
setting.milliseconds = {0} ezredmásodperc
setting.fullscreen.name = Teljes képernyő
setting.fps.name = FPS, memóriahasználat és ping megjelenítése
setting.fps.description = Megjeleníti a jelenlegi képkockasebességet (FPS), a memóriahasználatot MB/GB-ban\nés a hálózati pinget a képernyő sarkában.
setting.fps.description = Megjeleníti a jelenlegi képkockasebességet, a memóriahasználatot MB/GB-ban\nés a hálózati pinget a képernyő sarkában.
setting.console.name = Konzol engedélyezése
setting.console.description = Engedélyezi a játékon belüli JavaScript-konzolt.
setting.drawhitboxes.name = Ütközési dobozok megjelenítése
@@ -2922,7 +2922,7 @@ lglobal.@clientName = A kódot futtató kliens játékosneve
lglobal.@clientTeam = A kódot futtató kliens csapatazonosítója
lglobal.@clientMobile = Igaz, ha a kódot futtató kliens egy hordozható eszköz, egyébként hamis
lglobal.@clientMusicPlaying = Igaz, ha jelenleg folyamatban van bármilyen zene lejátszása
lglobal.@clientCurrentMusic = A jelenleg játszott zeneszám neve, vagy nulla
lglobal.@clientCurrentMusic = A jelenleg játszott zeneszám neve, vagy null
lenum.type = Az épület/egység típusa.\nPéldául bármilyen elosztó esetén a [accent]@router[] értéket adja vissza.\nNem karakterlánc.
lenum.shoot = Lövés egy adott pontra.
@@ -2945,63 +2945,63 @@ laccess.displayheight = Egy kijelzőblokk magassága pixelben.
laccess.buffersize = Üzenetek esetén: A tartalom hossza.\nKijelzők esetén: A feldolgozatlan grafikus parancsok száma.
laccess.operations = A blokkon végrehajtott műveletek száma.\nKijelzők esetén a drawflush-műveletek számát adja vissza.
laccess.maxunits = Egy csapat maximális egységeinek száma.\nCsak támaszpontokból érzékelhető.
laccess.totalitems = Total number of items contained.
laccess.firstitem = First item contained, or null if empty.
laccess.totalliquids = Total amount of liquid contained.
laccess.totalpower = For blocks with a buffered power store, the amount of power stored; for other blocks, buffer fullness from 0 to 1.
laccess.itemcapacity = Maximum number of items this building can hold.
laccess.liquidcapacity = Maximum amount of liquid this building can hold.
laccess.powercapacity = Maximum amount of power this building can store.
laccess.powernetstored = Total power stored in the connected power grid.
laccess.powernetcapacity = Total power storage capacity of the connected power grid.
laccess.powernetin = Power entering the connected power grid, per second.
laccess.powernetout = Power leaving the connected power grid, per second.
laccess.ammo = Current ammo count of a turret.
laccess.ammocapacity = Maximum ammo count of a turret.
laccess.health = Current health.\nFor bullets, their damage.
laccess.maxhealth = Maximum health.\nFor bullets, the base damage.
laccess.heat = Current heat of a turret that consumes heat, 0 to 1.
laccess.shield = Current shield amount of a unit.
laccess.armor = Armor value; flat damage reduction per hit.
laccess.efficiency = Operating efficiency of a building, where 1 is nominal.
laccess.timescale = Time scale multiplier affecting a building, where 1 is normal speed.
laccess.rotation = Facing angle of a unit or turret, in degrees.\nFor most other buildings, the 0 to 3 orientation.
laccess.x = X position, in tiles.
laccess.y = Y position, in tiles.
laccess.velocityx = X velocity of a unit, in tiles/sec.
laccess.velocityy = Y velocity of a unit, in tiles/sec.
laccess.shootx = X coordinate a unit or turret is aiming at.
laccess.shooty = Y coordinate a unit or turret is aiming at.
laccess.camerax = X position of the controlling player's camera.
laccess.cameray = Y position of the controlling player's camera.
laccess.camerawidth = Width of the controlling player's view, in tiles.
laccess.cameraheight = Height of the controlling player's view, in tiles.
laccess.solid = Whether this building blocks movement.
laccess.range = Range of a unit or turret, in tiles.
laccess.shooting = Whether a unit or turret is currently shooting.
laccess.boosting = Whether a unit is currently boosting or flying over terrain.
laccess.minex = X tile coordinate a unit is mining, or -1 if not mining.
laccess.miney = Y tile coordinate a unit is mining, or -1 if not mining.
laccess.mining = Whether a unit is currently mining.
laccess.buildx = X tile coordinate a unit is building at, or -1 if not building.
laccess.buildy = Y tile coordinate a unit is building at, or -1 if not building.
laccess.pingx = X coordinate a player is pinging, or null if not pinging.
laccess.pingy = Y coordinate a player is pinging, or null if not pinging.
laccess.pingtext = Text of a player's current ping, or null if not pinging.
laccess.building = Building a unit is currently constructing, or null.
laccess.breaking = Building a unit is currently deconstructing, or null.
laccess.team = Team ID of a unit or building.
laccess.flag = Numeric flag value stored on a unit.
laccess.flying = Whether a unit is currently airborne.
laccess.name = Name of the player controlling this unit, or null.
laccess.payloadcount = Number of payloads currently held.
laccess.payloadtype = Type of the last payload picked up, or null.
laccess.totalpayload = Combined size of all held payloads.
laccess.payloadcapacity = Maximum combined payload size a unit or building can carry.
laccess.selectedblock = Block currently selected by the controlling player, or null.
laccess.selectedrotation = Build rotation currently selected by the controlling player, 0 to 3.
laccess.bulletlifetime = Total lifetime of a bullet, in ticks.
laccess.bullettime = Time a bullet has existed, in ticks.
laccess.totalitems = A tárolt elemek teljes száma.
laccess.firstitem = Az első tárolt elem, vagy null, ha üres.
laccess.totalliquids = A tárolt folyadék teljes mennyisége.
laccess.totalpower = Pufferezett energiatárolóval rendelkező blokkoknál a tárolt energia mennyisége; más blokkoknál a puffer telítettsége 0-tól 1-ig.
laccess.itemcapacity = A maximális elemszám, amit ez az épület tárolni tud.
laccess.liquidcapacity = A maximális folyadékmennyiség, amit ez az épület tárolni tud.
laccess.powercapacity = A maximális energiamennyiség, amit ez az épület tárolni tud.
laccess.powernetstored = Az összekapcsolt energiahálózatban tárolt teljes energiamennyiség.
laccess.powernetcapacity = Az összekapcsolt energiahálózat teljes energiatárolási kapacitása.
laccess.powernetin = Az összekapcsolt energiahálózatba másodpercenként belépő energia.
laccess.powernetout = Az összekapcsolt energiahálózatból másodpercenként kilépő energia.
laccess.ammo = Egy lövegtorony jelenlegi lőszerkészlete.
laccess.ammocapacity = Egy lövegtorony maximális lőszerkészlete.
laccess.health = Jelenlegi életerő.\nLövedékek esetén azok sebzése.
laccess.maxhealth = Maximális életerő.\nLövedékek esetén az alapsebzés.
laccess.heat = Hőt fogyasztó lövegtorony jelenlegi hője, 0-tól 1-ig.
laccess.shield = Egy egység jelenlegi pajzsának mennyisége.
laccess.armor = Páncélzat értéke; fix sebzéscsökkentés találatonként.
laccess.efficiency = Egy épület működési hatásfoka, ahol az 1 a normális érték.
laccess.timescale = Egy épületre ható időskálaszorzó, ahol az 1 a normál sebesség.
laccess.rotation = Egy egység vagy lövegtorony irányszöge fokban.\nA legtöbb más épületnél a 0-tól 3-ig terjedő tájolás.
laccess.x = X-pozíció mezőkben.
laccess.y = Y-pozíció mezőkben.
laccess.velocityx = Egy egység X-irányú sebessége (mező/mp).
laccess.velocityy = Egy egység Y-irányú sebessége (mező/mp).
laccess.shootx = Annak a mezőnek az X-koordinátája, amire egy egység vagy lövegtorony céloz.
laccess.shooty = Annak a mezőnek az Y-koordinátája, amire egy egység vagy lövegtorony céloz.
laccess.camerax = Az irányító játékos kamerájának X-pozíciója.
laccess.cameray = Az irányító játékos kamerájának Y-pozíciója.
laccess.camerawidth = Az irányító játékos nézetének szélessége mezőkben.
laccess.cameraheight = Az irányító játékos nézetének magassága mezőkben.
laccess.solid = Meghatározza, hogy akadályozza-e ez az épület a mozgást.
laccess.range = Egy egység vagy lövegtorony hatótávolsága mezőkben.
laccess.shooting = Meghatározza, hogy éppen lő-e egy egység vagy lövegtorony.
laccess.boosting = Meghatározza, hogy gyorsít-e, vagy repül-e éppen a terep felett egy egység.
laccess.minex = Annak a mezőnek az X-koordinátája, amit egy egység bányászik, vagy -1, ha nem.
laccess.miney = Annak a mezőnek az Y-koordinátája, amit egy egység bányászik, vagy -1, ha nem.
laccess.mining = Meghatározza, hogy éppen bányászik-e egy egység.
laccess.buildx = Annak a mezőnek az X-koordinátája, ahol egy egység épít, vagy -1, ha nem.
laccess.buildy = Annak a mezőnek az Y-koordinátája, ahol egy egység épít, vagy -1, ha nem.
laccess.pingx = Annak a mezőnek az X-koordinátája, amit egy játékos pingel,\nvagy null, ha nem.
laccess.pingy = Annak a mezőnek az Y-koordinátája, amit egy játékos pingel,\nvagy null, ha nem.
laccess.pingtext = Egy játékos jelenlegi pingjének szövege, vagy null, ha nincs ping.
laccess.building = Az az épület, amit egy egység éppen épít, vagy null.
laccess.breaking = Az az épület, amit egy egység éppen lebont, vagy null.
laccess.team = Egy egység vagy épület csapatának azonosítója.
laccess.flag = Egy egységen tárolt számszerű jelző értéke.
laccess.flying = Meghatározza, hogy repül-e éppen egy egység.
laccess.name = Az egységet irányító játékos neve, vagy null.
laccess.payloadcount = A jelenleg hordozott rakományok száma.
laccess.payloadtype = A legutóbb felvett rakomány típusa, vagy null.
laccess.totalpayload = Az összes hordozott rakomány együttes mérete.
laccess.payloadcapacity = A maximális együttes rakományméret, amit egy egység vagy épület elbír.
laccess.selectedblock = Az irányító játékos által jelenleg kiválasztott blokk, vagy null.
laccess.selectedrotation = Az irányító játékos által jelenleg kiválasztott építési irány, 0-tól 3-ig.
laccess.bulletlifetime = Egy lövedék teljes élettartama tickekben.
laccess.bullettime = Az idő, amióta egy lövedék létezik, tickekben.
lcategory.unknown = Ismeretlen
lcategory.unknown.description = Nem kategorizált utasítások.
@@ -3145,11 +3145,11 @@ lenum.boost = Erősítés indítása/leállítása.
lenum.flushtext = Az írási puffer tartalmának ürítése a jelölőre, ha alkalmazható.\nHa a „fetch” igaz, akkor megpróbálja lekérni a tulajdonságokat a pálya nyelvi csomagjából vagy a játék csomagjából.
lenum.texture = A textúra neve közvetlenül a játék textúra-atlaszából (úgynevezett „kebab-case” elnevezési stílus használatával).\nHa a „printFlush” igaz, akkor a szöveges puffer tartalmát használja szöveges argumentumként.
lenum.texturesize = A textúra mérete mezőben. A nulla érték a jelölő szélességét az eredeti textúra méretére skálázza.
lenum.texturesize = A textúra mérete mezőben. A null érték a jelölő szélességét az eredeti textúra méretére skálázza.
lenum.autoscale = Meghatározza, hogy a jelölő a játékos nagyítási szintjéhez igazodik-e.
lenum.posi = Indexelt pozíció, vonal- és négyszögjelzőkhöz használatos, ahol a nulla az első pozíció.
lenum.posi = Indexelt pozíció, vonal- és négyszögjelzőkhöz használatos, ahol a null az első pozíció.
lenum.uvi = A textúra pozíciója nullától egyig, négyzetjelölőkhöz használatos.
lenum.colori = Indexelt szín, vonal- és négyzetjelölőkhöz használatos, ahol a nulla az első szín.
lenum.colori = Indexelt szín, vonal- és négyzetjelölőkhöz használatos, ahol a null az első szín.
lenum.wavetimer = Meghatározza, hogy a hullámok automatikusan indulnak-e az időzítő alapján. Ha nem, akkor a hullámok a lejátszásgomb megnyomásakor indulnak.
lenum.wave = Jelenlegi hullámszám. Bármi lehet a nem-hullámalapú játékmódokban.
@@ -3391,14 +3391,14 @@ logicrule.label.wavetimer = hullámidőzítő?
logicrule.label.waves = hullámok
logicrule.label.wave = hullám
logicrule.label.wavespacing = hullámok közötti idő
logicrule.label.wavesending = hullámok véget érnek?
logicrule.label.wavesending = hullámok küldése?
logicrule.label.attackmode = támadó mód?
logicrule.label.enemycorebuildradius = ellenséges támaszpont építési sugara
logicrule.label.dropzoneradius = ledobási zóna sugara
logicrule.label.unitcap = egységkorlát
logicrule.label.maparea = térkép területe
logicrule.label.lighting = világítás?
logicrule.label.cangameover = lehetséges játék vége
logicrule.label.cangameover = befejeződhet a játék
logicrule.label.ambientlight = környezeti fény
logicrule.label.unitlight = egység fénye
logicrule.label.solarmultiplier = napelemszorzó
@@ -3456,7 +3456,7 @@ radartarget.label.player = játékos
radartarget.label.attacker = támadó
radartarget.label.flying = légi
radartarget.label.ground = földi
radartarget.label.boss = boss
radartarget.label.boss = főellenség
tilelayer.label.floor = padló
tilelayer.label.ore = érc
tilelayer.label.block = blokk
@@ -3522,7 +3522,7 @@ name.token.-lookup = = keresés
name.token.type = típus
name.token.get = lekérés
name.token.team = csapat
name.token.angle = angle
name.token.angle = szög
name.token.spawn = elhelyezés
name.token.-bullet = = lövedék
name.token.unit = egység
+68 -68
View File
@@ -882,7 +882,7 @@ bannedunits.whitelist = Unit yang Dilarang Sebagai Whitelist
bannedblocks.whitelist = Blok yang Dilarang Sebagai Whitelist
addall = Tambah Semua
launch.from = Meluncurkan Dari: [accent]{0}
launch.capacity = Kapasitas item yang Diluncurkan: [accent]{0}
launch.capacity = Kapasitas Item yang Diluncurkan: [accent]{0}
launch.destination = Destinasi: {0}
landing.sources = Total Sumber Sektor: [accent]{0}[]
landing.import = Total Impor Maksimum: {0}[accent]{1}[lightgray]/mnt
@@ -1074,7 +1074,7 @@ sector.caldera-erekir.description = Sumber daya yang terdeteksi di sektor ini te
sector.stronghold.description = Markas musuh yang besar di sektor ini menjaga simpanan [accent]torium[] dalam jumlah besar.\nGunakan itu untuk mengembangkan unit dan menara ke tingkat yang lebih tinggi.
sector.crevice.description = Musuh akan mengirimkan pasukan serangan yang hebat untuk menghancurkan markasmu di sektor ini.\nKembangkan [accent]karbida[] dan [accent]Generator Pirolisis[] mungkin imperatif untuk bertahan hidup.
sector.siege.description = Sektor ini memiliki dua ngarai paralel yang akan memaksa serangan dari dua arah.\nRiset [accent]sianogen[] untuk mendapatkan kemampuan untuk memproduksi unit tank yang lebih kuat.\nPeringatan: Rudal jarak jauh milik musuh telah terdeteksi. Rudal tersebut mungkin ditembak jatuh sebelum terjadi benturan.
sector.crossroads.description = Markas musuh di sektor ini telah didirikan di berbagai medan. Riset unit yang berbeda untuk beradaptasi.\nSelain itu, beberapa markas telah dilindungi oleh perisai. Cari tahu bagaimana mereka diberi daya.
sector.crossroads.description = Markas musuh di sektor ini telah didirikan di berbagai medan. Riset unit yang berbeda untuk beradaptasi.\nSelain itu, beberapa markas telah dilindungi oleh perisai. Cari tahu bagaimana mereka diberi tenaga.
sector.karst.description = Sektor ini kaya akan sumber daya, namun akan diserang oleh musuh begitu inti baru mendarat.\nManfaatkan sumber daya dan riset [accent]fabrik phase[].
sector.origin.description = Sektor terakhir dengan kehadiran musuh yang signifikan.\nTidak ada peluang riset yang tersisa - fokus menghancurkan semua inti musuh.
@@ -1299,7 +1299,7 @@ bar.cargounitcap = Kapasitas Unit Kargo Telah Mencapai Batas
bar.drillspeed = Kecepatan Bor: {0}/d
bar.pumpspeed = Kecepatan Pompa: {0}/d
bar.efficiency = Efisiensi: {0}%
bar.yield = Hasil: +{0}%
bar.yield = Hasil: {0}%
bar.boost = Pendorongan: +{0}%
bar.powerbuffer = Tenaga Baterai: {0}/{1}
bar.powerbalance = Tenaga: {0}/d
@@ -1447,7 +1447,7 @@ setting.autotarget.name = Bidik Musuh Secara Otomatis
setting.autotarget.description = Ketika diaktifkan, unit Anda akan secara otomatis membidik dan menembaki musuh di sekitar.
setting.keyboard.name = Kontrol Tetikus+Papan Ketik
setting.fpscap.name = Batas FPS
setting.fpscap.description = Mengatur jumlah maksimum bingkai per detik (FPS) saat permainan berjalan.\nNilai yang lebih tinggi dapat meningkatkan konsumsi daya baterai.
setting.fpscap.description = Mengatur jumlah maksimum bingkai per detik (FPS) saat permainan berjalan.\nNilai yang lebih tinggi dapat meningkatkan konsumsi baterai.
setting.fpscap.none = Tidak Ada
setting.fpscap.text = {0} FPS
setting.uiscale.name = Skala UI
@@ -2453,7 +2453,7 @@ onset.defenses = [accent]Siapkan pertahanan:[lightgray] {0}
onset.attack = Musuh dalam keadaan rentan diserang. Lancarkan serangan balasan.
onset.cores = Inti baru dapat ditempatkan di [accent]ubin inti[].\nInti baru berfungsi sebagai pangkalan depan dan berbagi sumber daya dengan inti lainnya.\nTempatkan sebuah :core-bastion: inti.
onset.detect = Musuh akan dapat mendeteksi Anda dalam 2 menit.\nSiapkan pertahanan, penambangan, dan produksi.
onset.commandmode = Tahan [accent]shift[] untuk masuk ke[accent]mode perintah[].\n[accent]Klik kiri dan seret[] untuk memilih unit.\n[accent]Klik kanan[] untuk memerintahkan unit yang dipilih untuk bergerak atau menyerang.
onset.commandmode = Tahan [accent]shift[] untuk masuk ke [accent]mode perintah[].\n[accent]Klik kiri dan seret[] untuk memilih unit.\n[accent]Klik kanan[] untuk memerintahkan unit yang dipilih untuk bergerak atau menyerang.
onset.commandmode.mobile = Tekan tombol [accent]perintah[] untuk masuk ke [accent]mode perintah[].\nTekan dan tahan jari Anda, lalu [accent]seret[] untuk memilih unit.\n[accent]Ketuk[] untuk memerintahkan unit yang dipilih untuk bergerak atau menyerang.
aegis.tungsten = Tungsten dapat ditambang menggunakan [accent]bor tumbukan[].\nBangunan ini memerlukan [accent]air[] dan [accent]tenaga[].
@@ -2686,7 +2686,7 @@ block.smite.description = Menembakan semburan peluru yang menusuk dan menyambar.
block.malign.description = Menembakkan rentetan muatan laser pelacak ke arah musuh. Memerlukan pemanasan ekstensif.
block.silicon-arc-furnace.description = Memurnikan silikon dari pasir dan grafit.
block.oxidation-chamber.description = Mengubah berilium dan ozon menjadi oksida. Memancarkan panas sebagai produk sampingan.
block.electric-heater.description = Pemanas yang menghadap ke arah blok. Memerlukan daya yang besar.
block.electric-heater.description = Pemanas yang menghadap ke arah blok. Memerlukan tenaga yang besar.
block.slag-heater.description = Pemanas yang menghadap ke arah blok. Memerlukan lava.
block.phase-heater.description = Pemanas yang menghadap ke arah blok. Memerlukan fabrik phase.
block.heat-redirector.description = Mengalihkan akumulasi panas ke blok lain.
@@ -2700,7 +2700,7 @@ block.carbide-crucible.description = Memadukan grafit dan tungsten menjadi karbi
block.cyanogen-synthesizer.description = Mensintesis sianogen dari arkisit dan grafit. Memerlukan panas.
block.slag-incinerator.description = Membakar benda atau cairan yang tidak mudah menguap. Memerlukan lava.
block.vent-condenser.description = Mengondensasi gas ventilasi menjadi air. Memerlukan tenaga.
block.plasma-bore.description = Saat ditempatkan menghadap dinding bijih, mengeluarkan bahan tanpa batas. Memerlukan daya dalam jumlah kecil.
block.plasma-bore.description = Saat ditempatkan menghadap dinding bijih, mengeluarkan bahan tanpa batas. Memerlukan tenaga dalam jumlah kecil.
block.large-plasma-bore.description = Bor plasma yang lebih besar. Mampu menambang tungsten dan torium. Memerlukan hidrogen dan tenaga.
block.cliff-crusher.description = Menghancurkan dinding, mengeluarkan pasir tanpa batas. Memerlukan tenaga. Efisiensi bervariasi berdasarkan jenis dinding.
block.large-cliff-crusher.description = Menghancurkan dinding, mengeluarkan pasir tanpa batas. Memerlukan tenaga dan hidrogen. Efisiensi bervariasi berdasarkan jenis dinding. Dapat menggunakan grafit untuk meningkatkan efisiensi.
@@ -2741,7 +2741,7 @@ block.turbine-condenser.description = Menghasilkan tenaga ketika ditempatkan pad
block.chemical-combustion-chamber.description = Menghasilkan tenaga dari arkisit dan ozon.
block.pyrolysis-generator.description = Menghasilkan tenaga dalam jumlah besar dari arkisit dan lava. Memproduksi air sebagai produk sampingan.
block.flux-reactor.description = Menghasilkan tenaga dalam jumlah besar ketika dipanaskan. Memerlukan sianogen sebagai penstabil. Tenaga yang dihasilkan dan kebutuhan sianogen sebanding dengan panas yang masuk.\nMeledak jika sianogen yang disediakan tidak mencukupi.
block.neoplasia-reactor.description = Menggunakan arkisit, air, dan fabrik phase untuk menghasilkan daya dalam jumlah besar. Menghasilkan panas dan neoplasma yang berbahaya sebagai produk sampingan.\nMeledak jika neoplasma tidak dikeluarkan dari reaktor melalui saluran.
block.neoplasia-reactor.description = Menggunakan arkisit, air, dan fabrik phase untuk menghasilkan tenaga dalam jumlah besar. Menghasilkan panas dan neoplasma yang berbahaya sebagai produk sampingan.\nMeledak jika neoplasma tidak dikeluarkan dari reaktor melalui saluran.
block.build-tower.description = Secara otomatis membangun kembali bangunan dalam jangkauan dan membantu unit lain dalam konstruksi.
block.regen-projector.description = Perlahan memperbaiki bangunan sekutu di perimeter persegi. Memerlukan hidrogen. Dapat menggunakan fabrik phase untuk meningkatkan efisiensi.
block.reinforced-container.description = Menyimpan sejumlah kecil item. Isi kontainer dapat dibongkar melalui pembongkar muatan. Tidak dapat meningkatkan kapasitas penyimpanan inti.
@@ -2945,63 +2945,63 @@ laccess.displayheight = Tinggi blok tampilan logika dalam piksel.
laccess.buffersize = Untuk pesan: Panjang dari isi pesan.\nUntuk tampilan: Jumlah dari perintah grafis mentah.
laccess.operations = Jumlah operasi yang dilakukan pada blok.\nUntuk tampilan, mengembalikan jumlah dari operasi drawflush.
laccess.maxunits = Jumlah unit maksimum yang dapat dimiliki sebuah tim.\nHanya dapat dideteksi dari inti.
laccess.totalitems = Total number of items contained.
laccess.firstitem = First item contained, or null if empty.
laccess.totalliquids = Total amount of liquid contained.
laccess.totalpower = For blocks with a buffered power store, the amount of power stored; for other blocks, buffer fullness from 0 to 1.
laccess.itemcapacity = Maximum number of items this building can hold.
laccess.liquidcapacity = Maximum amount of liquid this building can hold.
laccess.powercapacity = Maximum amount of power this building can store.
laccess.powernetstored = Total power stored in the connected power grid.
laccess.powernetcapacity = Total power storage capacity of the connected power grid.
laccess.powernetin = Power entering the connected power grid, per second.
laccess.powernetout = Power leaving the connected power grid, per second.
laccess.ammo = Current ammo count of a turret.
laccess.ammocapacity = Maximum ammo count of a turret.
laccess.health = Current health.\nFor bullets, their damage.
laccess.maxhealth = Maximum health.\nFor bullets, the base damage.
laccess.heat = Current heat of a turret that consumes heat, 0 to 1.
laccess.shield = Current shield amount of a unit.
laccess.armor = Armor value; flat damage reduction per hit.
laccess.efficiency = Operating efficiency of a building, where 1 is nominal.
laccess.timescale = Time scale multiplier affecting a building, where 1 is normal speed.
laccess.rotation = Facing angle of a unit or turret, in degrees.\nFor most other buildings, the 0 to 3 orientation.
laccess.x = X position, in tiles.
laccess.y = Y position, in tiles.
laccess.velocityx = X velocity of a unit, in tiles/sec.
laccess.velocityy = Y velocity of a unit, in tiles/sec.
laccess.shootx = X coordinate a unit or turret is aiming at.
laccess.shooty = Y coordinate a unit or turret is aiming at.
laccess.camerax = X position of the controlling player's camera.
laccess.cameray = Y position of the controlling player's camera.
laccess.camerawidth = Width of the controlling player's view, in tiles.
laccess.cameraheight = Height of the controlling player's view, in tiles.
laccess.solid = Whether this building blocks movement.
laccess.range = Range of a unit or turret, in tiles.
laccess.shooting = Whether a unit or turret is currently shooting.
laccess.boosting = Whether a unit is currently boosting or flying over terrain.
laccess.minex = X tile coordinate a unit is mining, or -1 if not mining.
laccess.miney = Y tile coordinate a unit is mining, or -1 if not mining.
laccess.mining = Whether a unit is currently mining.
laccess.buildx = X tile coordinate a unit is building at, or -1 if not building.
laccess.buildy = Y tile coordinate a unit is building at, or -1 if not building.
laccess.pingx = X coordinate a player is pinging, or null if not pinging.
laccess.pingy = Y coordinate a player is pinging, or null if not pinging.
laccess.pingtext = Text of a player's current ping, or null if not pinging.
laccess.building = Building a unit is currently constructing, or null.
laccess.breaking = Building a unit is currently deconstructing, or null.
laccess.team = Team ID of a unit or building.
laccess.flag = Numeric flag value stored on a unit.
laccess.flying = Whether a unit is currently airborne.
laccess.name = Name of the player controlling this unit, or null.
laccess.payloadcount = Number of payloads currently held.
laccess.payloadtype = Type of the last payload picked up, or null.
laccess.totalpayload = Combined size of all held payloads.
laccess.payloadcapacity = Maximum combined payload size a unit or building can carry.
laccess.selectedblock = Block currently selected by the controlling player, or null.
laccess.selectedrotation = Build rotation currently selected by the controlling player, 0 to 3.
laccess.bulletlifetime = Total lifetime of a bullet, in ticks.
laccess.bullettime = Time a bullet has existed, in ticks.
laccess.totalitems = Jumlah total item yang tersimpan.
laccess.firstitem = Item pertama yang dimuat, atau null jika kosong.
laccess.totalliquids = Jumlah total cairan yang tersimpan.
laccess.totalpower = Untuk blok dengan penyimpanan tenaga berpenyangga (dioda), jumlah tenaga yang tersimpan; untuk blok lainnya, tingkat keterisian penyangga dari 0 hingga 1.
laccess.itemcapacity = Jumlah maksimum item yang dapat disimpan oleh bangunan ini.
laccess.liquidcapacity = Jumlah maksimum cairan yang dapat disimpan oleh bangunan ini.
laccess.powercapacity = Jumlah tenaga maksimum yang dapat disimpan oleh bangunan ini.
laccess.powernetstored = Total Tenaga yang tersimpan dalam jaringan listrik yang terhubung.
laccess.powernetcapacity = Total kapasitas penyimpanan tenaga dari jaringan listrik yang terhubung.
laccess.powernetin = Tenaga yang masuk ke jaringan listrik yang terhubung, per detik.
laccess.powernetout = Tenaga yang keluar dari jaringan listrik yang terhubung, per detik.
laccess.ammo = Jumlah amunisi menara saat ini.
laccess.ammocapacity = Jumlah amunisi maksimum menara.
laccess.health = Nyawa saat ini.\nUntuk peluru, besaran damage-nya.
laccess.maxhealth = Nyawa maksimum.\nUntuk peluru, damage dasar.
laccess.heat = Unit panas saat ini dari menara yang mengonsumsi unit panas, 0 hingga 1.
laccess.shield = Jumlah perisai yang dimiliki oleh unit saat ini.
laccess.armor = Nilai armor; pengurangan damage tetap per serangan.
laccess.efficiency = Efisiensi operasional bangunan, dengan nilai nominal 1.
laccess.timescale = Pengali skala waktu yang memengaruhi bangunan, dengan nilai 1 berarti kecepatan normal.
laccess.rotation = Sudut hadap unit atau turret, dalam derajat.\nUntuk sebagian besar bangunan lainnya, orientasi berkisar antara 0 hingga 3.
laccess.x = Posisi X, dalam satuan ubin.
laccess.y = Posisi Y, dalam satuan ubin.
laccess.velocityx = Kecepatan X suatu unit, dalam satuan ubin/detik.
laccess.velocityy = Kecepatan Y suatu unit, dalam satuan ubin/detik.
laccess.shootx = Koordinat X yang dituju oleh unit atau turret.
laccess.shooty = Koordinat Y yang dituju oleh unit atau turret.
laccess.camerax = Posisi X kamera pemain yang memegang kendali.
laccess.cameray = Posisi Y kamera pemain yang memegang kendali.
laccess.camerawidth = Lebar pandangan pemain yang memegang kendali, dalam satuan ubin.
laccess.cameraheight = Tinggi pandangan pemain yang memegang kendali, dalam satuan ubin.
laccess.solid = Apakah bangunan ini menghalangi pergerakan.
laccess.range = Jangkauan unit atau turret, dalam satuan ubin.
laccess.shooting = Apakah unit atau turret sedang menembak.
laccess.boosting = Apakah unit saat ini sedang mengaktifkan pendorong atau terbang melintasi medan.
laccess.minex = Koordinat ubin X tempat unit sedang menambang, atau -1 jika tidak sedang menambang.
laccess.miney = Koordinat ubin Y tempat unit sedang menambang, atau -1 jika tidak sedang menambang.
laccess.mining = Apakah suatu unit sedang menambang.
laccess.buildx = Koordinat ubin X tempat unit sedang membangun, atau -1 jika tidak sedang membangun.
laccess.buildy = Koordinat ubin Y tempat unit sedang membangun, atau -1 jika tidak sedang membangun.
laccess.pingx = Koordinat X yang sedang ditandai oleh pemain, atau null jika tidak sedang menandai.
laccess.pingy = Koordinat Y yang sedang ditandai oleh pemain, atau null jika tidak sedang menandai.
laccess.pingtext = Teks yang menunjukkan ping pemain saat ini, atau null jika tidak sedang melakukan ping.
laccess.building = Unit yang sedang membangun saat ini, atau null.
laccess.breaking = Unit yang sedang mendekonstruksi saat ini, atau null.
laccess.team = ID Tim dari unit atau bangunan.
laccess.flag = Nilai flag numerik yang disimpan pada unit.
laccess.flying = Apakah suatu unit saat ini sedang berada di udara.
laccess.name = Nama pemain yang mengendalikan unit ini, atau null.
laccess.payloadcount = Jumlah muatan yang saat ini dimiliki.
laccess.payloadtype = Jenis muatan terakhir yang diambil, atau null.
laccess.totalpayload = Ukuran gabungan dari semua muatan yang disimpan.
laccess.payloadcapacity = Ukuran muatan gabungan maksimum yang dapat dibawa oleh unit atau bangunan.
laccess.selectedblock = Blok yang saat ini dipilih oleh pemain yang memegang kendali, atau null.
laccess.selectedrotation = Rotasi bangunan yang saat ini dipilih oleh pemain yang memegang kendali, 0 hingga 3.
laccess.bulletlifetime = Total masa hidup peluru, dalam satuan tick.
laccess.bullettime = Durasi peluru aktif, dalam satuan tick.
lcategory.unknown = Tak Diketahui
lcategory.unknown.description = Instruksi tanpa kategori.
@@ -3282,7 +3282,7 @@ graphicstype.label.reset = atur ulang
laccess.label.totalitems = total item
laccess.label.firstitem = item pertama
laccess.label.totalliquids = total cairan
laccess.label.totalpower = total daya
laccess.label.totalpower = total tenaga
laccess.label.itemcapacity = kapasitas item
laccess.label.liquidcapacity = kapasitas cairan
laccess.label.powercapacity = kapasitas tenaga
@@ -3351,7 +3351,7 @@ laccess.label.selectedblock = blok terpilih
laccess.label.selectedrotation = rotasi terpilih
laccess.label.bulletlifetime = masa aktif peluru
laccess.label.bullettime = waktu peluru
laccess.label.enabled = diaktifkan
laccess.label.enabled = aktifkan
laccess.label.shoot = tembak
laccess.label.shootp = prediksi tembak
laccess.label.config = konfig
@@ -3456,7 +3456,7 @@ radartarget.label.player = pemain
radartarget.label.attacker = penyerang
radartarget.label.flying = terbang
radartarget.label.ground = darat
radartarget.label.boss = boss
radartarget.label.boss = penjaga
tilelayer.label.floor = lantai
tilelayer.label.ore = bijih
tilelayer.label.block = blok
+65 -65
View File
@@ -1299,7 +1299,7 @@ bar.cargounitcap = Достигнут предел грузовой единиц
bar.drillspeed = Скорость бурения: {0}/с
bar.pumpspeed = Скорость выкачивания: {0}/с
bar.efficiency = Эффективность: {0}%
bar.yield = Получение: +{0}%
bar.yield = Получение: {0}%
bar.boost = Ускорение: +{0}%
bar.powerbuffer = Энергия в аккумуляторах: {0}/{1}
bar.powerbalance = Энергия: {0}/с
@@ -2945,63 +2945,63 @@ laccess.displayheight = Высота дисплея, в пикселях.
laccess.buffersize = Количество необработанных команд в графическом буфере дисплея.
laccess.operations = Количество операций, выполненных в блоке.\nДля дисплеев, возвращает количество выполненных операций Вывод рисования/drawflush.
laccess.maxunits = Максимальное количество единиц, которое может быть у команды.\nОпределяется с помощью ядер.
laccess.totalitems = Total number of items contained.
laccess.firstitem = First item contained, or null if empty.
laccess.totalliquids = Total amount of liquid contained.
laccess.totalpower = For blocks with a buffered power store, the amount of power stored; for other blocks, buffer fullness from 0 to 1.
laccess.itemcapacity = Maximum number of items this building can hold.
laccess.liquidcapacity = Maximum amount of liquid this building can hold.
laccess.powercapacity = Maximum amount of power this building can store.
laccess.powernetstored = Total power stored in the connected power grid.
laccess.powernetcapacity = Total power storage capacity of the connected power grid.
laccess.powernetin = Power entering the connected power grid, per second.
laccess.powernetout = Power leaving the connected power grid, per second.
laccess.ammo = Current ammo count of a turret.
laccess.ammocapacity = Maximum ammo count of a turret.
laccess.health = Current health.\nFor bullets, their damage.
laccess.maxhealth = Maximum health.\nFor bullets, the base damage.
laccess.heat = Current heat of a turret that consumes heat, 0 to 1.
laccess.shield = Current shield amount of a unit.
laccess.armor = Armor value; flat damage reduction per hit.
laccess.efficiency = Operating efficiency of a building, where 1 is nominal.
laccess.timescale = Time scale multiplier affecting a building, where 1 is normal speed.
laccess.rotation = Facing angle of a unit or turret, in degrees.\nFor most other buildings, the 0 to 3 orientation.
laccess.x = X position, in tiles.
laccess.y = Y position, in tiles.
laccess.velocityx = X velocity of a unit, in tiles/sec.
laccess.velocityy = Y velocity of a unit, in tiles/sec.
laccess.shootx = X coordinate a unit or turret is aiming at.
laccess.shooty = Y coordinate a unit or turret is aiming at.
laccess.camerax = X position of the controlling player's camera.
laccess.cameray = Y position of the controlling player's camera.
laccess.camerawidth = Width of the controlling player's view, in tiles.
laccess.cameraheight = Height of the controlling player's view, in tiles.
laccess.solid = Whether this building blocks movement.
laccess.range = Range of a unit or turret, in tiles.
laccess.shooting = Whether a unit or turret is currently shooting.
laccess.boosting = Whether a unit is currently boosting or flying over terrain.
laccess.minex = X tile coordinate a unit is mining, or -1 if not mining.
laccess.miney = Y tile coordinate a unit is mining, or -1 if not mining.
laccess.mining = Whether a unit is currently mining.
laccess.buildx = X tile coordinate a unit is building at, or -1 if not building.
laccess.buildy = Y tile coordinate a unit is building at, or -1 if not building.
laccess.pingx = X coordinate a player is pinging, or null if not pinging.
laccess.pingy = Y coordinate a player is pinging, or null if not pinging.
laccess.pingtext = Text of a player's current ping, or null if not pinging.
laccess.building = Building a unit is currently constructing, or null.
laccess.breaking = Building a unit is currently deconstructing, or null.
laccess.team = Team ID of a unit or building.
laccess.flag = Numeric flag value stored on a unit.
laccess.flying = Whether a unit is currently airborne.
laccess.name = Name of the player controlling this unit, or null.
laccess.payloadcount = Number of payloads currently held.
laccess.payloadtype = Type of the last payload picked up, or null.
laccess.totalpayload = Combined size of all held payloads.
laccess.payloadcapacity = Maximum combined payload size a unit or building can carry.
laccess.selectedblock = Block currently selected by the controlling player, or null.
laccess.selectedrotation = Build rotation currently selected by the controlling player, 0 to 3.
laccess.bulletlifetime = Total lifetime of a bullet, in ticks.
laccess.bullettime = Time a bullet has existed, in ticks.
laccess.totalitems = Общее количество хранимых предметов.
laccess.firstitem = Первый хранимый предмет. Если пусто - возвращает null.
laccess.totalliquids = Общее количество хранимой жидкости.
laccess.totalpower = Для блоков, хранящих энергию, возвращает её количество; для остальных блоков, их уровень энергии от 0 до 1.
laccess.itemcapacity = Максимальное количество предметов, хранимых этой постройкой.
laccess.liquidcapacity = Максимальное количество жидкости, хранимой этой постройкой.
laccess.powercapacity = Максимальное количество энергии, хранимой этой постройкой.
laccess.powernetstored = Общее количество энергии, хранимой в сети.
laccess.powernetcapacity = Максимальное количество энергии, хранимой в сети.
laccess.powernetin = Энергия, входящая в сеть за секунду.
laccess.powernetout = Энергия, выходящая из сети за секунду.
laccess.ammo = Текущее количество боеприпасов в турели.
laccess.ammocapacity = Максимальное количество боеприпасов в турели.
laccess.health = Текущее здоровье.\nДля пуль возвращает их урон.
laccess.maxhealth = Максимальное здоровье.\nДля пуль возвращает их базовый урон.
laccess.heat = Текущий нагрев турели, от 0 до 1.
laccess.shield = Общее количество щита у юнита.
laccess.armor = Значение брони; на сколько снизится получаемый урон за удар.
laccess.efficiency = Эффективность работы постройки. 1 - обычная эффективность.
laccess.timescale = Множитель скорости, применённый на эту постройку. 1 - обычная скорость.
laccess.rotation = Угол направления юнита или турели в градусах.\nДля большинства других построек возвращает 0-3 в зависимости от их направления.
laccess.x = Позиция X блока/юнита в блоках.
laccess.y = Позиция Y блока/юнита в блоках.
laccess.velocityx = Скорость юнита по X в блоках/сек.
laccess.velocityy = Скорость юнита по Y в блоках/сек.
laccess.shootx = Позиция X, в которую нацелен юнит или турель.
laccess.shooty = Позиция Y, в которую нацелен юнит или турель.
laccess.camerax = Позиция X камеры управляющего игрока.
laccess.cameray = Позиция Y камеры управляющего игрока.
laccess.camerawidth = Ширина камеры управляющего игрока в блоках.
laccess.cameraheight = Высота камеры управляющего игрока в блоках.
laccess.solid = Блокирует ли этот блок движение.
laccess.range = Радиус юнита или турели в блоках.
laccess.shooting = Стреляет ли юнит/турель в данный момент.
laccess.boosting = Летает ли этот наземный юнит.
laccess.minex = Позиция X руды, которую сейчас добывает юнит, или -1, если не добывает.
laccess.miney = Позиция Y руды, которую сейчас добывает юнит, или -1, если не добывает.
laccess.mining = Добывает ли юнит руду.
laccess.buildx = Позиция X, на которой сейчас строит юнит, или -1, если не строит.
laccess.buildy = Позиция Y, на которой сейчас строит юнит, или -1, если не строит.
laccess.pingx = Позиция X отметки, поставленной игроком, или null, если отметки нет.
laccess.pingy = Позиция Y отметки, поставленной игроком, или null, если отметки нет.
laccess.pingtext = Текст отметки, поставленной игроком, или null, если отметки нет.
laccess.building = Блок, который сейчас строится юнитом, или null.
laccess.breaking = Блок, который сейчас разбирается юнитом, или null.
laccess.team = ID команды юнита/блока.
laccess.flag = Числовой флаг, назначенный юниту.
laccess.flying = Летает ли этот юнит.
laccess.name = Имя управляющего игрока, или null.
laccess.payloadcount = Количество перевозимых грузов.
laccess.payloadtype = Тип последнего подобранного груза, или null.
laccess.totalpayload = Суммарный размер всех перевозимых грузов.
laccess.payloadcapacity = Максимальный суммарный размер всех перевозимых грузов юнита.
laccess.selectedblock = Блок, выбранный управляющим игроком, или null.
laccess.selectedrotation = Вращение блока, выбранного управляющим игроком, от 0 до 3.
laccess.bulletlifetime = Максимальное время жизни пули в тиках.
laccess.bullettime = Время существования пули в тиках.
lcategory.unknown = Неизвестно
lcategory.unknown.description = Нет категории.
@@ -3496,9 +3496,9 @@ name.token.global = глобальный
name.token.target = цель
name.token.and = и
name.token.or = или
name.token.b-and = бит-и
name.token.xor = ис-или
name.token.flip = бит-не
name.token.b-and = b-and
name.token.xor = xor
name.token.flip = flip
name.token.order = порядок
name.token.sort = сортировка
name.token.output = выход
@@ -3509,8 +3509,8 @@ name.token.find = найти
name.token.group = группа
name.token.enemy = враг?
name.token.ore = руда
name.token.outX = X
name.token.outY = Y
name.token.outX = X цели
name.token.outY = Y цели
name.token.owner = владелец
name.token.found = найден?
name.token.building = постройка
@@ -3532,7 +3532,7 @@ name.token.natural = естественная
name.token.speed = скорость
name.token.level = уровень
name.token.duration = длительность
name.token.seconds = seconds
name.token.seconds = секунд
name.token.shown = отображается
name.token.data = данные
name.token.effect = эффект
@@ -3599,7 +3599,7 @@ name.token.blockFall = падение блока
name.token.placeBlock = размещение блока
name.token.placeBlockSpark = размещение блока (искры)
name.token.breakBlock = разрушение блока
name.token.-spawn = = spawn
name.token.-spawn = = создать
name.token.trail = след
name.token.breakProp = разрушение валуна
name.token.smokeCloud = облако дыма
+89 -89
View File
@@ -50,7 +50,7 @@ mods.browser.add = 安装
mods.browser.reinstall = 重新安装
mods.browser.view-releases = 查看版本
mods.browser.noreleases = [scarlet]找不到任何版本\n[accent]无法找到该模组的任何版本。请检查一下该模组的仓库是否发布了版本。
mods.browser.current = [lightgray]Most recent commit
mods.browser.current = [lightgray]最新提交
mods.browser.latest = [lightgray][最新]
mods.browser.releases = 版本
mods.browser.fetching = 获取版本中...
@@ -145,7 +145,7 @@ mods.initfailed = [red]⚠[] Mindustry 上一次启动失败。这可能是由
mods = 模组
mods.name = 模组:
mods.none = [lightgray]未找到模组!
mods.restore = Restore Failed
mods.restore = 恢复失败
mods.guide = 模组指南
mods.report = 举报错误
mods.openfolder = 打开文件夹
@@ -164,7 +164,7 @@ mod.installed = [[已安装]
mod.display = [gray]模组:[orange] {0}
mod.enabled = [lightgray]已启用
mod.disabled = [red]未启用
mod.failed = [red]Failed
mod.failed = [red]失败
mod.multiplayer.compatible = [gray]支持多人游戏
mod.disable = 禁用
mod.version = 版本:
@@ -1237,9 +1237,9 @@ stat.buildspeedmultiplier = 建造速度倍率
stat.reactive = 反应
stat.immunities = 免疫
stat.healing = 治疗
stat.status = Status Effect
stat.status = 状态效果
stat.efficiency = [stat]{0}% 效率
stat.chance = [stat]{0}%[lightgray] chance of [white]
stat.chance = [stat]{0}%[lightgray] 概率 [white]
stat.hitsize = 碰撞箱大小
stat.resettime = 重置时间
@@ -1288,7 +1288,7 @@ ability.stat.minspeed = [stat]{0}格/秒[lightgray] 最低速度
ability.stat.duration = [stat]{0} 秒[lightgray] 持续时间
ability.stat.buildtime = [stat]{0} 秒[lightgray] 建造时间
bar.displaytoolarge = 尺寸太大\n(Max:{0}x{0})
bar.displaytoolarge = 尺寸太大\n(上限:{0}x{0})
bar.onlycoredeposit = 仅可将资源丢入核心
bar.drilltierreq = 需要更高级的钻头
bar.nobatterypower = 电池电力储存不足
@@ -1299,7 +1299,7 @@ bar.cargounitcap = 达到货运单位上限
bar.drillspeed = 挖掘速度:{0}/秒
bar.pumpspeed = 泵送速度:{0}/秒
bar.efficiency = 效率:{0}%
bar.yield = Yield: +{0}%
bar.yield = 产量: +{0}%
bar.boost = 超速:+{0}%
bar.powerbuffer = 电池电力:{0}/{1}
bar.powerbalance = 电力:{0}/秒
@@ -1435,8 +1435,8 @@ setting.distinctcontrolgroups.name = 每单位限制一个编队
setting.distinctcontrolgroups.description = 启用后,每个单位只能从属于一个编队。
setting.modcrashdisable.name = 游戏启动崩溃后禁用模组
setting.modcrashdisable.description = 启用后,若启动时模组崩溃,则会禁用所有模组以避免无休止的崩溃。
setting.animatedwater.name = 动态液体
setting.animatedwater.description = 是否开启液体表面的动画,如水和矿渣。
setting.animatedwater.name = 动态效果
setting.animatedwater.description = 是否显示水、矿渣和护盾等表面的动画。
setting.playerindicators.name = 玩家指示器
setting.playerindicators.description = 在地图上显示标记,来指示其他玩家的方向。
setting.showpings.name = 显示标记
@@ -1738,7 +1738,7 @@ rules.enemyteam = 敌方队伍
rules.playerteam = 玩家队伍
rules.title.waves = 波次
rules.title.resourcesbuilding = 资源与建筑
rules.title.enemy = 敌对阵营
rules.title.enemy = 敌人
rules.title.unit = 单位
rules.title.experimental = 实验性
rules.title.environment = 环境
@@ -2831,7 +2831,7 @@ lst.read = 从连接的内存读取数字。
lst.write = 向连接的内存写入数字。
lst.print = 添加文字到打印缓存\n使用[accent]打印文本[]后才会真正显示。
lst.printchar = 向打印缓存添加一个 UTF-16 字符或内容图标。\n直到使用[accent]打印文本[]后才会真正显示。
lst.format = 用一个值替换文本缓冲区中的下一个占位符。\n如果占位符模式无效,则不会执行任何操作。\n占位模式:"{[accent]number 0-9[]}"\n示例:\n[accent]打印 "test {0}"\n格式 “示例”。
lst.format = 用一个值替换文本缓冲区中的下一个占位符。\n如果占位符模式无效,则不会执行任何操作。\n占位模式:"{[accent]number 0-9[]}"\n示例:\n[accent]打印 "test {0}"\n格式化 “示例”。
lst.draw = 添加绘图操作到绘图缓存\n使用[accent]打印绘图[]后才会真正显示。
lst.drawflush = 将绘图缓存中的[accent]绘图[]队列刷新到显示屏。
lst.printflush = 将打印缓存中的[accent]打印[]队列刷新到信息板。
@@ -2945,63 +2945,63 @@ laccess.displayheight = 显示屏的高度(以像素为单位)。
laccess.buffersize = 显示器图形缓冲区中未处理的命令数。
laccess.operations = 方块执行操作的次数。\n对于显示屏,返回[accent]打印绘图[]调用次数。
laccess.maxunits = 队伍能拥有的最大单位数。\n只能从核心中读取。
laccess.totalitems = Total number of items contained.
laccess.firstitem = First item contained, or null if empty.
laccess.totalliquids = Total amount of liquid contained.
laccess.totalpower = For blocks with a buffered power store, the amount of power stored; for other blocks, buffer fullness from 0 to 1.
laccess.itemcapacity = Maximum number of items this building can hold.
laccess.liquidcapacity = Maximum amount of liquid this building can hold.
laccess.powercapacity = Maximum amount of power this building can store.
laccess.powernetstored = Total power stored in the connected power grid.
laccess.powernetcapacity = Total power storage capacity of the connected power grid.
laccess.powernetin = Power entering the connected power grid, per second.
laccess.powernetout = Power leaving the connected power grid, per second.
laccess.ammo = Current ammo count of a turret.
laccess.ammocapacity = Maximum ammo count of a turret.
laccess.health = Current health.\nFor bullets, their damage.
laccess.maxhealth = Maximum health.\nFor bullets, the base damage.
laccess.heat = Current heat of a turret that consumes heat, 0 to 1.
laccess.shield = Current shield amount of a unit.
laccess.armor = Armor value; flat damage reduction per hit.
laccess.efficiency = Operating efficiency of a building, where 1 is nominal.
laccess.timescale = Time scale multiplier affecting a building, where 1 is normal speed.
laccess.rotation = Facing angle of a unit or turret, in degrees.\nFor most other buildings, the 0 to 3 orientation.
laccess.x = X position, in tiles.
laccess.y = Y position, in tiles.
laccess.velocityx = X velocity of a unit, in tiles/sec.
laccess.velocityy = Y velocity of a unit, in tiles/sec.
laccess.shootx = X coordinate a unit or turret is aiming at.
laccess.shooty = Y coordinate a unit or turret is aiming at.
laccess.camerax = X position of the controlling player's camera.
laccess.cameray = Y position of the controlling player's camera.
laccess.camerawidth = Width of the controlling player's view, in tiles.
laccess.cameraheight = Height of the controlling player's view, in tiles.
laccess.solid = Whether this building blocks movement.
laccess.range = Range of a unit or turret, in tiles.
laccess.shooting = Whether a unit or turret is currently shooting.
laccess.boosting = Whether a unit is currently boosting or flying over terrain.
laccess.minex = X tile coordinate a unit is mining, or -1 if not mining.
laccess.miney = Y tile coordinate a unit is mining, or -1 if not mining.
laccess.mining = Whether a unit is currently mining.
laccess.buildx = X tile coordinate a unit is building at, or -1 if not building.
laccess.buildy = Y tile coordinate a unit is building at, or -1 if not building.
laccess.pingx = X coordinate a player is pinging, or null if not pinging.
laccess.pingy = Y coordinate a player is pinging, or null if not pinging.
laccess.pingtext = Text of a player's current ping, or null if not pinging.
laccess.building = Building a unit is currently constructing, or null.
laccess.breaking = Building a unit is currently deconstructing, or null.
laccess.team = Team ID of a unit or building.
laccess.flag = Numeric flag value stored on a unit.
laccess.flying = Whether a unit is currently airborne.
laccess.name = Name of the player controlling this unit, or null.
laccess.payloadcount = Number of payloads currently held.
laccess.payloadtype = Type of the last payload picked up, or null.
laccess.totalpayload = Combined size of all held payloads.
laccess.payloadcapacity = Maximum combined payload size a unit or building can carry.
laccess.selectedblock = Block currently selected by the controlling player, or null.
laccess.selectedrotation = Build rotation currently selected by the controlling player, 0 to 3.
laccess.bulletlifetime = Total lifetime of a bullet, in ticks.
laccess.bullettime = Time a bullet has existed, in ticks.
laccess.totalitems = 含有的物品总数。
laccess.firstitem = 含有的第一个物品,若为空则返回 null。
laccess.totalliquids = 含有的液体总量。
laccess.totalpower = 对于能储电的建筑,指存储的电量;对于其他建筑,以0~1表示供电满足率。
laccess.itemcapacity = 该建筑可容纳的最大物品数量。
laccess.liquidcapacity = 该建筑可容纳的最大液体量。
laccess.powercapacity = 该建筑可存储的最大电量。
laccess.powernetstored = 相连接电网的总储电量。
laccess.powernetcapacity = 相连接电网的总储电容量。
laccess.powernetin = 相连接的电网每秒输入的电力。
laccess.powernetout = 相连接的电网每秒输出的电力。
laccess.ammo = 炮塔当前的弹药数量。
laccess.ammocapacity = 炮塔的最大弹药量。
laccess.health = 当前生命值\n对于子弹,指其伤害值。
laccess.maxhealth = 最大生命值\n对于子弹,指其基础伤害。
laccess.heat = 耗热炮塔当前的热量值,范围为 0 到 1。
laccess.shield = 单位当前的护盾值。
laccess.armor = 护甲值;每次受击时的固定伤害减免。
laccess.efficiency = 建筑的运行效率,以 1 为标准值。
laccess.timescale = 影响建筑的时间缩放倍率,其中1为正常速度。
laccess.rotation = 单位或炮塔的朝向角度(以度为单位)。\n对于大多数其他建筑,朝向值为 0 到 3。
laccess.x = X 坐标(以格为单位)。
laccess.y = Y 坐标(以格为单位)。
laccess.velocityx = 单位的 X 轴速度,单位为格/秒。
laccess.velocityy = 单位的 Y 轴速度,单位为格/秒。
laccess.shootx = 单位或炮塔所瞄准目标的 X 坐标。
laccess.shooty = 单位或炮塔所瞄准目标的 Y 坐标。
laccess.camerax = 控制玩家镜头的 X 坐标。
laccess.cameray = 控制玩家镜头的 Y 坐标。
laccess.camerawidth = 控制玩家镜头的宽度(以格为单位)。
laccess.cameraheight = 控制玩家镜头的高度(以格为单位)。
laccess.solid = 普通陆地单位是否不可通过该建筑。
laccess.range = 单位或炮塔的射程(以格为单位)。
laccess.shooting = 单位或炮塔当前是否正在射击。
laccess.boosting = 单位当前是否处于助推状态或正在飞越地形。
laccess.minex = 单位所采矿物的 X 地块坐标,若未在采矿则为 -1。
laccess.miney = 单位所采矿物的 Y 地块坐标,若未在采矿则为 -1。
laccess.mining = 单位是否正在进行采矿。
laccess.buildx = 单位正在建造的建筑 X 坐标,若未建造则为 -1。
laccess.buildy = 单位正在建造的建筑 Y 坐标,若未建造则为 -1。
laccess.pingx = 玩家标记的标记点位置的 X 坐标,若未标记则为 null。
laccess.pingy = 玩家标记的标记点位置的 Y 坐标,若未标记则为 null。
laccess.pingtext = 玩家标记的标记点文本内容,若无则为 null。
laccess.building = 正在建造的建筑原始名称,若无则为 null。
laccess.breaking = 正在拆除的建筑原始名称,若无则为 null。
laccess.team = 单位或建筑的队伍 ID。
laccess.flag = 存储在单位身上的 flag。
laccess.flying = 单位当前是否正在飞行。
laccess.name = 控制该单位的玩家名称,若无则为 null。
laccess.payloadcount = 当前持有的有效载荷数量。
laccess.payloadtype = 最后获取的有效载荷类型,若无则为 null。
laccess.totalpayload = 所有持有的有效载荷的总大小。
laccess.payloadcapacity = 单位或建筑所能承载的最大综合有效载荷大小。
laccess.selectedblock = 玩家当前在建筑列表选中的方块,若无则为 null。
laccess.selectedrotation = 玩家当前在建筑列表选择的建造旋转角度,范围为 0 到 3。
laccess.bulletlifetime = 子弹可存在的总时长(以 tick 为单位)。
laccess.bullettime = 子弹已存在的时长(以 tick 为单位)。
lcategory.unknown = 未知
lcategory.unknown.description = 未分类的指令
@@ -3111,7 +3111,7 @@ unitradar.output = 找到的单位存入该变量
control.of = 要控制的建筑
control.unit = 要瞄准的单位或建筑
control.shoot = 是否射击
control.shoot = 射击?
unitlocate.enemy = 是否搜寻敌方建筑(0 或 false 则搜寻己方建筑)
unitlocate.found = 若找到,在该变量中存入 true;未找到则存入 false
@@ -3154,7 +3154,7 @@ lenum.colori = 索引位置,用于线和四边形标记,索引零表示第
lenum.wavetimer = 波次是否自动出现在计时器上。如果没有,按下播放按钮时会出现波次
lenum.wave = 当前波数,可以是非波次模式下的任何值
lenum.currentwavetime = 波次倒计时(以 tick 为单位)
lenum.waves = 波次是否可以生成
lenum.waves = 波次是否可生成
lenum.wavesending = 是否可以通过播放按钮手动生成波次
lenum.attackmode = 游戏是否为进攻模式
lenum.wavespacing = 波次之间的时间间隔(以 tick 为单位)
@@ -3221,8 +3221,8 @@ instruction.setrate = 设置速率
instruction.fetch = 获取对象
instruction.sync = 网络同步
instruction.clientdata = 客户端数据
instruction.getflag = 获取flag
instruction.setflag = 设置flag
instruction.getflag = 获取 flag
instruction.setflag = 设置 flag
instruction.setprop = 设置属性
instruction.playsound = 播放音效
instruction.playmusic = 播放音乐
@@ -3253,8 +3253,8 @@ cutsceneaction.label.pan = 移动
cutsceneaction.label.zoom = 缩放
cutsceneaction.label.stop = 停止
cutsceneaction.label.shake = 抖动
cutsceneaction.label.gethud = 获取Hud
cutsceneaction.label.sethud = 设置Hud
cutsceneaction.label.gethud = 获取 Hud
cutsceneaction.label.sethud = 设置 Hud
fetchtype.label.unit = 单位
fetchtype.label.player = 玩家控制单位
fetchtype.label.core = 核心
@@ -3294,8 +3294,8 @@ laccess.label.ammo = 弹药量
laccess.label.ammocapacity = 弹药容量
laccess.label.currentammotype = 当前弹药类型
laccess.label.memorycapacity = 内存块单元数量
laccess.label.health = 生命值
laccess.label.maxhealth = 最大生命值
laccess.label.health = 生命值/伤害
laccess.label.maxhealth = 最大生命值/基础伤害
laccess.label.heat = 热量
laccess.label.shield = 护盾
laccess.label.armor = 护甲
@@ -3309,10 +3309,10 @@ laccess.label.velocityx = X轴移动速度
laccess.label.velocityy = Y轴移动速度
laccess.label.shootx = 射击X坐标
laccess.label.shooty = 射击Y坐标
laccess.label.camerax = 相机X坐标
laccess.label.cameray = 相机Y坐标
laccess.label.camerawidth = 相机宽度
laccess.label.cameraheight = 相机高度
laccess.label.camerax = 镜头X坐标
laccess.label.cameray = 镜头Y坐标
laccess.label.camerawidth = 镜头宽度
laccess.label.cameraheight = 镜头高度
laccess.label.displaywidth = 显示屏宽度
laccess.label.displayheight = 显示屏高度
laccess.label.buffersize = 缓冲区大小
@@ -3321,18 +3321,18 @@ laccess.label.size = 大小/长度
laccess.label.solid = 实体
laccess.label.dead = 已摧毁/失效
laccess.label.range = 雷达范围
laccess.label.shooting = 射击状态
laccess.label.boosting = 助推状态
laccess.label.shooting = 射击?
laccess.label.boosting = 助推?
laccess.label.minex = 采矿X坐标
laccess.label.miney = 采矿Y坐标
laccess.label.mining = 采矿状态
laccess.label.mining = 采矿?
laccess.label.buildx = 建造于X坐标
laccess.label.buildy = 建造于Y坐标
laccess.label.pingx = 标记点X坐标
laccess.label.pingy = 标记点Y坐标
laccess.label.pingtext = 标记点文本
laccess.label.building = 建造状态
laccess.label.breaking = 破坏状态
laccess.label.building = 建造的建筑
laccess.label.breaking = 破坏的建筑
laccess.label.speed = 速度
laccess.label.team = 队伍
laccess.label.type = 类型
@@ -3380,7 +3380,7 @@ lmarkercontrol.label.fontsize = 字体大小
lmarkercontrol.label.textheight = 文本高度
lmarkercontrol.label.textalign = 文本对齐
lmarkercontrol.label.linealign = 线对齐
lmarkercontrol.label.labelflags = flag标签
lmarkercontrol.label.labelflags = flag 标签
lmarkercontrol.label.texture = 纹理
lmarkercontrol.label.texturesize = 纹理大小
lmarkercontrol.label.posi = 位置
@@ -3388,7 +3388,7 @@ lmarkercontrol.label.uvi = 纹理位置范围
lmarkercontrol.label.colori = 颜色
logicrule.label.currentwavetime = 波次倒计时
logicrule.label.wavetimer = 有波次计时器?
logicrule.label.waves = 波次是否可以生成
logicrule.label.waves = 波次可生成?
logicrule.label.wave = 当前波数
logicrule.label.wavespacing = 波次间隔
logicrule.label.wavesending = 手动生成波次?
@@ -3398,7 +3398,7 @@ logicrule.label.dropzoneradius = 敌人出生点半径
logicrule.label.unitcap = 单位上限
logicrule.label.maparea = 地图大小和有效范围
logicrule.label.lighting = 启用环境光?
logicrule.label.cangameover = 游戏可否结束
logicrule.label.cangameover = 游戏可结束?
logicrule.label.ambientlight = 环境光颜色
logicrule.label.unitlight = 单位光
logicrule.label.solarmultiplier = 太阳能板效率
@@ -3431,7 +3431,7 @@ lunitcontrol.label.itemtake = 从建筑取出物品
lunitcontrol.label.paydrop = 卸下载荷
lunitcontrol.label.paytake = 拾取载荷
lunitcontrol.label.payenter = 进入载荷
lunitcontrol.label.flag = 赋予单位flag
lunitcontrol.label.flag = 赋予单位 flag
lunitcontrol.label.mine = 采集矿物
lunitcontrol.label.build = 建造建筑
lunitcontrol.label.getblock = 用坐标获取类型
+1 -1
View File
@@ -2461,7 +2461,7 @@ split.pickup = 某些物品可以被核心單位撿起。\n撿起這個[accent]
split.pickup.mobile = 某些物品可以被核心單位撿起。\n撿起這個[accent]容器[],然後放到 [accent]重物裝載機[] 上。\n(要撿起或放下東西,請長按該物品。)
split.acquire = 您必須獲取一些鎢才能建造單位。
split.build = 單位必須被運送到牆的另一邊。\n在牆的兩側各放一個[accent]重物質量驅動器[]。\n通過按壓其中一個來設置連結,然後選擇另一個。
split.container = 類似於容器,單位也可以使用[accent]重物質量驅動器[]進行運輸。\n將一個單位兵工廠放置在重物裝載機旁邊以裝載它們,然後將它們送到牆的另一側以進攻敵方基地。
split.container = 類似於容器,單位也可以使用[accent]重物質量驅動器[]進行運輸。\n將一個單位兵工廠放置在重物質量驅動器旁邊以裝載它們,然後將它們送到牆的另一側以進攻敵方基地。
item.copper.description = 最基本的結構材料。在各種類型的方塊中廣泛使用。
item.copper.details = 銅,蕈孢星上異常常見的金屬。加工前結構脆弱。
Binary file not shown.
+4 -1
View File
@@ -183,7 +183,10 @@ public abstract class ClientLauncher extends ApplicationCore implements Platform
assets.load(schematics);
assets.loadRun("contentinit", ContentLoader.class, () -> content.init(), () -> content.load());
assets.loadRun("contentinit", ContentLoader.class, () -> content.init(), () -> {
content.load();
mods.loadModPatches();
});
assets.loadRun("baseparts", BaseRegistry.class, () -> {}, () -> bases.load());
Core.assets.load("sprites/schematic-background.png", Texture.class).loaded = t -> t.setWrap(TextureWrap.repeat);
+6 -2
View File
@@ -164,6 +164,7 @@ public class ControlPathfinder implements Runnable{
//main thread only!
long lastUpdateId = state.updateId;
long lastRecomputeTime;
//both threads
volatile boolean notFound = false;
@@ -456,7 +457,7 @@ public class ControlPathfinder implements Runnable{
Cluster[][] dim1 = clusters[team];
if(dim1 == null){
dim1 = clusters[team] = new Cluster[Team.all.length][];
dim1 = clusters[team] = new Cluster[costTypes.size][];
}
Cluster[] dim2 = dim1[pathCost];
@@ -1192,7 +1193,9 @@ public class ControlPathfinder implements Runnable{
long fieldKey = FieldIndex.get(destPos, costId, team);
//use existing request if it exists.
if(request != null && request.destination == destPos){
if(request != null && (request.destination == destPos ||
//can only recompute path only twice a second, unless it's far away
(Time.timeSinceMillis(request.lastRecomputeTime) < 1000 && Mathf.dst(destX, destY, request.destination % wwidth, request.destination / wwidth) <= 4f))){
request.lastUpdateId = state.updateId;
Tile initialTileOn = tileOn;
@@ -1313,6 +1316,7 @@ public class ControlPathfinder implements Runnable{
unitRequests.put(unit, request = new PathRequest(unit, team, costId, destPos));
PathRequest f = request;
request.lastRecomputeTime = Time.millis();
//on the pathfinding thread: initialize the request
queue.post(() -> {
+1 -2
View File
@@ -8,7 +8,6 @@ import arc.struct.*;
import arc.util.TaskQueue;
import arc.util.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.core.*;
import mindustry.game.EventType.*;
import mindustry.game.*;
@@ -263,7 +262,7 @@ public class Pathfinder implements Runnable{
tile.build == null || !solid || tile.block() instanceof CoreBlock ? 0 : Math.min((int)(tile.build.health / 40), 80),
tid == 0 && tile.build != null && state.rules.coreCapture ? 255 : tid, //use teamid = 255 when core capture is enabled to mark out derelict structures
solid,
tile.floor().isLiquid && tile.block() == Blocks.air,
tile.floor().isLiquid && !tile.block().solid,
tile.legSolid(),
nearLiquid,
nearGround,
+2 -1
View File
@@ -259,7 +259,8 @@ public class CommandAI extends AIController{
targetPos = new Vec2();
lastTargetPos = targetPos;
}
targetPos.set(attackTarget);
//don't target where target dummies are right now, target their block
targetPos.set(attackTarget instanceof TargetDummyUnit t && t.building != null ? t.building : attackTarget);
if(unit.isGrounded() && attackTarget instanceof Building build && build.tile.solid() && unit.type.pathCostId != ControlPathfinder.costIdLegs && !ramming){
Tile best = build.findClosestEdge(unit, Tile::solid);
@@ -92,7 +92,7 @@ public class AvoidanceProcess implements AsyncProcess{
float rad = Float.intBitsToFloat(items[i + 1]);
float rad2 = rad * rad;
int r = Math.max(1, Mathf.ceil(rad));
int r = Mathf.clamp(1, Mathf.ceil(rad), 20);
for(int dx = -r; dx <= r; dx++){
for(int dy = -r; dy <= r; dy++){
+10 -1
View File
@@ -26,6 +26,7 @@ public class PhysicsProcess implements AsyncProcess{
private PhysicsWorld[] physics;
private Seq<PhysicRef> refs = new Seq<>(false, 20, PhysicRef.class);
private Seq<Future<?>> futures = new Seq<>(false, layers, Future.class);
private Seq<PhysicRef> pendingAdds = new Seq<>(false, 20, PhysicRef.class);
private static volatile long maxPhysicsTime = 0;
@@ -44,7 +45,8 @@ public class PhysicsProcess implements AsyncProcess{
PhysicRef ref = new PhysicRef(unit, body);
refs.add(ref);
if(ref.lastLayer >= 0) physics[ref.lastLayer].add(body);
//defer adds until physics update is done
pendingAdds.add(ref);
}
@Override
@@ -68,6 +70,13 @@ public class PhysicsProcess implements AsyncProcess{
PerfCounter.unitPhysicsAsync.add(maxPhysicsTime);
maxPhysicsTime = 0;
//flush newly added entities
for(int i = 0; i < pendingAdds.size; i++){
PhysicRef ref = pendingAdds.items[i];
if(ref.lastLayer >= 0) physics[ref.lastLayer].add(ref.body);
}
pendingAdds.clear();
//move entities
for(PhysicRef ref : refs){
Physicsc entity = ref.entity;
+6 -4
View File
@@ -392,13 +392,15 @@ public class SoundControl{
ambientThread.inputSources.add(source);
}else{
launchingAmbientThread = true;
ambientThread = new AudioThread();
ambientThread.setDaemon(true);
AudioThread thread = new AudioThread();
thread.setDaemon(true);
ambientThread = thread;
//start thread with all the sources that were added during launch
Core.app.post(() -> {
if(ambientThread != null){
if(!ambientThread.isAlive()) ambientThread.start();
//only start if this is still the active thread, and only ever once
if(ambientThread == thread){
thread.start();
launchingAmbientThread = false;
}
});
+4 -5
View File
@@ -6484,7 +6484,7 @@ public class Blocks{
regionSuffix = "-dark";
size = 3;
configurable = false;
showAllCommands = false;
consumePower(3f);
consumeLiquid(Liquids.hydrogen, 3f / 60f);
consumeItems(with(Items.silicon, 40, Items.tungsten, 30));
@@ -6502,7 +6502,7 @@ public class Blocks{
regionSuffix = "-dark";
size = 3;
configurable = false;
showAllCommands = false;
consumePower(2.5f);
consumeLiquid(Liquids.hydrogen, 3f / 60f);
consumeItems(with(Items.silicon, 60, Items.tungsten, 40));
@@ -6521,7 +6521,7 @@ public class Blocks{
regionSuffix = "-dark";
size = 3;
configurable = false;
showAllCommands = false;
consumePower(2.5f);
consumeLiquid(Liquids.hydrogen, 3f / 60f);
consumeItems(with(Items.silicon, 50, Items.tungsten, 40));
@@ -6534,7 +6534,6 @@ public class Blocks{
);
}};
//yes very silly name
primeRefabricator = new Reconstructor("prime-refabricator"){{
requirements(Category.units, with(Items.thorium, 250, Items.oxide, 200, Items.tungsten, 200, Items.silicon, 400));
regionSuffix = "-dark";
@@ -6542,7 +6541,7 @@ public class Blocks{
researchCostMultipliers.put(Items.thorium, 0.2f);
size = 5;
configurable = false;
showAllCommands = false;
consumePower(4.5f);
consumeLiquid(Liquids.nitrogen, 10f / 60f);
consumeItems(with(Items.thorium, 80, Items.silicon, 100));
@@ -4647,6 +4647,8 @@ public class UnitTypes{
useUnitCap = false;
killable = false;
physics = false;
internal = true;
internalGenerateSprites = true;
flyingLayer = Layer.flyingUnit - 1f;
drag = 0.33f;
+1
View File
@@ -413,6 +413,7 @@ public class Logic implements ApplicationListener{
//map is over, no more world processor objective stuff
state.rules.disableWorldProcessors = true;
state.markers.clear(); //TODO: should this optional?
Call.clearObjectives();
+3 -1
View File
@@ -972,8 +972,10 @@ public class NetServer implements ApplicationListener{
}else{
Seq<DataAsset> res = new Seq<>();
Seq<DataAsset> allAssets = state.data.getAllExternalAssets();
Bits requestedIds = new Bits(allAssets.size);
for(short id : ids){
if(id >= allAssets.size || id < 0) continue;
if(id >= allAssets.size || id < 0 || requestedIds.get(id)) continue;
requestedIds.set(id);
res.add(allAssets.get(id));
}
+4 -2
View File
@@ -408,8 +408,9 @@ public class UI implements ApplicationListener, Loadable{
table.touchable = Touchable.disabled;
table.setFillParent(true);
if(cinfo.visible && !state.isMenu()) table.marginTop(cinfo.getPrefHeight() / Scl.scl() / 2);
table.update(() -> {
table.visible(() -> {
if(state.isMenu()) table.remove();
return ui.hudfrag.shown;
});
table.actions(Actions.delay(duration * 0.9f), Actions.fadeOut(duration * 0.1f, Interp.fade), Actions.remove());
table.top().table(Styles.black3, t -> t.margin(4).add(info).style(Styles.outlineLabel)).padTop(10);
@@ -431,11 +432,12 @@ public class UI implements ApplicationListener, Loadable{
}
table.setFillParent(true);
table.touchable = Touchable.disabled;
table.update(() -> {
table.visible(() -> {
if(state.isMenu()){
table.remove();
if(id != null) popups.remove(id);
}
return ui.hudfrag.shown;
});
table.actions(Actions.delay(duration), Actions.remove(), Actions.run(() -> { if(id != null) popups.remove(id); }));
table.align(align).table(Styles.black3, t -> t.margin(4).add(info).style(Styles.outlineLabel)).pad(top, left, bottom, right);
+5 -1
View File
@@ -78,7 +78,11 @@ public class MapEditor{
if(build != null && tile.isCenter()){
builds.add(build);
}
tiles.seti(i, new EditorTile(tile.x, tile.y, tile.floorID(), tile.overlayID(), build == null ? tile.blockID() : 0));
var newTile = new EditorTile(tile.x, tile.y, tile.floorID(), tile.overlayID(), build == null ? tile.blockID() : 0);
newTile.floorData = tile.floorData;
newTile.extraData = tile.extraData;
tiles.seti(i, newTile);
}
for(var build : builds){
@@ -38,10 +38,15 @@ public class MapAudioView implements AssetView{
Fi file = asset.getCacheFile();
var audioSource = (AudioSource)Core.assets.getOrNull(DataAudioLoader.prefix + asset.name, (Class<?>)(type == DataAssetType.music ? Music.class : Sound.class));
if(file == null || audioSource == null || !audioSource.valid()){
if(file == null || audioSource == null || (!audioSource.valid() && !audioSource.isLazy())){
list.button(Icon.warning, Styles.graySquarei, iconMed, () -> ui.showInfo(file == null ? "@asset.broken" : "@asset.audio.invalid")).size(h);
}else{
list.button(Icon.play, Styles.graySquarei, iconMed, () -> {
if(!audioSource.valid() && !audioSource.isLazy()){
ui.showInfo("@asset.audio.invalid");
return;
}
if(lastPlaying != null && lastPlaying.countPlaying() > 0){
lastPlaying.stop();
if(lastPlaying == audioSource){
@@ -56,16 +61,26 @@ public class MapAudioView implements AssetView{
lastPlaying = s;
s.play(control.sound.uiBus);
}
}).update(i -> i.getStyle().imageUp = audioSource != null && audioSource.countPlaying() > 0 ? Icon.pause : Icon.play).size(h);
}).update(i -> i.getStyle().imageUp = (!audioSource.isLazy() && !audioSource.valid()) ? Icon.warning : audioSource.countPlaying() > 0 ? Icon.pause : Icon.play).size(h);
}
float w = (mobile ? 390f : 450f);
list.table(Styles.grayPanel, in -> {
in.left();
in.table(v -> {
v.left();
v.add("[accent]" + asset.name).labelAlign(Align.left).left().ellipsis(true).width(w / 2f);
v.add("[accent]" + asset.name).labelAlign(Align.left).left().ellipsis(true).width(audioSource instanceof Music ? w / 2f : w * 0.8f);
v.row();
v.add("[lightgray][[" + (audioSource == null ? "?" : UI.formatTime(audioSource.getLength() * 60f)) + "]").left();
if(audioSource != null){
Runnable addTime = () -> v.add("[lightgray][[" + UI.formatTime(audioSource.getLength() * 60f) + "]").left();
if(audioSource.valid()){
addTime.run();
}else if(audioSource instanceof Sound s){
//force-load sounds when viewing so that length/invalid status is shown
s.checkLazyLoad(addTime);
}
}
}).width(w / 2f).tooltip("dp-" + asset.name.replace(' ', '_'));
if(audioSource instanceof Music m){
+1 -1
View File
@@ -23,7 +23,7 @@ public class Effect{
public static final Seq<Effect> all = new Seq<>();
private boolean initialized;
private transient boolean initialized;
public final int id;
+1 -1
View File
@@ -84,7 +84,7 @@ public class Lightning{
Unit furthest = Geometry.findFurthest(x, y, entities);
if(furthest != null){
if(furthest != null && furthest.within(x, y, hitRange * 2f)){
hit.add(furthest.id());
x = furthest.x();
y = furthest.y();
@@ -1843,7 +1843,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
}
public boolean canPickup(){
return block.canPickup;
return block.allowedInPayloads;
}
/** Called right before this building is picked up. */
@@ -16,10 +16,18 @@ abstract class TargetDummyComp implements Unitc, Healthc{
}
}
@Replace
@Override
public void rawDamage(float amount){
if(building instanceof TargetDummyBuild td){
td.dummyHit(amount);
}
}
@Override
@Replace
public boolean canLand(){
//dummies should always respect the boost config even when the landing area is obstructed (usually by other dummies)
return true;
}
}
@@ -174,7 +174,8 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
/** @return whether there is solid, un-occupied ground under this unit. */
public boolean canLand(){
return !onSolid() && Units.count(x, y, physicSize(), f -> f != self() && f.isGrounded()) == 0;
float psize = physicSize();
return !onSolid() && !Units.any(x - psize/2f, y - psize/2f, psize, psize, f -> f != self() && f.isGrounded());
}
public boolean inRange(Position other){
@@ -87,9 +87,9 @@ public class ParticleEffect extends Effect{
float rawfin = e.fin();
float fin = e.fin(interp);
float colFin = e.fin(colorInterp);
float rad = sizeInterp.apply(sizeFrom, sizeTo, Mathf.curve(rawfin, sizeChangeStart / lifetime, 1f)) * 2;
float width = rad * (widthInterp.apply(widthFrom, widthTo, Mathf.curve(rawfin, widthChangeStart / lifetime, 1f)) * 2);
float height = rad * (heightInterp.apply(heightFrom, heightTo, Mathf.curve(rawfin, heightChangeStart / lifetime, 1f)) * 2);
float rad = sizeInterp.apply(sizeFrom, sizeTo, Mathf.curve(rawfin, sizeChangeStart / lifetime, 1f)) * 2f;
float width = rad * widthInterp.apply(widthFrom, widthTo, Mathf.curve(rawfin, widthChangeStart / lifetime, 1f));
float height = rad * heightInterp.apply(heightFrom, heightTo, Mathf.curve(rawfin, heightChangeStart / lifetime, 1f));
float ox = e.x + Angles.trnsx(realRotation, offsetX * flip, offsetY), oy = e.y + Angles.trnsy(realRotation, offsetX * flip, offsetY);
Draw.color(colorFrom, colorTo, colFin);
+15 -1
View File
@@ -7,8 +7,9 @@ import mindustry.game.MapObjectives.*;
import mindustry.io.*;
import java.io.*;
import java.util.*;
public class MapMarkers{
public class MapMarkers implements Iterable<ObjectiveMarker>{
/** Maps marker unique ID to marker. */
private IntMap<ObjectiveMarker> map = new IntMap<>();
@@ -16,6 +17,13 @@ public class MapMarkers{
public Seq<ObjectiveMarker> mapMarkers = new Seq<>(false);
public Seq<ObjectiveMarker> lightMarkers = new Seq<>(false);
public void clear(){
worldMarkers.clear();
mapMarkers.clear();
lightMarkers.clear();
map.clear();
}
public void add(int id, ObjectiveMarker marker){
if(marker == null) return;
var prev = map.put(id, marker);
@@ -111,4 +119,10 @@ public class MapMarkers{
}
}
/** @deprecated use the seq fields instead */
@Deprecated
@Override
public Iterator<ObjectiveMarker> iterator(){
return worldMarkers.iterator();
}
}
+4
View File
@@ -343,6 +343,10 @@ public class Rules{
return unitFactoryActivationDelay + teams.get(team).unitFactoryActivationDelay;
}
public boolean isInfiniteResources(Team team){
return infiniteResources || teams.get(team).infiniteResources;
}
/** A team-specific ruleset. */
public static class TeamRule{
/** Whether, when AI is enabled, ships should be spawned from the core. TODO remove / unnecessary? */
+9
View File
@@ -6,6 +6,7 @@ import arc.math.geom.*;
import arc.struct.*;
import arc.util.*;
import arc.util.io.*;
import arc.util.serialization.*;
import mindustry.content.*;
import mindustry.content.TechTree.*;
import mindustry.core.*;
@@ -554,6 +555,14 @@ public abstract class SaveVersion extends SaveFileReader{
public void readDataPatches(DataInput stream, SaveReadState saveState) throws IOException{
stream.readInt(); //version - ignored for now
//the requiredPlanets filter needs this, since the rules aren't read yet
if(headless){
try{
Planet planet = content.planet(new JsonReader().parse(saveState.ruleString).getString("planet", Planets.serpulo.name));
state.rules.planet = planet == null ? Planets.serpulo : planet;
}catch(Exception ignored){}
}
int total = stream.readInt();
Seq<DataAsset> assets = new Seq<>(total);
+36 -14
View File
@@ -11,9 +11,6 @@ import mindustry.logic.LExecutor.*;
public class LAssembler{
public static ObjectMap<String, Func<String[], LStatement>> customParsers = new ObjectMap<>();
private static final long invalidNumNegative = Long.MIN_VALUE;
private static final long invalidNumPositive = Long.MAX_VALUE;
public boolean privileged;
/** Maps names to variable. */
public OrderedMap<String, LVar> vars = new OrderedMap<>();
@@ -110,23 +107,48 @@ public class LAssembler{
}
double parseDouble(String symbol){
//fail fast for obvious non-numbers
if(symbol.isEmpty() || !isNumStart(symbol.charAt(0))) return Double.NaN;
//parse hex/binary syntax
if(symbol.startsWith("0b")) return parseLong(false, symbol, 2, 2, symbol.length());
if(symbol.startsWith("+0b")) return parseLong(false, symbol, 2, 3, symbol.length());
if(symbol.startsWith("-0b")) return parseLong(true,symbol, 2, 3, symbol.length());
if(symbol.startsWith("0x")) return parseLong(false,symbol, 16, 2, symbol.length());
if(symbol.startsWith("+0x")) return parseLong(false,symbol, 16, 3, symbol.length());
if(symbol.startsWith("-0x")) return parseLong(true,symbol, 16, 3, symbol.length());
if(symbol.startsWith("0b")) return parseHexOrBin(false, symbol, true, 2);
if(symbol.startsWith("+0b")) return parseHexOrBin(false, symbol, true, 3);
if(symbol.startsWith("-0b")) return parseHexOrBin(true, symbol, true, 3);
if(symbol.startsWith("0x")) return parseHexOrBin(false, symbol, false, 2);
if(symbol.startsWith("+0x")) return parseHexOrBin(false, symbol, false, 3);
if(symbol.startsWith("-0x")) return parseHexOrBin(true, symbol, false, 3);
if(symbol.startsWith("%[") && symbol.endsWith("]") && symbol.length() > 3) return parseNamedColor(symbol);
if(symbol.startsWith("%") && (symbol.length() == 7 || symbol.length() == 9)) return parseColor(symbol);
return Strings.parseDouble(symbol, Double.NaN);
}
double parseLong(boolean negative, String s, int radix, int start, int end) {
long usedInvalidNum = negative ? invalidNumPositive : invalidNumNegative;
long l = Strings.parseLong(s, radix, start, end, usedInvalidNum);
return l == usedInvalidNum ? Double.NaN : negative ? -l : l;
boolean isNumStart(char c){
//note that 'e10' isn't a valid number; '%ffffff' is. Hex numbers start with '0x'.
return c >= '0' && c <= '9' || c == '.' || c == '-' || c == '+' || c == '%';
}
//parses *unsigned* hex or bin number, including negative ones (0xffffffffffffffff as -1)
//detects overflow by input length and uses bit manipulation to avoid signed arithmetics
double parseHexOrBin(boolean negative, String s, boolean binary, int offset){
int end = s.length();
if(offset >= end) return Double.NaN;
int pos = offset;
while(pos < end && s.charAt(pos) == '0') pos ++; //skip leading zeros to avoid incorrect overflow detection
int shift = binary ? 1 : 4;
if(end - pos > 64 / shift) return Double.NaN;
long acc = 0;
int radix = 1 << shift;
while(pos < end){
int digit = Character.digit(s.charAt(pos), radix);
if(digit < 0) return Double.NaN;
acc = acc << shift | digit;
pos ++;
}
return negative ? -acc : acc;
}
double parseColor(String symbol){
@@ -178,4 +200,4 @@ public class LAssembler{
return vars.get(name);
}
}
}
+3 -1
View File
@@ -122,6 +122,8 @@ public class LExecutor{
/** Loads with a specified assembler. Resets all variables. */
public void load(LAssembler builder){
stop = false;
textBuffer.setLength(0);
graphicsBuffer.clear();
nameMap = null;
//retain constants that are links, which, by convention, don't start with @ (builtin) or _ (numeric constant)
vars = builder.vars.values().toSeq().retainAll(var -> !var.constant || var.name.charAt(0) != '_' && var.name.charAt(0) != '@').toArray(LVar.class);
@@ -1583,7 +1585,7 @@ public class LExecutor{
public void run(LExecutor exec){
if(net.client()) return;
Tile tile = world.tile(Mathf.round(x.numf()), Mathf.round(y.numf()));
Tile tile = world.tile(x.numi(), y.numi());
if(tile != null && block.obj() instanceof Block b){
switch(layer){
case ore -> {
+1 -1
View File
@@ -90,7 +90,7 @@ public abstract class LStatement{
/** Sanitizes variable input strings from text fields into values that will not break logic parsing. */
public static String sanitize(String value){
if(value.length() == 0){
return "";
return "null";
}else if(value.length() == 1){
if(value.charAt(0) == '"' || value.charAt(0) == ';' || value.charAt(0) == ' ' ||
value.charAt(0) == '\n' || value.charAt(0) == '\t' || value.charAt(0) == '#'){
+6 -20
View File
@@ -440,11 +440,8 @@ public class LStatements{
//Q: why don't you just use arrays for this?
//A: arrays aren't as easy to serialize so the code generator doesn't handle them
int c = 0;
for(int i = 0; i < type.params.length; i++){
fields(table, type.params[i], i == 0 ? p1 : i == 1 ? p2 : i == 2 ? p3 : p4, i == 0 ? v -> p1 = v : i == 1 ? v -> p2 = v : i == 2 ? v -> p3 = v : v -> p4 = v);
fields(table, type.params[i], type.params.length > 1 && LCanvas.isCompact(), i == 0 ? p1 : i == 1 ? p2 : i == 2 ? p3 : p4, i == 0 ? v -> p1 = v : i == 1 ? v -> p2 = v : i == 2 ? v -> p3 = v : v -> p4 = v);
}
}
@@ -537,7 +534,7 @@ public class LStatements{
table.add(" = ");
tfield = field(table, type, str -> type = str).padRight(0f).get();
tfield = field(table, type, str -> type = str).width(LCanvas.isCompact() ? 140f : 180f).padRight(0f).get();
table.button(b -> {
b.image(Icon.pencilSmall);
@@ -699,16 +696,7 @@ public class LStatements{
}else{
//"function"-type operations have the name at the left and arguments on the right
if(op.func){
if(LCanvas.isCompact()){
table.left();
table.table(c -> {
c.color.set(category().color);
c.left();
funcs(c, table);
}).colspan(2).left();
}else{
funcs(table, table);
}
funcs(table, table);
}else{
field(table, a, str -> a = str);
@@ -1947,9 +1935,7 @@ public class LStatements{
fields(table, "team", team, s -> team = s);
if(type != FetchType.coreCount && type != FetchType.playerCount && type != FetchType.unitCount && type != FetchType.buildCount){
table.add(" # ");
fields(table, index, i -> index = i);
fields(table, "#", index, i -> index = i);
}
if(type == FetchType.buildCount || type == FetchType.build){
@@ -2408,7 +2394,7 @@ public class LStatements{
private static String soundCategory(String entryName){
String normalized = entryName.replace('\\', '/');
int end = normalized.lastIndexOf('/');
if(end < 0) return "Data Patch";
if(end < 0) return "data patch";
int start = normalized.lastIndexOf('/', end - 1);
return normalized.substring(start + 1, end);
@@ -2555,7 +2541,7 @@ public class LStatements{
b.label(() -> bundle(type));
b.clicked(() -> showSelect(b, MapObjectives.allMarkerTypeNames.toArray(String.class), type, t -> {
type = bundle(t);
type = t;
build(table);
}, 2, cell -> cell.size(160, 50)));
}, Styles.logict, () -> {}).size(180, 40).color(table.color).left().padLeft(2);
+2 -1
View File
@@ -30,7 +30,8 @@ public class DataAudioLoader{
}
Fi file = asset.getCacheFile();
Sound sound = Vars.headless || file == null ? new Sound() : Sound.createStream(file);
//large sounds become streams, standard ones don't
Sound sound = Vars.headless || file == null ? new Sound() : file.length() > 100_000 ? Sound.createStream(file) : Sound.createLazy(file);
loadedSounds.add(sound);
Sounds.registerSound(sound, nextSoundId ++);
+4 -1
View File
@@ -12,6 +12,7 @@ import arc.util.*;
import arc.util.Log.*;
import mindustry.*;
import mindustry.game.EventType.*;
import mindustry.graphics.*;
import mindustry.mod.data.*;
import java.io.*;
@@ -106,6 +107,8 @@ public class DataImagePacker{
try{
Pixmap pixmap = new Pixmap(cacheFile);
Pixmaps.antialias(pixmap);
Drawf.checkBleed(pixmap);
//don't add the double dp prefix, only add it if it's not already present
String name = (image.isGenerated() && image.name.contains("-dp-") ? "" : regionPrefix) + image.name;
@@ -178,7 +181,7 @@ public class DataImagePacker{
public void unload(){
if(patchAtlas != null){
for(var texture : patchAtlas.getTextures()){
if(texture != null) patchAtlas.getTextures().remove(texture);
if(texture != null) Core.atlas.getTextures().remove(texture);
}
for(var region : patchAtlas.getRegions()){
if(region != null){
+18 -12
View File
@@ -78,6 +78,7 @@ public class DataManager{
PixmapRegion error = new PixmapRegion(Pixmaps.blankPixmap());
UnlockableContent[] currentContent = {null};
String[] currentHash = {null};
Fi serverGeneratedDir = Vars.dataDirectory.child("assets/sprites/generated");
MultiPacker saver = new MultiPacker(false){
@Override
@@ -89,10 +90,17 @@ public class DataManager{
if(name.startsWith(DataImagePacker.regionPrefix)) name = name.substring(DataImagePacker.regionPrefix.length());
String path = "generated/" + currentHash[0] + "/" + name + ".png";
ImageAsset newImage = new ImageAsset();
newImage.setPath(path);
//it would be nice to do this async, but the pixmap typically gets disposed right after add() exist
//it would be nice to do this async, but the pixmap typically gets disposed right after add()
byte[] bytes = PixmapIO.writePngBytes(region.pixmap);
newImage.updateData(bytes);
if(Vars.headless){ //TODO: doesn't actually work on the server yet
Fi file = serverGeneratedDir.child(name + ".png");
file.writeBytes(bytes);
newImage.readOverride(path, file);
}else{
newImage.setPath(path);
newImage.updateData(bytes);
}
images.add(newImage);
packed[0] ++;
@@ -150,17 +158,15 @@ public class DataManager{
imagePixmaps.each((key, val) -> val.pixmap.dispose());
error.pixmap.dispose();
if(packed[0] > 0 || forcePack){
if(!Vars.headless && (packed[0] > 0 || forcePack)){
reloadImages();
if(!Vars.headless){
for(var cont : contentToPack){
try{
cont.loadIcon();
cont.load();
}catch(Exception e){
Log.err("Failed to load icons for " + cont, e);
}
for(var cont : contentToPack){
try{
cont.loadIcon();
cont.load();
}catch(Exception e){
Log.err("Failed to load icons for " + cont, e);
}
}
}
+2 -2
View File
@@ -195,8 +195,8 @@ public class DataPatcher{
//register global variables
for(var cont : all){
if(!cont.hasErrored() && cont instanceof UnlockableContent u && Vars.logicVars.get("@" + u.name) == null){
addedVars.add(Vars.logicVars.put("@" + u.name, u, false));
if(!cont.hasErrored() && cont instanceof UnlockableContent u && Vars.logicVars.get("@" + (u instanceof StatusEffect ? "status-" : "") + u.name) == null){
addedVars.add(Vars.logicVars.put("@" + (u instanceof StatusEffect ? "status-" : "") + u.name, u, false));
}
}
+34 -2
View File
@@ -1,10 +1,16 @@
package mindustry.mod;
import arc.struct.*;
import arc.util.*;
import mindustry.ui.dialogs.*;
/** Mod listing as a data class. */
public class ModListing{
public String repo, name, internalName, author, lastUpdated, description, minGameVersion, version;
public String repo, name, internalName, author, lastUpdated, description, minGameVersion, version, iconHash = "";
public boolean hasScripts, hasJava, iosCompatible, legacyCompatible, hasIcon;
public String[] contentTypes = {};
/** game build -> release ID + mod version */
public @Nullable ArrayMap<String, ModRelease> releases;
public String[] tags = {};
public int stars;
@Override
@@ -22,4 +28,30 @@ public class ModListing{
", stars=" + stars +
'}';
}
/** @return the specific release that matches the current game version, or null if no specific match is found (i.e. /latest should be used) */
public @Nullable ModRelease getMatchingRelease(){
if(releases == null) return null;
for(var entry : releases){
if(ModsDialog.matchesGameVersion(ModsDialog.parseVersion(entry.key))){
return entry.value;
}
}
return null;
}
public static class ModRelease{
/** Github release ID ($API/releases/$ID) */
public String id = "";
/** Actual mod version string in release's mod.json */
public String version = "";
@Override
public String toString(){
return "ModRelease{" +
"id='" + id + '\'' +
", version='" + version + '\'' +
'}';
}
}
}
+19
View File
@@ -22,6 +22,7 @@ import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.graphics.MultiPacker.*;
import mindustry.mod.ContentParser.*;
import mindustry.mod.data.*;
import mindustry.type.*;
import mindustry.ui.*;
@@ -936,6 +937,24 @@ public class Mods implements Loadable{
Events.fire(new ModContentLoadEvent());
}
public void loadModPatches(){
for(LoadedMod mod : orderedMods()){
if(mod.root.child("patches").exists()){
try{
Seq<Fi> patches = mod.root.child("patches").findAll(f -> f.extEquals("json") || f.extEquals("hjson"));
if(patches.size > 0){
//create a new patcher per mod so the fields don't get reset
DataPatcher patcher = new DataPatcher();
patches.sort();
patcher.apply(patches.map(f -> new PatchAsset(f.readString())), new Seq<>());
}
}catch(Exception e){
Log.err("Failed to apply patches from mod " + mod.meta.name, e);
}
}
}
}
public void handleContentError(Content content, Throwable error){
parser.markError(content, error);
}
+1 -1
View File
@@ -346,7 +346,7 @@ public class Fonts{
@Override
public float imageSize(){
return size;
return size / Scl.scl(1f);
}
};
@@ -177,7 +177,7 @@ public class CustomRulesDialog extends BaseDialog{
number("@rules.blockdamagemultiplier", f -> rules.blockDamageMultiplier = f, () -> rules.blockDamageMultiplier);
if(Core.bundle.get("configure").toLowerCase().contains(ruleSearch)){
current.button("@configure",
current.button("@configure", Icon.boxSmall,
() -> loadoutDialog.show(999999, rules.loadout,
i -> true,
() -> rules.loadout.clear().add(new ItemStack(Items.copper, 100)),
@@ -186,7 +186,7 @@ public class CustomRulesDialog extends BaseDialog{
}
if(Core.bundle.get("bannedblocks").toLowerCase().contains(ruleSearch)){
current.button("@bannedblocks", () -> bannedBlocks.show(rules.bannedBlocks)).left().width(300f).row();
current.button("@bannedblocks", Icon.cancelSmall, () -> bannedBlocks.show(rules.bannedBlocks)).left().width(300f).row();
}
check("@rules.hidebannedblocks", b -> rules.hideBannedBlocks = b, () -> rules.hideBannedBlocks);
check("@bannedblocks.whitelist", b -> rules.blockWhitelist = b, () -> rules.blockWhitelist);
@@ -207,7 +207,7 @@ public class CustomRulesDialog extends BaseDialog{
check("@rules.logicunitdeconstruct", b -> rules.logicUnitDeconstruct = b, () -> rules.logicUnitDeconstruct, () -> rules.logicUnitControl);
if(Core.bundle.get("bannedunits").toLowerCase().contains(ruleSearch)){
current.button("@bannedunits", () -> bannedUnits.show(rules.bannedUnits)).left().width(300f).row();
current.button("@bannedunits", Icon.unitsSmall, () -> bannedUnits.show(rules.bannedUnits)).left().width(300f).row();
}
check("@bannedunits.whitelist", b -> rules.unitWhitelist = b, () -> rules.unitWhitelist);
@@ -234,7 +234,7 @@ public class CustomRulesDialog extends BaseDialog{
number("@rules.solarmultiplier", f -> rules.solarMultiplier = f, () -> rules.solarMultiplier);
if(Core.bundle.get("rules.weather").toLowerCase().contains(ruleSearch)){
current.button("@rules.weather", this::weatherDialog).width(250f).left().row();
current.button("@rules.weather", Icon.rainSmall, this::weatherDialog).width(250f).left().row();
}
category("light");
@@ -251,10 +251,6 @@ public class CustomRulesDialog extends BaseDialog{
}
check("@rules.lighting.unitlight", b -> rules.unitLight = b, () -> rules.unitLight);
if(Core.bundle.get("rules.weather").toLowerCase().contains(ruleSearch)){
current.button("@rules.weather", this::weatherDialog).width(250f).left().row();
}
category("music");
Boolp allowMusic = () -> !rules.disableMusic;
@@ -130,7 +130,7 @@ public class EditorMapsDialog extends MapListDialog{
if(!map.tags.get("description", "").isEmpty()){
t.add("@editor.description").padRight(10).color(Color.gray).top();
t.row();
t.add(map.description()).growX().wrap().padTop(2);
t.add(map.description()).growX().wrap(true).padTop(2);
}
}).height(mapsize).width(mapsize);
@@ -167,6 +167,7 @@ public class KeybindDialog extends Dialog{
buttons.button("@back", Icon.left, this::hide).size(bw, bh).get().addListener(blocker);
buttons.button("@settings.unbindKey", Icon.cancel, () -> {
keyBind.unset();
keyBind.save();
hide();
}).size(bw, bh).get().addListener(blocker);
}};
@@ -65,6 +65,11 @@ public class ModBrowserDialog extends BaseDialog{
shown(this::rebuildBrowser);
}
public @Nullable ModListing getCachedMod(String repo){
if(modList == null) return null;
return modList.find(m -> m.repo.equalsIgnoreCase(repo));
}
public void getModList(Cons<Seq<ModListing>> listener){
//mods already fetched, use that
if(modList != null){
@@ -247,9 +252,9 @@ public class ModBrowserDialog extends BaseDialog{
textureCache.put(repo, last = Core.atlas.find("nomap"));
if(mod.hasIcon){
Fi cacheFolder = Vars.mobile ? Core.files.cache("modIconCache"): dataDirectory.child("modIconCache");
Fi cacheFolder = mobile ? Core.files.cache("modIconCache"): dataDirectory.child("modIconCache");
cacheFolder.mkdirs();
Fi cacheFile = cacheFolder.child(Strings.sanitizeFilename(mod.repo + mod.lastUpdated) + ".png");
Fi cacheFile = cacheFolder.child(Strings.sanitizeFilename(mod.repo + "_" + mod.iconHash) + ".png");
if(!cacheFile.exists()){ //fetch from Github
ConsT<HttpResponse, Exception> fetch = res -> {
@@ -337,7 +342,7 @@ public class ModBrowserDialog extends BaseDialog{
var found = mods.list().find(l -> mod.repo != null && mod.repo.equals(l.getRepo()));
sel.buttons.button(found == null ? "@mods.browser.add" : "@mods.browser.reinstall", Icon.download, () -> {
sel.hide();
ui.mods.githubImportMod(mod.repo, mod.hasJava, null, true);
ui.mods.githubImportMod(mod);
});
if(Core.graphics.isPortrait()){
+72 -4
View File
@@ -17,6 +17,7 @@ import arc.util.Http.*;
import arc.util.io.*;
import arc.util.serialization.*;
import arc.util.serialization.Jval.*;
import mindustry.core.*;
import mindustry.ctype.*;
import mindustry.game.EventType.*;
import mindustry.gen.*;
@@ -26,10 +27,13 @@ import mindustry.mod.Mods.*;
import mindustry.ui.*;
import java.util.*;
import java.util.regex.*;
import static mindustry.Vars.*;
public class ModsDialog extends BaseDialog{
private static final Pattern modVersionPattern = Pattern.compile("\\[[vb](\\d+)(?:\\.(\\d+))?\\]");
public ModBrowserDialog browser;
protected float modImportProgress;
@@ -105,7 +109,11 @@ public class ModsDialog extends BaseDialog{
var mod = repoToMod.get(entry.repo);
if(mod != null){
modToListing.put(mod, entry);
if(Strings.checkNewerSemver(entry.version, mod.meta.version)) withUpdates.add(mod);
var release = entry.getMatchingRelease();
//Only compare to the release that fits the current version the client is using, if one exists; don't look for updates that don't match the version
if(Strings.checkNewerSemver(entry.version, release == null ? mod.meta.version : release.version)){
withUpdates.add(mod);
}
}
}
@@ -171,8 +179,15 @@ public class ModsDialog extends BaseDialog{
if(text.startsWith("https://github.com/")) text = text.substring("https://github.com/".length());
Core.settings.put("lastmod", text);
//there's no good way to know if it's a java mod here, so assume it's not
githubImportMod(text, false, null, true);
var listing = browser.getCachedMod(text);
if(listing != null){
//auto-choose release when a listing is found
githubImportMod(listing);
}else{
//this will auto-detect whether it's java, then grab latest release unconditionally
//TODO: would be nice to grab version-appropriate release but I don't want to copy-paste browser logic for this
githubImportMod(text, false, null, true);
}
});
}).margin(12f);
});
@@ -526,7 +541,7 @@ public class ModsDialog extends BaseDialog{
}
}
public void viewReleases(String repo, boolean isJava, boolean reinstall) {
public void viewReleases(String repo, boolean isJava, boolean reinstall){
BaseDialog load = new BaseDialog("");
load.cont.add("[accent]" + Core.bundle.get("mods.browser.fetching"));
load.show();
@@ -596,6 +611,11 @@ public class ModsDialog extends BaseDialog{
}));
}
public void githubImportMod(ModListing mod){
var matchingRelease = mod.getMatchingRelease();
githubImportMod(mod.repo, mod.hasJava, matchingRelease == null ? null : matchingRelease.id, true);
}
public void githubImportMod(String repo, boolean isJava, boolean forceEnable){
githubImportMod(repo, isJava, null, forceEnable);
}
@@ -686,4 +706,52 @@ public class ModsDialog extends BaseDialog{
}, this::importFail);
}
}
/** @return {major, minor} parsed from a leading/trailing "[v{major}]" or "[v{major}.{minor}]" tag, or null if none is found at either end (or the numbers are unparseable). */
public static @Nullable int[] parseVersionTag(String str){
if(str == null) return null;
Matcher m = modVersionPattern.matcher(str);
while(m.find()){
if(m.start() == 0 || m.end() == str.length()){
int major = Strings.parseInt(m.group(1));
//any major version below 15 is likely a major-version tag like [v7] and should be ignored
if(major == Integer.MIN_VALUE || major < 15) return null;
int minor = m.group(2) != null ? Strings.parseInt(m.group(2)) : 0;
if(minor == Integer.MIN_VALUE) return null;
return new int[]{major, minor};
}
}
return null;
}
public static @Nullable int[] parseVersion(String str){
if(str == null || str.isEmpty()) return null;
int dot = str.indexOf('.');
String majorStr = dot == -1 ? str : str.substring(0, dot);
String minorStr = dot == -1 ? null : str.substring(dot + 1);
if(majorStr.isEmpty() || (dot != -1 && (minorStr.isEmpty() || str.indexOf('.', dot + 1) != -1))) return null;
int major = Strings.parseInt(majorStr);
if(major == Integer.MIN_VALUE) return null;
int minor = minorStr != null ? Strings.parseInt(minorStr) : 0;
if(minor == Integer.MIN_VALUE) return null;
return new int[]{major, minor};
}
/** @return whether the specified release name and its tags match the current game build (e.g. "Bingus Mod [v160]" should only match build 160) */
public static boolean matchesGameVersion(String releaseTitle){
return matchesGameVersion(parseVersionTag(releaseTitle));
}
public static boolean matchesGameVersion(@Nullable int[] tag){
//version not specified, matches anything.
if(tag == null) return true;
//must match exactly; custom builds (-1) do not match.
//for revisions, either match if the revision is unspecified (v160 -> matches ALL 160.x builds), OR, if it is specified, match the exact version (the mod author must have had a good reason for it)
return Version.build == tag[0] && (tag[1] == 0 || Version.revision == tag[1]);
}
}
@@ -563,7 +563,11 @@ public class SettingsMenuDialog extends BaseDialog{
Core.settings.put("swapdiagonal", false);
}
dev.checkPref("console", false);
dev.checkPref("console", false, val -> {
if(val == false && ui.consolefrag != null){
ui.consolefrag.close();
}
});
dev.checkPref("drawhitboxes", false);
dev.checkPref("showperformance", false);
@@ -40,7 +40,7 @@ public class ConsoleFragment extends Table{
font = Fonts.def;
visible(() -> {
if(input.keyTap(Binding.console) && settings.getBool("console") && (scene.getKeyboardFocus() == chatfield || !(scene.getKeyboardFocus() instanceof TextField)) && !ui.chatfrag.shown()){
if(input.keyTap(Binding.console) && (settings.getBool("console") || shown) && (scene.getKeyboardFocus() == chatfield || !(scene.getKeyboardFocus() instanceof TextField)) && !ui.chatfrag.shown()){
shown = !shown;
if(shown && !open && settings.getBool("console")){
toggle();
@@ -227,6 +227,11 @@ public class ConsoleFragment extends Table{
open = false; //never true on mobile
}
public void close(){
shown = false;
open = false;
}
public void toggle(){
if(!open){
@@ -312,7 +312,7 @@ public class PlacementFragment{
button.update(() -> { //color unplacable things gray
Building core = player.core();
Color color = (state.rules.infiniteResources || (core != null && (core.items.has(block.requirements, state.rules.buildCostMultiplier) || state.rules.infiniteResources))) && player.isBuilder() ? Color.white : Color.gray;
Color color = (state.rules.isInfiniteResources(player.team()) || (core != null && (core.items.has(block.requirements, state.rules.buildCostMultiplier) || state.rules.infiniteResources))) && player.isBuilder() ? Color.white : Color.gray;
button.forEach(elem -> elem.setColor(color));
button.setChecked(control.input.block == block);
@@ -407,7 +407,7 @@ public class PlacementFragment{
line.label(() -> {
Building core = player.core();
int stackamount = Math.round(stack.amount * state.rules.buildCostMultiplier);
if(core == null || state.rules.infiniteResources) return "*/" + stackamount;
if(core == null || state.rules.isInfiniteResources(player.team())) return "*/" + stackamount;
int amount = core.items.get(stack.item);
String color = (amount < stackamount / 2f ? "[scarlet]" : amount < stackamount ? "[accent]" : "[white]");
@@ -132,8 +132,7 @@ public class PlayerListFragment{
});
button.add(iconTable).size(h);
button.labelWrap("[#" + user.color().toString().toUpperCase() + "]" + user.name()).style(Styles.outlineLabel).width(170f).pad(10);
button.add().grow();
button.add("[#" + user.color().toString().toUpperCase() + "]" + user.name()).style(Styles.outlineLabel).growX().wrap(true).pad(10);
button.background(Tex.underline);
@@ -236,8 +235,6 @@ public class PlayerListFragment{
dialog.cont.button("@back", Icon.left, dialog::hide).padTop(-1f).size(220f, 55f);
dialog.show();
}).size(h);
}
}else if(!user.isLocal() && !user.admin && net.client() && Groups.player.size() >= 3 && player.team() == user.team()){ //votekick
@@ -249,7 +246,7 @@ public class PlayerListFragment{
.size(h);
}
content.add(button).width(350f).height(h + 14);
content.add(button).width(mobile ? 350f : 470f).height(h + 14);
content.row();
}
+5 -2
View File
@@ -67,6 +67,8 @@ public class Block extends UnlockableContent implements Senseable{
public boolean acceptsItems = false;
/** If true, this block won't be affected by the onlyDepositCore rule. */
public boolean alwaysAllowDeposit = false;
/** If false, this block cannot be placed in payloads. */
public boolean allowedInPayloads = true;
/** Cooldown, in seconds, applied to player item depositing when any item is deposited to this block. Overrides the itemDepositCooldown if non-negative. */
public float depositCooldown = -1f;
/** If true, all item capacities of this block are separate instead of pooled as one number. */
@@ -172,7 +174,8 @@ public class Block extends UnlockableContent implements Senseable{
public boolean updateInUnits = true;
/** if true, this block updates in payloads in units regardless of the experimental game rule */
public boolean alwaysUpdateInUnits = false;
/** if true, this block can be picked up in payloads */
/** @deprecated use allowedInPayloads instead */
@Deprecated
public boolean canPickup = true;
/** if false, only incinerable liquids are dropped when deconstructing; otherwise, all liquids are dropped. */
public boolean deconstructDropAllLiquid = false;
@@ -757,7 +760,7 @@ public class Block extends UnlockableContent implements Senseable{
}
//nothing was added, so it's safe to add a dynamic liquid bar (probably?)
if(!added){
if(!added && liquidCapacity > 0f){
addLiquidBar(build -> build.liquids.current());
}
}
+1 -1
View File
@@ -186,7 +186,7 @@ public class Build{
return false;
}
if(!state.rules.editor && checkCoreRadius){
if(!state.rules.editor && checkCoreRadius && !(!checkVisible && team == Team.derelict)){
//find closest core, if it doesn't match the team, placing is not legal
if(state.rules.polygonCoreProtection){
float mindst = Float.MAX_VALUE;
@@ -62,7 +62,7 @@ public class BaseShield extends Block{
hasPower = true;
update = solid = true;
rebuildable = false;
canPickup = true;
allowedInPayloads = false;
}
@Override
@@ -5,15 +5,14 @@ import arc.graphics.g2d.*;
import arc.math.*;
import arc.scene.ui.TextField.*;
import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.*;
import arc.util.io.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.graphics.*;
import mindustry.entities.units.*;
import mindustry.game.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.*;
@@ -23,6 +22,8 @@ import mindustry.world.meta.*;
import static mindustry.Vars.*;
public class TargetDummy extends Block{
static final float maxDummySize = 30f;
public final int dpsUpdateTime = timers++;
public UnitType unitType = UnitTypes.dummy;
public float pullScale = 0.33f;
@@ -38,18 +39,19 @@ public class TargetDummy extends Block{
configurable = logicConfigurable = true;
underBullets = true;
targetable = false;
allowedInPayloads = false;
canOverdrive = false;
saveConfig = true;
config(FloatSeq.class, (TargetDummyBuild tile, FloatSeq config) -> {
if(config.size > 0){
tile.unitTeam = tile.team;
if(config.get(0) == 1) tile.unitTeam = Team.get(tile.dummyTeam());
}
if(config.size > 1) tile.boosting = config.get(1) == 1;
if(config.size > 2) tile.unitArmor = config.get(2);
if(config.size > 3) tile.resetTime = config.get(3);
if(config.size > 4) tile.dummySize = config.get(4);
config(int[].class, (TargetDummyBuild tile, int[] config) -> {
if(config.length != 5) return; //invalid, must have 5 values exactly
tile.unitTeam = tile.team;
if(config[0] == 1) tile.unitTeam = Team.get(tile.dummyTeam());
tile.boosting = config[1] == 1;
tile.unitArmor = Mathf.clamp(config[2], 0, 100_000);
tile.resetTime = config[3];
tile.dummySize = Mathf.clamp(Float.intBitsToFloat(config[4]), 0.1f, maxDummySize * tilesize);
if(Float.isNaN(tile.dummySize) || Float.isInfinite(tile.dummySize)) tile.dummySize = 8f;
});
}
@@ -90,6 +92,11 @@ public class TargetDummy extends Block{
public float unitArmor;
public Team unitTeam = Team.derelict;
@Override
public boolean canPickup(){
return false;
}
@Override
public void created(){
if(unitTeam == Team.derelict) unitTeam = team;
@@ -235,24 +242,28 @@ public class TargetDummy extends Block{
t.background(Styles.black6);
t.defaults().left();
t.check(Core.bundle.get("rules.enemyteam"), unitTeam != team, b -> configureFloat(0, Mathf.num(b))).colspan(3).row();
t.check(Core.bundle.get("stat.flying"), boosting, b -> configureFloat(1, Mathf.num(b))).colspan(3).row();
t.check(Core.bundle.get("rules.enemyteam"), unitTeam != team, b -> configureInt(0, Mathf.num(b))).colspan(3).row();
t.check(Core.bundle.get("stat.flying"), boosting, b -> configureInt(1, Mathf.num(b))).colspan(3).row();
t.add(Core.bundle.get("stat.armor"));
t.field("" + (int)unitArmor, TextFieldFilter.digitsOnly, s -> configureFloat(2, Strings.parseInt(s))).width(200f).padLeft(8f).colspan(2).row();
t.field("" + (int)unitArmor, TextFieldFilter.digitsOnly, s -> configureInt(2, Strings.parseInt(s))).valid(val -> Strings.parseInt(val, Integer.MAX_VALUE) < 100_000).width(200f).padLeft(8f).colspan(2).row();
t.add(Core.bundle.get("stat.resettime"));
t.field(Strings.autoFixed(resetTime / 60f, 2), TextFieldFilter.floatsOnly, s -> configureFloat(3, Strings.parseFloat(s) * 60f)).padLeft(8f).growX();
t.field(Strings.autoFixed(resetTime / 60f, 2), TextFieldFilter.floatsOnly, s -> configureInt(3, (int)(Strings.parseFloat(s) * 60f))).valid(Strings::canParsePositiveFloat).padLeft(8f).growX();
t.add(StatUnit.seconds.localized()).padLeft(8).row();
t.add(Core.bundle.get("stat.hitsize"));
t.field("" + (dummySize/tilesize), TextFieldFilter.floatsOnly, s -> configureFloat(4, Strings.parseFloat(s) * tilesize)).padLeft(8f).growX();
t.field("" + (dummySize/tilesize), TextFieldFilter.floatsOnly, s -> configureInt(4, Float.floatToIntBits(Strings.parseFloat(s) * tilesize)))
.valid(val -> {
float parsed = Strings.parseFloat(val, Float.MAX_VALUE);
return parsed >= 0.1f && parsed <= maxDummySize;
}).padLeft(8f).growX();
t.add(StatUnit.blocks.localized()).padLeft(8f);
}).top().grow().margin(8f);
}
//helper to send the rest of values, since config does not support arrays
public void configureFloat(int index, float value){
FloatSeq seq = FloatSeq.with(Mathf.num(unitTeam != team), Mathf.num(boosting), unitArmor, resetTime, dummySize);
seq.set(index, value);
configure(seq);
public void configureInt(int index, int value){
int[] values = config();
values[index] = value;
configure(values);
}
public int dummyTeam(){
@@ -261,8 +272,9 @@ public class TargetDummy extends Block{
}
@Override
public Object config(){
return FloatSeq.with(Mathf.num(unitTeam != team), Mathf.num(boosting), unitArmor, resetTime, dummySize);
public int[] config(){
//note: float[] is not supported in build 160
return new int[]{Mathf.num(unitTeam != team), Mathf.num(boosting), (int)unitArmor, (int)resetTime, Float.floatToIntBits(dummySize)};
}
@Override
@@ -162,7 +162,7 @@ public class DirectionalUnloader extends Block{
public void read(Reads read, byte revision){
super.read(read, revision);
int id = read.s();
unloadItem = id == -1 ? null : content.items().get(id);
unloadItem = id == -1 ? null : content.item(id);
offset = read.s();
}
}
@@ -17,7 +17,6 @@ import mindustry.io.*;
import mindustry.type.*;
import mindustry.world.*;
import mindustry.world.blocks.*;
import mindustry.world.blocks.storage.*;
import static mindustry.Vars.*;
@@ -87,7 +86,7 @@ public class PayloadSource extends PayloadBlock{
}
public boolean canProduce(Block b){
return !b.removed && b.isVisible() && b.size < size && !(b instanceof CoreBlock) && !state.rules.isBanned(b) && b.environmentBuildable();
return !b.removed && b.isVisible() && b.size < size && b.allowedInPayloads && !state.rules.isBanned(b) && b.environmentBuildable();
}
public boolean canProduce(UnitType t){
@@ -43,6 +43,15 @@ public class ThermalGenerator extends PowerGenerator{
lightClipSize = Math.max(lightClipSize, 45f * size * 2f * 2f);
}
@Override
public void afterPatch(){
super.afterPatch();
if(outputLiquid != null){
outputsLiquid = true;
hasLiquids = true;
}
}
@Override
public void setStats(){
super.setStats();
@@ -82,7 +91,7 @@ public class ThermalGenerator extends PowerGenerator{
generateEffect.at(x + Mathf.range(3f), y + Mathf.range(3f));
}
if(outputLiquid != null){
if(outputLiquid != null && hasLiquids){
float added = Math.min(productionEfficiency * delta() * outputLiquid.amount, liquidCapacity - liquids.get(outputLiquid.liquid));
liquids.add(outputLiquid.liquid, added);
dumpLiquid(outputLiquid.liquid);
@@ -11,11 +11,15 @@ import mindustry.world.meta.*;
/** A crafter that gains efficiency from attribute tiles. */
public class AttributeCrafter extends GenericCrafter{
public Attribute attribute = Attribute.heat;
/** Base efficiency of the crafter. */
public float baseEfficiency = 1f;
/** Maximum efficiency/output boost from attributes. */
public float maxBoost = 1f;
/** Minimum efficiency required to place this block. */
public float minEfficiency = -1f;
public boolean displayEfficiency = true;
public boolean displayScaledOutput = true;
/** Whether to show this bar in the UI. */
public boolean displayEfficiency = true, displayScaledOutput = true;
/** Whether liquid consumption scales with efficiency. */
public boolean scaleLiquidConsumption = false;
/** Scaled output (yield) multiplier, scales with attribute. <=0 to disable. */
public float outputScale = 0f;
@@ -34,12 +38,10 @@ public class AttributeCrafter extends GenericCrafter{
drawPlaceText(
(displayEfficiency && boostScale > 0f ?
Core.bundle.format("bar.efficiency",
(int)((baseEfficiency + Math.min(maxBoost, boostScale * sumAttribute(attribute, x, y))) * 100f))
Core.bundle.format("bar.efficiency", (int)((baseEfficiency + Math.min(maxBoost, boostScale * sumAttribute(attribute, x, y))) * 100f))
: "") +
(displayScaledOutput && outputScale > 0f ? "\n" +
Core.bundle.format("bar.yield",
(int)(Math.min(maxBoost, outputScale * sumAttribute(attribute, x, y)) * 100f))
(displayScaledOutput && outputScale > 0f ?
"\n" + Core.bundle.format("bar.yield", (int)((1f + Math.min(maxBoost, outputScale * sumAttribute(attribute, x, y))) * 100f))
: ""), x, y, valid);
}
@@ -59,7 +61,7 @@ public class AttributeCrafter extends GenericCrafter{
if(displayScaledOutput && outputScale > 0f){
addBar("yield", (AttributeCrafterBuild entity) ->
new Bar(
() -> Core.bundle.format("bar.yield", (int)((entity.outputMultiplier() - baseEfficiency) * 100)),
() -> Core.bundle.format("bar.yield", (int)(entity.outputMultiplier() * 100)),
() -> Pal.lightOrange,
entity::outputMultiplier));
}
@@ -335,7 +335,10 @@ public class GenericCrafter extends Block{
public void dumpOutputs(){
if(outputItems != null && timer(timerDump, dumpTime / timeScale)){
for(ItemStack output : outputItems){
dump(output.item);
int amount = Math.max(1, Mathf.round(scaleOutput(output.amount)));
for(int i = 0; i < amount; i++){
if(!dump(output.item)) break;
}
}
}
@@ -83,6 +83,7 @@ public class CoreBlock extends StorageBlock{
envEnabled |= Env.space;
drawCached = false;
drawDynamic = true;
allowedInPayloads = false;
//support everything
replaceable = false;
@@ -673,12 +674,6 @@ public class CoreBlock extends StorageBlock{
}
}
@Override
public boolean canPickup(){
//cores can never be picked up
return false;
}
@Override
public void onDestroyed(){
if(state.rules.coreCapture){
@@ -39,6 +39,7 @@ public class Reconstructor extends UnitBlock{
public Sound createSound = Sounds.unitCreate;
public float createSoundVolume = 1f;
public boolean showAllCommands = true;
public Reconstructor(String name){
super(name);
@@ -187,7 +188,7 @@ public class Reconstructor extends UnitBlock{
if(build != null && build.team == this.team){
commandPos.set(build);
}
}
}
}
@Override
@@ -197,7 +198,7 @@ public class Reconstructor extends UnitBlock{
public boolean canSetCommand(){
var output = unit();
return output == null || output.allowChangeCommands;
return showAllCommands ? (output == null || output.allowChangeCommands) : output != null && output.commands.size > 1;
}
@Override
@@ -214,6 +215,8 @@ public class Reconstructor extends UnitBlock{
public void buildConfiguration(Table table){
var unit = unit();
if(!showAllCommands && unit == null) return;
var group = new ButtonGroup<ImageButton>();
group.setMinCheckCount(0);
int i = 0, columns = 5;
@@ -47,8 +47,10 @@ public class ItemModule extends BlockModule{
public void updateFlow(){
//update the flow at N fps at most
if(flowTimer.get(1, flowPollInterval)){
int len = content.items().size;
if(items.length != len) items = Arrays.copyOf(items, len);
if(flow == null){
if(flow == null || flow.length != len || cacheSums == null || cacheFlow == null){
if(cacheFlow == null || cacheFlow.length != items.length){
cacheFlow = new WindowedMean[items.length];
for(int i = 0; i < items.length; i++){
@@ -95,7 +97,7 @@ public class ItemModule extends BlockModule{
/** @return a specific item's flow rate in items/s; any value < 0 means not ready.*/
public float getFlowRate(Item item){
return flow == null ? -1f : displayFlow[item.id] * 60;
return flow == null ? -1f : displayFlow != null ? displayFlow[item.id] * 60 : -1f;
}
public boolean hasFlowItem(Item item){
@@ -290,6 +292,10 @@ public class ItemModule extends BlockModule{
public void checkArrayCapacity(int size){
if(items.length != size) items = Arrays.copyOf(items, size);
cacheFlow = null;
cacheSums = null;
displayFlow = null;
flow = null;
}
@Override
@@ -20,9 +20,9 @@ public class LiquidModule extends BlockModule{
public static float flowVisualRefreshInterval = 15f;
private static final Interval flowTimer = new Interval(2);
private static WindowedMean[] cacheFlow;
private static float[] cacheSums;
private static float[] displayFlow;
private static @Nullable WindowedMean[] cacheFlow;
private static @Nullable float[] cacheSums;
private static @Nullable float[] displayFlow;
private static final Bits cacheBits = new Bits();
private float[] liquids = new float[content.liquids().size];
@@ -32,7 +32,10 @@ public class LiquidModule extends BlockModule{
public void updateFlow(){
if(flowTimer.get(1, flowPollInterval)){
if(flow == null){
int len = content.liquids().size;
if(liquids.length != len) liquids = Arrays.copyOf(liquids, len);
if(flow == null || flow.length != len || cacheSums == null || cacheFlow == null){
if(cacheFlow == null || cacheFlow.length != liquids.length){
cacheFlow = new WindowedMean[liquids.length];
for(int i = 0; i < liquids.length; i++){
@@ -75,7 +78,7 @@ public class LiquidModule extends BlockModule{
/** @return current liquid's flow rate in u/s; any value < 0 means 'not ready'. */
public float getFlowRate(Liquid liquid){
return flow == null ? -1f : displayFlow[liquid.id] * 60;
return flow == null ? -1f : displayFlow != null ? displayFlow[liquid.id] * 60 : -1f;
}
public boolean hasFlowLiquid(Liquid liquid){
@@ -152,6 +155,10 @@ public class LiquidModule extends BlockModule{
public void checkArrayCapacity(int size){
if(liquids.length != size) liquids = Arrays.copyOf(liquids, size);
cacheFlow = null;
cacheSums = null;
displayFlow = null;
flow = null;
}
@Override
+1 -1
View File
@@ -26,4 +26,4 @@ org.gradle.caching=true
org.gradle.internal.http.socketTimeout=100000
org.gradle.internal.http.connectionTimeout=100000
android.enableR8.fullMode=false
archash=ae321d09e6
archash=7445105cd2
+2
View File
@@ -38,6 +38,8 @@
<true/>
<key>UIRequiresFullScreen</key>
<true/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>NSPhotoLibraryAddUsageDescription</key>
@@ -54,6 +54,7 @@ public class ServerLauncher implements ApplicationListener{
mods.loadScripts();
content.createModContent();
content.init();
mods.loadModPatches();
if(mods.hasContentErrors()){
err("Error occurred loading mod content:");
+120 -2
View File
@@ -1,3 +1,4 @@
import arc.graphics.*;
import mindustry.logic.*;
import mindustry.logic.LExecutor.*;
import org.junit.jupiter.api.*;
@@ -122,7 +123,7 @@ public class LogicTests{
Arguments.of("a bare single semicolon is invalid", ";", "invalid"),
Arguments.of("a bare single space is invalid", " ", "invalid"),
Arguments.of("a single ordinary character passes through unchanged", "a", "a"),
Arguments.of("empty input stays empty", "", ""),
Arguments.of("empty input gets converted to null", "", "null"),
Arguments.of("a plain already-quoted value is untouched", "\"hello\"", "\"hello\""),
Arguments.of("a unescaped quote at the end gets doubled", "\"hello\\\"", "\"hello\\\\\""),
Arguments.of(
@@ -243,6 +244,123 @@ public class LogicTests{
);
}
/** Values that must resolve to a numeric constant (isobj == false) or an object constant. */
static Stream<Arguments> parseValCases(){
return Stream.of(
// name, symbol, expected (Double => numeric, anything else => object)
Arguments.of("parse null", "null", null),
//decimal
Arguments.of("decimal: zero", "0", 0.0),
Arguments.of("decimal: positive integer", "42", 42.0),
Arguments.of("decimal: negative integer", "-42", -42.0),
Arguments.of("decimal: explicit plus sign", "+42", 42.0),
Arguments.of("decimal: fraction", "3.14", 3.14),
Arguments.of("decimal: negative fraction", "-3.14", -3.14),
Arguments.of("decimal: leading dot", ".5", 0.5),
Arguments.of("decimal: large integer", "123456789012", 123456789012.0),
Arguments.of("decimal: scientific", "1e3", 1000.0),
Arguments.of("decimal: scientific negative exponent", "1.5e-2", 0.015),
//hex
Arguments.of("hex: zero", "0x0", 0.0),
Arguments.of("hex: uppercase digits", "0xFF", 255.0),
Arguments.of("hex: lowercase digits", "0xff", 255.0),
Arguments.of("hex: mixed case", "0xDeadBeef", 3735928559.0),
Arguments.of("hex: explicit plus", "+0xFF", 255.0),
Arguments.of("hex: negative", "-0xFF", -255.0),
Arguments.of("hex: many leading zeros aren't overflow", "0x0000000000000000000000FF", 255.0),
Arguments.of("hex: only zeros", "0x" + "0".repeat(100), 0.0),
Arguments.of("hex: Long.MAX_VALUE", "0x7FFFFFFFFFFFFFFF", (double)Long.MAX_VALUE),
Arguments.of("hex: Long.MIN_VALUE (0x8000...)", "0x8000000000000000", (double)Long.MIN_VALUE),
Arguments.of("hex: unsigned long max wraps to -1", "0xFFFFFFFFFFFFFFFF", -1.0),
Arguments.of("hex: unsigned long max - 1 wraps to -2", "0xFFFFFFFFFFFFFFFE", -2.0),
Arguments.of("hex: negated -1 wrap gives 1", "-0xFFFFFFFFFFFFFFFF", 1.0),
Arguments.of("hex: negative Long.MAX_VALUE", "-0x7FFFFFFFFFFFFFFF", -(double)Long.MAX_VALUE),
//binary
Arguments.of("bin: zero", "0b0", 0.0),
Arguments.of("bin: one", "0b1", 1.0),
Arguments.of("bin: ten", "0b1010", 10.0),
Arguments.of("bin: explicit plus", "+0b1010", 10.0),
Arguments.of("bin: negative", "-0b1010", -10.0),
Arguments.of("bin: many leading zeros aren't overflow", "0b" + "0".repeat(70) + "1", 1.0),
Arguments.of("bin: 63 ones is Long.MAX_VALUE", "0b0" + "1".repeat(63), (double)Long.MAX_VALUE),
Arguments.of("bin: 1 followed by 63 zeros is Long.MIN_VALUE", "0b1" + "0".repeat(63), (double)Long.MIN_VALUE),
Arguments.of("bin: 64 ones wraps to -1", "0b" + "1".repeat(64), -1.0)
);
}
@ParameterizedTest(name = "{0}")
@MethodSource("parseValCases")
void parseVarValues(String name, String symbol, Object expected){
LAssembler asm = new LAssembler();
LVar v = asm.var(symbol);
if(expected instanceof Double d){
assertFalse(v.isobj, "should be numeric: " + symbol);
assertEquals(d, v.numval, 0.00001f);
}else{
assertTrue(v.isobj);
assertEquals(expected, v.objval);
}
}
/** Colors are packed into the bits of a (tiny, denormal) double, so they need an exact comparison. */
static Stream<Arguments> parseColorCases(){
return Stream.of(
Arguments.of("color: rgb white", "%ffffff", Color.toDoubleBits(255, 255, 255, 255)),
Arguments.of("color: rgba", "%ff000080", Color.toDoubleBits(255, 0, 0, 128)),
Arguments.of("color: named", "%[red]", Colors.get("red").toDoubleBits())
);
}
@ParameterizedTest(name = "{0}")
@MethodSource("parseColorCases")
void parseColorValues(String name, String symbol, double expected){
LAssembler asm = new LAssembler();
LVar v = asm.var(symbol);
assertFalse(v.isobj);
assertEquals(expected, v.numval, 0.0);
}
/** Anything here must NOT be parsed as a number (i.e. it becomes a plain variable name). */
static Stream<String> invalidNumberCases(){
return Stream.of(
//fail-fast: first char can't start a number
"",
"abc",
"e10",
"NaN",
"Infinity",
//prefix with no digits
"0x", "0b", "+0x", "-0b",
//invalid digits
"0xG", "0x12G4", "0b2", "0b102", "0x-1", "0x1.5",
//overflow: more than 64 significant bits
"0x1" + "0".repeat(16), //17 hex digits
"-0x1" + "0".repeat(16),
"0x" + "F".repeat(17),
"0b1" + "0".repeat(64), //65 binary digits
"0b" + "1".repeat(65),
//malformed colors
"%fff",
"%[nosuchcolor]"
);
}
@ParameterizedTest(name = "invalid: [{0}]")
@MethodSource("invalidNumberCases")
void parseInvalidNumbers(String symbol){
LAssembler asm = new LAssembler();
LVar v = asm.var(symbol);
assertTrue(v.isobj, "should not parse as a number: " + symbol);
assertNull(v.objval);
}
//unterminated / malformed string literals: these must fail loudly, never silently misparse
@ParameterizedTest(name = "{0}")
@@ -336,4 +454,4 @@ public class LogicTests{
void crlfLabelsResolveToTheSameJumpLocationAsLfLabels(){
assertDoesNotThrow(() -> load("loop:\r\njump loop always\r\n"));
}
}
}
+14 -3
View File
@@ -95,7 +95,12 @@ public class SchemaGenerator{
var root = getTypeDecl(field.getDeclaringClass());
if(root != null) root.getFieldByName(field.getName()).ifPresent(fdec -> {
String[] docAndDefault = determineJavadocAndDefault(field, fdec, fdec.getVariables().getFirst().orElseThrow());
var variable = fdec.getVariables().stream()
.filter(v -> v.getNameAsString().equals(field.getName()))
.findFirst().orElse(null);
if(variable == null) return;
String[] docAndDefault = determineJavadocAndDefault(field, fdec, variable);
if(docAndDefault[0] != null) inner.put("doc", docAndDefault[0]);
if(docAndDefault[1] != null) inner.put("default", docAndDefault[1]);
});
@@ -302,8 +307,14 @@ public class SchemaGenerator{
initValue = "[]";
}
//field
if(initValue.contains(".") && !(baseField.getType().isArray())){
//numeric literal: drop the Java-only suffix (f/F/d/D/L), keep the decimal point for JSON
boolean numeric = initValue.matches("-?(\\d+\\.?\\d*|\\.\\d+)([eE][-+]?\\d+)?[fFdDlL]?");
if(numeric){
initValue = initValue.replaceAll("[fFdDlL]$", "");
}
//field reference, e.g. Category.turret -> turret (never applied to numbers)
if(!numeric && initValue.contains(".") && !(baseField.getType().isArray())){
var split = initValue.split("\\.");
initValue = split[split.length - 1];
}