Merge branch 'master' of https://github.com/Anuken/Mindustry into crafting-rework

This commit is contained in:
Anuken
2018-12-09 11:16:39 -05:00
111 changed files with 1847 additions and 1998 deletions

1
.gitignore vendored
View File

@@ -28,6 +28,7 @@ logs/
/ios/src/io/anuke/mindustry/gen/ /ios/src/io/anuke/mindustry/gen/
/core/src/io/anuke/mindustry/gen/ /core/src/io/anuke/mindustry/gen/
ios/robovm.properties ios/robovm.properties
config/
*.gif *.gif
version.properties version.properties

View File

@@ -20,7 +20,7 @@
<activity <activity
android:name="io.anuke.mindustry.AndroidLauncher" android:name="io.anuke.mindustry.AndroidLauncher"
android:label="@string/app_name" android:label="@string/app_name"
android:screenOrientation="sensor" android:screenOrientation="user"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout"> android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout">
<intent-filter> <intent-filter>

View File

@@ -8,12 +8,11 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.0' classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.0'
classpath "com.badlogicgames.gdx:gdx-tools:1.9.8" classpath "com.badlogicgames.gdx:gdx-tools:1.9.9"
} }
} }
allprojects { allprojects {
apply plugin: "eclipse"
apply plugin: "idea" apply plugin: "idea"
version = 'release' version = 'release'
@@ -21,11 +20,11 @@ allprojects {
ext { ext {
versionNumber = '4' versionNumber = '4'
versionModifier = 'alpha' versionModifier = 'alpha'
versionType = 'official' if (!project.hasProperty("versionType")) versionType = 'official'
appName = 'Mindustry' appName = 'Mindustry'
gdxVersion = '1.9.9' gdxVersion = '1.9.9'
roboVMVersion = '2.3.0' roboVMVersion = '2.3.0'
uCoreVersion = '7eb80a9765557d025d589f28fa1910dffa3fc8ed' uCoreVersion = '5871d2d0385370bc937fed3e5e301d6962a50476'
getVersionString = { getVersionString = {
String buildVersion = getBuildVersion() String buildVersion = getBuildVersion()
@@ -105,17 +104,19 @@ project(":ios") {
apply plugin: "robovm" apply plugin: "robovm"
task copyGen{ task copyGen{
copy{ doLast {
from ("core/build/classes/java/main/io/anuke/mindustry/gen/"){ copy {
include "**/*.java" from("../core/build/classes/java/main/io/anuke/mindustry/gen/") {
} include "**/*.java"
}
into "core/src/io/anuke/mindustry/gen" into "../core/src/io/anuke/mindustry/gen"
}
} }
doFirst{ doFirst{
delete{ delete{
delete "core/src/io/anuke/mindustry/gen/" delete "../core/src/io/anuke/mindustry/gen/"
} }
} }
} }
@@ -133,7 +134,7 @@ project(":ios") {
props['app.mainclass'] = 'io.anuke.mindustry.IOSLauncher' props['app.mainclass'] = 'io.anuke.mindustry.IOSLauncher'
props['app.executable'] = 'IOSLauncher' props['app.executable'] = 'IOSLauncher'
props['app.name'] = 'Mindustry' props['app.name'] = 'Mindustry'
props['app.build'] = (!props.hasProperty("app.build") ? 40 : props['app.build'].toInteger() + 1)+"" props['app.build'] = (!props.containsKey("app.build") ? 40 : props['app.build'].toInteger() + 1)+""
props.store(vfile.newWriter(), null) props.store(vfile.newWriter(), null)
} }
@@ -149,7 +150,7 @@ project(":ios") {
compile "com.badlogicgames.gdx:gdx-backend-robovm:$gdxVersion" compile "com.badlogicgames.gdx:gdx-backend-robovm:$gdxVersion"
compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-ios" compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-ios"
compile "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-ios" compile "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-ios"
compileOnly project(":annotations") //compileOnly project(":annotations")
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 277 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 B

View File

@@ -133,7 +133,7 @@ text.confirmunban = Are you sure you want to unban this player?
text.confirmadmin = Are you sure you want to make this player an admin? text.confirmadmin = Are you sure you want to make this player an admin?
text.confirmunadmin = Are you sure you want to remove admin status from this player? text.confirmunadmin = Are you sure you want to remove admin status from this player?
text.joingame.title = Join Game text.joingame.title = Join Game
text.joingame.ip = IP: text.joingame.ip = Address:
text.disconnect = Disconnected. text.disconnect = Disconnected.
text.disconnect.data = Failed to load world data! text.disconnect.data = Failed to load world data!
text.connecting = [accent]Connecting... text.connecting = [accent]Connecting...
@@ -409,14 +409,16 @@ keybind.chat_scroll.name = Chat scroll
keybind.drop_unit.name = drop unit keybind.drop_unit.name = drop unit
keybind.zoom_minimap.name = Zoom minimap keybind.zoom_minimap.name = Zoom minimap
mode.text.help.title = Description of modes mode.text.help.title = Description of modes
mode.waves.name = waves mode.waves.name = Waves
mode.waves.description = the normal mode. limited resources and automatic incoming waves. mode.waves.description = The normal mode. Limited resources and automatic incoming waves.
mode.sandbox.name = sandbox mode.sandbox.name = Sandbox
mode.sandbox.description = infinite resources and no timer for waves. mode.sandbox.description = Infinite resources and no timer for waves.
mode.freebuild.name = freebuild mode.freebuild.name = Freebuild
mode.freebuild.description = limited resources and no timer for waves. mode.freebuild.description = Limited resources and no timer for waves.
mode.pvp.name = PvP mode.pvp.name = PvP
mode.pvp.description = fight against other players locally. mode.pvp.description = Fight against other players locally.
mode.attack.name = Attack
mode.attack.descrption = No waves, with the goal to destroy the enemy base.
content.item.name = Items content.item.name = Items
content.liquid.name = Liquids content.liquid.name = Liquids
content.unit.name = Units content.unit.name = Units

View File

@@ -493,7 +493,7 @@ text.mech.ability = [LIGHT_GRAY]Hablidad: {0}
text.liquid.heatcapacity = [LIGHT_GRAY]Capacidad Térmica: {0} text.liquid.heatcapacity = [LIGHT_GRAY]Capacidad Térmica: {0}
text.liquid.viscosity = [LIGHT_GRAY]Viscosidad: {0} text.liquid.viscosity = [LIGHT_GRAY]Viscosidad: {0}
text.liquid.temperature = [LIGHT_GRAY]Temperatura: {0} text.liquid.temperature = [LIGHT_GRAY]Temperatura: {0}
block.constructing = {0}\n[LIGHT_GRAY](Constructing) block.constructing = {0}\n[LIGHT_GRAY](Construyendo)
block.spawn.name = Punto de generación block.spawn.name = Punto de generación
block.core.name = Núcleo block.core.name = Núcleo
block.metalfloor.name = Suelo de Metal block.metalfloor.name = Suelo de Metal

View File

@@ -349,6 +349,7 @@ text.category.items = Objets
text.category.crafting = Fabrication text.category.crafting = Fabrication
text.category.shooting = Défense text.category.shooting = Défense
text.category.optional = Améliorations facultatives text.category.optional = Améliorations facultatives
setting.indicators.name = Indicateurs d'alliés
setting.autotarget.name = Visée automatique setting.autotarget.name = Visée automatique
setting.fpscap.name = Max FPS setting.fpscap.name = Max FPS
setting.fpscap.none = Vide setting.fpscap.none = Vide
@@ -437,9 +438,9 @@ item.silicon.description = Un matériau semi-conducteur extrêmement utile, avec
item.plastanium.name = Plastanium item.plastanium.name = Plastanium
item.plastanium.description = Un matériau léger et docile utilisé dans l'aviation avancée et dans les munitions à fragmentation. item.plastanium.description = Un matériau léger et docile utilisé dans l'aviation avancée et dans les munitions à fragmentation.
item.phase-fabric.name = Phase Fabric item.phase-fabric.name = Phase Fabric
item.phase-fabric.description = A near-weightless substance used in advanced electronics and self-repairing technology. item.phase-fabric.description = Une substance presque en apesanteur utilisée dans l'électronique de pointe et la technologie autoréparable.
item.surge-alloy.name = Alliage superchargé item.surge-alloy.name = Alliage superchargé
item.surge-alloy.description = An advanced alloy with unique electrical properties. item.surge-alloy.description = Un alliage avancé aux propriétés électriques uniques.
item.biomatter.name = Biomasse item.biomatter.name = Biomasse
item.biomatter.description = Un mélange de matières organiques; utilisé pour la transformation en pétrole ou en tant que carburant de base. item.biomatter.description = Un mélange de matières organiques; utilisé pour la transformation en pétrole ou en tant que carburant de base.
item.sand.name = Sable item.sand.name = Sable
@@ -463,7 +464,7 @@ mech.delta-mech.description = Un mécha rapide avec une armure légère fait pou
mech.tau-mech.name = Tau mech.tau-mech.name = Tau
mech.tau-mech.weapon = Laser restructurant mech.tau-mech.weapon = Laser restructurant
mech.tau-mech.ability = Explosion réparante mech.tau-mech.ability = Explosion réparante
mech.tau-mech.description = Un mécha de support. Soigne les blocs alliés en tirant dessus. Il peut aussi éteindre les feux et soigner ses alliés en zone avec sa compétence. mech.tau-mech.description = Le support technique. Soigne les blocs alliés en leur tirant dessus. Peut soigner les alliés dans un rayon grâce à sa capacité de réparation.
mech.omega-mech.name = Omega mech.omega-mech.name = Omega
mech.omega-mech.weapon = Essaim de missiles auto-guidés mech.omega-mech.weapon = Essaim de missiles auto-guidés
mech.omega-mech.ability = Armure mech.omega-mech.ability = Armure

View File

@@ -2,15 +2,15 @@ text.credits.text = Created by [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[]\n\n[
text.credits = Creditos text.credits = Creditos
text.discord = Junte-se ao Discord do Mindustry! (Lá nós falamos em inglês) text.discord = Junte-se ao Discord do Mindustry! (Lá nós falamos em inglês)
text.link.discord.description = O discord oficial do Mindustry text.link.discord.description = O discord oficial do Mindustry
text.link.github.description = Game source code text.link.github.description = Codigo fonte do jogo.
text.link.dev-builds.description = Desenvolvimentos Instaveis text.link.dev-builds.description = Desenvolvimentos Instaveis
text.link.trello.description = Trello Oficial para Updates Planejados text.link.trello.description = Trello Oficial para Updates Planejados
text.link.itch.io.description = Pagina da Itch.io com os Downloads text.link.itch.io.description = Pagina da Itch.io com os Downloads
text.link.google-play.description = Google Play store listing text.link.google-play.description = Listamento do google play store
text.link.wiki.description = Wiki oficial do Mindustry text.link.wiki.description = Wiki oficial do Mindustry
text.linkfail = Falha ao abrir o link\nO Url foi copiado text.linkfail = Falha ao abrir o link\nO Url foi copiado
text.gameover = O núcleo foi destruído. text.gameover = O núcleo foi destruído.
text.gameover.pvp = The[accent] {0}[] team is victorious! text.gameover.pvp = O time[accent] {0}[] É vitorioso!
text.sector.gameover = Esse setor foi perdido! Soltar Novamente? text.sector.gameover = Esse setor foi perdido! Soltar Novamente?
text.sector.retry = Tentar novamente? text.sector.retry = Tentar novamente?
text.highscore = [YELLOW]Novo recorde! text.highscore = [YELLOW]Novo recorde!
@@ -20,11 +20,11 @@ text.level.delete.title = Confirmar exclusão
text.map.delete = Certeza que quer deletar o mapa "[accent]{0}[]"? text.map.delete = Certeza que quer deletar o mapa "[accent]{0}[]"?
text.level.select = Seleção de Fase text.level.select = Seleção de Fase
text.level.mode = Modo de Jogo: text.level.mode = Modo de Jogo:
text.construction.desktop = Desktop controls have been changed.\nTo deselect a block or stop building, [accent]use space[]. text.construction.desktop = Os controles do Desktop foram Mudados.\nPara descelecionar um bloco ou parar de construir, [accent]Use espaço.[].
text.construction.title = Guia de contrução de blocos text.construction.title = Guia de contrução de blocos
text.construction = You've just selected [accent]block construction mode[].\n\nTo begin placing, simply tap a valid location near your ship.\nOnce you have selected some blocks, press the checkbox to confirm, and your ship will begin constructing them.\n\n- [accent]Remove blocks[] from your selection by tapping them.\n- [accent]Shift the selection[] by holding and dragging any block in the selection.\n- [accent]Place blocks in a line[] by tapping and holding an empty spot, then dragging in a direction.\n- [accent]Cancel construction or selection[] by pressing the X at the bottom left. text.construction =Você selecionou [accent]Modo de construção de blocos[].\n\nPara começar a colocar, Simplesmente clique um lugar valido perto de sua nave.\nUma vez que você selecionou alguns blocos, Clique na caixa para confirmar, E sua nave vai começar a construi-los.\n\n- [accent]Remova blocos[] De sua seleção clicando neles.\n- [accent]Mude a seleção[] Segurando e arrastando qualquer bloco na seleção.\n- [accent]Coloque os blocos em linha[] Clicando e segurando em um lugar vazio e arrastando em uma direção.\n- [accent]Cancele a construção ou seleção[] Pressionando X no canto esquerdo.
text.deconstruction.title = Block Deconstruction Guide text.deconstruction.title = Block Deconstruction Guide
text.deconstruction = You've just selected [accent]block deconstruction mode[].\n\nTo begin breaking, simply tap a block near your ship.\nOnce you have selected some blocks, press the checkbox to confirm, and your ship will begin de-constructing them.\n\n- [accent]Remove blocks[] from your selection by tapping them.\n- [accent]Remove blocks in an area[] by tapping and holding an empty spot, then dragging in a direction.\n- [accent]Cancel deconstruction or selection[] by pressing the X at the bottom left. text.deconstruction = Você selecionou [accent]O modo de destruição de blocos[].\n\nPara Começar a quebrar, Simplesmente clique num bloco perto da nave.\nQuando tiver selecionados alguns blocos, Aperte a caixa para confirmar, E sua nave vai começar a construir.\n\n- [accent]Remova blocos[] De sua seleção clicando neles.\n- [accent]Remova blocos em uma area[] Clicando e Apertando um lugar vazio então arraste numa direção.\n- [accent]Cancele a construção ou Seleção[] Apertando X no canto Esquerdo.
text.showagain = Não mostrar na proxima sessão text.showagain = Não mostrar na proxima sessão
text.coreattack = < A base está sobre ataque! > text.coreattack = < A base está sobre ataque! >
text.unlocks = Desbloqueados text.unlocks = Desbloqueados
@@ -37,31 +37,31 @@ text.sectors = Setores
text.sector = Setor Selecionado: [LIGHT_GRAY]{0} text.sector = Setor Selecionado: [LIGHT_GRAY]{0}
text.sector.time = Tempo: [LIGHT_GRAY]{0} text.sector.time = Tempo: [LIGHT_GRAY]{0}
text.sector.deploy = Soltar text.sector.deploy = Soltar
text.sector.abandon = Abandon text.sector.abandon = Abandonar
text.sector.abandon.confirm = Are you sure you want to abandon all progress at this sector?\nThis cannot be undone! text.sector.abandon.confirm = Certeza que quer abandonar seu progresso nesse setor?\nThis cannot be undone!
text.sector.resume = Voltar text.sector.resume = Voltar
text.sector.locked = [scarlet][[Incomplete] text.sector.locked = [scarlet][[Não liberado]
text.sector.unexplored = [accent][[Unexplored] text.sector.unexplored = [accent][[Inexplorado]
text.missions = Missions:[LIGHT_GRAY] {0} text.missions = Missões:[LIGHT_GRAY] {0}
text.mission = Missão:[LIGHT_GRAY] {0} text.mission = Missão:[LIGHT_GRAY] {0}
text.mission.main = Main Mission:[LIGHT_GRAY] {0} text.mission.main = Missão principal:[LIGHT_GRAY] {0}
text.mission.info = Mission Info text.mission.info = Info da missão
text.mission.complete = Mission complete! text.mission.complete = Missão completa!
text.mission.complete.body = Sector {0},{1} has been conquered. text.mission.complete.body = Setor {0},{1} Foi conquistado.
text.mission.wave = Sobrevive [accent]{0}/{1}[] Onda\nOnda em {2} text.mission.wave = Sobrevive [accent]{0}/{1}[] Onda\nOnda em {2}
text.mission.wave.enemies = Survive[accent] {0}/{1} []waves\n{2} Enemies text.mission.wave.enemies = Sobreviva[accent] {0}/{1} []ondas\n{2} inimigos
text.mission.wave.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy text.mission.wave.enemy = Sobreviva[accent] {0}/{1} []Ondas\n{2} Inimigos
text.mission.wave.menu = Survive[accent] {0} []waves text.mission.wave.menu = Sobreviva[accent] {0} []Ondas
text.mission.battle = Destrua a base inimiga. text.mission.battle = Destrua a base inimiga.
text.mission.resource.menu = Obtain {0} x{1} text.mission.resource.menu = Obtenha {0} x{1}
text.mission.resource = Obtain {0}:\n[accent]{1}/{2}[] text.mission.resource = Obtenha {0}:\n[accent]{1}/{2}[]
text.mission.block = Create {0} text.mission.block = Criar {0}
text.mission.unit = Create {0} Unit text.mission.unit = Criar {0} Unidade
text.mission.command = Send Command {0} To Units text.mission.command = Enviar comando {0} As unidades
text.mission.linknode = Link Power Node text.mission.linknode = Ligar nodo de energia
text.mission.display = [accent]Mission:\n[LIGHT_GRAY]{0} text.mission.display = [accent]Missão:\n[LIGHT_GRAY]{0}
text.mission.mech = Switch to mech[accent] {0}[] text.mission.mech = Trocar para Meca[accent] {0}[]
text.mission.create = Create[accent] {0}[] text.mission.create = Criar[accent] {0}[]
text.none = <none> text.none = <none>
text.close = Fechar text.close = Fechar
text.quit = Sair text.quit = Sair
@@ -71,16 +71,16 @@ text.nextmission = Próxima Missão
text.maps.none = [LIGHT_GRAY]Nenhum Mapa Encontrado! text.maps.none = [LIGHT_GRAY]Nenhum Mapa Encontrado!
text.about.button = Sobre text.about.button = Sobre
text.name = Nome: text.name = Nome:
text.filename = File Name: text.filename = Nome do arquivo:
text.unlocked = Novo bloco Desbloqueado! text.unlocked = Novo bloco Desbloqueado!
text.unlocked.plural = Novos Blocos desbloqueados! text.unlocked.plural = Novos Blocos desbloqueados!
text.players = {0} Jogadores Ativos text.players = {0} Jogadores Ativos
text.players.single = {0} Jogador Ativo text.players.single = {0} Jogador Ativo
text.server.closing = [accent]Fechando servidor... text.server.closing = [accent]Fechando servidor...
text.server.kicked.kick = Voce foi expulso do servidor! text.server.kicked.kick = Voce foi expulso do servidor!
text.server.kicked.serverClose = Server closed. text.server.kicked.serverClose = Servidor Fechado.
text.server.kicked.sectorComplete = Sector completed. text.server.kicked.sectorComplete = Setor completo.
text.server.kicked.sectorComplete.text = Your mission is complete.\nThe server will now continue at the next sector. text.server.kicked.sectorComplete.text = Sua missão esta completa.\nO servidor vai continuar no proximo setor.
text.server.kicked.clientOutdated = Cliente desatualizado! Atualize seu jogo! text.server.kicked.clientOutdated = Cliente desatualizado! Atualize seu jogo!
text.server.kicked.serverOutdated = Servidor desatualiado! Peca ao dono para atualizar! text.server.kicked.serverOutdated = Servidor desatualiado! Peca ao dono para atualizar!
text.server.kicked.banned = Voce foi banido do servidor. text.server.kicked.banned = Voce foi banido do servidor.
@@ -90,9 +90,9 @@ text.server.kicked.nameEmpty = Voce deve ter pelo menos uma letra ou numero.
text.server.kicked.idInUse = Voce ja esta neste servidor! Conectar com duas contas não é permitido. text.server.kicked.idInUse = Voce ja esta neste servidor! Conectar com duas contas não é permitido.
text.server.kicked.customClient = Este servidor não suporta construções customizadas. Baixe a versão original. text.server.kicked.customClient = Este servidor não suporta construções customizadas. Baixe a versão original.
text.host.info = The [accent]Hospedar[]Botão Hopeda um servidor no Host[scarlet]6567[] e [scarlet]6568.[]\nQualquer um no [LIGHT_GRAY]Wi-fi Ou Internet local[] Pode ver este servidor na lista de servidores.\n\nSe voce quer poder entrar em qualquer servidor em seu ip, [accent]port forwarding[] é requerido.\n\n[LIGHT_GRAY]Note: Se alguem esta com problemas em conectar no seu servidor lan, Tenha certeza que deixou mindustry Acessar sua internet local nas configurações de firewall text.host.info = The [accent]Hospedar[]Botão Hopeda um servidor no Host[scarlet]6567[] e [scarlet]6568.[]\nQualquer um no [LIGHT_GRAY]Wi-fi Ou Internet local[] Pode ver este servidor na lista de servidores.\n\nSe voce quer poder entrar em qualquer servidor em seu ip, [accent]port forwarding[] é requerido.\n\n[LIGHT_GRAY]Note: Se alguem esta com problemas em conectar no seu servidor lan, Tenha certeza que deixou mindustry Acessar sua internet local nas configurações de firewall
text.join.info = Here, you can enter a [accent]server IP[] to connect to, or discover [accent]local network[] servers to connect to.\nBoth LAN and WAN multiplayer is supported.\n\n[LIGHT_GRAY]Note: There is no automatic global server list; if you want to connect to someone by IP, you would need to ask the host for their IP. text.join.info = Aqui, Você pode entar em um [accent]IP De servidor[] Para conectar, Ou descobrir [accent]Servidores[] Da rede local.\nAmbos os servidores LAN e WAN São suportados.\n\n[LIGHT_GRAY]Note: Não tem uma lista de servidores automaticos; Se você quer conectar ao IP de alguem, Você precisa pedir o IP Ao Rosteador.
text.hostserver = Hospedar servidor text.hostserver = Hospedar servidor
text.hostserver.mobile = Host\nGame text.hostserver.mobile = Hospedar\nJogo
text.host = Hospedar text.host = Hospedar
text.hosting = [accent]Abrindo server... text.hosting = [accent]Abrindo server...
text.hosts.refresh = atualizar text.hosts.refresh = atualizar
@@ -103,7 +103,7 @@ text.host.invalid = [scarlet]Não foi possivel Hospedar.
text.trace = Traçar jogador text.trace = Traçar jogador
text.trace.playername = Nome do jogador: [accent]{0} text.trace.playername = Nome do jogador: [accent]{0}
text.trace.ip = IP: [accent]{0} text.trace.ip = IP: [accent]{0}
text.trace.id = Unique ID: [accent]{0} text.trace.id = ID unico: [accent]{0}
text.trace.android = Cliente Androide: [accent]{0} text.trace.android = Cliente Androide: [accent]{0}
text.trace.modclient = Cliente Customizado: [accent]{0} text.trace.modclient = Cliente Customizado: [accent]{0}
text.trace.totalblocksbroken = Blocos totais quebrados: [accent]{0} text.trace.totalblocksbroken = Blocos totais quebrados: [accent]{0}
@@ -125,7 +125,7 @@ text.server.outdated.client = [crimson]Cliente desatualizado![]
text.server.version = [lightgray]Versão: {0} text.server.version = [lightgray]Versão: {0}
text.server.custombuild = [yellow]Construção customizada text.server.custombuild = [yellow]Construção customizada
text.confirmban = Certeza que quer banir este jogador? text.confirmban = Certeza que quer banir este jogador?
text.confirmkick = Are you sure you want to kick this player? text.confirmkick = Certeza que quer kickar o jogador?
text.confirmunban = Certeza que quer desbanir este jogador? text.confirmunban = Certeza que quer desbanir este jogador?
text.confirmadmin = Certeza que quer fazer este jogador um administrador? text.confirmadmin = Certeza que quer fazer este jogador um administrador?
text.confirmunadmin = Certeza que quer remover o estatus de adminstrador deste jogador? text.confirmunadmin = Certeza que quer remover o estatus de adminstrador deste jogador?
@@ -201,9 +201,9 @@ text.builtin = Built-In
text.map.delete.confirm = Certeza que quer deletar este mapa? Isto não pode ser desfeito! text.map.delete.confirm = Certeza que quer deletar este mapa? Isto não pode ser desfeito!
text.map.random = [accent]Mapa aleatório text.map.random = [accent]Mapa aleatório
text.map.nospawn = Esse mapa não contém um [yellow]core[] para o jogador Nascer! [ROYAL]blue[] Coloque um [yellow]core[] no editor de mapa. text.map.nospawn = Esse mapa não contém um [yellow]core[] para o jogador Nascer! [ROYAL]blue[] Coloque um [yellow]core[] no editor de mapa.
text.map.nospawn.pvp = This map does not have any enemy cores for player to spawn into! Add[SCARLET] red[] cores to this map in the editor. text.map.nospawn.pvp = Esse mapa não tem cores inimigos para os jogadores nascerem! Adicione[SCARLET] Cores vermelhos[] no mapa no editor.
text.map.invalid = Error loading map: corrupted or invalid map file. text.map.invalid = Erro ao carregar o mapa: Arquivo de mapa invalido ou corrupto.
text.editor.brush = Brush text.editor.brush = Pincel
text.editor.slope = \\ text.editor.slope = \\
text.editor.openin = Abrir no Editor text.editor.openin = Abrir no Editor
text.editor.oregen = Geração de minério text.editor.oregen = Geração de minério
@@ -260,13 +260,13 @@ text.editor = Editor
text.mapeditor = Editor de mapa text.mapeditor = Editor de mapa
text.donate = Doar text.donate = Doar
text.connectfail = [crimson]Falha ao entrar no servidor: [accent]{0} text.connectfail = [crimson]Falha ao entrar no servidor: [accent]{0}
text.error.unreachable = Server unreachable. text.error.unreachable = Servidor inalcançavel.
text.error.invalidaddress = Invalid address. text.error.invalidaddress = Endereço invalido.
text.error.timedout = Timed out!\nMake sure the host has port forwarding set up, and that the address is correct! text.error.timedout = Desconectado!\nTenha certeza que o Rosteador tenha feito Port forwading, E que o indereço esteja correto!
text.error.mismatch = Packet error:\npossible client/server version mismatch.\nMake sure you and the host have the latest version of Mindustry! text.error.mismatch = Erro de pacote:\nPossivel versão do cliente/Servidor incompatibilidade.\nTenha certeza que você e o host tenham a ultima versão!
text.error.alreadyconnected = Already connected. text.error.alreadyconnected = conectado.
text.error.mapnotfound = Map file not found! text.error.mapnotfound = Arquivo de mapa não encontrado!
text.error.any = Unkown network error. text.error.any = Erro de rede desconhecido.
text.settings.language = Linguagem text.settings.language = Linguagem
text.settings.reset = Restaurar Padrões text.settings.reset = Restaurar Padrões
text.settings.rebind = Religar text.settings.rebind = Religar
@@ -274,12 +274,12 @@ text.settings.controls = Controles
text.settings.game = Jogo text.settings.game = Jogo
text.settings.sound = Som text.settings.sound = Som
text.settings.graphics = Gráficos text.settings.graphics = Gráficos
text.settings.cleardata = Clear Game Data... text.settings.cleardata = Data do jogo limpa...
text.settings.clear.confirm = Are you sure you want to clear this data?\nWhat is done cannot be undone! text.settings.clear.confirm = Certeza que quer limpar a data?\nOque é feito não pode ser desfeito!
text.settings.clearall.confirm = [scarlet]WARNING![]\nThis will clear all data, including saves, maps, unlocks and keybinds.\nOnce you press 'ok' the game will wipe all data and automatically exit. text.settings.clearall.confirm = [scarlet]Aviso![]\nIsso vai limpar toda a data, Incluindo saves, mapas, Keybinds e desbloqueados.\nQuando apertar 'ok' Vai apagar toda a data e sair automaticamente.
text.settings.clearsectors = Clear Sectors text.settings.clearsectors = Limpar setores
text.settings.clearunlocks = Clear Unlocks text.settings.clearunlocks = Limpar liberados
text.settings.clearall = Clear All text.settings.clearall = Limpar tudo
text.paused = Pausado text.paused = Pausado
text.yes = Sim text.yes = Sim
text.no = Não text.no = Não
@@ -298,11 +298,11 @@ text.blocks.liquidcapacity = Capacidade de Líquido
text.blocks.maxitemssecond = Máximo de itens/segundo text.blocks.maxitemssecond = Máximo de itens/segundo
text.blocks.powerrange = Alcance da Energia text.blocks.powerrange = Alcance da Energia
text.blocks.poweruse = Uso de energia text.blocks.poweruse = Uso de energia
text.blocks.powerdamage = Power/Damage text.blocks.powerdamage = Dano/Poder
text.blocks.inputitemcapacity = Configurar capacidade de itens text.blocks.inputitemcapacity = Configurar capacidade de itens
text.blocks.outputitemcapacity = Configurar capacidade de itens text.blocks.outputitemcapacity = Configurar capacidade de itens
text.blocks.itemcapacity = Capacidade de Itens text.blocks.itemcapacity = Capacidade de Itens
text.blocks.basepowergeneration = Base Power Generation text.blocks.basepowergeneration = Geração de poder base
text.blocks.powertransferspeed = Transferência de energia text.blocks.powertransferspeed = Transferência de energia
text.blocks.craftspeed = Velocidade de produção text.blocks.craftspeed = Velocidade de produção
text.blocks.inputliquid = Líquido de entrada text.blocks.inputliquid = Líquido de entrada
@@ -313,14 +313,14 @@ text.blocks.outputitem = Itens de saida
text.blocks.drilltier = Furaveis text.blocks.drilltier = Furaveis
text.blocks.drillspeed = Velocidade da furadeira base text.blocks.drillspeed = Velocidade da furadeira base
text.blocks.liquidoutput = Saida de liquido text.blocks.liquidoutput = Saida de liquido
text.blocks.liquidoutputspeed = Liquid Output Speed text.blocks.liquidoutputspeed = Velocidade da saida de líquido
text.blocks.liquiduse = Uso de liquido text.blocks.liquiduse = Uso de liquido
text.blocks.coolant = Esfriador text.blocks.coolant = Esfriador
text.blocks.coolantuse = Uso do esfriador text.blocks.coolantuse = Uso do esfriador
text.blocks.inputliquidfuel = Liquido de combustivel text.blocks.inputliquidfuel = Liquido de combustivel
text.blocks.liquidfueluse = Uso do liquido de combustivel text.blocks.liquidfueluse = Uso do liquido de combustivel
text.blocks.boostitem = Boost Item text.blocks.boostitem = Acelerar item
text.blocks.boostliquid = Boost Liquid text.blocks.boostliquid = Acelerar líquido
text.blocks.health = Saúde text.blocks.health = Saúde
text.blocks.inaccuracy = Imprecisão text.blocks.inaccuracy = Imprecisão
text.blocks.shots = Tiros text.blocks.shots = Tiros
@@ -345,12 +345,12 @@ text.category.liquids = Liquidos
text.category.items = Itens text.category.items = Itens
text.category.crafting = Construindo text.category.crafting = Construindo
text.category.shooting = Atirando text.category.shooting = Atirando
text.category.optional = Optional Enhancements text.category.optional = Melhoras opcionais
setting.autotarget.name = Auto-Target setting.autotarget.name = Alvo automatico
setting.fpscap.name = FPS Maximo setting.fpscap.name = FPS Maximo
setting.fpscap.none = Nenhum setting.fpscap.none = Nenhum
setting.fpscap.text = {0} FPS setting.fpscap.text = {0} FPS
setting.difficulty.training = training setting.difficulty.training = treinamento
setting.difficulty.easy = Fácil setting.difficulty.easy = Fácil
setting.difficulty.normal = Normal setting.difficulty.normal = Normal
setting.difficulty.hard = Difícil setting.difficulty.hard = Difícil
@@ -370,21 +370,21 @@ setting.musicvol.name = Volume da Música
setting.mutemusic.name = Desligar Música setting.mutemusic.name = Desligar Música
setting.sfxvol.name = Volume de Efeitos setting.sfxvol.name = Volume de Efeitos
setting.mutesound.name = Desligar Som setting.mutesound.name = Desligar Som
setting.crashreport.name = Send Anonymous Crash Reports setting.crashreport.name = Enviar denuncias de crash anonimas
text.keybind.title = Refazer teclas text.keybind.title = Refazer teclas
category.general.name = General category.general.name = Geral
category.view.name = View category.view.name = Ver
category.multiplayer.name = Multiplayer category.multiplayer.name = Multijogador
command.attack = Attack command.attack = Atacar
command.retreat = Retreat command.retreat = Recuar
command.patrol = Patrol command.patrol = Patrulha
keybind.press = Press a key... keybind.press = Pressione uma tecla...
keybind.press.axis = Press an axis or key... keybind.press.axis = Pressione uma Axis ou tecla...
keybind.move_x.name = move_x keybind.move_x.name = mover_x
keybind.move_y.name = move_y keybind.move_y.name = mover_y
keybind.select.name = selecionar keybind.select.name = selecionar
keybind.break.name = quebrar keybind.break.name = quebrar
keybind.deselect.name = Deselect keybind.deselect.name = Deselecionar
keybind.shoot.name = Atirar keybind.shoot.name = Atirar
keybind.zoom_hold.name = segurar_zoom keybind.zoom_hold.name = segurar_zoom
keybind.zoom.name = zoom keybind.zoom.name = zoom
@@ -396,49 +396,49 @@ keybind.player_list.name = Lista_de_jogadores
keybind.console.name = console keybind.console.name = console
keybind.rotate.name = girar keybind.rotate.name = girar
keybind.toggle_menus.name = Toggle menus keybind.toggle_menus.name = Toggle menus
keybind.chat_history_prev.name = Chat history prev keybind.chat_history_prev.name = Historico do chat anterior
keybind.chat_history_next.name = Chat history next keybind.chat_history_next.name = Historico do proximo chat
keybind.chat_scroll.name = Chat scroll keybind.chat_scroll.name = Rolar chat
keybind.drop_unit.name = drop unit keybind.drop_unit.name = Soltar unidade
keybind.zoom_minimap.name = Zoom minimap keybind.zoom_minimap.name = Zoom minimap
mode.text.help.title = Descrição dos modos mode.text.help.title = Descrição dos modos
mode.waves.name = hordas mode.waves.name = hordas
mode.waves.description = O modo normal. Recursos limitados E os ataques vem automaticamente. mode.waves.description = O modo normal. Recursos limitados E os ataques vem automaticamente.
mode.sandbox.name = sandbox mode.sandbox.name = Caixa de areia
mode.sandbox.description = Recursos infinitos E sem tempo para Ataques. mode.sandbox.description = Recursos infinitos E sem tempo para Ataques.
mode.freebuild.name = construção \nlivre mode.freebuild.name = construção \nlivre
mode.freebuild.description = recursos limitados e Sem tempo para Ataques. mode.freebuild.description = recursos limitados e Sem tempo para Ataques.
mode.pvp.name = PvP mode.pvp.name = PvP
mode.pvp.description = fight against other players locally. mode.pvp.description = Lutar contra outros jogadores locais.
content.item.name = Itens content.item.name = Itens
content.liquid.name = Liquidos content.liquid.name = Liquidos
content.unit.name = Units content.unit.name = Units
content.recipe.name = Blocos content.recipe.name = Blocos
content.mech.name = Mechs content.mech.name = Mecas
item.stone.name = Pedra item.stone.name = Pedra
item.stone.description = Um Material Incomum Cru. Usado para separar e refinar Em outros materiais,Ou Derreter em Lava. item.stone.description = Um Material Incomum Cru. Usado para separar e refinar Em outros materiais,Ou Derreter em Lava.
item.copper.name = Cobre item.copper.name = Cobre
item.copper.description = A useful structure material. Used extensively in all types of blocks. item.copper.description = Um material de estrutura util. Usado extensivamente em Maioria dos blocos.
item.lead.name = Chumbo item.lead.name = Chumbo
item.lead.description = Material de comeco basico. usado intensivamente em Blocos de transporte de liquidos e eletronicos. item.lead.description = Material de comeco basico. usado intensivamente em Blocos de transporte de liquidos e eletronicos.
item.coal.name = Carvão item.coal.name = Carvão
item.coal.description = Combustivel pronto. item.coal.description = Combustivel pronto.
item.dense-alloy.name = Dense Alloy item.dense-alloy.name = Liga densa
item.dense-alloy.description = A tough alloy made with lead and copper. Used in advanced transportation blocks and high-tier drills. item.dense-alloy.description = Uma liga densa de chumbo e cobre. Usado na transportação de blocos e mineradoras de alto nivel.
item.titanium.name = Titânio item.titanium.name = Titânio
item.titanium.description = Um Material raro super leve, metal usado intensivamente na transportação de líquidos, Brocas e Aeronaves. item.titanium.description = Um Material raro super leve, metal usado intensivamente na transportação de líquidos, Brocas e Aeronaves.
item.thorium.name = Urânio item.thorium.name = Urânio
item.thorium.description = A dense, radioactive metal used as structural support and nuclear fuel. item.thorium.description = Um metal denso e radioativo, Usado como suporte material e combustivel nuclear.
item.silicon.name = Sílicio item.silicon.name = Sílicio
item.silicon.description = Condutor extremamente importante,Com aplicação em paneis solares e dispositivos complexos. item.silicon.description = Condutor extremamente importante,Com aplicação em paneis solares e dispositivos complexos.
item.plastanium.name = Plastanio item.plastanium.name = Plastanio
item.plastanium.description = Leve, Material dutil Usado em aeronaves Avançadas E munição de fragmentação. item.plastanium.description = Leve, Material dutil Usado em aeronaves Avançadas E munição de fragmentação.
item.phase-fabric.name = Phase Fabric item.phase-fabric.name = Fabrica fase
item.phase-fabric.description = A near-weightless substance used in advanced electronics and self-repairing technology. item.phase-fabric.description = Uma substancia quase sem peso Usado em eletronica avançada E tecnologia de auto-reparo.
item.surge-alloy.name = Liga de surto item.surge-alloy.name = Liga de surto
item.surge-alloy.description = An advanced alloy with unique electrical properties. item.surge-alloy.description = Uma liga com propriedades unicas eletricas.
item.biomatter.name = Biomateria item.biomatter.name = Biomateria
item.biomatter.description = A clump of organic mush; used for conversion into oil or as a basic fuel. item.biomatter.description = Um monte de materia organica; Usado na conversão de oleo Ou como oleo basico.
item.sand.name = Areia item.sand.name = Areia
item.sand.description = Um material comum Que é usado intensivamente em derretimento, Tanto em ligas como fluxo. item.sand.description = Um material comum Que é usado intensivamente em derretimento, Tanto em ligas como fluxo.
item.blast-compound.name = Composto de explosão item.blast-compound.name = Composto de explosão
@@ -449,54 +449,54 @@ liquid.water.name = Água
liquid.lava.name = Lava liquid.lava.name = Lava
liquid.oil.name = Petróleo liquid.oil.name = Petróleo
liquid.cryofluid.name = Crio Fluido liquid.cryofluid.name = Crio Fluido
mech.alpha-mech.name = Alpha mech.alpha-mech.name = Alfa
mech.alpha-mech.weapon = Heavy Repeater mech.alpha-mech.weapon = Repetidor pesado
mech.alpha-mech.ability = Drone Swarm mech.alpha-mech.ability = Onda de drones
mech.alpha-mech.description = The standard mech. Has decent speed and damage output; can create up to 3 drones for increased offensive capability. mech.alpha-mech.description = O meca padrão. Tem uma saida de dano e velocidade decente; Pode criar até 3 drones Para capacidades ofensivas aumentadas.
mech.delta-mech.name = Delta mech.delta-mech.name = Delta
mech.delta-mech.weapon = Arc Generator mech.delta-mech.weapon = Gerador Arc
mech.delta-mech.ability = Discharge mech.delta-mech.ability = Descarga
mech.delta-mech.description = A fast, lightly-armored mech made for hit-and-run attacks. Does little damage against structures, but can kill large groups of enemy units very quickly with its arc lightning weapons. mech.delta-mech.description = Um meca rapido, De baixa armadura Feito for para ataques rapidos. Da pouco dano as estruturas, Mas pode matar grandes grupos de unidades inimigas muito rapidamente Com sua arma ARC.
mech.tau-mech.name = Tau mech.tau-mech.name = Tau
mech.tau-mech.weapon = Restruct Laser mech.tau-mech.weapon = Laser restruturador
mech.tau-mech.ability = Repair Burst mech.tau-mech.ability = Tiro reparador
mech.tau-mech.description = The support mech. Heals allied blocks by shooting at them. Can extinguish fires and heal allies in a radius with its repair ability. mech.tau-mech.description = O meca de suporte. Conserta blocos aliados Atirando neles. Pode extinguir o fogo e consertar aliados em uma distancia Com sua habilidade de consertar.
mech.omega-mech.name = Omega mech.omega-mech.name = Omega
mech.omega-mech.weapon = Swarm Missiles mech.omega-mech.weapon = Onda de missies
mech.omega-mech.ability = Armored Configuration mech.omega-mech.ability = Configuração Armadurada
mech.omega-mech.description = A bulky and well-armored mech, made for front-line assaults. Its armor ability can block up to 90% of incoming damage. mech.omega-mech.description = Um meca volumoso e bem armadurado, Feito para assaltos da primeira linha. Sua habilidade de armadura Pode bloquear 90% de dano.
mech.dart-ship.name = Dart mech.dart-ship.name = Dardo
mech.dart-ship.weapon = Repeater mech.dart-ship.weapon = Repetidor
mech.dart-ship.description = The standard ship. Reasonably fast and light, but has little offensive capability and low mining speed. mech.dart-ship.description = Nave padrão. Consideravelmente leve e rapido, Tem pouca capacidade ofensiva E baixa velocidade de mineração.
mech.javelin-ship.name = Javelin mech.javelin-ship.name = Javelin
mech.javelin-ship.description = A hit-and-run strike ship. While initially slow, it can accelerate to great speeds and fly by enemy outposts, dealing large amounts of damage with its lightning ability and missiles. mech.javelin-ship.description = Uma nave de espinhos de atacar e correr. Quando inicialmente lento, pode acelerar a altas velocidades e voar até bases inimigas, Dando altas quantidades de dano Com seus raios e habilidades.
mech.javelin-ship.weapon = Burst Missiles mech.javelin-ship.weapon = Ondas de misseis
mech.javelin-ship.ability = Discharge Booster mech.javelin-ship.ability = Acelerador de explosão
mech.trident-ship.name = Trident mech.trident-ship.name = Tridente
mech.trident-ship.description = A heavy bomber. Reasonably well armored. mech.trident-ship.description = Um bombardeiro pesado. Consideravelmente bem armadurado.
mech.trident-ship.weapon = Bomb Bay mech.trident-ship.weapon = Carga de bombas
mech.glaive-ship.name = Glaive mech.glaive-ship.name = Glaive
mech.glaive-ship.description = A large, well-armored gunship. Equipped with an incendiary repeater. Good acceleration and maximum speed. mech.glaive-ship.description = Uma nave armada, bem armadurada. Com um repetidor incendario equipado. Boa aceleração e maxima velocidade.
mech.glaive-ship.weapon = Flame Repeater mech.glaive-ship.weapon = Repetidor de fogo
text.item.explosiveness = [LIGHT_GRAY]Explosividade: {0} text.item.explosiveness = [LIGHT_GRAY]Explosividade: {0}
text.item.flammability = [LIGHT_GRAY]Inflamabilidade: {0} text.item.flammability = [LIGHT_GRAY]Inflamabilidade: {0}
text.item.radioactivity = [LIGHT_GRAY]RadioAtividade: {0} text.item.radioactivity = [LIGHT_GRAY]RadioAtividade: {0}
text.item.fluxiness = [LIGHT_GRAY]Poder do fluxo: {0} text.item.fluxiness = [LIGHT_GRAY]Poder do fluxo: {0}
text.unit.health = [LIGHT_GRAY]Health: {0} text.unit.health = [LIGHT_GRAY]Vida: {0}
text.unit.speed = [LIGHT_GRAY]Speed: {0} text.unit.speed = [LIGHT_GRAY]Velocidade: {0}
text.mech.weapon = [LIGHT_GRAY]Weapon: {0} text.mech.weapon = [LIGHT_GRAY]Arma: {0}
text.mech.armor = [LIGHT_GRAY]Armor: {0} text.mech.armor = [LIGHT_GRAY]Armadura: {0}
text.mech.itemcapacity = [LIGHT_GRAY]Item Capacity: {0} text.mech.itemcapacity = [LIGHT_GRAY]Capacidade de itens: {0}
text.mech.minespeed = [LIGHT_GRAY]Mining Speed: {0} text.mech.minespeed = [LIGHT_GRAY]Velocidade de mineração: {0}
text.mech.minepower = [LIGHT_GRAY]Mining Power: {0} text.mech.minepower = [LIGHT_GRAY]Poder de mineração: {0}
text.mech.ability = [LIGHT_GRAY]Ability: {0} text.mech.ability = [LIGHT_GRAY]Habilidade: {0}
text.liquid.heatcapacity = [LIGHT_GRAY]Capacidade de aquecimento: {0} text.liquid.heatcapacity = [LIGHT_GRAY]Capacidade de aquecimento: {0}
text.liquid.viscosity = [LIGHT_GRAY]Viscosidade: {0} text.liquid.viscosity = [LIGHT_GRAY]Viscosidade: {0}
text.liquid.temperature = [LIGHT_GRAY]Temperatura: {0} text.liquid.temperature = [LIGHT_GRAY]Temperatura: {0}
block.constructing = {0}\n[LIGHT_GRAY](Constructing) block.constructing = {0}\n[LIGHT_GRAY](Construindo)
block.spawn.name = Enemy Spawn block.spawn.name = Spawn dos inimigos
block.core.name = Core block.core.name = Core
block.metalfloor.name = Metal Floor block.metalfloor.name = Chão de metal
block.deepwater.name = água funda block.deepwater.name = água funda
block.water.name = água block.water.name = água
block.lava.name = lava block.lava.name = lava
@@ -508,24 +508,24 @@ block.sand.name = areia
block.ice.name = gelo block.ice.name = gelo
block.snow.name = neve block.snow.name = neve
block.grass.name = grama block.grass.name = grama
block.shrub.name = shrub block.shrub.name = Arbusto
block.rock.name = rocha block.rock.name = rocha
block.blackrock.name = rocha negra block.blackrock.name = rocha negra
block.icerock.name = rocha de gelo block.icerock.name = rocha de gelo
block.copper-wall.name = Parede de Cobre block.copper-wall.name = Parede de Cobre
block.copper-wall-large.name = Parede de Cobre Grande block.copper-wall-large.name = Parede de Cobre Grande
block.dense-alloy-wall.name = Dense Alloy Wall block.dense-alloy-wall.name = Parede de liga densa
block.dense-alloy-wall-large.name = Large Dense Alloy Wall block.dense-alloy-wall-large.name = Parede de liga densa grande
block.phase-wall.name = Phase Wall block.phase-wall.name = Parede de fase
block.phase-wall-large.name = Large Phase Wall block.phase-wall-large.name = Parde de fase grande
block.thorium-wall.name = Parede de tório block.thorium-wall.name = Parede de tório
block.thorium-wall-large.name = Parede larga de tório block.thorium-wall-large.name = Parede larga de tório
block.door.name = Porta block.door.name = Porta
block.door-large.name = Porta Grande block.door-large.name = Porta Grande
block.duo.name = Duplo block.duo.name = Dupla
block.scorch.name = Quimar block.scorch.name = Queimar
block.hail.name = Hail block.hail.name = Hail
block.lancer.name = Lancer block.lancer.name = Lancador
block.conveyor.name = Esteira block.conveyor.name = Esteira
block.titanium-conveyor.name = Esteira de Titanio block.titanium-conveyor.name = Esteira de Titanio
block.junction.name = Junção block.junction.name = Junção
@@ -553,21 +553,21 @@ block.battery-large.name = Bateria Grande
block.combustion-generator.name = Gerador de combustão block.combustion-generator.name = Gerador de combustão
block.turbine-generator.name = Gerador de Turbina block.turbine-generator.name = Gerador de Turbina
block.mechanical-drill.name = Furadera Mecânica block.mechanical-drill.name = Furadera Mecânica
block.pneumatic-drill.name = Pneumatic Drill block.pneumatic-drill.name = Mineradora Pneumatica
block.laser-drill.name = Broca a Laser block.laser-drill.name = Broca a Laser
block.water-extractor.name = Extrator de Agua block.water-extractor.name = Extrator de Agua
block.cultivator.name = Cultivador block.cultivator.name = Cultivador
block.alpha-mech-pad.name = Alpha Mech Pad block.alpha-mech-pad.name = Controle do meca Alfa
block.dart-ship-pad.name = Dart Ship Pad block.dart-ship-pad.name = Controle do meca Dart
block.delta-mech-pad.name = Delta Mech Pad block.delta-mech-pad.name = Controle do meca Delta
block.javelin-ship-pad.name = Javelin Ship Pad block.javelin-ship-pad.name = Controle do meca Javelin
block.trident-ship-pad.name = Trident Ship Pad block.trident-ship-pad.name = Controle do meca Tridente
block.glaive-ship-pad.name = Glaive Ship Pad block.glaive-ship-pad.name = Controle do meca Glaive
block.omega-mech-pad.name = Omega Mech Pad block.omega-mech-pad.name = Controle do meca Omega
block.tau-mech-pad.name = Tau Mech Pad block.tau-mech-pad.name = Controle do meca Tau
block.conduit.name = Cano block.conduit.name = Cano
block.mechanical-pump.name = Bomba Mecanica block.mechanical-pump.name = Bomba Mecanica
block.itemsource.name = Item Source block.itemsource.name = Fonte do item
block.itemvoid.name = Item Void block.itemvoid.name = Item Void
block.liquidsource.name = Liquid Source block.liquidsource.name = Liquid Source
block.powervoid.name = Power Void block.powervoid.name = Power Void
@@ -582,19 +582,19 @@ block.phase-conveyor.name = Esteira de Fases
block.bridge-conveyor.name = Esteira-Ponte block.bridge-conveyor.name = Esteira-Ponte
block.plastanium-compressor.name = Compressor de Plastanio block.plastanium-compressor.name = Compressor de Plastanio
block.pyratite-mixer.name = Misturador de Piratita block.pyratite-mixer.name = Misturador de Piratita
block.blast-mixer.name = Blast Mixer block.blast-mixer.name = Misturador de Explosão
block.solidifer.name = Solidificador block.solidifer.name = Solidificador
block.solar-panel.name = Painel Solar block.solar-panel.name = Painel Solar
block.solar-panel-large.name = Painel Solar Grande block.solar-panel-large.name = Painel Solar Grande
block.oil-extractor.name = Extrator de Oleo block.oil-extractor.name = Extrator de Oleo
block.spirit-factory.name = Spirit Drone Factory block.spirit-factory.name = Fabrica de Drone Spirit
block.phantom-factory.name = Phantom Drone Factory block.phantom-factory.name = Fabrica de Drone Phantom
block.wraith-factory.name = Wraith Fighter Factory block.wraith-factory.name = Fabrica de Drone Wraith
block.ghoul-factory.name = Ghoul Bomber Factory block.ghoul-factory.name = Fabrica de Bombardeiro Ghoul
block.dagger-factory.name = Dagger Mech Factory block.dagger-factory.name = Fabrica de meca Dagger
block.titan-factory.name = Titan Mech Factory block.titan-factory.name = Fabrica de meca titan
block.fortress-factory.name = Fortress Mech Factory block.fortress-factory.name = Fabrica de meca Fortress
block.revenant-factory.name = Revenant Fighter Factory block.revenant-factory.name = Fabrica de lutadores Revenant
block.repair-point.name = Ponto de Reparo block.repair-point.name = Ponto de Reparo
block.pulse-conduit.name = Conduto de Pulso block.pulse-conduit.name = Conduto de Pulso
block.phase-conduit.name = Conduto de Fase block.phase-conduit.name = Conduto de Fase
@@ -603,178 +603,178 @@ block.liquid-tank.name = Tanque de Líquido
block.liquid-junction.name = Junção de Líquido block.liquid-junction.name = Junção de Líquido
block.bridge-conduit.name = Conduto-Ponte block.bridge-conduit.name = Conduto-Ponte
block.rotary-pump.name = Bomba Rotatoria block.rotary-pump.name = Bomba Rotatoria
block.thorium-reactor.name = Thorium Reactor block.thorium-reactor.name = Reator Torio
block.command-center.name = Centro De Comando block.command-center.name = Centro De Comando
block.mass-driver.name = Mass Driver block.mass-driver.name = Drive de Massa
block.blast-drill.name = Blast Drill block.blast-drill.name = Mineradora de Explosão
block.thermal-pump.name = Thermal Pump block.thermal-pump.name = Cano termico
block.thermal-generator.name = Gerador Térmico block.thermal-generator.name = Gerador Térmico
block.alloy-smelter.name = Alloy Smtler block.alloy-smelter.name = Fundidora de Liga
block.mend-projector.name = Mend Projector block.mend-projector.name = Projetor Mend
block.surge-wall.name = Surge Wall block.surge-wall.name = Parede de Surge
block.surge-wall-large.name = Large Surge Wall block.surge-wall-large.name = Parede de surge grande
block.cyclone.name = Cyclone block.cyclone.name = Ciclone
block.fuse.name = Fuse block.fuse.name = Fundir
block.shock-mine.name = Shock Mine block.shock-mine.name = Mina de Choque
block.overdrive-projector.name = Overdrive Projector block.overdrive-projector.name = Projetor Overdrive
block.force-projector.name = Force Projector block.force-projector.name = Projetor Force
block.arc.name = Arc block.arc.name = Arc
block.rtg-generator.name = RTG Generator block.rtg-generator.name = Gerador RTG
block.spectre.name = Spectre block.spectre.name = Espectra
block.meltdown.name = Meltdown block.meltdown.name = Derreter
block.container.name = Container block.container.name = Container
block.core.description = The most important building in the game. block.core.description = A mais importante construção do jogo.
team.blue.name = blue team.blue.name = Azul
team.red.name = red team.red.name = Vermelho
team.orange.name = orange team.orange.name = Laranja
team.none.name = gray team.none.name = Cinza
team.green.name = green team.green.name = Verde
team.purple.name = purple team.purple.name = Roxo
unit.alpha-drone.name = Alpha Drone unit.alpha-drone.name = Drone alfa
unit.spirit.name = Spirit Drone unit.spirit.name = Drone Spirit
unit.spirit.description = The starter drone unit. Spawns in the core by default. Automatically mines ores, collects items and repairs blocks. unit.spirit.description = A unidade de drone inicial. Ele nasce no core por padrão. Minera minérios automaticamente, Coleta itens e repara blocos.
unit.phantom.name = Phantom Drone unit.phantom.name = Drone Phantom
unit.phantom.description = An advanced drone unit. Automatically mines ores, collects items and repairs blocks. Significantly more effective than a drone. unit.phantom.description = Uma unidade de drone avançada. Minera minérios automaticamente, Coleta itens e repara blocos automaticamente. Significantemente mais efetiva.
unit.dagger.name = Dagger unit.dagger.name = Dagger
unit.dagger.description = A basic ground unit. Useful in swarms. unit.dagger.description = Unidade terrestre basica, Forte em grupos.
unit.titan.name = Titan unit.titan.name = Titan
unit.titan.description = An advanced armored ground unit. Uses carbide as ammo. Attacks both ground and air targets. unit.titan.description = Uma unidade armadurada terreste avancada. Usa carbide como munição. Ataca ambas as unidades de Aereas e terrestres.
unit.ghoul.name = Ghoul Bomber unit.ghoul.name = Bombardeiro Ghoul
unit.ghoul.description = A heavy carpet bomber. Uses blast compound or pyratite as ammo. unit.ghoul.description = Um bombardeiro pesado. Usa composto de explosão Ou piratite como munição.
unit.wraith.name = Wraith Fighter unit.wraith.name = Lutador Wraith
unit.wraith.description = A fast, hit-and-run interceptor unit. unit.wraith.description = Uma unidade rapida, Interceptadora de bater e correr.
unit.fortress.name = Fortress unit.fortress.name = Fortaleza
unit.fortress.description = A heavy artillery ground unit. unit.fortress.description = Uma unidade pesada de artilharia terrestre.
unit.revenant.name = Revenant unit.revenant.name = Revenant
unit.revenant.description = A heavy laser platform. unit.revenant.description = Uma plataforma de laser pesada.
tutorial.begin = Your mission here is to eradicate the[LIGHT_GRAY] enemy[].\n\nBegin by[accent] mining copper[]. Tap a copper ore vein near your core to do this. tutorial.begin = Sua missão aqui é de erradicar[LIGHT_GRAY] Inimigo[].\n\nComeçe por[accent] Minerar cobre[]. Clique numa veia de cobre perto de seu core para fazer isso.
tutorial.drill = Mining manually is inefficient.\n[accent]Drills []can mine automatically.\nPlace one on a copper vein. tutorial.drill = Minerar manualmente é ineficiente.\n[accent]Mineradoras []podem minerar automaticamente.\nColoque uma numa veia de cobre.
tutorial.conveyor = [accent]Conveyors[] are used to transport items to the core.\nMake a line of conveyors from the drill to the core. tutorial.conveyor = [accent]Esteiras[] São usadas para transportar itens até o core.\nFaça uma linha de Esteiras da mineradora até o core.
tutorial.morecopper = More copper is required.\n\nEither mine it manually, or place more drills. tutorial.morecopper = Mais cobre é preciso.\n\nTanto minere manualmente, Ou coloque mais mineradoras.
tutorial.turret = Defensive structures must be built to repel the[LIGHT_GRAY] enemy[].\nBuild a duo turret near your base. tutorial.turret = Estruturas defensivas devem ser construidas para repelir[LIGHT_GRAY] O inimigo[].\nConstrua uma torre dupla perto de sua base.
tutorial.drillturret = Duo turrets require[accent] copper ammo []to shoot.\nPlace a drill next to the turret to supply it with mined copper. tutorial.drillturret = Torres duplas precisam de[accent] Cobre como munição []Para atirar.\nColoque uma mineradoura Proxima a torre Para carregar ela com cobre minerado.
tutorial.waves = The[LIGHT_GRAY] enemy[] approaches.\n\nDefend your core for 2 waves. Build more turrets. tutorial.waves = O[LIGHT_GRAY] Inimigo[] se aproxima.\n\nDefenda seu core por 2 ondas. Construa mais torres.
tutorial.lead = More ores are available. Explore and mine[accent] lead[].\n\nDrag from your unit to the core to transfer resources. tutorial.lead = Mais minerios estão disponiveis. Explore e minere[accent] Cobre[].\n\nArraste Da sua unidade até o core para transferir recursos.
tutorial.smelter = Copper and lead are weak metals.\nSuperior[accent] Dense Alloy[] can be created in a smelter.\n\nBuild one. tutorial.smelter = Cobre e chumbo são materiais fracos.\nLiga densa[accent] Superior[] Pode ser feito num fundidor.\n\nConstrua um.
tutorial.densealloy = The smelter will now produce alloy.\nGet some.\nImprove the production if necessary. tutorial.densealloy = O fundidor agora vai fazer a liga.\nPegue.\nMelhore a produção se necessario.
tutorial.siliconsmelter = The core will now create a[accent] spirit drone[] for mining and repairing blocks.\n\nFactories for other units can be created with [accent] silicon.\nMake a silicon smelter. tutorial.siliconsmelter = O core agora vai criar[accent] O drone Spirit[] Para minerar e consertar blocos.\n\nFabricas para outras unidades podem ser criadas usando [accent] silicio.\nFaça um fundidor de Silicio.
tutorial.silicondrill = Silicon requires[accent] coal[] and[accent] sand[].\nStart by making drills. tutorial.silicondrill = Silicio requer[accent] carvão[] e[accent] areia[].\nComeçe a fazer mineradouras.
tutorial.generator = This technology requires power.\nCreate a[accent] combustion generator[] for it. tutorial.generator = Essa tecnologia requer energia.\nCrie[accent] um gerador a combustão[] para isso.
tutorial.generatordrill = Combustion generators need fuel.\nFuel it with coal from a drill. tutorial.generatordrill = Gerador de combustão requer combustivel.\nCarregue com carvão minerado.
tutorial.node = Power requires transport.\nCreate a[accent] power node[] next to your combustion generator to transfer its power. tutorial.node = Energia requer transporte.\nCrie um[accent] Nodo de energia[] Proximo do gerador de combustão.
tutorial.nodelink = Power can be transferred through contacting power blocks and generators, or by linked power nodes.\n\nLink power by tapping the node and selecting the generator and silicon smelter. tutorial.nodelink = Poder pode ser transportado construindo blocos de energia e geradores, Apenas construindo nodos de Energia.\n\nLigue a energia clicando no nodo e selecionando o gerador e o fundidor de silicio.
tutorial.silicon = Silicon is being produced. Get some.\n\nImproving the production system is advised. tutorial.silicon = Silicio esta sendo feito. Pegue.\n\nMelhorar a produção é recomendado.
tutorial.daggerfactory = Construct a[accent] dagger mech factory.[]\n\nThis will be used to create attack mechs. tutorial.daggerfactory = Construa uma[accent] Fabrica do meca Dagger.[]\n\nIsso vai ser feito para construi mecas de ataque.
tutorial.router = Factories need resources to function.\nCreate a router to split conveyor resources. tutorial.router = Fabricas precisam de recursos pra construir\nCrie um roteador para espalhadar recursos da esteira.
tutorial.dagger = Link power nodes to the factory.\nOnce requirements are met, a mech will be created.\n\nCreate more drills, generators and conveyors as necessary. tutorial.dagger = Ligue os nodos de energia a fabrica.\nQuando os requerimentos forem alcançados, Um meca vai ser criado.\n\nCrie mais mineradoras, geradoras e esteiras se necessario.
tutorial.battle = The[LIGHT_GRAY] enemy[] has revealed their core.\nDestroy it with your unit and dagger mechs. tutorial.battle = O[LIGHT_GRAY] Inimigo[] revelou seu core.\nDestrua com sua unidade e Dagger's.
block.copper-wall.description = A cheap defensive block.\nUseful for protecting the core and turrets in the first few waves. block.copper-wall.description = Um bloco defensivo e barato.\nUtil para proteger o core e torres no começo.
block.copper-wall-large.description = A cheap defensive block.\nUseful for protecting the core and turrets in the first few waves.\nSpans multiple tiles. block.copper-wall-large.description = Um bloco defensivo e barato.\nUtil para proteger o core e torres no começo.\nOcupa multiplos espaços.
block.dense-alloy-wall.description = A standard defensive block.\nAdequate protection from enemies. block.dense-alloy-wall.description = Um bloco defensivo padrão.\nProteção adequada contra inimigos.
block.dense-alloy-wall-large.description = A standard defensive block.\nAdequate protection from enemies.\nSpans multiple tiles. block.dense-alloy-wall-large.description = Um bloco defensivo padrão.\nProteção adequada contra inimigos.\nOcupa multiplos espaços.
block.thorium-wall.description = A strong defensive block.\nGood protection from enemies. block.thorium-wall.description = A strong defensive block.\nBoa proteção contra inimigos.
block.thorium-wall-large.description = A strong defensive block.\nGood protection from enemies.\nSpans multiple tiles. block.thorium-wall-large.description = Um bloco grande e defensivo.\nBoa proteção contra inimigos.\nOcupa multiplos espaços.
block.phase-wall.description = Not as strong as a thorium wall but will deflect bullets unless they are too powerful. block.phase-wall.description = Não tão forte quanto a parede de torio Mas vai defletir balas a menos que seja muito forte.
block.phase-wall-large.description = Not as strong as a thorium wall but will deflect bullets unless they are too powerful.\nSpans multiple tiles. block.phase-wall-large.description = Não tão forte quanto a parde de torio mas vai defletir balas a menos que seja muito forte.\nOcupa multiplos espaços.
block.surge-wall.description = The strongest defensive block.\nHas a small chance of triggering lightning towards the attacker. block.surge-wall.description = O bloco defensivo mais forte.\nQue tem uma pequena chance de lancar um raio Contra o atacante.
block.surge-wall-large.description = The strongest defensive block.\nHas a small chance of triggering lightning towards the attacker.\nSpans multiple tiles. block.surge-wall-large.description = O bloco defensivo mais forte.\nQue tem uma pequena chance de lancar um raio Contra o atacante.\nOcupa multiplos espaços
block.door.description = A small door that can be opened and closed by tapping on it.\nIf opened, enemies can shoot and move through. block.door.description = Uma pequena porta que pode ser aberta o fechada quando voce clica.\nSe aberta, Os inimigos podem atirar e passar.
block.door-large.description = A large door that can be opened and closed by tapping on it.\nIf opened, enemies can shoot and move through.\nSpans multiple tiles. block.door-large.description = Uma grande porta que pode ser aberta o fechada quando voce clica.\nSe aberta, Os inimigos podem atirar e passar..\nOcupa multiplos espaços.
block.mend-projector.description = Periodically heals buildings in its vicinity. block.mend-projector.description = Periodicamente conserta as construções.
block.overdrive-projector.description = Increases the speed of nearby buildings like drills and conveyors. block.overdrive-projector.description = Aumenta a velocidade de unidades proximas de geradores e esteiras.
block.force-projector.description = Creates a hexagonal force field around itself, protecting buildings and units inside from damage through bullets. block.force-projector.description = Cria um campo de forca hexagonal em volta de si mesmo, Protegendo construções e unidades dentro de dano por balas.
block.shock-mine.description = Damages enemies stepping on the mine. Nearly invisible to the enemy. block.shock-mine.description = Danifica inimigos em cima da mina. Quase invisivel ao inimigo.
block.duo.description = A small, cheap turret. block.duo.description = Uma torre pequena e barata.
block.arc.description = A small turret which shoots electricity in a random arc towards the enemy. block.arc.description = Uma pequena torre que atira eletricidade em um pequeno arc aleatoriamente no inimigo.
block.hail.description = A small artillery turret. block.hail.description = Uma pequena torre de artilharia.
block.lancer.description = A medium-sized turret which shoots charged electricity beams. block.lancer.description = Uma torre de Tamanho-Medio que atira raios de eletricidade.
block.wave.description = A medium-sized rapid-fire turret which shoots liquid bubbles. block.wave.description = Uma torre que Tamanho medio que atira bolhas.
block.salvo.description = A medium-sized turret which fires shots in salvos. block.salvo.description = Uma torre media que da tiros em salvos.
block.swarmer.description = A medium-sized turret which shoots burst missiles. block.swarmer.description = Uma torre media que atira ondas de misseis.
block.ripple.description = A large artillery turret which fires several shots simultaneously. block.ripple.description = Uma grande torre que atira simultaneamente.
block.cyclone.description = A large rapid fire turret. block.cyclone.description = Uma grande torre de tiro rapido.
block.fuse.description = A large turret which shoots powerful short-range beams. block.fuse.description = Uma torre grande que atira raios de curta distancia poderosos.
block.spectre.description = A large turret which shoots two powerful bullets at once. block.spectre.description = Uma grande torre que da dois tiros poderosos ao mesmo tempo.
block.meltdown.description = A large turret which shoots powerful long-range beams. block.meltdown.description = Uma grande torre que atira dois raios poderosos ao mesmo tempo.
block.conveyor.description = Basic item transport block. Moved items forward and automatically deposits them into turrets or crafters. Rotatable. block.conveyor.description = Bloco de transporte de item basico. Move os itens a frente e os deposita automaticamente Em torres ou construtores. Rotacionavel.
block.titanium-conveyor.description = Advanced item transport block. Moves items faster than standard conveyors. block.titanium-conveyor.description = Bloco de transporte de item avancado. Move itens mais rapidos que esteiras padrões.
block.phase-conveyor.description = Advanced item transport block. Uses power to teleport items to a connected phase conveyor over several tiles. block.phase-conveyor.description = Bloco de transporte de item avançado. Usa energia para teleportar itens a uma esteira de fase sobre uma severa distancia.
block.junction.description = Acts as a bridge for two crossing conveyor belts. Useful in situations with two different conveyors carrying different materials to different locations. block.junction.description = Funciona como uma ponte Para duas esteiras que estejam se cruzando. Util em situações que tenha duas esteiras diferentes carregando materiais diferentes para lugares diferentes.
block.mass-driver.description = Ultimate item transport block. Collects several items and then shoots them to another mass driver over a long range. block.mass-driver.description = Bloco de transporte de itens supremo. Coleta itens severos e atira eles em outro mass driver de uma longa distancia.
block.smelter.description = Burns coal for smelting copper and lead into dense alloy. block.smelter.description = Queima carvão para derreter cobre e chumbo em liga densa.
block.arc-smelter.description = Smelts copper and lead into dense alloy by using an external power source. block.arc-smelter.description = Derrete Cobre e chumbo em liga densa usando energia exterior.
block.silicon-smelter.description = Reduces sand with highly pure coke in order to produce silicon. block.silicon-smelter.description = Reduz areia a coque altamente puro Para fazer silicio.
block.plastanium-compressor.description = Produces plastanium from oil and titanium. block.plastanium-compressor.description = Produz plastanio para usando oleo e titanio.
block.phase-weaver.description = Produces phase fabric from radioactive thorium and high amounts of sand. block.phase-weaver.description = Produz tecido de fase de torio radioativo e grandes quantidades de areia.
block.alloy-smelter.description = Produces surge alloy from titanium, lead, silicon and copper. block.alloy-smelter.description = Produz liga de surge de titanio, chumbo, silicio e cobre.
block.pulverizer.description = Crushes stone into sand. Useful when there is a lack of natural sand. block.pulverizer.description = Esmaga pedra em areia. Util quando esta em falta de areia natural.
block.pyratite-mixer.description = Mixes coal, lead and sand into highly flammable pyratite. block.pyratite-mixer.description = Mistura carvão, Cobre e areia em piratite altamente inflamavel
block.blast-mixer.description = Uses oil for transforming pyratite into the less flammable but more explosive blast compound. block.blast-mixer.description = Usa oleo em Transformar piratite em composto de explosão menos inflamavel mas mais explosivo
block.cryofluidmixer.description = Combines water and titanium into cryofluid which is much more efficient for cooling. block.cryofluidmixer.description = Combina agua e titanio em cryo fluido que é mais eficiente em esfriar.
block.solidifer.description = Cools lava to stone at a fast pace. block.solidifer.description = Esfria lava em pedra em um ritmo rapido.
block.melter.description = Heats up stone to very high temperatures to obtain lava. block.melter.description = Aquece pedra em altas temperaturas para fazer lava.
block.incinerator.description = Gets rid of any excess item or liquid. block.incinerator.description = Se livra de itens em excesso ou liquidos.
block.biomattercompressor.description = Compresses biomatter in order to retrieve oil. block.biomattercompressor.description = Compressa Biomassa para recuperar oleo.
block.separator.description = Exposes stone to water pressure in order to obtain various minerals contained in the stone. block.separator.description = Expos pedra em agua em pressão para ter varios mineiras contendo na pedra.
block.centrifuge.description = More efficient than the separator, but also more expensive to build and requires power. block.centrifuge.description = Mais eficiente que o separador, Mas mais caro e precisa de energia.
block.power-node.description = Transmits power to connected nodes. Up to four power sources, sinks or nodes can be connected. The node will receive power from or supply power to any adjacent blocks. block.power-node.description = Transmite poder em nodos. Maximo de 4 fontes de energia, sinks ou nodos podem ser conectados. Os nodos vão receber energia de ou dar energia para qualquer bloco adjacente.
block.power-node-large.description = Has a larger radius than the power node and connects to up to six power sources, sinks or nodes. block.power-node-large.description = Tem um raio maior que o nodo de energia e pode conectar até 6 fontes de energia, sinks ou nodos.
block.battery.description = Stores power whenever there is an abundance and provides power whenever there is a shortage, as long as there is capacity left. block.battery.description = Guarda energia sempre que tiver em abundancia e da energia sempre que precisar enquanto tiver capacidade.
block.battery-large.description = Stores much more power than a regular battery. block.battery-large.description = Guarda muito mais energia que uma beteria comum
block.combustion-generator.description = Generates power by burning oil or flammable materials. block.combustion-generator.description = Gera poder usando combustivel ou oleo.
block.turbine-generator.description = More efficient than a combustion generator, but requires additional water. block.turbine-generator.description = Mais eficiente que o gerador de Combustão, Mas requer agua adicional.
block.thermal-generator.description = Generates a large amount of power from lava. block.thermal-generator.description = Gera uma quantidade grande de energia usando lava.
block.solar-panel.description = Provides a small amount of power from the sun. block.solar-panel.description = Gera pequenas quantidades de energia do sol.
block.solar-panel-large.description = Provides much better power supply than a standard solar panel, but is also much more expensive to build. block.solar-panel-large.description = Da muito mais energia que o painel solar comum, Mas sua produção é mais cara.
block.thorium-reactor.description = Generates huge amounts of power from highly radioactive thorium. Requires constant cooling. Will explode violently if insufficient amounts of coolant are supplied. block.thorium-reactor.description = Gera altas quantidades de energia do torio radioativo. Requer resfriamento constante. Vai explodir violentamente Se resfriamento insuficiente for fornecido.
block.rtg-generator.description = A radioisotope thermoelectric generator which does not require cooling but provides less power than a thorium reactor. block.rtg-generator.description = Um Gerador termoelétrico de radioisótopos Que não precisa de refriamento Mas da muito mais energia que o reator de torio.
block.unloader.description = Unloads items from a container, vault or core onto a conveyor or directly into an adjacent block. The type of item to be unloaded can be changed by tapping on the unloader. block.unloader.description = Descarrega itens de um container, Descarrega em uma esteira ou diretamente em um bloco adjacente. O tipo de item que pode ser descarregado pode ser mudado clicando no descarregador.
block.container.description = Stores a small amount of items. Use it for creating buffers when there is a non-constant demand of materials. An[LIGHT_GRAY] unloader[] can be used to retrieve items from the container. block.container.description = Carrega uma baixa quantidade de itens. Usado para criar fontes Quando não tem uma necessidade constante de materiais. Um[LIGHT_GRAY] Descarregador[] pode ser usado para recuperar esses itens do container.
block.vault.description = Stores a large amount of items. Use it for creating buffers when there is a non-constant demand of materials. An[LIGHT_GRAY] unloader[] can be used to retrieve items from the vault. block.vault.description = Carrega uma alta quantidade de itens. Usado para criar fontes Quando não tem uma necessidade constante de materiais. Um[LIGHT_GRAY] Descarregador[] pode ser usado para recuperar esses itens do container.
block.mechanical-drill.description = A cheap drill. When placed on appropriate tiles, outputs items at a slow pace indefinitely. block.mechanical-drill.description = Uma mineradoura barata. Quando colocado em blocos apropriados, retira itens em um ritmo lento e indefinitavamente.
block.pneumatic-drill.description = An improved drill which is faster and able to process harder materials by making use of air pressure. block.pneumatic-drill.description = Uma mineradora improvisada que é mais rapida e capaz de processar mateirais mais duros usando a pressao do ar
block.laser-drill.description = Allows drilling even faster through laser technology, but requires power. Additionally, radioactive thorium can be retrieved with this drill. block.laser-drill.description = Possibilita a mineração ainda mais rapida usando tecnologia a laser, Mas requer poder adcionalmente torio radioativo pode ser recuperado com essa mineradora
block.blast-drill.description = The ultimate drill. Requires large amounts of power. block.blast-drill.description = A melhor mineradora. Requer muita energia.
block.water-extractor.description = Extracts water from the ground. Use it when there is no lake nearby. block.water-extractor.description = Extrai agua do chão. Use quando não tive nenhum lago proximo
block.cultivator.description = Cultivates the soil with water in order to obtain biomatter. block.cultivator.description = Cultiva o solo com agua para pegar bio materia.
block.oil-extractor.description = Uses large amounts of power in order to extract oil from sand. Use it when there is no direct source of oil nearby. block.oil-extractor.description = Usa altas quantidades de energia Para extrair oleo da areia. Use quando não tiver fontes de oleo por perto
block.dart-ship-pad.description = Leave your current vessel and change into a basic fighter aircraft.\nUse the pad by double tapping while standing on it. block.dart-ship-pad.description = Deixe sua atual embarcação e mude para uma aeronave lutadora basica.\nUse o pad clicando duas vezes em cima enquando fica em cima dele.
block.trident-ship-pad.description = Leave your current vessel and change into a reasonably well armored heavy bomber.\nUse the pad by double tapping while standing on it. block.trident-ship-pad.description = Deixe sua atual embarcação e mude para um bombardeiro resionavelmente bem armadurado.\nUse o pad clicando duas vezes em cima enquando fica em cima dele.
block.javelin-ship-pad.description = Leave your current vessel and change into a strong and fast interceptor with lightning weapons.\nUse the pad by double tapping while standing on it. block.javelin-ship-pad.description = Deixe sua atual embarcação e mude para um interceptador forte e rapido com armas de raio.\nUse o pad clicando duas vezes em cima enquando fica em cima dele.
block.glaive-ship-pad.description = Leave your current vessel and change into a large, well-armored gunship.\nUse the pad by double tapping while standing on it. block.glaive-ship-pad.description = Deixe sua atual embarcação e mude para grande, bem armadurada nave de combate.\nUse o pad clicando duas vezes em cima enquando fica em cima dele.
block.tau-mech-pad.description = Leave your current vessel and change into a support mech which can heal friendly buildings and units.\nUse the pad by double tapping while standing on it. block.tau-mech-pad.description = Deixe sua atual embarcação e mude para o meca de suporte que pode consertar construções aliadas e unidades.\nUse o pad clicando duas vezes em cima enquando fica em cima dele.
block.delta-mech-pad.description = Leave your current vessel and change into a fast, lightly-armored mech made for hit-and-run attacks.\nUse the pad by double tapping while standing on it. block.delta-mech-pad.description = Deixe sua atual embarcação e mude para o rapido, Levemente armadurado meca feito para ataques rapidos.\nUse o pad clicando duas vezes em cima enquando fica em cima dele.
block.omega-mech-pad.description = Leave your current vessel and change into a bulky and well-armored mech, made for front-line assaults.\nUse the pad by double tapping while standing on it. block.omega-mech-pad.description = Deixe sua atual embarcação e mude para o volumoso e bem armadurado meca feito para ataques da primeira linha.\nUse o pad clicando duas vezes em cima enquando fica em cima dele.
block.spirit-factory.description = Produces light drones which mine ore and repair blocks. block.spirit-factory.description = Produz drones leves que mineram e reparam blocos.
block.phantom-factory.description = Produces advanced drone units which are significantly more effective than a spirit drone. block.phantom-factory.description = Produz unidades de drone avancadas Que são significativamente mais efetivos que um drone spirit.
block.wraith-factory.description = Produces fast, hit-and-run interceptor units. block.wraith-factory.description = produz unidades interceptor de ataque rapido.
block.ghoul-factory.description = Produces heavy carpet bombers. block.ghoul-factory.description = Produz bombardeiros pesados.
block.dagger-factory.description = Produces basic ground units. block.dagger-factory.description = Produz unidades terrestres.
block.titan-factory.description = Produces advanced, armored ground units. block.titan-factory.description = Produz unidades avancadas, armaduradas e terrestres.
block.fortress-factory.description = Produces heavy artillery ground units. block.fortress-factory.description = Produz unidades terrestres pesadas de artilharia.
block.revenant-factory.description = Produces heavy laser ground units. block.revenant-factory.description = Produz unidades laser, pesadas e terrestres.
block.repair-point.description = Continuously heals the closest damaged unit in its vicinity. block.repair-point.description = Continuamente repara a unidade danificada mais proxima.
block.command-center.description = Allows changing friendly AI behavior. Currently, attack, retreat and patrol commands are supported. block.command-center.description = Permite mudar o comportamento IA dos aliados. Atualmente, atacar, recuar e patrulha são suportados.
block.conduit.description = Basic liquid transport block. Works like a conveyor, but with liquids. Best used with extractors, pumps or other conduits. block.conduit.description = Bloco de transporte de liquido basico. Funciona como a esteira, Mas com liquidos. Melhor usado com extratores, Bombas ou condutos.
block.pulse-conduit.description = Advanced liquid transport block. Transports liquids faster and stores more than standard conduits. block.pulse-conduit.description = Bloco avancado de transporte de liquido. Transporta liquidos mais rapido E armazena mais que os condutos padrões.
block.phase-conduit.description = Advanced liquid transport block. Uses power to teleport liquids to a connected phase conduit over several tiles. block.phase-conduit.description = Bloco avancado de transporte de liquido. Usa energia para teleportar liquidos conduto de fase sobre uma distancia severa.
block.liquid-router.description = Accepts liquids from one direction and outputs them to up to 3 other directions equally. Can also store a certain amount of liquid. Useful for splitting the liquids from one source to multiple targets. block.liquid-router.description = Aceita liquidos de uma direcão e os joga em 3 direções igualmente. Pode armazenar uma certa quantidade de liquido. Util para espalhar liquidosd a fonte para multiplos alvos.
block.liquid-tank.description = Stores a large amount of liquids. Use it for creating buffers when there is a non-constant demand of materials or as a safeguard for cooling vital blocks. block.liquid-tank.description = Armazena grandes quantidades de liquido. Use quando a demanda de materiais não for constante ou para guardar itens para resfriar blocos vitais.
block.liquid-junction.description = Acts as a bridge for two crossing conduits. Useful in situations with two different conduits carrying different liquids to different locations. block.liquid-junction.description = Age como uma ponte para dois canos que se cruzam. Util em situações que tem dois condutos carregando liquidos diferentes até localizações diferentes.
block.bridge-conduit.description = Advanced liquid transport block. Allows transporting liquids over up to 3 tiles of any terrain or building. block.bridge-conduit.description = Bloco de transporte de liquidos avancados. Possibilita o transporte de liquido sobre 3 blocos acima de construções ou paredes
block.mechanical-pump.description = A cheap pump with slow output, but no power consumption. block.mechanical-pump.description = Uma bomba barata mais saida de liquidos lenta, Sem consumo de energia.
block.rotary-pump.description = An advanced pump which doubles up speed by using power. block.rotary-pump.description = Uma bomba avancada que duplica a velocidade da saida de liquida usando energia.
block.thermal-pump.description = The ultimate pump. Three times as fast as a mechanical pump and the only pump which is able to retrieve lava. block.thermal-pump.description = A melhor bomba. Trez vezes mais rapida que a bomba mecanica e a unica bomba capaz de pegar lava.
block.router.description = Accepts items from one direction and outputs them to up to 3 other directions equally. Useful for splitting the materials from one source to multiple targets. block.router.description = Aceita itens de uma direção e os divide em 3 direções igualmente. Util para espalhar materiais da fonte para multiplos alvos.
block.distributor.description = An advanced router which splits items to up to 7 other directions equally. block.distributor.description = Um roteador avancada que espalhas os itens em 7 outras direções igualmente.
block.bridge-conveyor.description = Advanced item transport block. Allows transporting items over up to 3 tiles of any terrain or building. block.bridge-conveyor.description = Bloco de transporte de itens avancado. Possibilita o transporte de itens acima de 3 blocos de construção ou paredes.
block.alpha-mech-pad.description = When given enough power, rebuilds your ship into the[accent] Alpha[] mech. block.alpha-mech-pad.description = Quando dado energia o suficiente, Reconstrua sua nave em [accent] Alpha[] mech.
block.itemsource.description = Infinitely outputs items. Sandbox only. block.itemsource.description = Infinivamente da itens. Apenas caixa de areia.
block.liquidsource.description = Infinitely outputs liquids. Sandbox only. block.liquidsource.description = Infinitivamente da Liquidos. Apenas caixa de areia.
block.itemvoid.description = Destroys any items which go into it without using power. Sandbox only. block.itemvoid.description = Destroi qualquer item que entre sem requerir energia. Apenas caixa de areia.
block.powerinfinite.description = Infinitely outputs power. Sandbox only. block.powerinfinite.description = Infinitivamente da energia. Apenas caixa de areia.
block.powervoid.description = Voids all power inputted into it. Sandbox only. block.powervoid.description = Destroi qualquer energia que entre dentro. Apenas caixa de areia.
liquid.water.description = Commonly used for cooling machines and waste processing. liquid.water.description = Comumente usado em resfriamento e no processo de perda.
liquid.lava.description = Can be transformed into[LIGHT_GRAY] stone[], used for generating power or used as ammo for certain turrets. liquid.lava.description = Pode ser transformado em[LIGHT_GRAY] pedra[], usado para gerar energia ou usado como munição para certas torres.
liquid.oil.description = Can be burnt, exploded or used as a coolant. liquid.oil.description = Pode ser queimado, explodido ou usado como resfriador.
liquid.cryofluid.description = The most efficient liquid for cooling things down. liquid.cryofluid.description = A maneira mais eficiente de resfriar qualquer coisa.

View File

@@ -1,4 +1,4 @@
text.credits.text = Создатель [ROYAL] Anuken. - [SKY]anukendev@gmail.com[][]\n\nЕсть недороботки в переводе?\nПишите в офф. discord-сервер mindustry в канал #русский.\n\nПереводчики на русский язык:\n[YELLOW]Prosta4ok_ua\n[GREEN]xga\n[BLACK]XZimur text.credits.text = Создатель [ROYAL] Anuken. - [SKY]anukendev@gmail.com[][]\n\nЕсть недоработки в переводе?\nПишите в офф. discord-сервер mindustry в канал #русский.\n\nПереводчики на русский язык:\n[YELLOW]Prosta4ok_ua\n[GREEN]xga\n[BLACK]XZimur
text.credits = Авторы text.credits = Авторы
text.contributors = Переводчики и контрибьюторы text.contributors = Переводчики и контрибьюторы
text.discord = Присоединяйтесь к нашему Discord! text.discord = Присоединяйтесь к нашему Discord!
@@ -12,7 +12,7 @@ text.link.wiki.description = Официальная вики Mindustry(англ.
text.linkfail = Не удалось открыть ссылку!\nURL-адрес был скопирован в буфер обмена. text.linkfail = Не удалось открыть ссылку!\nURL-адрес был скопирован в буфер обмена.
text.gameover = Игра окончена text.gameover = Игра окончена
text.gameover.pvp = [accent] {0}[] команда победила! text.gameover.pvp = [accent] {0}[] команда победила!
text.sector.gameover = Этот сектор потерян. Высадится повторно? text.sector.gameover = Этот сектор потерян. Высадиться повторно?
text.sector.retry = Повторить попытку text.sector.retry = Повторить попытку
text.highscore = [YELLOW]Новый рекорд! text.highscore = [YELLOW]Новый рекорд!
text.wave.lasted = Вы продержались до [accent]{0}[]-ой волны. text.wave.lasted = Вы продержались до [accent]{0}[]-ой волны.
@@ -49,9 +49,9 @@ text.mission.main = Главная мисия:[LIGHT_GRAY] {0}
text.mission.info = Информация о миссии text.mission.info = Информация о миссии
text.mission.complete = Миссия выполнена! text.mission.complete = Миссия выполнена!
text.mission.complete.body = Сектор {0},{1} был завоёван. text.mission.complete.body = Сектор {0},{1} был завоёван.
text.mission.wave = Осталось[accent] {0}[] волн из[accent] {1}[]\nВолна через {2} text.mission.wave = Волна[accent] {0}[] из[accent] {1}[]\nВолна через {2}
text.mission.wave.enemies = Осталось[accent] {0}/{1}[] волн:\n{2} враг. text.mission.wave.enemies = Волна[accent] {0} из {1}[]\n{2} враг.
text.mission.wave.enemy = Осталось[accent] {0}/{1}[] волн\n{2} враг text.mission.wave.enemy = Волна[accent] {0} из {1}[]\n{2} враг
text.mission.wave.menu = Пережить[accent] {0} []волн text.mission.wave.menu = Пережить[accent] {0} []волн
text.mission.battle = Уничтожьте ядро противника. text.mission.battle = Уничтожьте ядро противника.
text.mission.resource.menu = Добыть {0} х{1} text.mission.resource.menu = Добыть {0} х{1}
@@ -266,7 +266,7 @@ text.error.invalidaddress = Некорректный адрес.
text.error.timedout = Время ожидания истекло!\nУбедитесь, что хост настроен для перенаправления портов и адрес корректный! text.error.timedout = Время ожидания истекло!\nУбедитесь, что хост настроен для перенаправления портов и адрес корректный!
text.error.mismatch = Ошибка пакета:\nвозможное несоответствие версии клиента/сервера. \nУбедитесь, что у Вас и у владельца сервера установлена последняя версия Mindustry! text.error.mismatch = Ошибка пакета:\nвозможное несоответствие версии клиента/сервера. \nУбедитесь, что у Вас и у владельца сервера установлена последняя версия Mindustry!
text.error.alreadyconnected = Вы уже подключены. text.error.alreadyconnected = Вы уже подключены.
text.error.mapnotfound = Map file not found! text.error.mapnotfound = Не найден файл карты!
text.error.any = Неизвестная сетевая ошибка. text.error.any = Неизвестная сетевая ошибка.
text.settings.language = Язык text.settings.language = Язык
text.settings.reset = Сбросить по умолчанию text.settings.reset = Сбросить по умолчанию
@@ -345,7 +345,7 @@ text.category.power = Энергия
text.category.liquids = Жидкости text.category.liquids = Жидкости
text.category.items = Предметы text.category.items = Предметы
text.category.crafting = Создание text.category.crafting = Создание
text.category.shooting = Cтрельба text.category.shooting = Стрельба
text.category.optional = Дополнительные улучшения text.category.optional = Дополнительные улучшения
setting.autotarget.name = Авто-цель setting.autotarget.name = Авто-цель
setting.fpscap.name = Макс. FPS setting.fpscap.name = Макс. FPS
@@ -407,8 +407,8 @@ mode.waves.name = Волны
mode.waves.description = Обычный режим. В режиме "Волны" надо самим добывать ресурсы и сами волны идут безостановочно. mode.waves.description = Обычный режим. В режиме "Волны" надо самим добывать ресурсы и сами волны идут безостановочно.
mode.sandbox.name = Песочница mode.sandbox.name = Песочница
mode.sandbox.description = Бесконечные ресурсы и нет таймера для волн, но можно самим вызвать волну. mode.sandbox.description = Бесконечные ресурсы и нет таймера для волн, но можно самим вызвать волну.
mode.freebuild.name = Cвободная\nстрой mode.freebuild.name = Свободная\nстройка
mode.freebuild.description = ограниченные ресурсы и нет таймера для волн. mode.freebuild.description = Ограниченные ресурсы и нет таймера для волн.
mode.pvp.name = Противо-\nстояние mode.pvp.name = Противо-\nстояние
mode.pvp.description = боритесь против других игроков. mode.pvp.description = боритесь против других игроков.
content.item.name = Предметы content.item.name = Предметы
@@ -435,7 +435,7 @@ item.silicon.description = Очень полезный полупроводни
item.plastanium.name = Пластиний item.plastanium.name = Пластиний
item.plastanium.description = Легкий, пластичный материал, используемый в современных самолетах и боеприпасах для фрагментации. item.plastanium.description = Легкий, пластичный материал, используемый в современных самолетах и боеприпасах для фрагментации.
item.phase-fabric.name = Фазовая ткань item.phase-fabric.name = Фазовая ткань
item.phase-fabric.description = Невесомое вещество, используемое в современной электронике и технологии самовосстановления. item.phase-fabric.description = Невесомое вещество, используемое в современной электронике и технологии самовосстановления. Непригодна для вышивания.
item.surge-alloy.name = Высокопрочный сплав item.surge-alloy.name = Высокопрочный сплав
item.surge-alloy.description = Передовой сплав с уникальными электрическими свойствами. item.surge-alloy.description = Передовой сплав с уникальными электрическими свойствами.
item.biomatter.name = Биоматерия item.biomatter.name = Биоматерия
@@ -461,7 +461,7 @@ mech.delta-mech.description = Быстрый, легкобронированны
mech.tau-mech.name = Тау mech.tau-mech.name = Тау
mech.tau-mech.weapon = Восстановительный лазер mech.tau-mech.weapon = Восстановительный лазер
mech.tau-mech.ability = Регенирирующая вспышка mech.tau-mech.ability = Регенирирующая вспышка
mech.tau-mech.description = Мех поддержки. Исцеляет союзные блоки, стреляя в них. Может исцелить союзников радиусом с его способностью восстанавления. mech.tau-mech.description = Мех поддержки. Чинит союзные блоки, стреляя в них. Может исцелить союзников радиусом с его способностью восстанавления.
mech.omega-mech.name = Омега mech.omega-mech.name = Омега
mech.omega-mech.weapon = Ракетомётный пулемётконфигурация mech.omega-mech.weapon = Ракетомётный пулемётконфигурация
mech.omega-mech.ability = Защитная mech.omega-mech.ability = Защитная
@@ -498,7 +498,7 @@ block.constructing = {0}[LIGHT_GRAY](В процессе)
block.spawn.name = Точка появления врагов block.spawn.name = Точка появления врагов
block.core.name = Ядро block.core.name = Ядро
block.space.name = Пустота block.space.name = Пустота
block.metalfloor.name = Мeталичeский пoл block.metalfloor.name = Металлическая плита
block.deepwater.name = Глубоководье block.deepwater.name = Глубоководье
block.water.name = Вода block.water.name = Вода
block.lava.name = Лава block.lava.name = Лава
@@ -731,8 +731,8 @@ block.solar-panel-large.description = Зелёная энергия. Больш
block.thorium-reactor.description = Производит энергию в большом количестве. Может взорваться. Требуется торий и жидкость для охлаждения (вода или криогенная). block.thorium-reactor.description = Производит энергию в большом количестве. Может взорваться. Требуется торий и жидкость для охлаждения (вода или криогенная).
block.rtg-generator.description = Радиоизотопный термоэлектрический генератор, который не требует охлаждения, но обеспечивает меньшую мощность, чем ториевый реактор. block.rtg-generator.description = Радиоизотопный термоэлектрический генератор, который не требует охлаждения, но обеспечивает меньшую мощность, чем ториевый реактор.
block.unloader.description = Выгружает из ядра или хранилища верхний левый предмет. block.unloader.description = Выгружает из ядра или хранилища верхний левый предмет.
block.container.description = Хранит небольшое количество предметов(250). Используйте его для создания буферов, когда существует непостоянная потребность в материалах. [LIGHT_GRAY] Разгрузчик[] можно использовать для извлечения элементов из хранилища. block.container.description = Хранит небольшое количество предметов(200). Используйте его для создания буферов, когда существует непостоянная потребность в материалах. [LIGHT_GRAY] Разгрузчик[] можно использовать для извлечения элементов из хранилища.
block.vault.description = Хранит большое количество предметов(1000). Используйте его для создания буферов, когда существует непостоянная потребность в материалах.[LIGHT_GRAY] Разгрузчик[] можно использовать для извлечения элементов из хранилища. block.vault.description = Хранит большое количество предметов(900). Используйте его для создания буферов, когда существует непостоянная потребность в материалах.[LIGHT_GRAY] Разгрузчик[] можно использовать для извлечения элементов из хранилища.
block.mechanical-drill.description = Самый первый доступный бур. \n\nДобывает медь, свинец, уголь, песок. \n\nМожно подвести к нему [BLUE] воду[] для увеличения скорости сверления. block.mechanical-drill.description = Самый первый доступный бур. \n\nДобывает медь, свинец, уголь, песок. \n\nМожно подвести к нему [BLUE] воду[] для увеличения скорости сверления.
block.pneumatic-drill.description = Улучшенная версия механического бура.\n\nДобывает тоже самое, что и механический бур. Также может добывать титан и камень.\n\nМожно подвести к нему[BLUE] воду[] для увеличения скорости сверления. block.pneumatic-drill.description = Улучшенная версия механического бура.\n\nДобывает тоже самое, что и механический бур. Также может добывать титан и камень.\n\nМожно подвести к нему[BLUE] воду[] для увеличения скорости сверления.
block.laser-drill.description = Улучшенная версия пневматического бура.\n\nДобывает тоже самое, что и пневматический бур. Также может добывать торий.\n\nМожно подвести к нему[BLUE] воду[] для увеличения скорости сверления. block.laser-drill.description = Улучшенная версия пневматического бура.\n\nДобывает тоже самое, что и пневматический бур. Также может добывать торий.\n\nМожно подвести к нему[BLUE] воду[] для увеличения скорости сверления.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 103 KiB

View File

@@ -24,7 +24,6 @@ ButtonStyle: {
}, },
TextButtonStyle: { TextButtonStyle: {
default: {over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: gray, down: button-down, up: button}, default: {over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: gray, down: button-down, up: button},
left: {over: button-left-over, font: default-font, fontColor: white, disabledFontColor: gray, down: button-left-down, up: button-left},
right: {over: button-right-over, font: default-font, fontColor: white, disabledFontColor: gray, down: button-right-down, up: button-right}, right: {over: button-right-over, font: default-font, fontColor: white, disabledFontColor: gray, down: button-right-down, up: button-right},
wave: {font: default-font, fontColor: white, disabledFontColor: gray, up: button-edge-4}, wave: {font: default-font, fontColor: white, disabledFontColor: gray, up: button-edge-4},
clear: {over: flat-over, font: default-font, fontColor: white, disabledFontColor: gray, down: pane, up: flat}, clear: {over: flat-over, font: default-font, fontColor: white, disabledFontColor: gray, down: pane, up: flat},
@@ -33,6 +32,7 @@ TextButtonStyle: {
clear-partial: {down: white, up: button-select, over: flat-down, font: default-font, fontColor: white, disabledFontColor: gray }, clear-partial: {down: white, up: button-select, over: flat-down, font: default-font, fontColor: white, disabledFontColor: gray },
clear-partial-2: {down: flat-over, up: none, over: flat-over, font: default-font, fontColor: white, disabledFontColor: gray }, clear-partial-2: {down: flat-over, up: none, over: flat-over, font: default-font, fontColor: white, disabledFontColor: gray },
empty: {font: default-font}, empty: {font: default-font},
clear-toggle: {font: default-font, fontColor: white, checked: flat-down, down: flat-down, up: flat, over: flat-over, disabled: flat, disabledFontColor: gray }
toggle: {font: default-font, fontColor: white, checked: button-down, down: button-down, up: button, over: button-over, disabled: button, disabledFontColor: gray } toggle: {font: default-font, fontColor: white, checked: button-down, down: button-down, up: button, over: button-over, disabled: button, disabledFontColor: gray }
}, },
ImageButtonStyle: { ImageButtonStyle: {

View File

@@ -51,8 +51,8 @@ public class BlockIndexer{
public BlockIndexer(){ public BlockIndexer(){
Events.on(TileChangeEvent.class, event -> { Events.on(TileChangeEvent.class, event -> {
if(typeMap.get(event.tile.packedPosition()) != null){ if(typeMap.get(event.tile.pos()) != null){
TileIndex index = typeMap.get(event.tile.packedPosition()); TileIndex index = typeMap.get(event.tile.pos());
for(BlockFlag flag : index.flags){ for(BlockFlag flag : index.flags){
getFlagged(index.team)[flag.ordinal()].remove(event.tile); getFlagged(index.team)[flag.ordinal()].remove(event.tile);
} }
@@ -86,7 +86,7 @@ public class BlockIndexer{
process(tile); process(tile);
if(tile.entity != null && tile.entity.healthf() < 0.9999f){ if(tile.entity != null && tile.entity.damaged()){
notifyTileDamaged(tile.entity); notifyTileDamaged(tile.entity);
} }
} }
@@ -116,7 +116,7 @@ public class BlockIndexer{
ObjectSet<Tile> set = damagedTiles[team.ordinal()]; ObjectSet<Tile> set = damagedTiles[team.ordinal()];
for(Tile tile : set){ for(Tile tile : set){
if(tile.entity == null || tile.entity.getTeam() != team || tile.entity.healthf() >= 0.9999f){ if(tile.entity == null || tile.entity.getTeam() != team || !tile.entity.damaged()){
returnArray.add(tile); returnArray.add(tile);
} }
} }
@@ -230,7 +230,7 @@ public class BlockIndexer{
map[flag.ordinal()] = arr; map[flag.ordinal()] = arr;
} }
typeMap.put(tile.packedPosition(), new TileIndex(tile.block().flags, tile.getTeam())); typeMap.put(tile.pos(), new TileIndex(tile.block().flags, tile.getTeam()));
} }
if(ores == null) return; if(ores == null) return;

View File

@@ -10,9 +10,9 @@ import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.game.Waves; import io.anuke.mindustry.game.Waves;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.core.Events; import io.anuke.ucore.core.Events;
import io.anuke.ucore.util.Structs;
import io.anuke.ucore.util.GridBits; import io.anuke.ucore.util.GridBits;
import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Structs;
import java.io.DataInput; import java.io.DataInput;
import java.io.DataOutput; import java.io.DataOutput;
@@ -21,7 +21,7 @@ import java.io.IOException;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
public class WaveSpawner{ public class WaveSpawner{
private static final int quadsize = 4; private static final int quadsize = 6;
private GridBits quadrants; private GridBits quadrants;
@@ -164,7 +164,7 @@ public class WaveSpawner{
for(int y = quady * quadsize; y < world.height() && y < (quady + 1) * quadsize; y++){ for(int y = quady * quadsize; y < world.height() && y < (quady + 1) * quadsize; y++){
Tile tile = world.tile(x, y); Tile tile = world.tile(x, y);
if(tile == null || tile.solid() || world.pathfinder.getValueforTeam(Team.red, x, y) == Float.MAX_VALUE){ if(tile == null || tile.solid() || tile.getTeam() == defaultTeam || world.pathfinder.getValueforTeam(Team.red, x, y) == Float.MAX_VALUE || tile.floor().isLiquid){
setQuad(quadx, quady, false); setQuad(quadx, quady, false);
break outer; break outer;
} }
@@ -217,8 +217,8 @@ public class WaveSpawner{
//TODO instead of randomly scattering locations around the map, find spawns close to each other //TODO instead of randomly scattering locations around the map, find spawns close to each other
private void findLocation(GroundSpawn spawn){ private void findLocation(GroundSpawn spawn){
spawn.x = -1; spawn.x = Mathf.random(quadWidth()-1);
spawn.y = -1; spawn.y = Mathf.random(quadHeight()-1);
int shellWidth = quadWidth() * 2 + quadHeight() * 2 * 6; int shellWidth = quadWidth() * 2 + quadHeight() * 2 * 6;
shellWidth = Math.min(quadWidth() * quadHeight() / 4, shellWidth); shellWidth = Math.min(quadWidth() * quadHeight() / 4, shellWidth);

View File

@@ -83,7 +83,7 @@ public class Items implements ContentList{
}}; }};
biomatter = new Item("biomatter", Color.valueOf("648b55")){{ biomatter = new Item("biomatter", Color.valueOf("648b55")){{
flammability = 0.4f; flammability = 0.55f;
fluxiness = 0.3f; fluxiness = 0.3f;
}}; }};

View File

@@ -26,7 +26,7 @@ public class Liquids implements ContentList{
lava = new Liquid("lava", Color.valueOf("e37341")){ lava = new Liquid("lava", Color.valueOf("e37341")){
{ {
temperature = 0.8f; temperature = 1f;
viscosity = 0.8f; viscosity = 0.8f;
tier = 2; tier = 2;
effect = StatusEffects.melting; effect = StatusEffects.melting;

View File

@@ -123,6 +123,7 @@ public class Mechs implements ContentList{
speed = 0.44f; speed = 0.44f;
drag = 0.35f; drag = 0.35f;
boostSpeed = 0.8f; boostSpeed = 0.8f;
canHeal = true;
weapon = Weapons.healBlaster; weapon = Weapons.healBlaster;
armor = 15f; armor = 15f;
trailColorTo = Palette.heal; trailColorTo = Palette.heal;
@@ -287,8 +288,8 @@ public class Mechs implements ContentList{
trident = new Mech("trident-ship", true){ trident = new Mech("trident-ship", true){
{ {
drillPower = 2; drillPower = 2;
speed = 0.12f; speed = 0.14f;
drag = 0.035f; drag = 0.034f;
mass = 2.5f; mass = 2.5f;
turnCursor = false; turnCursor = false;
armor = 20f; armor = 20f;

View File

@@ -42,17 +42,23 @@ public class Recipes implements ContentList{
new Recipe(defense, DefenseBlocks.surgeWall, new ItemStack(Items.surgealloy, 12)); new Recipe(defense, DefenseBlocks.surgeWall, new ItemStack(Items.surgealloy, 12));
new Recipe(defense, DefenseBlocks.surgeWallLarge, new ItemStack(Items.surgealloy, 12 * 4)); new Recipe(defense, DefenseBlocks.surgeWallLarge, new ItemStack(Items.surgealloy, 12 * 4));
new Recipe(effect, StorageBlocks.container, new ItemStack(Items.densealloy, 200));
new Recipe(effect, StorageBlocks.vault, new ItemStack(Items.densealloy, 500), new ItemStack(Items.thorium, 250));
//core disabled due to being broken
new Recipe(effect, StorageBlocks.core,
new ItemStack(Items.copper, 2000), new ItemStack(Items.densealloy, 1500),
new ItemStack(Items.silicon, 1500), new ItemStack(Items.thorium, 500),
new ItemStack(Items.surgealloy, 500), new ItemStack(Items.phasefabric, 750)
);
//projectors //projectors
new Recipe(effect, DefenseBlocks.mendProjector, new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 150), new ItemStack(Items.titanium, 50), new ItemStack(Items.silicon, 180)); new Recipe(effect, DefenseBlocks.mendProjector, new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 150), new ItemStack(Items.titanium, 50), new ItemStack(Items.silicon, 180));
new Recipe(effect, DefenseBlocks.overdriveProjector, new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 150), new ItemStack(Items.titanium, 150), new ItemStack(Items.silicon, 250)); new Recipe(effect, DefenseBlocks.overdriveProjector, new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 150), new ItemStack(Items.titanium, 150), new ItemStack(Items.silicon, 250));
new Recipe(effect, DefenseBlocks.forceProjector, new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 150), new ItemStack(Items.titanium, 150), new ItemStack(Items.silicon, 250)); new Recipe(effect, DefenseBlocks.forceProjector, new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 150), new ItemStack(Items.titanium, 150), new ItemStack(Items.silicon, 250));
new Recipe(effect, StorageBlocks.unloader, new ItemStack(Items.densealloy, 50), new ItemStack(Items.silicon, 60));
new Recipe(effect, StorageBlocks.container, new ItemStack(Items.densealloy, 200));
new Recipe(effect, StorageBlocks.vault, new ItemStack(Items.densealloy, 500), new ItemStack(Items.thorium, 250));
new Recipe(effect, DefenseBlocks.shockMine, new ItemStack(Items.lead, 50), new ItemStack(Items.silicon, 25)) new Recipe(effect, DefenseBlocks.shockMine, new ItemStack(Items.lead, 50), new ItemStack(Items.silicon, 25))
.setDependencies(Items.blastCompound); .setDependencies(Items.blastCompound);
//TURRETS //TURRETS
new Recipe(turret, TurretBlocks.duo, new ItemStack(Items.copper, 40)).setAlwaysUnlocked(true); new Recipe(turret, TurretBlocks.duo, new ItemStack(Items.copper, 40)).setAlwaysUnlocked(true);
@@ -82,6 +88,7 @@ public class Recipes implements ContentList{
new Recipe(distribution, DistributionBlocks.sorter, new ItemStack(Items.densealloy, 4), new ItemStack(Items.copper, 4)); new Recipe(distribution, DistributionBlocks.sorter, new ItemStack(Items.densealloy, 4), new ItemStack(Items.copper, 4));
new Recipe(distribution, DistributionBlocks.overflowGate, new ItemStack(Items.densealloy, 4), new ItemStack(Items.copper, 8)); new Recipe(distribution, DistributionBlocks.overflowGate, new ItemStack(Items.densealloy, 4), new ItemStack(Items.copper, 8));
new Recipe(distribution, DistributionBlocks.itemBridge, new ItemStack(Items.densealloy, 8), new ItemStack(Items.copper, 8)); new Recipe(distribution, DistributionBlocks.itemBridge, new ItemStack(Items.densealloy, 8), new ItemStack(Items.copper, 8));
new Recipe(distribution, StorageBlocks.unloader, new ItemStack(Items.densealloy, 50), new ItemStack(Items.silicon, 60));
new Recipe(distribution, DistributionBlocks.massDriver, new ItemStack(Items.densealloy, 250), new ItemStack(Items.silicon, 150), new ItemStack(Items.lead, 250), new ItemStack(Items.thorium, 100)); new Recipe(distribution, DistributionBlocks.massDriver, new ItemStack(Items.densealloy, 250), new ItemStack(Items.silicon, 150), new ItemStack(Items.lead, 250), new ItemStack(Items.thorium, 100));
//CRAFTING //CRAFTING
@@ -133,13 +140,6 @@ public class Recipes implements ContentList{
new Recipe(power, PowerBlocks.thoriumReactor, new ItemStack(Items.lead, 600), new ItemStack(Items.silicon, 400), new ItemStack(Items.densealloy, 300), new ItemStack(Items.thorium, 300)); new Recipe(power, PowerBlocks.thoriumReactor, new ItemStack(Items.lead, 600), new ItemStack(Items.silicon, 400), new ItemStack(Items.densealloy, 300), new ItemStack(Items.thorium, 300));
new Recipe(power, PowerBlocks.rtgGenerator, new ItemStack(Items.lead, 200), new ItemStack(Items.silicon, 150), new ItemStack(Items.phasefabric, 50), new ItemStack(Items.plastanium, 150), new ItemStack(Items.thorium, 100)); new Recipe(power, PowerBlocks.rtgGenerator, new ItemStack(Items.lead, 200), new ItemStack(Items.silicon, 150), new ItemStack(Items.phasefabric, 50), new ItemStack(Items.plastanium, 150), new ItemStack(Items.thorium, 100));
//core disabled due to being broken
/*new Recipe(distribution, StorageBlocks.core,
new ItemStack(Items.copper, 2000), new ItemStack(Items.densealloy, 1500),
new ItemStack(Items.silicon, 1500), new ItemStack(Items.thorium, 500),
new ItemStack(Items.surgealloy, 500), new ItemStack(Items.phasefabric, 750)
);*/
//DRILLS, PRODUCERS //DRILLS, PRODUCERS
new Recipe(production, ProductionBlocks.mechanicalDrill, new ItemStack(Items.copper, 45)).setAlwaysUnlocked(true); new Recipe(production, ProductionBlocks.mechanicalDrill, new ItemStack(Items.copper, 45)).setAlwaysUnlocked(true);
new Recipe(production, ProductionBlocks.pneumaticDrill, new ItemStack(Items.copper, 60), new ItemStack(Items.densealloy, 50)); new Recipe(production, ProductionBlocks.pneumaticDrill, new ItemStack(Items.copper, 60), new ItemStack(Items.densealloy, 50));

View File

@@ -11,7 +11,7 @@ import io.anuke.ucore.core.Timers;
import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Mathf;
public class StatusEffects implements ContentList{ public class StatusEffects implements ContentList{
public static StatusEffect none, burning, freezing, wet, melting, tarred, overdrive, shielded; public static StatusEffect none, burning, freezing, wet, melting, tarred, overdrive, shielded, shocked;
@Override @Override
public void load(){ public void load(){
@@ -47,7 +47,8 @@ public class StatusEffects implements ContentList{
freezing = new StatusEffect(5 * 60f){ freezing = new StatusEffect(5 * 60f){
{ {
oppositeScale = 0.4f; oppositeScale = 0.4f;
speedMultiplier = 0.5f; speedMultiplier = 0.6f;
armorMultiplier = 0.8f;
} }
@Override @Override
@@ -65,6 +66,17 @@ public class StatusEffects implements ContentList{
speedMultiplier = 0.9f; speedMultiplier = 0.9f;
} }
@Override
public StatusEntry getTransition(Unit unit, StatusEffect to, float time, float newTime, StatusEntry result){
if(to == shocked){
//get shocked when wet
unit.damage(15f);
return result.set(this, time);
}
return super.getTransition(unit, to, time, newTime, result);
}
@Override @Override
public void update(Unit unit, float time){ public void update(Unit unit, float time){
if(Mathf.chance(Timers.delta() * 0.15f)){ if(Mathf.chance(Timers.delta() * 0.15f)){
@@ -145,6 +157,13 @@ public class StatusEffects implements ContentList{
} }
}; };
shocked = new StatusEffect(1f){
{
armorMultiplier = 3f;
}
};
wet.setOpposites(shocked);
melting.setOpposites(wet, freezing); melting.setOpposites(wet, freezing);
wet.setOpposites(burning); wet.setOpposites(burning);
freezing.setOpposites(burning, melting); freezing.setOpposites(burning, melting);

View File

@@ -152,7 +152,7 @@ public class Weapons implements ContentList{
bomberTrident = new Weapon("bomber"){{ bomberTrident = new Weapon("bomber"){{
length = 0f; length = 0f;
width = 2f; width = 2f;
reload = 9f; reload = 8f;
shots = 2; shots = 2;
roundrobin = true; roundrobin = true;
ejectEffect = Fx.none; ejectEffect = Fx.none;

View File

@@ -185,9 +185,9 @@ public class CraftingBlocks extends BlockList implements ContentList{
biomatterCompressor = new Compressor("biomattercompressor"){{ biomatterCompressor = new Compressor("biomattercompressor"){{
liquidCapacity = 60f; liquidCapacity = 60f;
itemCapacity = 50; itemCapacity = 50;
craftTime = 25f; craftTime = 20f;
outputLiquid = Liquids.oil; outputLiquid = Liquids.oil;
outputLiquidAmount = 1.5f; outputLiquidAmount = 2.5f;
size = 2; size = 2;
health = 320; health = 320;
hasLiquids = true; hasLiquids = true;

View File

@@ -92,8 +92,11 @@ public class DebugBlocks extends BlockList implements ContentList{
@Override @Override
public void update(Tile tile){ public void update(Tile tile){
SorterEntity entity = tile.entity(); SorterEntity entity = tile.entity();
if(entity.sortItem == null) return;
entity.items.set(entity.sortItem, 1); entity.items.set(entity.sortItem, 1);
tryDump(tile, entity.sortItem); tryDump(tile, entity.sortItem);
entity.items.set(entity.sortItem, 0);
} }
@Override @Override

View File

@@ -50,10 +50,10 @@ public class LiquidBlocks extends BlockList implements ContentList{
}}; }};
liquidRouter = new LiquidRouter("liquid-router"){{ liquidRouter = new LiquidRouter("liquid-router"){{
liquidCapacity = 40f; liquidCapacity = 20f;
}}; }};
liquidtank = new LiquidRouter("liquid-tank"){{ liquidtank = new LiquidTank("liquid-tank"){{
size = 3; size = 3;
liquidCapacity = 1500f; liquidCapacity = 1500f;
health = 500; health = 500;

View File

@@ -21,7 +21,7 @@ public class PowerBlocks extends BlockList implements ContentList{
thermalGenerator = new LiquidHeatGenerator("thermal-generator"){{ thermalGenerator = new LiquidHeatGenerator("thermal-generator"){{
maxLiquidGenerate = 2f; maxLiquidGenerate = 2f;
powerCapacity = 40f; powerCapacity = 40f;
powerPerLiquid = 0.3f; powerPerLiquid = 0.35f;
generateEffect = BlockFx.redgeneratespark; generateEffect = BlockFx.redgeneratespark;
size = 2; size = 2;
}}; }};

View File

@@ -99,13 +99,13 @@ public class ProductionBlocks extends BlockList implements ContentList{
cultivator = new Cultivator("cultivator"){{ cultivator = new Cultivator("cultivator"){{
result = Items.biomatter; result = Items.biomatter;
drillTime = 260; drillTime = 200;
size = 2; size = 2;
hasLiquids = true; hasLiquids = true;
hasPower = true; hasPower = true;
consumes.power(0.08f); consumes.power(0.08f);
consumes.liquid(Liquids.water, 0.2f); consumes.liquid(Liquids.water, 0.15f);
}}; }};
} }

View File

@@ -13,20 +13,21 @@ public class StorageBlocks extends BlockList implements ContentList{
public void load(){ public void load(){
core = new CoreBlock("core"){{ core = new CoreBlock("core"){{
health = 1100; health = 1100;
itemCapacity = 3000;
}}; }};
vault = new Vault("vault"){{ vault = new Vault("vault"){{
size = 3; size = 3;
itemCapacity = 900; itemCapacity = 1000;
}}; }};
container = new Vault("container"){{ container = new Vault("container"){{
size = 2; size = 2;
itemCapacity = 200; itemCapacity = 300;
}}; }};
unloader = new SortedUnloader("unloader"){{ unloader = new SortedUnloader("unloader"){{
speed = 12f; speed = 7f;
}}; }};
} }
} }

View File

@@ -69,7 +69,7 @@ public class TurretBlocks extends BlockList implements ContentList{
inaccuracy = 5f; inaccuracy = 5f;
shootCone = 50f; shootCone = 50f;
shootEffect = ShootFx.shootLiquid; shootEffect = ShootFx.shootLiquid;
range = 70f; range = 90f;
health = 360; health = 360;
drawer = (tile, entity) -> { drawer = (tile, entity) -> {

View File

@@ -39,6 +39,8 @@ public class TurretBullets extends BulletList implements ContentList{
lifetime = Lightning.lifetime; lifetime = Lightning.lifetime;
hiteffect = BulletFx.hitLancer; hiteffect = BulletFx.hitLancer;
despawneffect = Fx.none; despawneffect = Fx.none;
status = StatusEffects.shocked;
statusIntensity = 1f;
} }
}; };
@@ -71,7 +73,7 @@ public class TurretBullets extends BulletList implements ContentList{
super.hit(b); super.hit(b);
tile = tile.target(); tile = tile.target();
if(tile.getTeam() == b.getTeam() && !(tile.block() instanceof BuildBlock)){ if(tile != null && tile.getTeam() == b.getTeam() && !(tile.block() instanceof BuildBlock)){
Effects.effect(BlockFx.healBlockFull, Palette.heal, tile.drawx(), tile.drawy(), tile.block().size); Effects.effect(BlockFx.healBlockFull, Palette.heal, tile.drawx(), tile.drawy(), tile.block().size);
tile.entity.healBy(healPercent / 100f * tile.entity.maxHealth()); tile.entity.healBy(healPercent / 100f * tile.entity.maxHealth());
} }
@@ -332,7 +334,7 @@ public class TurretBullets extends BulletList implements ContentList{
lifetime = 200f; lifetime = 200f;
despawneffect = BlockFx.smeltsmoke; despawneffect = BlockFx.smeltsmoke;
hiteffect = BulletFx.hitBulletBig; hiteffect = BulletFx.hitBulletBig;
drag = 0.01f; drag = 0.005f;
} }
@Override @Override

View File

@@ -26,7 +26,10 @@ import io.anuke.mindustry.ui.dialogs.FloatingDialog;
import io.anuke.ucore.core.*; import io.anuke.ucore.core.*;
import io.anuke.ucore.entities.EntityQuery; import io.anuke.ucore.entities.EntityQuery;
import io.anuke.ucore.modules.Module; import io.anuke.ucore.modules.Module;
import io.anuke.ucore.util.*; import io.anuke.ucore.util.Atlas;
import io.anuke.ucore.util.Bundles;
import io.anuke.ucore.util.Strings;
import io.anuke.ucore.util.Timer;
import java.io.IOException; import java.io.IOException;
@@ -372,7 +375,7 @@ public class Control extends Module{
} }
} }
if(Inputs.keyTap("screenshot")){ if(!mobile && Inputs.keyTap("screenshot") && !ui.chatfrag.chatOpen()){
renderer.takeMapScreenshot(); renderer.takeMapScreenshot();
} }

View File

@@ -79,7 +79,9 @@ public class NetServer extends Module{
public NetServer(){ public NetServer(){
Events.on(WorldLoadEvent.class, event -> { Events.on(WorldLoadEvent.class, event -> {
connections.clear(); if(!headless){
connections.clear();
}
}); });
Net.handleServer(Connect.class, (id, connect) -> { Net.handleServer(Connect.class, (id, connect) -> {
@@ -125,7 +127,7 @@ public class NetServer extends Module{
return; return;
} }
if(packet.versionType == null || ((packet.version == -1 || !packet.versionType.equals("official")) && Version.build != -1 && !admins.allowsCustomClients())){ if(packet.versionType == null || ((packet.version == -1 || !packet.versionType.equals(Version.type)) && Version.build != -1 && !admins.allowsCustomClients())){
kick(id, KickReason.customClient); kick(id, KickReason.customClient);
return; return;
} }
@@ -279,6 +281,7 @@ public class NetServer extends Module{
} }
player.remove(); player.remove();
netServer.connections.remove(player.con.id); netServer.connections.remove(player.con.id);
Log.info("&lc{0} has disconnected.", player.name);
} }
private static float compound(float speed, float drag){ private static float compound(float speed, float drag){
@@ -379,7 +382,7 @@ public class NetServer extends Module{
return; return;
} }
if(other == null || (other.isAdmin && other != player)){ //fun fact: this means you can ban yourself if(other == null || ((other.isAdmin && !player.isLocal) && other != player)){
Log.err("{0} attempted to perform admin action on nonexistant or admin player.", player.name); Log.err("{0} attempted to perform admin action on nonexistant or admin player.", player.name);
return; return;
} }
@@ -490,7 +493,7 @@ public class NetServer extends Module{
//write all core inventory data //write all core inventory data
for(Tile tile : cores){ for(Tile tile : cores){
dataStream.writeInt(tile.packedPosition()); dataStream.writeInt(tile.pos());
tile.entity.items.write(dataStream); tile.entity.items.write(dataStream);
} }
@@ -596,14 +599,18 @@ public class NetServer extends Module{
} }
void sync(){ void sync(){
try{ try{
//iterate through each player //iterate through each player
for(Player player : connections.values()){ for(int i = 0; i < playerGroup.size(); i ++){
Player player = playerGroup.all().get(i);
if(player.isLocal) continue;
NetConnection connection = player.con; NetConnection connection = player.con;
if(!connection.isConnected()){ if(!connection.isConnected() || !connections.containsKey(connection.id)){
//player disconnected, ignore them //player disconnected, call d/c event
onDisconnect(player); onDisconnect(player);
return; return;
} }

View File

@@ -32,9 +32,22 @@ public abstract class Platform {
dialog.setFillParent(true); dialog.setFillParent(true);
dialog.content().top(); dialog.content().top();
dialog.content().defaults().height(65f); dialog.content().defaults().height(65f);
TextField[] use = {null};
dialog.content().addImageButton("icon-copy", "clear", 16*3, () -> use[0].copy())
.visible(() -> !use[0].getSelection().isEmpty()).width(65f);
dialog.content().addImageButton("icon-paste", "clear", 16*3, () ->
use[0].paste(Gdx.app.getClipboard().getContents(), false))
.visible(() -> Gdx.app.getClipboard() != null && Gdx.app.getClipboard().getContents() != null && !Gdx.app.getClipboard().getContents().isEmpty()).width(65f);
TextField to = dialog.content().addField(field.getText(), t-> {}).pad(15).width(250f).get(); TextField to = dialog.content().addField(field.getText(), t-> {}).pad(15).width(250f).get();
to.setMaxLength(maxLength); to.setMaxLength(maxLength);
to.keyDown(Keys.ENTER, () -> dialog.content().find("okb").fireClick()); to.keyDown(Keys.ENTER, () -> dialog.content().find("okb").fireClick());
use[0] = to;
dialog.content().addButton("$text.ok", () -> { dialog.content().addButton("$text.ok", () -> {
field.clearText(); field.clearText();
field.appendText(to.getText()); field.appendText(to.getText());

View File

@@ -152,7 +152,7 @@ public class Renderer extends RendererModule{
if(players[0].isDead()){ if(players[0].isDead()){
TileEntity core = players[0].getClosestCore(); TileEntity core = players[0].getClosestCore();
if(core != null && players[0].spawner == -1){ if(core != null && players[0].spawner == Unit.noSpawner){
smoothCamera(core.x, core.y, 0.08f); smoothCamera(core.x, core.y, 0.08f);
}else{ }else{
smoothCamera(position.x + 0.0001f, position.y + 0.0001f, 0.08f); smoothCamera(position.x + 0.0001f, position.y + 0.0001f, 0.08f);
@@ -395,8 +395,8 @@ public class Renderer extends RendererModule{
Graphics.getEffectSurface().setSize(w, h, true); Graphics.getEffectSurface().setSize(w, h, true);
Core.camera.viewportWidth = w; Core.camera.viewportWidth = w;
Core.camera.viewportHeight = h; Core.camera.viewportHeight = h;
Core.camera.position.x = w/2f; Core.camera.position.x = w/2f + tilesize/2f;
Core.camera.position.y = h/2f; Core.camera.position.y = h/2f + tilesize/2f;
draw(); draw();

View File

@@ -15,6 +15,7 @@ import io.anuke.mindustry.io.MapIO;
import io.anuke.mindustry.maps.*; import io.anuke.mindustry.maps.*;
import io.anuke.mindustry.maps.generation.WorldGenerator; import io.anuke.mindustry.maps.generation.WorldGenerator;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Pos;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.OreBlock; import io.anuke.mindustry.world.blocks.OreBlock;
import io.anuke.ucore.core.Events; import io.anuke.ucore.core.Events;
@@ -30,8 +31,8 @@ public class World extends Module{
public final Sectors sectors = new Sectors(); public final Sectors sectors = new Sectors();
public final WorldGenerator generator = new WorldGenerator(); public final WorldGenerator generator = new WorldGenerator();
public final BlockIndexer indexer = new BlockIndexer(); public final BlockIndexer indexer = new BlockIndexer();
public final Pathfinder pathfinder = new Pathfinder();
public final WaveSpawner spawner = new WaveSpawner(); public final WaveSpawner spawner = new WaveSpawner();
public final Pathfinder pathfinder = new Pathfinder();
private Map currentMap; private Map currentMap;
private Sector currentSector; private Sector currentSector;
@@ -103,12 +104,8 @@ public class World extends Module{
return tiles == null ? 0 : tiles[0].length; return tiles == null ? 0 : tiles[0].length;
} }
public int toPacked(int x, int y){ public Tile tile(int pos){
return x + y * width(); return tiles == null ? null : tile(Pos.x(pos), Pos.y(pos));
}
public Tile tile(int packed){
return tiles == null ? null : tile(packed % width(), packed / width());
} }
public Tile tile(int x, int y){ public Tile tile(int x, int y){

View File

@@ -567,16 +567,16 @@ public class MapEditorDialog extends Dialog implements Disposable{
button.getImage().remove(); button.getImage().remove();
button.update(() -> button.setChecked(editor.getDrawBlock() == block)); button.update(() -> button.setChecked(editor.getDrawBlock() == block));
group.add(button); group.add(button);
content.add(button).size(60f); content.add(button).size(50f);
if(i++ % 3 == 2){ if(++i % 4 == 0){
content.row(); content.row();
} }
} }
group.getButtons().get(2).setChecked(true); group.getButtons().get(2).setChecked(true);
table.table("underline", extra -> extra.labelWrap(() -> editor.getDrawBlock().formalName).width(220f).center()).growX(); table.table("underline", extra -> extra.labelWrap(() -> editor.getDrawBlock().formalName).width(200f).center()).growX();
table.row(); table.row();
table.add(pane).growY().fillX(); table.add(pane).growY().fillX();
} }

View File

@@ -58,7 +58,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
public boolean achievedFlight; public boolean achievedFlight;
public Color color = new Color(); public Color color = new Color();
public Mech mech; public Mech mech;
public int spawner = -1; public int spawner = noSpawner;
public NetConnection con; public NetConnection con;
public int playerIndex = 0; public int playerIndex = 0;
@@ -498,7 +498,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
updateRespawning(); updateRespawning();
return; return;
}else{ }else{
spawner = -1; spawner = noSpawner;
} }
avoidOthers(1f); avoidOthers(1f);
@@ -645,7 +645,8 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
} }
protected void updateFlying(){ protected void updateFlying(){
if(Units.invalidateTarget(target, this)){ if(Units.invalidateTarget(target, this) && !(target instanceof TileEntity && ((TileEntity) target).damaged() && target.getTeam() == team &&
mech.canHeal && distanceTo(target) < getWeapon().getAmmo().getRange())){
target = null; target = null;
} }
@@ -726,11 +727,22 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
isShooting = false; isShooting = false;
if(Settings.getBool("autotarget")){ if(Settings.getBool("autotarget")){
target = Units.getClosestTarget(team, x, y, getWeapon().getAmmo().getRange()); target = Units.getClosestTarget(team, x, y, getWeapon().getAmmo().getRange());
if(mech.canHeal && target == null){
target = Geometry.findClosest(x, y, world.indexer.getDamaged(Team.blue));
if(target != null && distanceTo(target) > getWeapon().getAmmo().getRange()){
target = null;
}else if(target != null){
target = ((Tile)target).entity;
}
}
if(target != null){ if(target != null){
setMineTile(null); setMineTile(null);
} }
} }
}else if(target.isValid()){ }else if(target.isValid() || (target instanceof TileEntity && ((TileEntity) target).damaged() && target.getTeam() == team &&
mech.canHeal && distanceTo(target) < getWeapon().getAmmo().getRange())){
//rotate toward and shoot the target //rotate toward and shoot the target
if(mech.turnCursor){ if(mech.turnCursor){
rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.2f); rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.2f);
@@ -788,23 +800,23 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
public void updateRespawning(){ public void updateRespawning(){
if(spawner != -1 && world.tile(spawner) != null && world.tile(spawner).entity instanceof SpawnerTrait){ if(spawner != noSpawner && world.tile(spawner) != null && world.tile(spawner).entity instanceof SpawnerTrait){
((SpawnerTrait) world.tile(spawner).entity).updateSpawning(this); ((SpawnerTrait) world.tile(spawner).entity).updateSpawning(this);
}else{ }else{
CoreEntity entity = (CoreEntity) getClosestCore(); CoreEntity entity = (CoreEntity) getClosestCore();
if(entity != null && !netServer.isWaitingForPlayers()){ if(entity != null && !netServer.isWaitingForPlayers()){
this.spawner = entity.tile.id(); this.spawner = entity.tile.pos();
} }
} }
} }
public void beginRespawning(SpawnerTrait spawner){ public void beginRespawning(SpawnerTrait spawner){
this.spawner = spawner.getTile().packedPosition(); this.spawner = spawner.getTile().pos();
this.dead = true; this.dead = true;
} }
public void endRespawning(){ public void endRespawning(){
spawner = -1; spawner = noSpawner;
} }
//endregion //endregion
@@ -860,7 +872,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
buffer.writeByte(Bits.toByte(isAdmin) | (Bits.toByte(dead) << 1) | (Bits.toByte(isBoosting) << 2)); buffer.writeByte(Bits.toByte(isAdmin) | (Bits.toByte(dead) << 1) | (Bits.toByte(isBoosting) << 2));
buffer.writeInt(Color.rgba8888(color)); buffer.writeInt(Color.rgba8888(color));
buffer.writeByte(mech.id); buffer.writeByte(mech.id);
buffer.writeInt(mining == null ? -1 : mining.packedPosition()); buffer.writeInt(mining == null ? -1 : mining.pos());
buffer.writeInt(spawner); buffer.writeInt(spawner);
buffer.writeShort((short) (baseRotation * 2)); buffer.writeShort((short) (baseRotation * 2));

View File

@@ -154,6 +154,10 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
} }
} }
public boolean damaged(){
return health < maxHealth() - 0.00001f;
}
public Tile getTile(){ public Tile getTile(){
return tile; return tile;
} }

View File

@@ -12,6 +12,7 @@ import io.anuke.mindustry.net.Interpolator;
import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.type.StatusEffect; import io.anuke.mindustry.type.StatusEffect;
import io.anuke.mindustry.type.Weapon; import io.anuke.mindustry.type.Weapon;
import io.anuke.mindustry.world.Pos;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.Floor; import io.anuke.mindustry.world.blocks.Floor;
import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Effects;
@@ -39,6 +40,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
public static final float velocityPercision = 8f; public static final float velocityPercision = 8f;
/**Maximum absolute value of a velocity vector component.*/ /**Maximum absolute value of a velocity vector component.*/
public static final float maxAbsVelocity = 127f / velocityPercision; public static final float maxAbsVelocity = 127f / velocityPercision;
public static final int noSpawner = Pos.get(-1, 1);
private static final Rectangle queryRect = new Rectangle(); private static final Rectangle queryRect = new Rectangle();
private static final Vector2 moveVector = new Vector2(); private static final Vector2 moveVector = new Vector2();

View File

@@ -48,7 +48,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{
public static void create(Tile tile){ public static void create(Tile tile){
if(Net.client() || tile == null) return; //not clientside. if(Net.client() || tile == null) return; //not clientside.
Fire fire = map.get(tile.packedPosition()); Fire fire = map.get(tile.pos());
if(fire == null){ if(fire == null){
fire = Pooling.obtain(Fire.class, Fire::new); fire = Pooling.obtain(Fire.class, Fire::new);
@@ -56,7 +56,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{
fire.lifetime = baseLifetime; fire.lifetime = baseLifetime;
fire.set(tile.worldx(), tile.worldy()); fire.set(tile.worldx(), tile.worldy());
fire.add(); fire.add();
map.put(tile.packedPosition(), fire); map.put(tile.pos(), fire);
}else{ }else{
fire.lifetime = baseLifetime; fire.lifetime = baseLifetime;
fire.time = 0f; fire.time = 0f;
@@ -75,8 +75,8 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{
* Attempts to extinguish a fire by shortening its life. If there is no fire here, does nothing. * Attempts to extinguish a fire by shortening its life. If there is no fire here, does nothing.
*/ */
public static void extinguish(Tile tile, float intensity){ public static void extinguish(Tile tile, float intensity){
if(tile != null && map.containsKey(tile.packedPosition())){ if(tile != null && map.containsKey(tile.pos())){
map.get(tile.packedPosition()).time += intensity * Timers.delta(); map.get(tile.pos()).time += intensity * Timers.delta();
} }
} }
@@ -157,7 +157,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{
@Override @Override
public void writeSave(DataOutput stream) throws IOException{ public void writeSave(DataOutput stream) throws IOException{
stream.writeInt(tile.packedPosition()); stream.writeInt(tile.pos());
stream.writeFloat(lifetime); stream.writeFloat(lifetime);
stream.writeFloat(time); stream.writeFloat(time);
} }
@@ -202,7 +202,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{
@Override @Override
public void removed(){ public void removed(){
if(tile != null){ if(tile != null){
map.remove(tile.packedPosition()); map.remove(tile.pos());
} }
reset(); reset();
} }

View File

@@ -6,7 +6,7 @@ import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Effects.Effect; import io.anuke.ucore.core.Effects.Effect;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
import io.anuke.ucore.entities.impl.EffectEntity; import io.anuke.ucore.entities.impl.EffectEntity;
import io.anuke.ucore.function.EffectRenderer; import io.anuke.ucore.core.Effects.EffectRenderer;
import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Mathf;
/** /**

View File

@@ -91,7 +91,6 @@ public class Lightning extends TimedEntity implements DrawTrait, SyncTrait, Time
x += Angles.trnsx(rotation, hitRange/2f); x += Angles.trnsx(rotation, hitRange/2f);
y += Angles.trnsy(rotation, hitRange/2f); y += Angles.trnsy(rotation, hitRange/2f);
} }
} }
} }

View File

@@ -73,7 +73,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
/**Returns the puddle on the specified tile. May return null.*/ /**Returns the puddle on the specified tile. May return null.*/
public static Puddle getPuddle(Tile tile){ public static Puddle getPuddle(Tile tile){
return map.get(tile.packedPosition()); return map.get(tile.pos());
} }
private static void deposit(Tile tile, Tile source, Liquid liquid, float amount, int generation){ private static void deposit(Tile tile, Tile source, Liquid liquid, float amount, int generation){
@@ -83,7 +83,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
reactPuddle(tile.floor().liquidDrop, liquid, amount, tile, reactPuddle(tile.floor().liquidDrop, liquid, amount, tile,
(tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f); (tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f);
Puddle p = map.get(tile.packedPosition()); Puddle p = map.get(tile.pos());
if(generation == 0 && p != null && p.lastRipple <= Timers.time() - 40f){ if(generation == 0 && p != null && p.lastRipple <= Timers.time() - 40f){
Effects.effect(BlockFx.ripple, tile.floor().liquidDrop.color, Effects.effect(BlockFx.ripple, tile.floor().liquidDrop.color,
@@ -93,7 +93,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
return; return;
} }
Puddle p = map.get(tile.packedPosition()); Puddle p = map.get(tile.pos());
if(p == null){ if(p == null){
if(Net.client()) return; //not clientside. if(Net.client()) return; //not clientside.
@@ -104,7 +104,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
puddle.generation = (byte) generation; puddle.generation = (byte) generation;
puddle.set((tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f); puddle.set((tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f);
puddle.add(); puddle.add();
map.put(tile.packedPosition(), puddle); map.put(tile.pos(), puddle);
}else if(p.liquid == liquid){ }else if(p.liquid == liquid){
p.accepting = Math.max(amount, p.accepting); p.accepting = Math.max(amount, p.accepting);
@@ -249,7 +249,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
@Override @Override
public void writeSave(DataOutput stream) throws IOException{ public void writeSave(DataOutput stream) throws IOException{
stream.writeInt(tile.packedPosition()); stream.writeInt(tile.pos());
stream.writeFloat(x); stream.writeFloat(x);
stream.writeFloat(y); stream.writeFloat(y);
stream.writeByte(liquid.id); stream.writeByte(liquid.id);
@@ -288,7 +288,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
@Override @Override
public void removed(){ public void removed(){
map.remove(tile.packedPosition()); map.remove(tile.pos());
reset(); reset();
} }
@@ -298,7 +298,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
data.writeFloat(y); data.writeFloat(y);
data.writeByte(liquid.id); data.writeByte(liquid.id);
data.writeShort((short) (amount * 4)); data.writeShort((short) (amount * 4));
data.writeInt(tile.packedPosition()); data.writeInt(tile.pos());
} }
@Override @Override
@@ -309,7 +309,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
targetAmount = data.readShort() / 4f; targetAmount = data.readShort() / 4f;
tile = world.tile(data.readInt()); tile = world.tile(data.readInt());
map.put(tile.packedPosition(), this); map.put(tile.pos(), this);
} }
@Override @Override

View File

@@ -16,6 +16,7 @@ import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.Recipe; import io.anuke.mindustry.type.Recipe;
import io.anuke.mindustry.world.Build; import io.anuke.mindustry.world.Build;
import io.anuke.mindustry.world.Pos;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.BuildBlock; import io.anuke.mindustry.world.blocks.BuildBlock;
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity; import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
@@ -27,7 +28,10 @@ import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Fill; import io.anuke.ucore.graphics.Fill;
import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.graphics.Shapes; import io.anuke.ucore.graphics.Shapes;
import io.anuke.ucore.util.*; import io.anuke.ucore.util.Angles;
import io.anuke.ucore.util.Geometry;
import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Translator;
import java.io.DataInput; import java.io.DataInput;
import java.io.DataOutput; import java.io.DataOutput;
@@ -72,7 +76,7 @@ public interface BuilderTrait extends Entity{
if(request != null){ if(request != null){
output.writeByte(request.breaking ? 1 : 0); output.writeByte(request.breaking ? 1 : 0);
output.writeInt(world.toPacked(request.x, request.y)); output.writeInt(Pos.get(request.x, request.y));
output.writeFloat(request.progress); output.writeFloat(request.progress);
if(!request.breaking){ if(!request.breaking){
output.writeByte(request.recipe.id); output.writeByte(request.recipe.id);
@@ -96,13 +100,13 @@ public interface BuilderTrait extends Entity{
float progress = input.readFloat(); float progress = input.readFloat();
BuildRequest request; BuildRequest request;
if(type == 1){ //remove if(type == 1){ //remove
request = new BuildRequest(position % world.width(), position / world.width()); request = new BuildRequest(Pos.x(position), Pos.y(position));
}else{ //place }else{ //place
byte recipe = input.readByte(); byte recipe = input.readByte();
byte rotation = input.readByte(); byte rotation = input.readByte();
request = new BuildRequest(position % world.width(), position / world.width(), rotation, content.recipe(recipe)); request = new BuildRequest(Pos.x(position), Pos.y(position), rotation, content.recipe(recipe));
} }
request.progress = progress; request.progress = progress;

View File

@@ -52,7 +52,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
protected boolean isWave; protected boolean isWave;
protected Squad squad; protected Squad squad;
protected int spawner = -1; protected int spawner = noSpawner;
/**internal constructor used for deserialization, DO NOT USE*/ /**internal constructor used for deserialization, DO NOT USE*/
public BaseUnit(){ public BaseUnit(){
@@ -111,16 +111,8 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
return type; return type;
} }
public Tile getSpawner(){
return world.tile(spawner);
}
public void setSpawner(Tile tile){ public void setSpawner(Tile tile){
this.spawner = tile.packedPosition(); this.spawner = tile.pos();
}
public void setIntSpawner(int pos){
this.spawner = pos;
} }
/**Sets this to a 'wave' unit, which means it has slightly different AI and will not run out of ammo.*/ /**Sets this to a 'wave' unit, which means it has slightly different AI and will not run out of ammo.*/
@@ -143,7 +135,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
} }
public void updateRespawning(){ public void updateRespawning(){
if(spawner == -1) return; if(spawner == noSpawner) return;
Tile tile = world.tile(spawner); Tile tile = world.tile(spawner);
if(tile != null && tile.entity != null){ if(tile != null && tile.entity != null){
@@ -151,7 +143,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
((SpawnerTrait) tile.entity).updateSpawning(this); ((SpawnerTrait) tile.entity).updateSpawning(this);
} }
}else{ }else{
spawner = -1; spawner = noSpawner;
} }
} }
@@ -305,7 +297,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
avoidOthers(1.25f); avoidOthers(1.25f);
if(spawner != -1 && (world.tile(spawner) == null || world.tile(spawner).entity == null)){ if(spawner != noSpawner && (world.tile(spawner) == null || world.tile(spawner).entity == null)){
damage(health); damage(health);
} }
@@ -336,7 +328,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
@Override @Override
public void removed(){ public void removed(){
spawner = -1; spawner = noSpawner;
} }
@Override @Override

View File

@@ -358,8 +358,8 @@ public class Drone extends FlyingUnit implements BuilderTrait{
@Override @Override
public void write(DataOutput data) throws IOException{ public void write(DataOutput data) throws IOException{
super.write(data); super.write(data);
data.writeInt(mineTile == null || !state.is(mine) ? -1 : mineTile.packedPosition()); data.writeInt(mineTile == null || !state.is(mine) ? -1 : mineTile.pos());
data.writeInt(state.is(repair) && target instanceof TileEntity ? ((TileEntity)target).tile.packedPosition() : -1); data.writeInt(state.is(repair) && target instanceof TileEntity ? ((TileEntity)target).tile.pos() : -1);
writeBuilding(data); writeBuilding(data);
} }

View File

@@ -3,7 +3,7 @@ package io.anuke.mindustry.game;
import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.traits.BuilderTrait; import io.anuke.mindustry.entities.traits.BuilderTrait;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.function.Event; import io.anuke.ucore.core.Events.Event;
public class EventType{ public class EventType{

View File

@@ -11,9 +11,8 @@ public enum GameMode{
freebuild{{ freebuild{{
disableWaveTimer = true; disableWaveTimer = true;
}}, }},
noWaves{{ attack{{
disableWaves = true; disableWaves = true;
hidden = true;
enemyCheat = true; enemyCheat = true;
}}, }},
victory{{ victory{{

View File

@@ -127,6 +127,7 @@ public class Saves{
saveMap.put(slot.index, slot); saveMap.put(slot.index, slot);
slot.meta = SaveIO.getData(slot.index); slot.meta = SaveIO.getData(slot.index);
current = slot; current = slot;
slot.meta.sector = invalidSector;
saveSlots(); saveSlots();
return slot; return slot;
} }
@@ -164,26 +165,17 @@ public class Saves{
public void save(){ public void save(){
long time = totalPlaytime; long time = totalPlaytime;
renderer.fog.writeFog();
long prev = totalPlaytime;
totalPlaytime = time;
threads.runGraphics(() -> { SaveIO.saveToSlot(index);
//Renderer fog needs to be written on graphics thread, but save() can run on logic thread meta = SaveIO.getData(index);
//thus, runGraphics is required here if(!state.is(State.menu)){
renderer.fog.writeFog(); current = this;
}
//save on the logic thread totalPlaytime = prev;
threads.run(() -> {
long prev = totalPlaytime;
totalPlaytime = time;
SaveIO.saveToSlot(index);
meta = SaveIO.getData(index);
if(!state.is(State.menu)){
current = this;
}
totalPlaytime = prev;
});
});
} }
public boolean isHidden(){ public boolean isHidden(){

View File

@@ -1,8 +1,6 @@
package io.anuke.mindustry.game; package io.anuke.mindustry.game;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ObjectMap; import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.ObjectMap.Entry;
import com.badlogic.gdx.utils.ObjectSet; import com.badlogic.gdx.utils.ObjectSet;
import io.anuke.mindustry.game.EventType.UnlockEvent; import io.anuke.mindustry.game.EventType.UnlockEvent;
import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.ContentType;
@@ -67,27 +65,8 @@ public class Unlocks{
save(); save();
} }
/**Loads 'legacy' unlocks. Will be removed in final release.*/
public void tryLoadLegacy(){
try{
ObjectMap<String, ObjectMap<ContentType, Array<String>>> sets = Settings.getObject("content-sets", ObjectMap.class, ObjectMap::new);
for(Entry<ContentType, Array<String>> entry : sets.get("root").entries()){
unlocked.put(entry.key, new ObjectSet<>());
unlocked.get(entry.key).addAll(entry.value);
}
}catch(Throwable t){
t.printStackTrace();
}
Settings.prefs().remove("content-sets");
Settings.save();
}
public void load(){ public void load(){
unlocked = Settings.getObject("unlockset", ObjectMap.class, ObjectMap::new); unlocked = Settings.getObject("unlockset", ObjectMap.class, ObjectMap::new);
if(Settings.has("content-sets")){
tryLoadLegacy();
}
} }
public void save(){ public void save(){

View File

@@ -96,6 +96,14 @@ public class Waves{
max = 10; max = 10;
}}, }},
new SpawnGroup(UnitTypes.fortress){{
begin = 40;
spacing = 5;
unitAmount = 2;
unitScaling = 3;
max = 10;
}},
new SpawnGroup(UnitTypes.dagger){{ new SpawnGroup(UnitTypes.dagger){{
begin = 35; begin = 35;
spacing = 3; spacing = 3;
@@ -134,6 +142,15 @@ public class Waves{
max = 8; max = 8;
}}, }},
new SpawnGroup(UnitTypes.revenant){{
begin = 50;
unitAmount = 4;
unitScaling = 3;
spacing = 5;
groupAmount = 2;
max = 8;
}},
new SpawnGroup(UnitTypes.ghoul){{ new SpawnGroup(UnitTypes.ghoul){{
begin = 53; begin = 53;
unitAmount = 2; unitAmount = 2;

View File

@@ -77,9 +77,11 @@ public class FogRenderer implements Disposable{
pixelBuffer.position(0); pixelBuffer.position(0);
for(int i = 0; i < world.width() * world.height(); i++){ for(int i = 0; i < world.width() * world.height(); i++){
int x = i % world.width();
int y = i / world.width();
byte r = pixelBuffer.get(); byte r = pixelBuffer.get();
if(r != 0){ if(r != 0){
world.tile(i).setVisibility((byte)1); world.tile(x, y).setVisibility((byte)1);
} }
pixelBuffer.position(pixelBuffer.position() + 3); pixelBuffer.position(pixelBuffer.position() + 3);
} }
@@ -128,10 +130,12 @@ public class FogRenderer implements Disposable{
changeQueue.clear(); changeQueue.clear();
if(dirty){ if(dirty){
for(int i = 0; i < world.width() * world.height(); i++){ for(int x = 0; x < world.width(); x++){
Tile tile = world.tile(i); for(int y = 0; y < world.height(); y++){
if(tile.discovered()){ Tile tile = world.tile(x, y);
Fill.rect(tile.worldx(), tile.worldy(), tilesize, tilesize); if(tile.discovered()){
Fill.rect(tile.worldx(), tile.worldy(), tilesize, tilesize);
}
} }
} }
dirty = false; dirty = false;

View File

@@ -200,9 +200,10 @@ public class OverlayRenderer{
} }
void drawBar(Color color, float x, float y, float finion){ void drawBar(Color color, float x, float y, float finion){
if(finion > 0.9f) finion = 1f; //fixes precision errors
finion = Mathf.clamp(finion); finion = Mathf.clamp(finion);
if(finion > 0) finion = Mathf.clamp(finion + 0.2f, 0.24f, 1f); if(finion > 0.001f) finion = Mathf.clamp(finion, 0.24f, 1f);
float len = 3; float len = 3;

View File

@@ -95,7 +95,7 @@ public abstract class InputHandler extends InputAdapter{
ItemTransfer.create(item, ItemTransfer.create(item,
player.x + Angles.trnsx(player.rotation + 180f, backTrns), player.y + Angles.trnsy(player.rotation + 180f, backTrns), player.x + Angles.trnsx(player.rotation + 180f, backTrns), player.y + Angles.trnsy(player.rotation + 180f, backTrns),
new Translator(tile.drawx() + stackTrns.x, tile.drawy() + stackTrns.y), () -> { new Translator(tile.drawx() + stackTrns.x, tile.drawy() + stackTrns.y), () -> {
if(tile.block() != block || tile.entity == null) return; if(tile.block() != block || tile.entity == null || tile.entity.items == null) return;
tile.block().handleStack(item, removed, tile, player); tile.block().handleStack(item, removed, tile, player);
remaining[1] -= removed; remaining[1] -= removed;

View File

@@ -96,6 +96,9 @@ public class MobileInput extends InputHandler implements GestureListener{
TileEntity entity = tile.entity; TileEntity entity = tile.entity;
player.setMineTile(null); player.setMineTile(null);
player.target = entity; player.target = entity;
}else if(tile != null && player.mech.canHeal && tile.entity != null && tile.getTeam() == player.getTeam() && tile.entity.damaged()){
player.setMineTile(null);
player.target = tile.entity;
} }
} }
} }
@@ -221,11 +224,6 @@ public class MobileInput extends InputHandler implements GestureListener{
} }
}).update(l -> l.setChecked(mode == breaking)); }).update(l -> l.setChecked(mode == breaking));
//rotate button
table.addImageButton("icon-arrow", "clear-partial", 16 * 2f, () -> rotation = Mathf.mod(rotation + 1, 4))
.update(i -> i.getImage().setRotationOrigin(rotation * 90, Align.center))
.visible(() -> recipe != null && recipe.result.rotate);
//cancel button //cancel button
table.addImageButton("icon-cancel", "clear-partial", 16 * 2f, () -> { table.addImageButton("icon-cancel", "clear-partial", 16 * 2f, () -> {
player.clearBuilding(); player.clearBuilding();
@@ -233,6 +231,11 @@ public class MobileInput extends InputHandler implements GestureListener{
recipe = null; recipe = null;
}).visible(() -> player.isBuilding() || recipe != null || mode == breaking); }).visible(() -> player.isBuilding() || recipe != null || mode == breaking);
//rotate button
table.addImageButton("icon-arrow", "clear-partial", 16 * 2f, () -> rotation = Mathf.mod(rotation + 1, 4))
.update(i -> i.getImage().setRotationOrigin(rotation * 90, Align.center))
.visible(() -> recipe != null && recipe.result.rotate);
//confirm button //confirm button
table.addImageButton("icon-check", "clear-partial", 16 * 2f, () -> { table.addImageButton("icon-check", "clear-partial", 16 * 2f, () -> {
for(PlaceRequest request : selection){ for(PlaceRequest request : selection){
@@ -242,8 +245,10 @@ public class MobileInput extends InputHandler implements GestureListener{
if(tile != null){ if(tile != null){
if(!request.remove){ if(!request.remove){
rotation = request.rotation; rotation = request.rotation;
Recipe before = recipe;
recipe = request.recipe; recipe = request.recipe;
tryPlaceBlock(tile.x, tile.y); tryPlaceBlock(tile.x, tile.y);
recipe = before;
}else{ }else{
tryBreakBlock(tile.x, tile.y); tryBreakBlock(tile.x, tile.y);
} }
@@ -596,6 +601,10 @@ public class MobileInput extends InputHandler implements GestureListener{
showGuide("construction"); showGuide("construction");
} }
if(recipe == null && mode == placing){
mode = none;
}
//automatically switch to placing after a new recipe is selected //automatically switch to placing after a new recipe is selected
if(lastRecipe != recipe && mode == breaking && recipe != null){ if(lastRecipe != recipe && mode == breaking && recipe != null){
mode = placing; mode = placing;

View File

@@ -50,7 +50,7 @@ public abstract class SaveFileVersion{
stream.writeShort(world.height()); stream.writeShort(world.height());
for(int i = 0; i < world.width() * world.height(); i++){ for(int i = 0; i < world.width() * world.height(); i++){
Tile tile = world.tile(i); Tile tile = world.tile(i % world.width(), i / world.width());
stream.writeByte(tile.getFloorID()); stream.writeByte(tile.getFloorID());
stream.writeByte(tile.getBlockID()); stream.writeByte(tile.getBlockID());
@@ -73,7 +73,7 @@ public abstract class SaveFileVersion{
int consecutives = 0; int consecutives = 0;
for(int j = i + 1; j < world.width() * world.height() && consecutives < 255; j++){ for(int j = i + 1; j < world.width() * world.height() && consecutives < 255; j++){
Tile nextTile = world.tile(j); Tile nextTile = world.tile(j % world.width(), j / world.width());
if(nextTile.getFloorID() != tile.getFloorID() || nextTile.block() != Blocks.air || nextTile.getElevation() != tile.getElevation()){ if(nextTile.getFloorID() != tile.getFloorID() || nextTile.block() != Blocks.air || nextTile.getElevation() != tile.getElevation()){
break; break;
@@ -89,13 +89,13 @@ public abstract class SaveFileVersion{
//write visibility, length-run encoded //write visibility, length-run encoded
for(int i = 0; i < world.width() * world.height(); i++){ for(int i = 0; i < world.width() * world.height(); i++){
Tile tile = world.tile(i); Tile tile = world.tile(i % world.width(), i / world.width());
boolean discovered = tile.discovered(); boolean discovered = tile.discovered();
int consecutives = 0; int consecutives = 0;
for(int j = i + 1; j < world.width() * world.height() && consecutives < 32767*2-1; j++){ for(int j = i + 1; j < world.width() * world.height() && consecutives < 32767*2-1; j++){
Tile nextTile = world.tile(j); Tile nextTile = world.tile(j % world.width(), j / world.width());
if(nextTile.discovered() != discovered){ if(nextTile.discovered() != discovered){
break; break;

View File

@@ -14,7 +14,7 @@ import java.util.zip.InflaterInputStream;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
public class SaveIO{ public class SaveIO{
public static final IntArray breakingVersions = IntArray.with(47, 48, 49, 50, 51, 52, 53, 54, 55, 56); public static final IntArray breakingVersions = IntArray.with(47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58);
public static final IntMap<SaveFileVersion> versions = new IntMap<>(); public static final IntMap<SaveFileVersion> versions = new IntMap<>();
public static final Array<SaveFileVersion> versionArray = Array.with( public static final Array<SaveFileVersion> versionArray = Array.with(
new Save16() new Save16()

View File

@@ -18,6 +18,7 @@ import io.anuke.mindustry.net.Packets.AdminAction;
import io.anuke.mindustry.net.Packets.KickReason; import io.anuke.mindustry.net.Packets.KickReason;
import io.anuke.mindustry.type.*; import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Pos;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Effects.Effect; import io.anuke.ucore.core.Effects.Effect;
@@ -52,6 +53,10 @@ public class TypeIO{
@WriteClass(Unit.class) @WriteClass(Unit.class)
public static void writeUnit(ByteBuffer buffer, Unit unit){ public static void writeUnit(ByteBuffer buffer, Unit unit){
if(unit.getGroup() == null){
buffer.put((byte)-1);
return;
}
buffer.put((byte) unit.getGroup().getID()); buffer.put((byte) unit.getGroup().getID());
buffer.putInt(unit.getID()); buffer.putInt(unit.getID());
} }
@@ -59,6 +64,7 @@ public class TypeIO{
@ReadClass(Unit.class) @ReadClass(Unit.class)
public static Unit readUnit(ByteBuffer buffer){ public static Unit readUnit(ByteBuffer buffer){
byte gid = buffer.get(); byte gid = buffer.get();
if(gid == -1) return null;
int id = buffer.getInt(); int id = buffer.getInt();
return (Unit) Entities.getGroup(gid).getByID(id); return (Unit) Entities.getGroup(gid).getByID(id);
} }
@@ -142,13 +148,12 @@ public class TypeIO{
@WriteClass(Tile.class) @WriteClass(Tile.class)
public static void writeTile(ByteBuffer buffer, Tile tile){ public static void writeTile(ByteBuffer buffer, Tile tile){
buffer.putInt(tile == null ? -1 : tile.packedPosition()); buffer.putInt(tile == null ? Pos.get(-1, -1) : tile.pos());
} }
@ReadClass(Tile.class) @ReadClass(Tile.class)
public static Tile readTile(ByteBuffer buffer){ public static Tile readTile(ByteBuffer buffer){
int position = buffer.getInt(); return world.tile(buffer.getInt());
return position == -1 ? null : world.tile(position);
} }
@WriteClass(Block.class) @WriteClass(Block.class)
@@ -166,7 +171,7 @@ public class TypeIO{
buffer.putShort((short)requests.length); buffer.putShort((short)requests.length);
for(BuildRequest request : requests){ for(BuildRequest request : requests){
buffer.put(request.breaking ? (byte) 1 : 0); buffer.put(request.breaking ? (byte) 1 : 0);
buffer.putInt(world.toPacked(request.x, request.y)); buffer.putInt(Pos.get(request.x, request.y));
if(!request.breaking){ if(!request.breaking){
buffer.put(request.recipe.id); buffer.put(request.recipe.id);
buffer.put((byte) request.rotation); buffer.put((byte) request.rotation);
@@ -184,11 +189,11 @@ public class TypeIO{
BuildRequest currentRequest; BuildRequest currentRequest;
if(type == 1){ //remove if(type == 1){ //remove
currentRequest = new BuildRequest(position % world.width(), position / world.width()); currentRequest = new BuildRequest(Pos.x(position), Pos.y(position));
}else{ //place }else{ //place
byte recipe = buffer.get(); byte recipe = buffer.get();
byte rotation = buffer.get(); byte rotation = buffer.get();
currentRequest = new BuildRequest(position % world.width(), position / world.width(), rotation, content.recipe(recipe)); currentRequest = new BuildRequest(Pos.x(position), Pos.y(position), rotation, content.recipe(recipe));
} }
reqs[i] = (currentRequest); reqs[i] = (currentRequest);

View File

@@ -59,7 +59,7 @@ public class Save16 extends SaveFileVersion{
stream.writeLong(TimeUtils.millis()); //last saved stream.writeLong(TimeUtils.millis()); //last saved
stream.writeLong(headless ? 0 : control.saves.getTotalPlaytime()); //playtime stream.writeLong(headless ? 0 : control.saves.getTotalPlaytime()); //playtime
stream.writeInt(Version.build); //build stream.writeInt(Version.build); //build
stream.writeInt(world.getSector() == null ? invalidSector : world.getSector().packedPosition()); //sector ID stream.writeInt(world.getSector() == null ? invalidSector : world.getSector().pos()); //sector ID
//--GENERAL STATE-- //--GENERAL STATE--
stream.writeByte(state.mode.ordinal()); //gamemode stream.writeByte(state.mode.ordinal()); //gamemode

View File

@@ -67,7 +67,7 @@ public class Sector{
return !headless && control.saves.getByID(saveID) != null; return !headless && control.saves.getByID(saveID) != null;
} }
public int packedPosition(){ public int pos(){
return Bits.packInt(x, y); return Bits.packInt(x, y);
} }
} }

View File

@@ -53,7 +53,7 @@ public class Sectors{
world.loadSector(sector); world.loadSector(sector);
logic.play(); logic.play();
if(!headless){ if(!headless){
sector.saveID = control.saves.addSave("sector-" + sector.packedPosition()).index; sector.saveID = control.saves.addSave("sector-" + sector.pos()).index;
} }
world.sectors.save(); world.sectors.save();
world.setSector(sector); world.setSector(sector);

View File

@@ -17,6 +17,7 @@ import io.anuke.mindustry.maps.Sector;
import io.anuke.mindustry.maps.missions.Mission; import io.anuke.mindustry.maps.missions.Mission;
import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Pos;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.Floor; import io.anuke.mindustry.world.blocks.Floor;
import io.anuke.mindustry.world.blocks.OreBlock; import io.anuke.mindustry.world.blocks.OreBlock;
@@ -86,7 +87,7 @@ public class WorldGenerator{
Tile tile = tiles[x][y]; Tile tile = tiles[x][y];
if(tile.block().isMultiblock()){ if(tile.block().isMultiblock()){
multiblocks.add(tile.packedPosition()); multiblocks.add(tile.pos());
} }
} }
} }
@@ -95,8 +96,8 @@ public class WorldGenerator{
for(int i = 0; i < multiblocks.size; i++){ for(int i = 0; i < multiblocks.size; i++){
int pos = multiblocks.get(i); int pos = multiblocks.get(i);
int x = pos % tiles.length; int x = Pos.x(pos);
int y = pos / tiles.length; int y = Pos.y(pos);
Block result = tiles[x][y].block(); Block result = tiles[x][y].block();
Team team = tiles[x][y].getTeam(); Team team = tiles[x][y].getTeam();

View File

@@ -38,7 +38,7 @@ public class BattleMission extends MissionWithStartingCore{
@Override @Override
public GameMode getMode(){ public GameMode getMode(){
return GameMode.noWaves; return GameMode.attack;
} }
@Override @Override

View File

@@ -2,10 +2,8 @@ package io.anuke.mindustry.maps.missions;
import com.badlogic.gdx.math.GridPoint2; import com.badlogic.gdx.math.GridPoint2;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.content.blocks.StorageBlocks;
import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.game.GameMode;
import io.anuke.mindustry.game.SpawnGroup; import io.anuke.mindustry.game.SpawnGroup;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.game.UnlockableContent; import io.anuke.mindustry.game.UnlockableContent;
import io.anuke.mindustry.maps.Sector; import io.anuke.mindustry.maps.Sector;
import io.anuke.mindustry.maps.generation.Generation; import io.anuke.mindustry.maps.generation.Generation;
@@ -34,7 +32,7 @@ public abstract class Mission{
} }
public GameMode getMode(){ public GameMode getMode(){
return GameMode.noWaves; return GameMode.attack;
} }
/**Sets the message displayed on mission begin. Returns this mission for chaining.*/ /**Sets the message displayed on mission begin. Returns this mission for chaining.*/

View File

@@ -42,6 +42,13 @@ public abstract class MissionWithStartingCore extends Mission{
startingCoreTile.setBlock(StorageBlocks.core); startingCoreTile.setBlock(StorageBlocks.core);
startingCoreTile.setTeam(team); startingCoreTile.setTeam(team);
state.teams.get(team).cores.add(startingCoreTile); state.teams.get(team).cores.add(startingCoreTile);
//makes sure there's a flat area around core
for(int dx = -2; dx <= 2; dx++){
for(int dy = -2; dy <= 2; dy++){
gen.tiles[startingCoreTile.x + dx][startingCoreTile.y + dy].setElevation(startingCoreTile.getElevation());
}
}
} }
/** /**

View File

@@ -74,7 +74,7 @@ public class WaveMission extends MissionWithStartingCore{
@Override @Override
public void update(){ public void update(){
if(state.wave > target){ if(state.wave > target){
state.mode = GameMode.noWaves; state.mode = GameMode.attack;
} }
} }

View File

@@ -1,5 +1,7 @@
package io.anuke.mindustry.net; package io.anuke.mindustry.net;
import io.anuke.mindustry.game.GameMode;
public class Host{ public class Host{
public final String name; public final String name;
public final String address; public final String address;
@@ -8,8 +10,9 @@ public class Host{
public final int players; public final int players;
public final int version; public final int version;
public final String versionType; public final String versionType;
public final GameMode mode;
public Host(String name, String address, String mapname, int wave, int players, int version, String versionType){ public Host(String name, String address, String mapname, int wave, int players, int version, String versionType, GameMode mode){
this.name = name; this.name = name;
this.address = address; this.address = address;
this.players = players; this.players = players;
@@ -17,5 +20,6 @@ public class Host{
this.wave = wave; this.wave = wave;
this.version = version; this.version = version;
this.versionType = versionType; this.versionType = versionType;
this.mode = mode;
} }
} }

View File

@@ -21,6 +21,7 @@ import io.anuke.ucore.util.Bits;
import java.io.*; import java.io.*;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
@@ -32,7 +33,7 @@ public class NetworkIO{
//--GENERAL STATE-- //--GENERAL STATE--
stream.writeByte(state.mode.ordinal()); //gamemode stream.writeByte(state.mode.ordinal()); //gamemode
stream.writeUTF(world.getMap().name); //map name stream.writeUTF(world.getMap().name); //map name
stream.writeInt(world.getSector() == null ? invalidSector : world.getSector().packedPosition()); //sector ID stream.writeInt(world.getSector() == null ? invalidSector : world.getSector().pos()); //sector ID
stream.writeInt(world.getSector() == null ? 0 : world.getSector().completedMissions); stream.writeInt(world.getSector() == null ? 0 : world.getSector().completedMissions);
//write tags //write tags
@@ -56,7 +57,7 @@ public class NetworkIO{
stream.writeShort(world.height()); stream.writeShort(world.height());
for(int i = 0; i < world.width() * world.height(); i++){ for(int i = 0; i < world.width() * world.height(); i++){
Tile tile = world.tile(i); Tile tile = world.tile(i % world.width(), i / world.width());
stream.writeByte(tile.getFloorID()); stream.writeByte(tile.getFloorID());
stream.writeByte(tile.getBlockID()); stream.writeByte(tile.getBlockID());
@@ -79,7 +80,7 @@ public class NetworkIO{
int consecutives = 0; int consecutives = 0;
for(int j = i + 1; j < world.width() * world.height() && consecutives < 255; j++){ for(int j = i + 1; j < world.width() * world.height() && consecutives < 255; j++){
Tile nextTile = world.tile(j); Tile nextTile = world.tile(j % world.width(), j / world.width());
if(nextTile.getFloorID() != tile.getFloorID() || nextTile.block() != Blocks.air || nextTile.getElevation() != tile.getElevation()){ if(nextTile.getFloorID() != tile.getFloorID() || nextTile.block() != Blocks.air || nextTile.getElevation() != tile.getElevation()){
break; break;
@@ -95,13 +96,13 @@ public class NetworkIO{
//write visibility, length-run encoded //write visibility, length-run encoded
for(int i = 0; i < world.width() * world.height(); i++){ for(int i = 0; i < world.width() * world.height(); i++){
Tile tile = world.tile(i); Tile tile = world.tile(i % world.width(), i / world.width());;
boolean discovered = tile.discovered(); boolean discovered = tile.discovered();
int consecutives = 0; int consecutives = 0;
for(int j = i + 1; j < world.width() * world.height() && consecutives < 32767*2-1; j++){ for(int j = i + 1; j < world.width() * world.height() && consecutives < 32767*2-1; j++){
Tile nextTile = world.tile(j); Tile nextTile = world.tile(j % world.width(), j / world.width());;
if(nextTile.discovered() != discovered){ if(nextTile.discovered() != discovered){
break; break;
@@ -129,7 +130,7 @@ public class NetworkIO{
stream.writeByte(data.cores.size); stream.writeByte(data.cores.size);
for(Tile tile : data.cores){ for(Tile tile : data.cores){
stream.writeInt(tile.packedPosition()); stream.writeInt(tile.pos());
} }
} }
@@ -298,24 +299,25 @@ public class NetworkIO{
int maxlen = 32; int maxlen = 32;
String host = (headless ? "Server" : players[0].name); String host = (headless ? "Server" : players[0].name);
String map = world.getMap().name; String map = world.getMap() == null ? "None" : world.getMap().name;
host = host.substring(0, Math.min(host.length(), maxlen)); host = host.substring(0, Math.min(host.length(), maxlen));
map = map.substring(0, Math.min(map.length(), maxlen)); map = map.substring(0, Math.min(map.length(), maxlen));
ByteBuffer buffer = ByteBuffer.allocate(128); ByteBuffer buffer = ByteBuffer.allocate(128);
buffer.put((byte) host.getBytes().length); buffer.put((byte) host.getBytes(StandardCharsets.UTF_8).length);
buffer.put(host.getBytes()); buffer.put(host.getBytes(StandardCharsets.UTF_8));
buffer.put((byte) map.getBytes().length); buffer.put((byte) map.getBytes(StandardCharsets.UTF_8).length);
buffer.put(map.getBytes()); buffer.put(map.getBytes(StandardCharsets.UTF_8));
buffer.putInt(playerGroup.size()); buffer.putInt(playerGroup.size());
buffer.putInt(state.wave); buffer.putInt(state.wave);
buffer.putInt(Version.build); buffer.putInt(Version.build);
buffer.put((byte)Version.type.getBytes().length); buffer.put((byte)Version.type.getBytes(StandardCharsets.UTF_8).length);
buffer.put(Version.type.getBytes()); buffer.put(Version.type.getBytes(StandardCharsets.UTF_8));
buffer.put((byte)state.mode.ordinal());
return buffer; return buffer;
} }
@@ -328,8 +330,8 @@ public class NetworkIO{
byte[] mb = new byte[mlength]; byte[] mb = new byte[mlength];
buffer.get(mb); buffer.get(mb);
String host = new String(hb); String host = new String(hb, StandardCharsets.UTF_8);
String map = new String(mb); String map = new String(mb, StandardCharsets.UTF_8);
int players = buffer.getInt(); int players = buffer.getInt();
int wave = buffer.getInt(); int wave = buffer.getInt();
@@ -337,8 +339,9 @@ public class NetworkIO{
byte tlength = buffer.get(); byte tlength = buffer.get();
byte[] tb = new byte[tlength]; byte[] tb = new byte[tlength];
buffer.get(tb); buffer.get(tb);
String vertype = new String(tb); String vertype = new String(tb, StandardCharsets.UTF_8);
GameMode mode = GameMode.values()[buffer.get()];
return new Host(host, hostAddress, map, wave, players, version, vertype); return new Host(host, hostAddress, map, wave, players, version, vertype, mode);
} }
} }

View File

@@ -34,6 +34,7 @@ public class Mech extends UnlockableContent{
public Color trailColorTo = Palette.boostTo; public Color trailColorTo = Palette.boostTo;
public int itemCapacity = 30; public int itemCapacity = 30;
public boolean turnCursor = true; public boolean turnCursor = true;
public boolean canHeal = false;
public float weaponOffsetX, weaponOffsetY; public float weaponOffsetX, weaponOffsetY;
public Weapon weapon = Weapons.blaster; public Weapon weapon = Weapons.blaster;

View File

@@ -41,17 +41,10 @@ public class AdminsDialog extends FloatingDialog{
ui.showConfirm("$text.confirm", "$text.confirmunadmin", () -> { ui.showConfirm("$text.confirm", "$text.confirmunadmin", () -> {
netServer.admins.unAdminPlayer(info.id); netServer.admins.unAdminPlayer(info.id);
playerGroup.forEach(player -> { playerGroup.forEach(player -> {
if(player.uuid.equals(info.id)){ if(player != null && player.uuid != null && player.uuid.equals(info.id)){
player.isAdmin = false; player.isAdmin = false;
} }
}); });
/*
for(Player player : playerGroup.all()){
if(player.con != null){
player.isAdmin = false;
break;
}
}*/
setup(); setup();
}); });
}).size(h).pad(-14f); }).size(h).pad(-14f);

View File

@@ -38,10 +38,6 @@ public class FileChooser extends FloatingDialog{
private Consumer<FileHandle> selectListener; private Consumer<FileHandle> selectListener;
private boolean open; private boolean open;
public FileChooser(String title, boolean open, Consumer<FileHandle> result){
this(title, defaultFilter, open, result);
}
public FileChooser(String title, Predicate<FileHandle> filter, boolean open, Consumer<FileHandle> result){ public FileChooser(String title, Predicate<FileHandle> filter, boolean open, Consumer<FileHandle> result){
super(title); super(title);
this.open = open; this.open = open;
@@ -127,7 +123,7 @@ public class FileChooser extends FloatingDialog{
updateFiles(true); updateFiles(true);
}); });
icontable.defaults().height(50).growX().uniform(); icontable.defaults().height(50).growX().padTop(5).uniform();
icontable.add(home); icontable.add(home);
icontable.add(back); icontable.add(back);
icontable.add(forward); icontable.add(forward);
@@ -202,7 +198,7 @@ public class FileChooser extends FloatingDialog{
//macs are confined to the Downloads/ directory //macs are confined to the Downloads/ directory
if(!OS.isMac){ if(!OS.isMac){
Image upimage = new Image("icon-folder-parent"); Image upimage = new Image("icon-folder-parent");
TextButton upbutton = new TextButton(".." + directory.toString()); TextButton upbutton = new TextButton(".." + directory.toString(), "clear-toggle");
upbutton.clicked(() -> { upbutton.clicked(() -> {
directory = directory.parent(); directory = directory.parent();
updateFiles(true); updateFiles(true);
@@ -224,7 +220,7 @@ public class FileChooser extends FloatingDialog{
String filename = file.name(); String filename = file.name();
TextButton button = new TextButton(shorten(filename), "toggle"); TextButton button = new TextButton(shorten(filename), "clear-toggle");
group.add(button); group.add(button);
button.clicked(() -> { button.clicked(() -> {

View File

@@ -96,11 +96,11 @@ public class JoinDialog extends FloatingDialog{
//why are java lambdas this bad //why are java lambdas this bad
TextButton[] buttons = {null}; TextButton[] buttons = {null};
TextButton button = buttons[0] = remote.addButton("[accent]" + server.displayIP(), () -> { TextButton button = buttons[0] = remote.addButton("[accent]" + server.displayIP(), "clear", () -> {
if(!buttons[0].childrenPressed()){ if(!buttons[0].childrenPressed()){
connect(server.ip, server.port); connect(server.ip, server.port);
} }
}).width(targetWidth()).height(150f).pad(4f).get(); }).width(targetWidth()).height(155f).pad(4f).get();
button.getLabel().setWrap(true); button.getLabel().setWrap(true);
@@ -156,10 +156,10 @@ public class JoinDialog extends FloatingDialog{
versionString = Bundles.get("text.server.outdated"); versionString = Bundles.get("text.server.outdated");
}else if(host.version < Version.build && Version.build != -1){ }else if(host.version < Version.build && Version.build != -1){
versionString = Bundles.get("text.server.outdated") + "\n" + versionString = Bundles.get("text.server.outdated") + "\n" +
Bundles.format("text.server.version", host.version); Bundles.format("text.server.version", host.version, "");
}else if(host.version > Version.build && Version.build != -1){ }else if(host.version > Version.build && Version.build != -1){
versionString = Bundles.get("text.server.outdated.client") + "\n" + versionString = Bundles.get("text.server.outdated.client") + "\n" +
Bundles.format("text.server.version", host.version); Bundles.format("text.server.version", host.version, "");
}else{ }else{
versionString = Bundles.format("text.server.version", host.version, host.versionType); versionString = Bundles.format("text.server.version", host.version, host.versionType);
} }
@@ -268,12 +268,13 @@ public class JoinDialog extends FloatingDialog{
if(totalHosts == 0){ if(totalHosts == 0){
local.clear(); local.clear();
} }
local.background((Drawable) null);
totalHosts ++; totalHosts ++;
float w = targetWidth(); float w = targetWidth();
local.row(); local.row();
TextButton button = local.addButton("[accent]" + host.name, () -> connect(host.address, port)) TextButton button = local.addButton("[accent]" + host.name, "clear", () -> connect(host.address, port))
.width(w).height(80f).pad(4f).get(); .width(w).height(80f).pad(4f).get();
button.left(); button.left();
button.row(); button.row();

View File

@@ -161,6 +161,7 @@ public class LoadDialog extends FloatingDialog{
control.saves.importSave(file); control.saves.importSave(file);
setup(); setup();
}catch(IOException e){ }catch(IOException e){
e.printStackTrace();
ui.showError(Bundles.format("text.save.import.fail", Strings.parseException(e, false))); ui.showError(Bundles.format("text.save.import.fail", Strings.parseException(e, false)));
} }
}else{ }else{

View File

@@ -24,9 +24,13 @@ import io.anuke.ucore.scene.Element;
import io.anuke.ucore.scene.Group; import io.anuke.ucore.scene.Group;
import io.anuke.ucore.scene.actions.Actions; import io.anuke.ucore.scene.actions.Actions;
import io.anuke.ucore.scene.event.Touchable; import io.anuke.ucore.scene.event.Touchable;
import io.anuke.ucore.scene.ui.*; import io.anuke.ucore.scene.ui.Image;
import io.anuke.ucore.scene.ui.ImageButton;
import io.anuke.ucore.scene.ui.Label;
import io.anuke.ucore.scene.ui.TextButton;
import io.anuke.ucore.scene.ui.layout.Stack; import io.anuke.ucore.scene.ui.layout.Stack;
import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.scene.ui.layout.Table;
import io.anuke.ucore.scene.ui.layout.Unit;
import io.anuke.ucore.util.Bundles; import io.anuke.ucore.util.Bundles;
import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Mathf;
@@ -347,7 +351,7 @@ public class HudFragment extends Fragment{
if(shown){ if(shown){
shown = false; shown = false;
blockfrag.toggle(dur, in); blockfrag.toggle(dur, in);
wavetable.actions(Actions.translateBy(0, (wavetable.getHeight() + dsize + 6) - wavetable.getTranslation().y, dur, in)); wavetable.actions(Actions.translateBy(0, (wavetable.getHeight() + Unit.dp.scl(dsize) + Unit.dp.scl(6)) - wavetable.getTranslation().y, dur, in));
infolabel.actions(Actions.translateBy(0, (wavetable.getHeight()) - wavetable.getTranslation().y, dur, in)); infolabel.actions(Actions.translateBy(0, (wavetable.getHeight()) - wavetable.getTranslation().y, dur, in));
}else{ }else{
shown = true; shown = true;

View File

@@ -36,9 +36,11 @@ public class PlacementFragment extends Fragment{
Tile hoverTile; Tile hoverTile;
Table blockTable, toggler, topTable; Table blockTable, toggler, topTable;
boolean shown = true; boolean shown = true;
boolean lastGround;
public PlacementFragment(){ public PlacementFragment(){
Events.on(WorldLoadGraphicsEvent.class, event -> { Events.on(WorldLoadGraphicsEvent.class, event -> {
currentCategory = Category.turret;
Group group = toggler.getParent(); Group group = toggler.getParent();
toggler.remove(); toggler.remove();
build(group); build(group);
@@ -109,13 +111,14 @@ public class PlacementFragment extends Fragment{
frame.table("button-edge-2", top -> { frame.table("button-edge-2", top -> {
topTable = top; topTable = top;
top.add(new Table()).growX().update(topTable -> { top.add(new Table()).growX().update(topTable -> {
if((tileDisplayBlock() == null && lastDisplay == getSelected()) || if((tileDisplayBlock() == null && lastDisplay == getSelected() && !lastGround) ||
(tileDisplayBlock() != null && lastDisplay == tileDisplayBlock())) return; (tileDisplayBlock() != null && lastDisplay == tileDisplayBlock() && lastGround)) return;
topTable.clear(); topTable.clear();
topTable.top().left().margin(5); topTable.top().left().margin(5);
lastDisplay = getSelected(); lastDisplay = getSelected();
lastGround = tileDisplayBlock() != null;
if(lastDisplay != null){ //show selected recipe if(lastDisplay != null){ //show selected recipe
topTable.table(header -> { topTable.table(header -> {
@@ -181,7 +184,7 @@ public class PlacementFragment extends Fragment{
categories.addImageButton("icon-" + cat.name(), "clear-toggle", 16*2, () -> { categories.addImageButton("icon-" + cat.name(), "clear-toggle", 16*2, () -> {
currentCategory = cat; currentCategory = cat;
rebuildCategory.run(); rebuildCategory.run();
}).group(group); }).group(group).update(i -> i.setChecked(currentCategory == cat));
if(cat.ordinal() %2 == 1) categories.row(); if(cat.ordinal() %2 == 1) categories.row();
} }

View File

@@ -104,19 +104,19 @@ public class PlayerListFragment extends Fragment{
if((Net.server() || players[0].isAdmin) && !player.isLocal && (!player.isAdmin || Net.server())){ if((Net.server() || players[0].isAdmin) && !player.isLocal && (!player.isAdmin || Net.server())){
button.add().growY(); button.add().growY();
float bs = (h + 14) / 2f; float bs = (h) / 2f;
button.table(t -> { button.table(t -> {
t.defaults().size(bs); t.defaults().size(bs);
t.addImageButton("icon-ban", 14 * 2, t.addImageButton("icon-ban", "clear-partial", 14 * 2,
() -> ui.showConfirm("$text.confirm", "$text.confirmban", () -> Call.onAdminRequest(player, AdminAction.ban))); () -> ui.showConfirm("$text.confirm", "$text.confirmban", () -> Call.onAdminRequest(player, AdminAction.ban)));
t.addImageButton("icon-cancel", 16 * 2, t.addImageButton("icon-cancel", "clear-partial", 16 * 2,
() -> ui.showConfirm("$text.confirm", "$text.confirmkick", () -> Call.onAdminRequest(player, AdminAction.kick))); () -> ui.showConfirm("$text.confirm", "$text.confirmkick", () -> Call.onAdminRequest(player, AdminAction.kick)));
t.row(); t.row();
t.addImageButton("icon-admin", "toggle", 14 * 2, () -> { t.addImageButton("icon-admin", "clear-toggle-partial", 14 * 2, () -> {
if(Net.client()) return; if(Net.client()) return;
String id = player.uuid; String id = player.uuid;
@@ -132,9 +132,9 @@ public class PlayerListFragment extends Fragment{
.touchable(() -> Net.client() ? Touchable.disabled : Touchable.enabled) .touchable(() -> Net.client() ? Touchable.disabled : Touchable.enabled)
.checked(player.isAdmin); .checked(player.isAdmin);
t.addImageButton("icon-zoom-small", 14 * 2, () -> ui.showError("Currently unimplemented.")/*Call.onAdminRequest(player, AdminAction.trace)*/); t.addImageButton("icon-zoom-small", "clear-partial", 14 * 2, () -> ui.showError("Currently unimplemented.")/*Call.onAdminRequest(player, AdminAction.trace)*/);
}).padRight(12).padTop(-5).padLeft(0).padBottom(-10).size(bs + 10f, bs); }).padRight(12).size(bs + 10f, bs);
} }
content.add(button).padBottom(-6).width(350f).maxHeight(h + 14); content.add(button).padBottom(-6).width(350f).maxHeight(h + 14);

View File

@@ -164,7 +164,7 @@ public class Block extends BaseBlock {
for(int i = 0; i < tile.entity.power.links.size; i++){ for(int i = 0; i < tile.entity.power.links.size; i++){
Tile other = world.tile(tile.entity.power.links.get(i)); Tile other = world.tile(tile.entity.power.links.get(i));
if(other != null && other.entity != null && other.entity.power != null){ if(other != null && other.entity != null && other.entity.power != null){
other.entity.power.links.removeValue(tile.packedPosition()); other.entity.power.links.removeValue(tile.pos());
} }
} }
} }
@@ -173,7 +173,7 @@ public class Block extends BaseBlock {
out.clear(); out.clear();
for(Tile other : tile.entity.proximity()){ for(Tile other : tile.entity.proximity()){
if(other.entity.power != null && !(consumesPower && other.block().consumesPower && !outputsPower && !other.block().outputsPower) if(other.entity.power != null && !(consumesPower && other.block().consumesPower && !outputsPower && !other.block().outputsPower)
&& !tile.entity.power.links.contains(other.packedPosition())){ && !tile.entity.power.links.contains(other.pos())){
out.add(other); out.add(other);
} }
} }
@@ -337,10 +337,8 @@ public class Block extends BaseBlock {
public void setBars(){ public void setBars(){
if(hasPower) bars.add(new BlockBar(BarType.power, true, tile -> tile.entity.power.amount / powerCapacity)); if(hasPower) bars.add(new BlockBar(BarType.power, true, tile -> tile.entity.power.amount / powerCapacity));
if(hasLiquids) if(hasLiquids) bars.add(new BlockBar(BarType.liquid, true, tile -> tile.entity.liquids.total() / liquidCapacity));
bars.add(new BlockBar(BarType.liquid, true, tile -> tile.entity.liquids.total() / liquidCapacity)); if(hasItems) bars.add(new BlockBar(BarType.inventory, true, tile -> (float) tile.entity.items.total() / itemCapacity));
if(hasItems)
bars.add(new BlockBar(BarType.inventory, true, tile -> (float) tile.entity.items.total() / itemCapacity));
} }
public String name(){ public String name(){
@@ -543,16 +541,16 @@ public class Block extends BaseBlock {
public Array<Object> getDebugInfo(Tile tile){ public Array<Object> getDebugInfo(Tile tile){
return Array.with( return Array.with(
"block", tile.block().name, "block", tile.block().name,
"floor", tile.floor().name, "floor", tile.floor().name,
"x", tile.x, "x", tile.x,
"y", tile.y, "y", tile.y,
"entity.name", tile.entity.getClass(), "entity.name", tile.entity.getClass(),
"entity.x", tile.entity.x, "entity.x", tile.entity.x,
"entity.y", tile.entity.y, "entity.y", tile.entity.y,
"entity.id", tile.entity.id, "entity.id", tile.entity.id,
"entity.items.total", hasItems ? tile.entity.items.total() : null, "entity.items.total", hasItems ? tile.entity.items.total() : null,
"entity.graph", tile.entity.power != null && tile.entity.power.graph != null ? tile.entity.power.graph.getID() : null "entity.graph", tile.entity.power != null && tile.entity.power.graph != null ? tile.entity.power.graph.getID() : null
); );
} }
} }

View File

@@ -0,0 +1,20 @@
package io.anuke.mindustry.world;
/**Methods for a packed position 'struct', contained in an int.*/
public class Pos{
/**Returns packed position from an x/y position. The values must be within short limits.*/
public static int get(int x, int y){
return (((short)x) << 16) | (((short)y) & 0xFFFF);
}
/**Returns the x component of a position.*/
public static short x(int pos){
return (short) (pos >>> 16);
}
/**Returns the y component of a position.*/
public static short y(int pos){
return (short) (pos & 0xFFFF);
}
}

View File

@@ -71,8 +71,9 @@ public class Tile implements PosTrait, TargetTrait{
return visibility > 0; return visibility > 0;
} }
public int packedPosition(){ /**Returns this tile's position as a {@link Pos}.*/
return x + y * world.width(); public int pos(){
return Pos.get(x, y);
} }
public byte getBlockID(){ public byte getBlockID(){
@@ -104,10 +105,6 @@ public class Tile implements PosTrait, TargetTrait{
return (T) entity; return (T) entity;
} }
public int id(){
return x + y * world.width();
}
public float worldx(){ public float worldx(){
return x * tilesize; return x * tilesize;
} }

View File

@@ -130,16 +130,16 @@ public class Floor extends Block{
@Override @Override
public void drawNonLayer(Tile tile){ public void drawNonLayer(Tile tile){
MathUtils.random.setSeed(tile.id()); MathUtils.random.setSeed(tile.pos());
drawEdges(tile, true); drawEdges(tile, true);
} }
@Override @Override
public void draw(Tile tile){ public void draw(Tile tile){
MathUtils.random.setSeed(tile.id()); MathUtils.random.setSeed(tile.pos());
Draw.rect(variantRegions[Mathf.randomSeed(tile.id(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy()); Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy());
if(tile.hasCliffs() && cliffRegions != null){ if(tile.hasCliffs() && cliffRegions != null){
for(int i = 0; i < 4; i++){ for(int i = 0; i < 4; i++){

View File

@@ -39,14 +39,14 @@ public class OreBlock extends Floor{
@Override @Override
public void draw(Tile tile){ public void draw(Tile tile){
Draw.rect(variantRegions[Mathf.randomSeed(tile.id(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy()); Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy());
drawEdges(tile, false); drawEdges(tile, false);
} }
@Override @Override
public void drawNonLayer(Tile tile){ public void drawNonLayer(Tile tile){
MathUtils.random.setSeed(tile.id()); MathUtils.random.setSeed(tile.pos());
base.drawEdges(tile, true); base.drawEdges(tile, true);
} }

View File

@@ -19,7 +19,7 @@ public class Rock extends Block{
@Override @Override
public void draw(Tile tile){ public void draw(Tile tile){
if(variants > 0){ if(variants > 0){
Draw.rect(regions[Mathf.randomSeed(tile.id(), 0, Math.max(0, regions.length - 1))], tile.worldx(), tile.worldy()); Draw.rect(regions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, regions.length - 1))], tile.worldx(), tile.worldy());
}else{ }else{
Draw.rect(region, tile.worldx(), tile.worldy()); Draw.rect(region, tile.worldx(), tile.worldy());
} }
@@ -28,7 +28,7 @@ public class Rock extends Block{
@Override @Override
public void drawShadow(Tile tile){ public void drawShadow(Tile tile){
if(shadowRegions != null){ if(shadowRegions != null){
Draw.rect(shadowRegions[(Mathf.randomSeed(tile.id(), 0, variants - 1))], tile.worldx(), tile.worldy()); Draw.rect(shadowRegions[(Mathf.randomSeed(tile.pos(), 0, variants - 1))], tile.worldx(), tile.worldy());
}else if(shadowRegion != null){ }else if(shadowRegion != null){
Draw.rect(shadowRegion, tile.drawx(), tile.drawy()); Draw.rect(shadowRegion, tile.drawx(), tile.drawy());
} }

View File

@@ -4,43 +4,32 @@ import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Item;
import io.anuke.ucore.function.Consumer; import io.anuke.ucore.function.Consumer;
import io.anuke.ucore.function.Supplier; import io.anuke.ucore.function.Supplier;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.scene.style.TextureRegionDrawable; import io.anuke.ucore.scene.style.TextureRegionDrawable;
import io.anuke.ucore.scene.ui.ButtonGroup; import io.anuke.ucore.scene.ui.ButtonGroup;
import io.anuke.ucore.scene.ui.ImageButton; import io.anuke.ucore.scene.ui.ImageButton;
import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.scene.ui.layout.Table;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.content;
import static io.anuke.mindustry.Vars.control;
public interface SelectionTrait{ public interface SelectionTrait{
default void buildItemTable(Table table, Supplier<Item> holder, Consumer<Item> consumer){ default void buildItemTable(Table table, Supplier<Item> holder, Consumer<Item> consumer){
buildItemTable(table, false, holder, consumer);
}
default void buildItemTable(Table table, boolean nullItem, Supplier<Item> holder, Consumer<Item> consumer){
Array<Item> items = content.items(); Array<Item> items = content.items();
ButtonGroup<ImageButton> group = new ButtonGroup<>(); ButtonGroup<ImageButton> group = new ButtonGroup<>();
group.setMinCheckCount(0);
Table cont = new Table(); Table cont = new Table();
cont.defaults().size(38); cont.defaults().size(38);
int i = 0; int i = 0;
if(nullItem){
ImageButton button = cont.addImageButton("white", "clear-toggle", 24, () -> consumer.accept(null)).group(group).get();
button.getStyle().imageUp = new TextureRegionDrawable(Draw.region("icon-nullitem"));
button.setChecked(holder.get() == null);
i ++;
}
for(Item item : items){ for(Item item : items){
if(!control.unlocks.isUnlocked(item)) continue; if(!control.unlocks.isUnlocked(item)) continue;
ImageButton button = cont.addImageButton("white", "clear-toggle", 24, () -> consumer.accept(item)) ImageButton button = cont.addImageButton("white", "clear-toggle", 24, () -> {}).group(group).get();
.group(group).get(); button.changed(() -> consumer.accept(button.isChecked() ? item : null));
button.getStyle().imageUp = new TextureRegionDrawable(item.region); button.getStyle().imageUp = new TextureRegionDrawable(item.region);
button.setChecked(holder.get() == item); button.setChecked(holder.get() == item);

View File

@@ -83,10 +83,10 @@ public class MendProjector extends Block{
if(other == null) continue; if(other == null) continue;
other = other.target(); other = other.target();
if(other.getTeamID() == tile.getTeamID() && !healed.contains(other.packedPosition()) && other.entity != null && other.entity.health < other.entity.maxHealth()){ if(other.getTeamID() == tile.getTeamID() && !healed.contains(other.pos()) && other.entity != null && other.entity.health < other.entity.maxHealth()){
other.entity.healBy(other.entity.maxHealth() * (healPercent + entity.phaseHeat*phaseBoost)/100f); other.entity.healBy(other.entity.maxHealth() * (healPercent + entity.phaseHeat*phaseBoost)/100f);
Effects.effect(BlockFx.healBlockFull, Hue.mix(color, phase, entity.phaseHeat), other.drawx(), other.drawy(), other.block().size); Effects.effect(BlockFx.healBlockFull, Hue.mix(color, phase, entity.phaseHeat), other.drawx(), other.drawy(), other.block().size);
healed.add(other.packedPosition()); healed.add(other.pos());
} }
} }
} }

View File

@@ -85,11 +85,11 @@ public class OverdriveProjector extends Block{
if(other == null) continue; if(other == null) continue;
other = other.target(); other = other.target();
if(other.getTeamID() == tile.getTeamID() && !healed.contains(other.packedPosition()) && other.entity != null){ if(other.getTeamID() == tile.getTeamID() && !healed.contains(other.pos()) && other.entity != null){
other.entity.timeScaleDuration = Math.max(other.entity.timeScaleDuration, reload + 1f); other.entity.timeScaleDuration = Math.max(other.entity.timeScaleDuration, reload + 1f);
other.entity.timeScale = Math.max(other.entity.timeScale, realBoost); other.entity.timeScale = Math.max(other.entity.timeScale, realBoost);
Effects.effect(BlockFx.overdriveBlockFull, Hue.mix(color, phase, entity.phaseHeat), other.drawx(), other.drawy(), other.block().size); Effects.effect(BlockFx.overdriveBlockFull, Hue.mix(color, phase, entity.phaseHeat), other.drawx(), other.drawy(), other.block().size);
healed.add(other.packedPosition()); healed.add(other.pos());
} }
} }
} }

View File

@@ -15,6 +15,7 @@ import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Edges; import io.anuke.mindustry.world.Edges;
import io.anuke.mindustry.world.Pos;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.meta.BlockGroup; import io.anuke.mindustry.world.meta.BlockGroup;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
@@ -58,8 +59,8 @@ public class ItemBridge extends Block{
public static void linkItemBridge(Player player, Tile tile, Tile other){ public static void linkItemBridge(Player player, Tile tile, Tile other){
ItemBridgeEntity entity = tile.entity(); ItemBridgeEntity entity = tile.entity();
ItemBridgeEntity oe = other.entity(); ItemBridgeEntity oe = other.entity();
entity.link = other.packedPosition(); entity.link = other.pos();
oe.incoming.add(tile.packedPosition()); oe.incoming.add(tile.pos());
} }
@Remote(targets = Loc.both, called = Loc.server, forward = true) @Remote(targets = Loc.both, called = Loc.server, forward = true)
@@ -68,7 +69,7 @@ public class ItemBridge extends Block{
entity.link = -1; entity.link = -1;
if(other != null){ if(other != null){
ItemBridgeEntity oe = other.entity(); ItemBridgeEntity oe = other.entity();
oe.incoming.remove(tile.packedPosition()); oe.incoming.remove(tile.pos());
} }
} }
@@ -90,7 +91,7 @@ public class ItemBridge extends Block{
Call.linkItemBridge(null, last, tile); Call.linkItemBridge(null, last, tile);
} }
} }
lastPlaced = tile.packedPosition(); lastPlaced = tile.pos();
} }
@Override @Override
@@ -122,7 +123,7 @@ public class ItemBridge extends Block{
for(int j = 0; j < 4; j++){ for(int j = 0; j < 4; j++){
Tile other = tile.getNearby(Geometry.d4[j].x * i, Geometry.d4[j].y * i); Tile other = tile.getNearby(Geometry.d4[j].x * i, Geometry.d4[j].y * i);
if(linkValid(tile, other)){ if(linkValid(tile, other)){
boolean linked = other.packedPosition() == entity.link; boolean linked = other.pos() == entity.link;
Draw.color(linked ? Palette.place : Palette.breakInvalid); Draw.color(linked ? Palette.place : Palette.breakInvalid);
Lines.square(other.drawx(), other.drawy(), Lines.square(other.drawx(), other.drawy(),
@@ -139,7 +140,7 @@ public class ItemBridge extends Block{
ItemBridgeEntity entity = tile.entity(); ItemBridgeEntity entity = tile.entity();
if(linkValid(tile, other)){ if(linkValid(tile, other)){
if(entity.link == other.packedPosition()){ if(entity.link == other.pos()){
Call.unlinkItemBridge(null, tile, other); Call.unlinkItemBridge(null, tile, other);
}else{ }else{
Call.linkItemBridge(null, tile, other); Call.linkItemBridge(null, tile, other);
@@ -254,7 +255,7 @@ public class ItemBridge extends Block{
if(rel == rel2) return false; if(rel == rel2) return false;
}else{ }else{
return source.block() instanceof ItemBridge && source.<ItemBridgeEntity>entity().link == tile.packedPosition() && tile.entity.items.total() < itemCapacity; return source.block() instanceof ItemBridge && source.<ItemBridgeEntity>entity().link == tile.pos() && tile.entity.items.total() < itemCapacity;
} }
return tile.entity.items.total() < itemCapacity; return tile.entity.items.total() < itemCapacity;
@@ -273,9 +274,7 @@ public class ItemBridge extends Block{
while(it.hasNext){ while(it.hasNext){
int v = it.next(); int v = it.next();
int x = v % world.width(); if(tile.absoluteRelativeTo(Pos.x(v), Pos.y(v)) == i){
int y = v / world.width();
if(tile.absoluteRelativeTo(x, y) == i){
return false; return false;
} }
} }
@@ -315,7 +314,7 @@ public class ItemBridge extends Block{
return false; return false;
} }
return other.block() == this && (!checkDouble || other.<ItemBridgeEntity>entity().link != tile.packedPosition()); return other.block() == this && (!checkDouble || other.<ItemBridgeEntity>entity().link != tile.pos());
} }
public static class ItemBridgeEntity extends TileEntity{ public static class ItemBridgeEntity extends TileEntity{

View File

@@ -3,6 +3,7 @@ package io.anuke.mindustry.world.blocks.distribution;
import com.badlogic.gdx.utils.IntSet.IntSetIterator; import com.badlogic.gdx.utils.IntSet.IntSetIterator;
import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.type.Liquid;
import io.anuke.mindustry.world.Pos;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.meta.BlockGroup; import io.anuke.mindustry.world.meta.BlockGroup;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
@@ -65,9 +66,7 @@ public class LiquidExtendingBridge extends ExtendingItemBridge{
while(it.hasNext){ while(it.hasNext){
int v = it.next(); int v = it.next();
int x = v % world.width(); if(tile.absoluteRelativeTo(Pos.x(v), Pos.y(v)) == i){
int y = v / world.width();
if(tile.absoluteRelativeTo(x, y) == i){
return false; return false;
} }
} }

View File

@@ -0,0 +1,8 @@
package io.anuke.mindustry.world.blocks.distribution;
public class LiquidTank extends LiquidRouter{
public LiquidTank(String name){
super(name);
}
}

View File

@@ -225,11 +225,11 @@ public class MassDriver extends Block{
MassDriverEntity entity = tile.entity(); MassDriverEntity entity = tile.entity();
if(entity.link == other.packedPosition()){ if(entity.link == other.pos()){
Call.linkMassDriver(null, tile, -1); Call.linkMassDriver(null, tile, -1);
return false; return false;
}else if(other.block() instanceof MassDriver && other.distanceTo(tile) <= range){ }else if(other.block() instanceof MassDriver && other.distanceTo(tile) <= range){
Call.linkMassDriver(null, tile, other.packedPosition()); Call.linkMassDriver(null, tile, other.pos());
return false; return false;
} }

View File

@@ -4,6 +4,7 @@ import io.anuke.annotations.Annotations.Loc;
import io.anuke.annotations.Annotations.Remote; import io.anuke.annotations.Annotations.Remote;
import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
@@ -12,7 +13,6 @@ import io.anuke.mindustry.world.meta.BlockGroup;
import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.scene.ui.layout.Table;
import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Mathf;
import io.anuke.mindustry.gen.Call;
import java.io.DataInput; import java.io.DataInput;
import java.io.DataOutput; import java.io.DataOutput;
@@ -40,15 +40,15 @@ public class Sorter extends Block implements SelectionTrait{
@Override @Override
public void playerPlaced(Tile tile){ public void playerPlaced(Tile tile){
if(lastItem != null){ threads.runDelay(() -> Call.setSorterItem(null, tile, lastItem));
threads.runDelay(() -> Call.setSorterItem(null, tile, lastItem));
}
} }
@Remote(targets = Loc.both, called = Loc.both, forward = true) @Remote(targets = Loc.both, called = Loc.both, forward = true)
public static void setSorterItem(Player player, Tile tile, Item item){ public static void setSorterItem(Player player, Tile tile, Item item){
SorterEntity entity = tile.entity(); SorterEntity entity = tile.entity();
if(entity != null) entity.sortItem = item; if(entity != null){
entity.sortItem = item;
}
} }
@Override @Override
@@ -56,6 +56,7 @@ public class Sorter extends Block implements SelectionTrait{
super.draw(tile); super.draw(tile);
SorterEntity entity = tile.entity(); SorterEntity entity = tile.entity();
if(entity.sortItem == null) return;
Draw.color(entity.sortItem.color); Draw.color(entity.sortItem.color);
Draw.rect("blank", tile.worldx(), tile.worldy(), 4f, 4f); Draw.rect("blank", tile.worldx(), tile.worldy(), 4f, 4f);
@@ -130,16 +131,17 @@ public class Sorter extends Block implements SelectionTrait{
} }
public static class SorterEntity extends TileEntity{ public static class SorterEntity extends TileEntity{
public Item sortItem = content.item(0); public Item sortItem;
@Override @Override
public void writeConfig(DataOutput stream) throws IOException{ public void writeConfig(DataOutput stream) throws IOException{
stream.writeByte(sortItem.id); stream.writeByte(sortItem == null ? -1 : sortItem.id);
} }
@Override @Override
public void readConfig(DataInput stream) throws IOException{ public void readConfig(DataInput stream) throws IOException{
sortItem = content.items().get(stream.readByte()); byte b = stream.readByte();
sortItem = b == -1 ? null : content.items().get(b);
} }
} }
} }

View File

@@ -14,7 +14,7 @@ public class LiquidHeatGenerator extends LiquidGenerator{
public void setStats(){ public void setStats(){
super.setStats(); super.setStats();
stats.add(BlockStat.basePowerGeneration, maxLiquidGenerate * powerPerLiquid * 60f, StatUnit.powerSecond); stats.add(BlockStat.basePowerGeneration, maxLiquidGenerate * powerPerLiquid * 60f * 0.5f, StatUnit.powerSecond);
} }
@Override @Override

View File

@@ -134,9 +134,9 @@ public class PowerGraph{
child.entity.power.graph = this; child.entity.power.graph = this;
add(child); add(child);
for(Tile next : child.block().getPowerConnections(child, outArray2)){ for(Tile next : child.block().getPowerConnections(child, outArray2)){
if(next.entity.power != null && next.entity.power.graph == null && !closedSet.contains(next.packedPosition())){ if(next.entity.power != null && next.entity.power.graph == null && !closedSet.contains(next.pos())){
queue.addLast(next); queue.addLast(next);
closedSet.add(next.packedPosition()); closedSet.add(next.pos());
} }
} }
} }
@@ -156,9 +156,9 @@ public class PowerGraph{
child.entity.power.graph = graph; child.entity.power.graph = graph;
graph.add(child); graph.add(child);
for(Tile next : child.block().getPowerConnections(child, outArray2)){ for(Tile next : child.block().getPowerConnections(child, outArray2)){
if(next != tile && next.entity.power != null && next.entity.power.graph == null && !closedSet.contains(next.packedPosition())){ if(next != tile && next.entity.power != null && next.entity.power.graph == null && !closedSet.contains(next.pos())){
queue.addLast(next); queue.addLast(next);
closedSet.add(next.packedPosition()); closedSet.add(next.pos());
} }
} }
} }

View File

@@ -47,18 +47,19 @@ public class PowerNode extends PowerBlock{
@Remote(targets = Loc.both, called = Loc.server, forward = true) @Remote(targets = Loc.both, called = Loc.server, forward = true)
public static void linkPowerNodes(Player player, Tile tile, Tile other){ public static void linkPowerNodes(Player player, Tile tile, Tile other){
if(tile.entity.power == null || !((PowerNode)tile.block()).linkValid(tile, other)) return; if(tile.entity.power == null || !((PowerNode)tile.block()).linkValid(tile, other)
|| tile.entity.power.links.size >= ((PowerNode)tile.block()).maxNodes) return;
TileEntity entity = tile.entity(); TileEntity entity = tile.entity();
if(!entity.power.links.contains(other.packedPosition())){ if(!entity.power.links.contains(other.pos())){
entity.power.links.add(other.packedPosition()); entity.power.links.add(other.pos());
} }
if(other.getTeamID() == tile.getTeamID()){ if(other.getTeamID() == tile.getTeamID()){
if(!other.entity.power.links.contains(tile.packedPosition())){ if(!other.entity.power.links.contains(tile.pos())){
other.entity.power.links.add(tile.packedPosition()); other.entity.power.links.add(tile.pos());
} }
} }
@@ -67,7 +68,7 @@ public class PowerNode extends PowerBlock{
@Remote(targets = Loc.both, called = Loc.server, forward = true) @Remote(targets = Loc.both, called = Loc.server, forward = true)
public static void unlinkPowerNodes(Player player, Tile tile, Tile other){ public static void unlinkPowerNodes(Player player, Tile tile, Tile other){
if(tile.entity.power == null) return; if(tile.entity.power == null || other.entity == null || other.entity.power == null) return;
TileEntity entity = tile.entity(); TileEntity entity = tile.entity();
@@ -75,8 +76,8 @@ public class PowerNode extends PowerBlock{
PowerGraph tg = entity.power.graph; PowerGraph tg = entity.power.graph;
tg.clear(); tg.clear();
entity.power.links.removeValue(other.packedPosition()); entity.power.links.removeValue(other.pos());
other.entity.power.links.removeValue(tile.packedPosition()); other.entity.power.links.removeValue(tile.pos());
//reflow from this point, covering all tiles on this side //reflow from this point, covering all tiles on this side
tg.reflow(tile); tg.reflow(tile);
@@ -99,14 +100,14 @@ public class PowerNode extends PowerBlock{
if(linkValid(tile, before) && before.block() instanceof PowerNode){ if(linkValid(tile, before) && before.block() instanceof PowerNode){
for(Tile near : before.entity.proximity()){ for(Tile near : before.entity.proximity()){
if(near.target() == tile){ if(near.target() == tile){
lastPlaced = tile.packedPosition(); lastPlaced = tile.pos();
return; return;
} }
} }
Call.linkPowerNodes(null, tile, before); Call.linkPowerNodes(null, tile, before);
} }
lastPlaced = tile.packedPosition(); lastPlaced = tile.pos();
} }
@Override @Override
@@ -202,7 +203,7 @@ public class PowerNode extends PowerBlock{
for(int i = 0; i < entity.power.links.size; i++){ for(int i = 0; i < entity.power.links.size; i++){
Tile link = world.tile(entity.power.links.get(i)); Tile link = world.tile(entity.power.links.get(i));
if(linkValid(tile, link) && (!(link.block() instanceof PowerNode) if(linkValid(tile, link) && (!(link.block() instanceof PowerNode)
|| ((tile.block().size > link.block().size) || (tile.block().size == link.block().size && tile.id() < link.id())))){ || ((tile.block().size > link.block().size) || (tile.block().size == link.block().size && tile.pos() < link.pos())))){
drawLaser(tile, link); drawLaser(tile, link);
} }
} }
@@ -211,7 +212,7 @@ public class PowerNode extends PowerBlock{
} }
protected boolean linked(Tile tile, Tile other){ protected boolean linked(Tile tile, Tile other){
return tile.entity.power.links.contains(other.packedPosition()); return tile.entity.power.links.contains(other.pos());
} }
protected boolean linkValid(Tile tile, Tile link){ protected boolean linkValid(Tile tile, Tile link){
@@ -227,7 +228,7 @@ public class PowerNode extends PowerBlock{
return Vector2.dst(tile.drawx(), tile.drawy(), link.drawx(), link.drawy()) <= Math.max(laserRange * tilesize, return Vector2.dst(tile.drawx(), tile.drawy(), link.drawx(), link.drawy()) <= Math.max(laserRange * tilesize,
((PowerNode) link.block()).laserRange * tilesize) ((PowerNode) link.block()).laserRange * tilesize)
+ (link.block().size - 1) * tilesize / 2f + (tile.block().size - 1) * tilesize / 2f && + (link.block().size - 1) * tilesize / 2f + (tile.block().size - 1) * tilesize / 2f &&
(!checkMaxNodes || (oe.power.links.size < ((PowerNode) link.block()).maxNodes || oe.power.links.contains(tile.packedPosition()))); (!checkMaxNodes || (oe.power.links.size < ((PowerNode) link.block()).maxNodes || oe.power.links.contains(tile.pos())));
}else{ }else{
return Vector2.dst(tile.drawx(), tile.drawy(), link.drawx(), link.drawy()) return Vector2.dst(tile.drawx(), tile.drawy(), link.drawx(), link.drawy())
<= laserRange * tilesize + (link.block().size - 1) * tilesize; <= laserRange * tilesize + (link.block().size - 1) * tilesize;
@@ -249,23 +250,9 @@ public class PowerNode extends PowerBlock{
x2 += t2.x; x2 += t2.x;
y2 += t2.y; y2 += t2.y;
float space = Vector2.dst(x1, y1, x2, y2); Draw.color(Palette.powerLight, Palette.power, Mathf.absin(Timers.time(), 8f, 1f));
float scl = 4f, mag = 2f, tscl = 4f, segscl = 3f; Lines.stroke(2f);
Lines.line(x1, y1, x2, y2);
int segments = Mathf.ceil(space / segscl);
Draw.color(Palette.power, Palette.powerLight, Mathf.absin(Timers.time(), 5f, 1f));
Lines.stroke(1f);
for(int i = 0; i < segments; i++){
float f1 = (float)i / segments;
float f2 = (float)(i+1) / segments;
t1.trns(angle1 + 90f, Mathf.lerp(Mathf.sin(tile.entity.id * 124f + Timers.time()/tscl + f1 * space, scl, mag), 0f, Math.abs(f1 - 0.5f)*2f));
t2.trns(angle1 + 90f, Mathf.lerp(Mathf.sin(tile.entity.id * 124f + Timers.time()/tscl + f2 * space, scl, mag), 0f, Math.abs(f2 - 0.5f)*2f));
Lines.line(x1 + (x2 - x1) * f1 + t1.x, y1 + (y2 - y1) * f1 + t1.y,
x1 + (x2 - x1) * f2 + t2.x, y1 + (y2 - y1) * f2 + t2.y);
}
} }
} }

View File

@@ -74,7 +74,7 @@ public class Cultivator extends Drill{
Draw.color(bottomColor, plantColorLight, entity.warmup); Draw.color(bottomColor, plantColorLight, entity.warmup);
random.setSeed(tile.packedPosition()); random.setSeed(tile.pos());
for(int i = 0; i < 12; i++){ for(int i = 0; i < 12; i++){
float offset = random.nextFloat() * 999999f; float offset = random.nextFloat() * 999999f;
float x = random.range(4f), y = random.range(4f); float x = random.range(4f), y = random.range(4f);

View File

@@ -51,7 +51,6 @@ public class CoreBlock extends StorageBlock{
update = true; update = true;
size = 3; size = 3;
hasItems = true; hasItems = true;
itemCapacity = 2000;
viewRange = 200f; viewRange = 200f;
flags = EnumSet.of(BlockFlag.resupplyPoint, BlockFlag.target); flags = EnumSet.of(BlockFlag.resupplyPoint, BlockFlag.target);
} }
@@ -83,8 +82,18 @@ public class CoreBlock extends StorageBlock{
if(entity != null) entity.solid = solid; if(entity != null) entity.solid = solid;
} }
@Override
public int getMaximumAccepted(Tile tile, Item item){
return itemCapacity * state.teams.get(tile.getTeam()).cores.size;
}
@Override @Override
public void onProximityUpdate(Tile tile) { public void onProximityUpdate(Tile tile) {
for(Tile other : state.teams.get(tile.getTeam()).cores){
if(other != tile){
tile.entity.items = other.entity.items;
}
}
state.teams.get(tile.getTeam()).cores.add(tile); state.teams.get(tile.getTeam()).cores.add(tile);
} }
@@ -96,6 +105,11 @@ public class CoreBlock extends StorageBlock{
@Override @Override
public void removed(Tile tile){ public void removed(Tile tile){
state.teams.get(tile.getTeam()).cores.remove(tile); state.teams.get(tile.getTeam()).cores.remove(tile);
int max = itemCapacity * state.teams.get(tile.getTeam()).cores.size;
for(Item item : content.items()){
tile.entity.items.set(item, Math.min(tile.entity.items.get(item), max));
}
} }
@Override @Override
@@ -222,7 +236,7 @@ public class CoreBlock extends StorageBlock{
return new CoreEntity(); return new CoreEntity();
} }
public class CoreEntity extends StorageEntity implements SpawnerTrait{ public class CoreEntity extends TileEntity implements SpawnerTrait{
public Unit currentUnit; public Unit currentUnit;
int droneID = -1; int droneID = -1;
boolean solid = true; boolean solid = true;

View File

@@ -7,6 +7,7 @@ import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.SelectionTrait; import io.anuke.mindustry.world.blocks.SelectionTrait;
import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Draw;
@@ -17,15 +18,37 @@ import java.io.DataOutput;
import java.io.IOException; import java.io.IOException;
import static io.anuke.mindustry.Vars.content; import static io.anuke.mindustry.Vars.content;
import static io.anuke.mindustry.Vars.threads;
public class SortedUnloader extends Unloader implements SelectionTrait{ public class SortedUnloader extends Block implements SelectionTrait{
protected float speed = 1f; protected float speed = 1f;
protected final int timerUnload = timers++;
private static Item lastItem;
public SortedUnloader(String name){ public SortedUnloader(String name){
super(name); super(name);
update = true;
solid = true;
health = 70;
hasItems = true;
configurable = true; configurable = true;
} }
@Override
public boolean canDump(Tile tile, Tile to, Item item){
Block block = to.target().block();
return !(block instanceof StorageBlock);
}
@Override
public void setBars(){}
@Override
public void playerPlaced(Tile tile){
threads.runDelay(() -> Call.setSortedUnloaderItem(null, tile, lastItem));
}
@Remote(targets = Loc.both, called = Loc.both, forward = true) @Remote(targets = Loc.both, called = Loc.both, forward = true)
public static void setSortedUnloaderItem(Player player, Tile tile, Item item){ public static void setSortedUnloaderItem(Player player, Tile tile, Item item){
SortedUnloaderEntity entity = tile.entity(); SortedUnloaderEntity entity = tile.entity();
@@ -65,7 +88,10 @@ public class SortedUnloader extends Unloader implements SelectionTrait{
@Override @Override
public void buildTable(Tile tile, Table table){ public void buildTable(Tile tile, Table table){
SortedUnloaderEntity entity = tile.entity(); SortedUnloaderEntity entity = tile.entity();
buildItemTable(table, true, () -> entity.sortItem, item -> Call.setSortedUnloaderItem(null, tile, item)); buildItemTable(table, () -> entity.sortItem, item -> {
lastItem = item;
Call.setSortedUnloaderItem(null, tile, item);
});
} }
@Override @Override

View File

@@ -1,20 +1,10 @@
package io.anuke.mindustry.world.blocks.storage; package io.anuke.mindustry.world.blocks.storage;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.entities.Unit;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.graphics.Shaders;
import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.world.BarType; import io.anuke.mindustry.world.BarType;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Fill;
import static io.anuke.mindustry.Vars.tilesize;
public abstract class StorageBlock extends Block{ public abstract class StorageBlock extends Block{
@@ -23,6 +13,16 @@ public abstract class StorageBlock extends Block{
hasItems = true; hasItems = true;
} }
@Override
public boolean acceptItem(Item item, Tile tile, Tile source){
return tile.entity.items.get(item) < getMaximumAccepted(tile, item);
}
@Override
public int getMaximumAccepted(Tile tile, Item item){
return itemCapacity;
}
@Override @Override
public void setBars(){ public void setBars(){
super.setBars(); super.setBars();
@@ -34,85 +34,6 @@ public abstract class StorageBlock extends Block{
return false; return false;
} }
@Override
public void onProximityAdded(Tile tile){
StorageEntity entity = tile.entity();
entity.graph.set(tile);
for(Tile prox : tile.entity.proximity()){
if(prox.block() instanceof StorageBlock){
StorageEntity other = prox.entity();
entity.graph.merge(other.graph);
}
}
}
@Override
public void onProximityRemoved(Tile tile){
StorageEntity entity = tile.entity();
entity.graph.remove(tile);
}
@Override
public void drawSelect(Tile tile){
StorageEntity entity = tile.entity();
if(entity.graph.getTiles().size > 1){
Shaders.outline.color.set(Palette.accent);
Graphics.beginShaders(Shaders.outline);
for(Tile other : entity.graph.getTiles()){
Fill.square(other.drawx(), other.drawy(), other.block().size * tilesize);
}
Draw.color(Color.CLEAR);
Graphics.endShaders();
Draw.color();
}
}
@Override
public boolean acceptItem(Item item, Tile tile, Tile source){
StorageEntity entity = tile.entity();
return entity.graph.accept(item);
}
@Override
public int acceptStack(Item item, int amount, Tile tile, Unit source){
StorageEntity entity = tile.entity();
if(acceptItem(item, tile, tile) && hasItems && (source == null || source.getTeam() == tile.getTeam())){
return Math.min(entity.graph.accept(item, amount), amount);
}else{
return 0;
}
}
@Override
public float inventoryScaling(Tile tile){
StorageEntity entity = tile.entity();
return 1f / entity.graph.getTiles().size;
}
@Override
public TileEntity newEntity(){
return new StorageEntity();
}
@Override
public Array<Object> getDebugInfo(Tile tile){
Array<Object> arr = super.getDebugInfo(tile);
StorageEntity entity = tile.entity();
arr.addAll("storage graph", entity.graph.getID(),
"graph capacity", entity.graph.getCapacity(),
"graph tiles", entity.graph.getTiles().size,
"graph item ID", entity.graph.items().getID());
return arr;
}
/** /**
* Removes an item and returns it. If item is not null, it should return the item. * Removes an item and returns it. If item is not null, it should return the item.
* Returns null if no items are there. * Returns null if no items are there.
@@ -144,8 +65,4 @@ public abstract class StorageBlock extends Block{
return entity.items.has(item); return entity.items.has(item);
} }
} }
public class StorageEntity extends TileEntity{
public StorageGraph graph = new StorageGraph();
}
} }

View File

@@ -1,151 +0,0 @@
package io.anuke.mindustry.world.blocks.storage;
import com.badlogic.gdx.utils.IntSet;
import com.badlogic.gdx.utils.ObjectSet;
import com.badlogic.gdx.utils.Queue;
import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.storage.StorageBlock.StorageEntity;
import io.anuke.mindustry.world.modules.ItemModule;
public class StorageGraph{
private static IntSet closedSet = new IntSet();
private static Queue<Tile> queue = new Queue<>();
private static ObjectSet<ItemModule> itemSet = new ObjectSet<>();
private static int lastID;
private final int id = lastID++;
private ObjectSet<Tile> tiles = new ObjectSet<>();
private ItemModule items = new ItemModule();
private int capacity;
public void set(Tile tile){
items.addAll(tile.entity.items);
items.setID(tile.entity.items.getID());
add(tile);
}
public void add(Tile tile){
if(!tiles.add(tile)) return;
StorageEntity e = tile.entity();
e.graph = this;
capacity += tile.block().itemCapacity;
if(tile.entity.items != null && tile.entity.items.getID() != items.getID()){
items.addAll(tile.entity.items);
}
tile.entity.items = items;
}
public void remove(Tile tile){
if(!tiles.contains(tile)) return;
for(Tile other : tiles){
if(other == tile) continue;
StorageEntity entity = other.entity();
entity.graph = null;
entity.items = new ItemModule();
float fraction = (float)other.block().itemCapacity / capacity;
items.forEach((item, amount) -> {
int added = (int)(fraction * amount);
entity.items.add(item, added);
items.remove(item, added);
});
}
//handle remaining items that didn't get added
Item taken;
while((taken = items.take()) != null){
for(Tile other : tiles){
if(other == tile) continue;
//insert item into first found block
if(other.entity.items.get(taken) < other.block().itemCapacity){
other.entity.items.add(taken, 1);
break;
}
}
}
items.clear();
capacity = 0;
for(Tile other : tile.entity.proximity()){
if(other.block() instanceof StorageBlock && other.<StorageEntity>entity().graph == null){
StorageGraph graph = new StorageGraph();
other.<StorageEntity>entity().graph = graph;
graph.reflow(tile, other);
}
}
}
public void reflow(Tile base, Tile tile){
queue.clear();
queue.addLast(tile);
closedSet.clear();
itemSet.clear();
while(queue.size > 0){
Tile child = queue.removeFirst();
StorageEntity entity = child.entity();
entity.graph = this;
if(!itemSet.add(child.entity.items)) child.entity.items = null;
add(child);
for(Tile next : child.entity.proximity()){
if(next != base && next.block() instanceof StorageBlock && next.<StorageEntity>entity().graph == null && !closedSet.contains(next.packedPosition())){
queue.addLast(next);
closedSet.add(next.packedPosition());
}
}
}
}
public void merge(StorageGraph other){
if(this == other || other == null) return;
itemSet.clear();
for(Tile tile : other.tiles){
if(!itemSet.add(tile.entity.items)){
tile.entity.items = null;
}
}
for(Tile tile : other.tiles){
add(tile);
}
}
public boolean accept(Item item){
return accept(item, 1) == 1;
}
public int accept(Item item, int amount){
return Math.min(capacity - items.get(item), amount);
}
public ObjectSet<Tile> getTiles(){
return tiles;
}
public int getID(){
return id;
}
public int getCapacity(){
return capacity;
}
public ItemModule items(){
return items;
}
}

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