This commit is contained in:
Anuken 2018-11-02 19:45:31 -04:00
commit 208ae6183c
24 changed files with 329 additions and 131 deletions

View File

@ -427,7 +427,7 @@ item.titanium.name = Titan
item.titanium.description = Ein seltenes sehr leichtes Metal. Häufig in Flüssigkeits-Transport Blöcken, Abbauanlagen und Flugzeugen verwendet. item.titanium.description = Ein seltenes sehr leichtes Metal. Häufig in Flüssigkeits-Transport Blöcken, Abbauanlagen und Flugzeugen verwendet.
item.thorium.name = Uran item.thorium.name = Uran
item.thorium.description = Ein dichtes radioaktives Metal, welches als strukturelle Unterstützung und nuklearer Kraftstoff verwendet wird. item.thorium.description = Ein dichtes radioaktives Metal, welches als strukturelle Unterstützung und nuklearer Kraftstoff verwendet wird.
item.silicon.name = Silikon item.silicon.name = Silizium
item.silicon.description = Ein sehr nützlicher Halbleiter. Findet Anwendung in Solar Anlagen und komplexer Elektronik. item.silicon.description = Ein sehr nützlicher Halbleiter. Findet Anwendung in Solar Anlagen und komplexer Elektronik.
item.plastanium.name = Plastanium item.plastanium.name = Plastanium
item.plastanium.description = Ein leichtes dehnbares Material welches in Flugzeugen und Splittermunition verwendet wird. item.plastanium.description = Ein leichtes dehnbares Material welches in Flugzeugen und Splittermunition verwendet wird.
@ -536,7 +536,7 @@ block.bridgeconveyor.name = Transportband Brücke
block.bridgeconveyor.description = Ein Transportband welches über Blöcke gehen kann. Insgesamt maximal zwei Blöcke hoch. block.bridgeconveyor.description = Ein Transportband welches über Blöcke gehen kann. Insgesamt maximal zwei Blöcke hoch.
block.smelter.name = Schmelzer block.smelter.name = Schmelzer
block.arc-smelter.name = Lichtbogen Schmelzer block.arc-smelter.name = Lichtbogen Schmelzer
block.silicon-smelter.name = Silikon Schmelzer block.silicon-smelter.name = Silizium Schmelzer
block.phase-weaver.name = Phase Weaver block.phase-weaver.name = Phase Weaver
block.pulverizer.name = Pulverisierer block.pulverizer.name = Pulverisierer
block.cryofluidmixer.name = Cryofluid Mixer block.cryofluidmixer.name = Cryofluid Mixer
@ -656,13 +656,13 @@ tutorial.waves = Der [LIGHT_GRAY] Gegner[] greift an.\n\nVerteidige deinen Kern
tutorial.lead = Mehr Erz ist verfügbar. Finde Blei und bau es ab.\n\n Klicke auf deine Einheit und ziehe die Maus auf den Kern um Ressourcen zu übertragen. tutorial.lead = Mehr Erz ist verfügbar. Finde Blei und bau es ab.\n\n Klicke auf deine Einheit und ziehe die Maus auf den Kern um Ressourcen zu übertragen.
tutorial.smelter = Kupfer und Blei sind schwache Metalle.\n Super [accent]dichte Legierung [] kann in einem Schmeltzer erzeugt werden.\n\n Bau einen. tutorial.smelter = Kupfer und Blei sind schwache Metalle.\n Super [accent]dichte Legierung [] kann in einem Schmeltzer erzeugt werden.\n\n Bau einen.
tutorial.densealloy = Der Schmeltzer wird nun Legierung produzieren.\n Produziere einige.\n Verbessere die Produktion sofern notwendig. tutorial.densealloy = Der Schmeltzer wird nun Legierung produzieren.\n Produziere einige.\n Verbessere die Produktion sofern notwendig.
tutorial.siliconsmelter = Der Kern wird nun [accent]spirit drohnen[] erstellen. Diese Bauen Rohstoffe und reparieren Blöcke.\n\nFabriken für andere Einheiten benötigen [accent]Silikon[].\n Baue ein Silikon Schmeltzer. tutorial.siliconsmelter = Der Kern wird nun [accent]spirit drohnen[] erstellen. Diese Bauen Rohstoffe und reparieren Blöcke.\n\nFabriken für andere Einheiten benötigen [accent]Silizium[].\n Baue ein Silizium Schmeltzer.
tutorial.silicondrill = Silikon benötigt [accent]Kohle[] und [accent]Sand[].\n Fange damit an die Bohrer zu platzieren. tutorial.silicondrill = Silizium benötigt [accent]Kohle[] und [accent]Sand[].\n Fange damit an die Bohrer zu platzieren.
tutorial.generator = Diese Technologie benötigt power.\n Erstelle einen Verbrennungs-Generator dafür. tutorial.generator = Diese Technologie benötigt power.\n Erstelle einen Verbrennungs-Generator dafür.
tutorial.generatordrill = Verbrennungs Generatoren benötigen Kraftstoff.\nBenutze Kohle aus einem Bohrer als Kraftstoff. tutorial.generatordrill = Verbrennungs Generatoren benötigen Kraftstoff.\nBenutze Kohle aus einem Bohrer als Kraftstoff.
tutorial.node = Power muss transportiert werden.\nErstelle einen [accent]Power Knoten[] nahe deinem Verbrennungs Generator um seine Power zu transportieren. tutorial.node = Power muss transportiert werden.\nErstelle einen [accent]Power Knoten[] nahe deinem Verbrennungs Generator um seine Power zu transportieren.
tutorial.nodelink = Power kann über verbundene Power Blocks, Generatoren oder Power Knoten transferierd werden.\n\n Verbinde die Power in dem du auf den Knoten klickst und dann den Generator und den Silikon Schmeltzer auswählst. tutorial.nodelink = Power kann über verbundene Power Blocks, Generatoren oder Power Knoten transferierd werden.\n\n Verbinde die Power in dem du auf den Knoten klickst und dann den Generator und den Silizium Schmeltzer auswählst.
tutorial.silicon = Silikon wird produziert. Produziere einiges.\n\n Verbesserungen am Produktionssystem werden empfohlen. tutorial.silicon = Silizium wird produziert. Produziere einiges.\n\n Verbesserungen am Produktionssystem werden empfohlen.
tutorial.daggerfactory = Konstruiere eine Dagger Mech Fabrik.\n\n Diese wird verwendet um Angreifende Mechs zu erstellen. tutorial.daggerfactory = Konstruiere eine Dagger Mech Fabrik.\n\n Diese wird verwendet um Angreifende Mechs zu erstellen.
tutorial.router = Fabriken benötigen Ressourcen um zu funktionieren.\n Platziere ein Router um Gegenstände auf Transportbändern aufzuteilen. tutorial.router = Fabriken benötigen Ressourcen um zu funktionieren.\n Platziere ein Router um Gegenstände auf Transportbändern aufzuteilen.
tutorial.dagger = Verbinde die Fabrik mit einem Power Knoten. Wenn alle Voraussetzungen gegeben sind, beginnt die Fabrik Mechs zu konstruieren.\n\n Platziere mehr Bohrer und Transportbänder um die Versorgung der Fabrik zu sichern. tutorial.dagger = Verbinde die Fabrik mit einem Power Knoten. Wenn alle Voraussetzungen gegeben sind, beginnt die Fabrik Mechs zu konstruieren.\n\n Platziere mehr Bohrer und Transportbänder um die Versorgung der Fabrik zu sichern.

View File

@ -1,7 +1,7 @@
text.credits.text = Created by [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[]\n\n[GRAY](In case you can't tell, this text is currently unfinished.\nTranslators, don't edit it yet\!) text.credits.text = Created by [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[]\n\n[GRAY](In case you can't tell, this text is currently unfinished.\nTranslators, don't edit it yet\!)
text.credits = Crédits text.credits = Crédits
text.discord = Rejoignez le discord de Mindustry text.discord = Rejoignez le discord de Mindustry
text.link.discord.description = the official Mindustry discord chatroom text.link.discord.description = Le discord officiel de mindustry
text.link.github.description = Code source du jeu text.link.github.description = Code source du jeu
text.link.dev-builds.description = Versions instables du jeu text.link.dev-builds.description = Versions instables du jeu
text.link.trello.description = Trello officiel pour les futurs ajouts . text.link.trello.description = Trello officiel pour les futurs ajouts .
@ -14,12 +14,12 @@ text.web.unsupported = La version web ne supporte pas cette fonction \! Téléch
text.gameover = Partie terminée. text.gameover = Partie terminée.
text.gameover.pvp = L'équipe [accent] {0}[] a gagnée \! text.gameover.pvp = L'équipe [accent] {0}[] a gagnée \!
text.sector.gameover = Ce secteur a été perdu. Réessayer? text.sector.gameover = Ce secteur a été perdu. Réessayer?
text.sector.retry = Retry text.sector.retry = Réessayer
text.highscore = [YELLOW]Nouveau meilleur score\! text.highscore = [YELLOW]Nouveau meilleur score\!
text.wave.lasted = You lasted until wave [accent]{0}[]. text.wave.lasted = Vous avez survécu jusqu'à la vague [accent]{0}[].
text.level.highscore = Meilleur score\: [accent]{0} text.level.highscore = Meilleur score\: [accent]{0}
text.level.delete.title = Confirmer text.level.delete.title = Confirmer
text.map.delete = Are you sure you want to delete the map "[orange]{0}[]"? text.map.delete = Êtes-vous sûr de supprimer cette carte"[orange]{0}[]"?
text.level.select = Sélection de niveau text.level.select = Sélection de niveau
text.level.mode = Mode de jeu \: text.level.mode = Mode de jeu \:
text.construction.desktop = Pour désélectionner un bloc ou arrêter de construire, appuyer sur [accent]espace[]. text.construction.desktop = Pour désélectionner un bloc ou arrêter de construire, appuyer sur [accent]espace[].
@ -308,7 +308,7 @@ text.blocks.outputitem = Objet produit
text.blocks.drilltier = Forable text.blocks.drilltier = Forable
text.blocks.drillspeed = Vitesse de forage de base text.blocks.drillspeed = Vitesse de forage de base
text.blocks.liquidoutput = Liquide en sortie text.blocks.liquidoutput = Liquide en sortie
text.blocks.liquidoutputspeed = Liquid Output Speed text.blocks.liquidoutputspeed = Vitesse de production de liquide
text.blocks.liquiduse = Quantité de liquide utilisée text.blocks.liquiduse = Quantité de liquide utilisée
text.blocks.coolant = Liquide de refroidissement text.blocks.coolant = Liquide de refroidissement
text.blocks.coolantuse = Quantité de liquide de refroidissement utilisée text.blocks.coolantuse = Quantité de liquide de refroidissement utilisée
@ -321,8 +321,8 @@ text.blocks.shots = Tir
text.blocks.reload = Tirs/Seconde text.blocks.reload = Tirs/Seconde
text.blocks.inputfuel = Carburant text.blocks.inputfuel = Carburant
text.blocks.fuelburntime = Durée du carburant text.blocks.fuelburntime = Durée du carburant
text.blocks.inputcapacity = Input capacity text.blocks.inputcapacity = Capacité d'entrée
text.blocks.outputcapacity = Output capacity text.blocks.outputcapacity = Capacité de production
text.unit.blocks = blocs text.unit.blocks = blocs
text.unit.powersecond = Énergie/seconde text.unit.powersecond = Énergie/seconde
text.unit.liquidsecond = Liquides/seconde text.unit.liquidsecond = Liquides/seconde
@ -369,31 +369,31 @@ setting.sfxvol.name = Volume des SFX
setting.mutesound.name = Couper les SFX setting.mutesound.name = Couper les SFX
text.keybind.title = Paramétrer les touches text.keybind.title = Paramétrer les touches
category.general.name = General category.general.name = General
category.view.name = View category.view.name = Voir
category.multiplayer.name = Multiplayer category.multiplayer.name = Multijoueur
command.attack = Attack command.attack = Attaque
command.retreat = Retreat command.retreat = Retraite
command.patrol = Patrol command.patrol = Patrouille
keybind.press = Press a key... keybind.press = Appuyer sur une touche...
keybind.press.axis = Press an axis or key... keybind.press.axis = Appuyer sur un axe ou une touche...
keybind.move_x.name = mouvement x keybind.move_x.name = mouvement x
keybind.move_y.name = mouvement y keybind.move_y.name = mouvement y
keybind.select.name = sélectionner keybind.select.name = sélectionner
keybind.break.name = Pause keybind.break.name = Pause
keybind.deselect.name = Deselect keybind.deselect.name = Déselectionner
keybind.shoot.name = tirer keybind.shoot.name = tirer
keybind.zoom_hold.name = tenir le zoom keybind.zoom_hold.name = tenir le zoom
keybind.zoom.name = zoom keybind.zoom.name = zoom
keybind.menu.name = menu keybind.menu.name = menu
keybind.pause.name = Pause keybind.pause.name = Pause
keybind.dash.name = sprint keybind.dash.name = Courir
keybind.chat.name = chat keybind.chat.name = chat
keybind.player_list.name = Liste des joueurs keybind.player_list.name = Liste des joueurs
keybind.console.name = console keybind.console.name = console
keybind.rotate.name = Tourner keybind.rotate.name = Tourner
keybind.toggle_menus.name = Toggle menus keybind.toggle_menus.name = Cacher/afficher les menus
keybind.chat_history_prev.name = Chat history prev keybind.chat_history_prev.name = remonter l'historique du chat
keybind.chat_history_next.name = Chat history next keybind.chat_history_next.name = descendre l'historique du chat
keybind.chat_scroll.name = Chat scroll 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
@ -403,7 +403,7 @@ mode.waves.description = le mode de jeu normal. Ressource limitée et vagues d'e
mode.sandbox.name = bac à sable mode.sandbox.name = bac à sable
mode.sandbox.description = Ressources infinies et pas de timer pour les vagues. mode.sandbox.description = Ressources infinies et pas de timer pour les vagues.
mode.custom.warning = Notez que les blocs débloqués en partie personnalisées ne sont pas conservés pour les secteurs.\n\n[LIGHT_GRAY]En mode bac à sable, seul les blocs débloqués en mode secteur peuvent être utilisés. mode.custom.warning = Notez que les blocs débloqués en partie personnalisées ne sont pas conservés pour les secteurs.\n\n[LIGHT_GRAY]En mode bac à sable, seul les blocs débloqués en mode secteur peuvent être utilisés.
mode.custom.warning.read = Just to make sure you've read it\:\n[scarlet]UNLOCKS IN CUSTOM GAMES DO NOT CARRY OVER TO SECTORS OR OTHER MODES\!\n\n[LIGHT_GRAY](I wish this wasn't necessary, but apparently it is) mode.custom.warning.read = Simplement pour vérifier que vous l'avez lu \:\n[scarlet]CE QUI EST DEBLOQUE LORS DES PARITES PERSONNALISEES NE L'EST POUR LES SECTEURS OU LES AUTRES MODES DE JEU\!\n\n[LIGHT_GRAY](J'aurais souhaité que ce ne soit pas nécessaire, mais ça a l'air de l'être )
mode.freebuild.name = construction libre mode.freebuild.name = construction libre
mode.freebuild.description = Ressource limitée et pas de timer pour les vagues. mode.freebuild.description = Ressource limitée et pas de timer pour les vagues.
mode.pvp.name = JcJ mode.pvp.name = JcJ
@ -427,14 +427,14 @@ item.titanium.name = Titane
item.titanium.description = Un métal rare super-léger largement utilisé dans le transport de liquides et d'objets ainsi que dans les foreuses de haut-niveau et l'aviation .item.thorium.name\=Thorium item.titanium.description = Un métal rare super-léger largement utilisé dans le transport de liquides et d'objets ainsi que dans les foreuses de haut-niveau et l'aviation .item.thorium.name\=Thorium
item.thorium.name = Thorium item.thorium.name = Thorium
item.thorium.description = Un métal dense, et radioactif utilisé comme support structurel et comme carburant nucléaire. item.thorium.description = Un métal dense, et radioactif utilisé comme support structurel et comme carburant nucléaire.
item.silicon.name = Silicon item.silicon.name = Silicone
item.silicon.description = An extremely useful semiconductor, with applications in solar panels and many complex electronics. item.silicon.description=Un matériau semi-conducteur extrêmement utile, avec des utilisations dans les panneaux solaires et beaucoup d'autre composants électroniques complexes.
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-matter.name = Matière phasée item.phase-matter.name = Matière phasée
item.surge-alloy.name = alliage superchargé item.surge-alloy.name = alliage superchargé
item.biomatter.name = Biomasse item.biomatter.name = Biomasse
item.biomatter.description = A clump of organic mush; used for conversion into oil or as a basic fuel. item.biomatter.description = Un mélange de matières organiques; utilisé pour la transformation en huile ou en tant que carburant de base.
item.sand.name = Sable item.sand.name = Sable
item.sand.description = Un matériau commun utilisé largement dans la fonte, à la fois dans l'alliage et comme un flux. item.sand.description = Un matériau commun utilisé largement dans la fonte, à la fois dans l'alliage et comme un flux.
item.blast-compound.name = Mélange explosif item.blast-compound.name = Mélange explosif
@ -528,13 +528,13 @@ block.router.name = [accent]routeur[]
block.router.description = Distribue les articles dans les 4 directions. Le seul et l'unique. block.router.description = Distribue les articles dans les 4 directions. Le seul et l'unique.
block.distributor.name = Distributeur block.distributor.name = Distributeur
block.distributor.description = C'est un bloc qui peut envoyer les articles dans 8 directions. block.distributor.description = C'est un bloc qui peut envoyer les articles dans 8 directions.
block.sorter.name = Sorter block.sorter.name = Sorteur
block.sorter.description = Trie les articles. Si un article rcorrespond à la sélection, il peut passer. Autrement, l'article est distribué vers la gauche ou la droite. block.sorter.description = Trie les articles. Si un article rcorrespond à la sélection, il peut passer. Autrement, l'article est distribué vers la gauche ou la droite.
block.overflow-gate.name = Barrière de Débordement block.overflow-gate.name = Barrière de Débordement
block.overflow-gate.description = C'est la combinaison entre un Routeur et un Diviseur qui peut seulement distribuer à gauche et à droite si le chemin de devant est bloqué. block.overflow-gate.description = C'est la combinaison entre un Routeur et un Diviseur qui peut seulement distribuer à gauche et à droite si le chemin de devant est bloqué.
block.bridgeconveyor.name = Pont block.bridgeconveyor.name = Pont
block.bridgeconveyor.description = C'est un convoyeur qui peut passer par-dessus les blocs, jusqu'à deux blocs de distance. block.bridgeconveyor.description = C'est un convoyeur qui peut passer par-dessus les blocs, jusqu'à deux blocs de distance.
block.smelter.name = Smelter block.smelter.name = Fonderie d'alliage lourd
block.arc-smelter.name = Fonderie d'alliage lourd électrique block.arc-smelter.name = Fonderie d'alliage lourd électrique
block.silicon-smelter.name = Fonderie de Silicone block.silicon-smelter.name = Fonderie de Silicone
block.phase-weaver.name = Tisseur à Phase block.phase-weaver.name = Tisseur à Phase
@ -593,7 +593,7 @@ block.wraith-factory.name = Usine de "Combattants spectraux"
block.ghoul-factory.name = Usine de "Bombardiers goules" block.ghoul-factory.name = Usine de "Bombardiers goules"
block.dagger-factory.name = Usine de "Poignards" block.dagger-factory.name = Usine de "Poignards"
block.titan-factory.name = Usine de "Titans" block.titan-factory.name = Usine de "Titans"
block.fortress-factory.name = Fortress Mech Factory block.fortress-factory.name = Usine de "Forteresse"
block.revenant-factory.name = Usine de "Revenants" block.revenant-factory.name = Usine de "Revenants"
block.repair-point.name = Point de Réparation block.repair-point.name = Point de Réparation
block.pulse-conduit.name = Conduit à Impulsion block.pulse-conduit.name = Conduit à Impulsion
@ -634,10 +634,10 @@ unit.spirit.name = Drone sppirituel
unit.spirit.description = L'unité de soutien de départ.Apparaît dans la base par défaut .Mine automatiquement les minerais, récupère les objets au sol et répare les blocs. unit.spirit.description = L'unité de soutien de départ.Apparaît dans la base par défaut .Mine automatiquement les minerais, récupère les objets au sol et répare les blocs.
unit.phantom.name = Drone Fantôme unit.phantom.name = Drone Fantôme
unit.phantom.description = Une unité de soutien avancée. Mine automatiquement les minerais, récupère les objets au sol et répare les blocs. Bien plus efficace qu'un drone spirituel. unit.phantom.description = Une unité de soutien avancée. Mine automatiquement les minerais, récupère les objets au sol et répare les blocs. Bien plus efficace qu'un drone spirituel.
unit.dagger.name = Dagger unit.dagger.name = Poignard
unit.dagger.description = A basic ground unit. Useful in swarms. unit.dagger.description = Une unité terrestre basiquee. Utile en armée.
unit.titan.name = Titan unit.titan.name = Titan
unit.titan.description = An advanced, armored ground unit. Attacks both ground and air targets. unit.titan.description = Une unité terrestre cuirassée avancée. Attaque les unités terrestres comme aériennes.
unit.ghoul.name = Bombardier goule unit.ghoul.name = Bombardier goule
unit.ghoul.description = Un bombardier lourd . Utilise de la pyratite ou des explosifs comme munitions. unit.ghoul.description = Un bombardier lourd . Utilise de la pyratite ou des explosifs comme munitions.
unit.wraith.name = Combattant spectral unit.wraith.name = Combattant spectral
@ -667,4 +667,4 @@ tutorial.daggerfactory = Construire [accent]une usine de "Poignards" []est recom
tutorial.router = Les usines ont besoin de ressources pour fonctionner.\nCréez un routeur pour séparer les objets. tutorial.router = Les usines ont besoin de ressources pour fonctionner.\nCréez un routeur pour séparer les objets.
tutorial.dagger = Reliez des transmetteurs énergétiques à l'usine.\nUne fois que les conditions seront remplies , un mécha sera créé.\nConstruisez autant de foreuses, de générateurs et de tapis roulants que nécessaire. tutorial.dagger = Reliez des transmetteurs énergétiques à l'usine.\nUne fois que les conditions seront remplies , un mécha sera créé.\nConstruisez autant de foreuses, de générateurs et de tapis roulants que nécessaire.
tutorial.battle = [LIGHT_GRAY]L'Ennemi[] a révélé sa base .\nDétruisez la avec votre unité et des méchas "Poignard". tutorial.battle = [LIGHT_GRAY]L'Ennemi[] a révélé sa base .\nDétruisez la avec votre unité et des méchas "Poignard".
block.bridge-conveyor.description = C'est un convoyeur qui peut passer par-dessus les blocs, jusqu'à deux blocs de distance. block.bridge-conveyor.description = C'est un convoyeur qui peut passer par-dessus les blocs, jusqu'à deux blocs de distance.

View File

@ -32,10 +32,10 @@ text.coreattack = < 코어가 공격받고 있습니다 ! >
text.unlocks = 아이템들 text.unlocks = 아이템들
text.savegame = 게임 저장 text.savegame = 게임 저장
text.loadgame = 게임 불러오기 text.loadgame = 게임 불러오기
text.joingame = 게임 참가 text.joingame = 멀티플레이
text.addplayers = 플레이어 추가/제거 text.addplayers = 플레이어 추가/제거
text.customgame = 커스텀 게임 text.customgame = 커스텀 게임
text.sectors = 구역 text.sectors = 싱글 플레이
text.sector = 구역 : [LIGHT_GRAY]{0} text.sector = 구역 : [LIGHT_GRAY]{0}
text.sector.time = 시간 : [LIGHT_GRAY]{0} text.sector.time = 시간 : [LIGHT_GRAY]{0}
text.sector.deploy = 시작 text.sector.deploy = 시작
@ -280,8 +280,11 @@ text.paused = 일시 정지
text.yes = text.yes =
text.no = 아니오 text.no = 아니오
text.info.title = [accent]정보 text.info.title = [accent]정보
text.error.title = [crimson]오류가 발생했습니다. text.error.title = [crimson]오류가 발생했습니다.
text.error.crashtitle = 오류가 발생했습니다. text.error.crashtitle = 오류가 발생했습니다.
text.error.alreadyconnected = 이미 접속중입니다.
text.blocks.blockinfo = 블록 정보 text.blocks.blockinfo = 블록 정보
text.blocks.powercapacity = 최대 전력 용량 text.blocks.powercapacity = 최대 전력 용량
text.blocks.powershot = 1발당 전력 소모량 text.blocks.powershot = 1발당 전력 소모량
@ -703,7 +706,7 @@ block.silicon-smelter.description = 실리콘을 제작할 수 있는 건물입
block.phase-weaver.description = 메타를 제작할 수 있는 건물입니다. block.phase-weaver.description = 메타를 제작할 수 있는 건물입니다.
block.pulverizer.description = 돌을 갈아서 모래로 만들 수 있는 건물입니다. block.pulverizer.description = 돌을 갈아서 모래로 만들 수 있는 건물입니다.
block.cryofluidmixer.description = 냉각수를 제작할 수 있는 건물입니다. block.cryofluidmixer.description = 냉각수를 제작할 수 있는 건물입니다.
block.melter.description = 용암을 돌로 만들 수 있는 건물입니다. block.melter.description = 돌로 용암을 만들 수 있는 건물입니다.
block.incinerator.description = 불필요한 아이템을 소각시켜 줄 수 있는 건물입니다. block.incinerator.description = 불필요한 아이템을 소각시켜 줄 수 있는 건물입니다.
block.biomattercompressor.description = 잔디밭에서 바이오메터를 추출할 수 있는 건물입니다. block.biomattercompressor.description = 잔디밭에서 바이오메터를 추출할 수 있는 건물입니다.
block.separator.description = 돌을 분해하여 각종 자원으로 재활용 할 수 있게 해 주는 건물입니다. block.separator.description = 돌을 분해하여 각종 자원으로 재활용 할 수 있게 해 주는 건물입니다.

View File

@ -2,7 +2,7 @@ package io.anuke.mindustry.ai;
import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.*; import com.badlogic.gdx.utils.*;
import io.anuke.mindustry.content.Items; import com.badlogic.gdx.utils.Bits;
import io.anuke.mindustry.content.blocks.Blocks; import io.anuke.mindustry.content.blocks.Blocks;
import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.game.EventType.TileChangeEvent; import io.anuke.mindustry.game.EventType.TileChangeEvent;
@ -14,10 +14,7 @@ import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.meta.BlockFlag; import io.anuke.mindustry.world.meta.BlockFlag;
import io.anuke.ucore.core.Events; import io.anuke.ucore.core.Events;
import io.anuke.ucore.function.Predicate; import io.anuke.ucore.function.Predicate;
import io.anuke.ucore.util.EnumSet; import io.anuke.ucore.util.*;
import io.anuke.ucore.util.Geometry;
import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.ThreadArray;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
@ -33,12 +30,14 @@ public class BlockIndexer{
private final static int structQuadrantSize = 12; private final static int structQuadrantSize = 12;
/**Set of all ores that are being scanned.*/ /**Set of all ores that are being scanned.*/
private final ObjectSet<Item> scanOres = ObjectSet.with(Items.copper, Items.coal, Items.lead, Items.thorium, Items.titanium); private final ObjectSet<Item> scanOres = new ObjectSet<Item>(){{addAll(Item.getAllOres());}};
private final ObjectSet<Item> itemSet = new ObjectSet<>(); private final ObjectSet<Item> itemSet = new ObjectSet<>();
/**Stores all ore quadtrants on the map.*/ /**Stores all ore quadtrants on the map.*/
private ObjectMap<Item, ObjectSet<Tile>> ores; private ObjectMap<Item, ObjectSet<Tile>> ores;
/**Tags all quadrants.*/ /**Tags all quadrants.*/
private Bits[] structQuadrants; private Bits[] structQuadrants;
/**Stores all damaged tile entities by team.*/
private ObjectSet<Tile>[] damagedTiles = new ObjectSet[Team.all.length];
/**Maps teams to a map of flagged tiles by type.*/ /**Maps teams to a map of flagged tiles by type.*/
private ObjectSet<Tile>[][] flagMap = new ObjectSet[Team.all.length][BlockFlag.all.length]; private ObjectSet<Tile>[][] flagMap = new ObjectSet[Team.all.length][BlockFlag.all.length];
@ -62,7 +61,9 @@ public class BlockIndexer{
}); });
Events.on(WorldLoadEvent.class, event -> { Events.on(WorldLoadEvent.class, event -> {
damagedTiles = new ObjectSet[Team.all.length];
flagMap = new ObjectSet[Team.all.length][BlockFlag.all.length]; flagMap = new ObjectSet[Team.all.length][BlockFlag.all.length];
for(int i = 0; i < flagMap.length; i++){ for(int i = 0; i < flagMap.length; i++){
for(int j = 0; j < BlockFlag.all.length; j++){ for(int j = 0; j < BlockFlag.all.length; j++){
flagMap[i][j] = new ObjectSet<>(); flagMap[i][j] = new ObjectSet<>();
@ -79,7 +80,13 @@ public class BlockIndexer{
for(int x = 0; x < world.width(); x++){ for(int x = 0; x < world.width(); x++){
for(int y = 0; y < world.height(); y++){ for(int y = 0; y < world.height(); y++){
process(world.tile(x, y)); Tile tile = world.tileWorld(x, y);
process(tile);
if(tile.entity != null && tile.entity.healthf() < 0.9999f){
notifyTileDamaged(tile.entity);
}
} }
} }
@ -97,6 +104,28 @@ public class BlockIndexer{
return flagMap[team.ordinal()]; return flagMap[team.ordinal()];
} }
/**Returns all damaged tiles by team.*/
public ObjectSet<Tile> getDamaged(Team team){
returnArray.clear();
if(damagedTiles[team.ordinal()] == null){
damagedTiles[team.ordinal()] = new ObjectSet<>();
}
ObjectSet<Tile> set = damagedTiles[team.ordinal()];
for(Tile tile : set){
if(tile.entity == null || tile.entity.getTeam() != team || tile.entity.healthf() >= 0.9999f){
returnArray.add(tile);
}
}
for(Tile tile : returnArray){
set.remove(tile);
}
return set;
}
/**Get all allied blocks with a flag.*/ /**Get all allied blocks with a flag.*/
public ObjectSet<Tile> getAllied(Team team, BlockFlag type){ public ObjectSet<Tile> getAllied(Team team, BlockFlag type){
return flagMap[team.ordinal()][type.ordinal()]; return flagMap[team.ordinal()][type.ordinal()];
@ -115,6 +144,15 @@ public class BlockIndexer{
return returnArray; return returnArray;
} }
public void notifyTileDamaged(TileEntity entity){
if(damagedTiles[entity.getTeam().ordinal()] == null){
damagedTiles[entity.getTeam().ordinal()] = new ObjectSet<>();
}
ObjectSet<Tile> set = damagedTiles[entity.getTeam().ordinal()];
set.add(entity.tile);
}
public TileEntity findTile(Team team, float x, float y, float range, Predicate<Tile> pred){ public TileEntity findTile(Team team, float x, float y, float range, Predicate<Tile> pred){
TileEntity closest = null; TileEntity closest = null;
float dst = 0; float dst = 0;

View File

@ -143,10 +143,14 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
public void damage(float damage){ public void damage(float damage){
if(dead) return; if(dead) return;
float preHealth = health;
Call.onTileDamage(tile, health - tile.block().handleDamage(tile, damage)); Call.onTileDamage(tile, health - tile.block().handleDamage(tile, damage));
if(health <= 0){ if(health <= 0){
Call.onTileDestroyed(tile); Call.onTileDestroyed(tile);
}else if(preHealth >= maxHealth() - 0.00001f && health < maxHealth()){ //when just damaged
world.indexer.notifyTileDamaged(this);
} }
} }

View File

@ -11,8 +11,9 @@ import io.anuke.ucore.entities.EntityGroup;
import io.anuke.ucore.entities.EntityQuery; import io.anuke.ucore.entities.EntityQuery;
import io.anuke.ucore.function.Consumer; import io.anuke.ucore.function.Consumer;
import io.anuke.ucore.function.Predicate; import io.anuke.ucore.function.Predicate;
import io.anuke.ucore.util.Threads;
import io.anuke.ucore.util.EnumSet; import io.anuke.ucore.util.EnumSet;
import io.anuke.ucore.util.Geometry;
import io.anuke.ucore.util.Threads;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
@ -125,6 +126,12 @@ public class Units{
return value[0]; return value[0];
} }
/**Returns the neareset damaged tile.*/
public static TileEntity findDamagedTile(Team team, float x, float y){
Tile tile = Geometry.findClosest(x, y, world.indexer.getDamaged(team));
return tile == null ? null : tile.entity;
}
/**Returns the neareset ally tile in a range.*/ /**Returns the neareset ally tile in a range.*/
public static TileEntity findAllyTile(Team team, float x, float y, float range, Predicate<Tile> pred){ public static TileEntity findAllyTile(Team team, float x, float y, float range, Predicate<Tile> pred){
return world.indexer.findTile(team, x, y, range, pred); return world.indexer.findTile(team, x, y, range, pred);

View File

@ -79,12 +79,14 @@ public class Drone extends FlyingUnit implements BuilderTrait{
} }
//if it's missing requirements, try and mine them //if it's missing requirements, try and mine them
for(ItemStack stack : entity.recipe.requirements){ if(entity.recipe != null){
if(!core.items.has(stack.item, stack.amount) && type.toMine.contains(stack.item)){ for(ItemStack stack : entity.recipe.requirements){
targetItem = stack.item; if(!core.items.has(stack.item, stack.amount) && type.toMine.contains(stack.item)){
getPlaceQueue().clear(); targetItem = stack.item;
setState(mine); getPlaceQueue().clear();
return; setState(mine);
return;
}
} }
} }
@ -102,22 +104,19 @@ public class Drone extends FlyingUnit implements BuilderTrait{
} }
public void update(){ public void update(){
if(target != null && (((TileEntity) target).health >= ((TileEntity) target).tile.block().health
|| target.distanceTo(Drone.this) > discoverRange)){
target = null;
}
if(target == null){ retarget(() -> {
retarget(() -> { target = Units.findDamagedTile(team, x, y);
target = Units.findAllyTile(team, x, y, discoverRange,
tile -> tile.entity != null && tile.entity.health + 0.0001f < tile.block().health);
if(target == null){ if(target == null){
setState(mine); setState(mine);
} }
}); });
}else if(target.distanceTo(Drone.this) > type.range){
circle(type.range); if(target == null) return;
if(target.distanceTo(Drone.this) > type.range){
circle(type.range*0.9f);
}else{ }else{
TileEntity entity = (TileEntity) target; TileEntity entity = (TileEntity) target;
entity.healBy(type.healSpeed * entity.tile.block().health / 100f * Timers.delta()); entity.healBy(type.healSpeed * entity.tile.block().health / 100f * Timers.delta());
@ -316,7 +315,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{
target = null; target = null;
} }
if(Net.client() && state.is(repair) && target instanceof TileEntity){ if(Net.client() && state.is(repair) && target instanceof TileEntity && target.distanceTo(this) < type.range){
TileEntity entity = (TileEntity) target; TileEntity entity = (TileEntity) target;
entity.health += type.healSpeed * Timers.delta(); entity.health += type.healSpeed * Timers.delta();
entity.health = Mathf.clamp(entity.health, 0, entity.tile.block().health); entity.health = Mathf.clamp(entity.health, 0, entity.tile.block().health);
@ -327,7 +326,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{
@Override @Override
protected void updateRotation(){ protected void updateRotation(){
if(target != null && (state.is(repair) || state.is(mine))){ if(target != null && ((state.is(repair) && target.distanceTo(this) < type.range) || state.is(mine))){
rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.3f); rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.3f);
}else{ }else{
rotation = Mathf.slerpDelta(rotation, velocity.angle(), 0.3f); rotation = Mathf.slerpDelta(rotation, velocity.angle(), 0.3f);
@ -353,7 +352,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{
TargetTrait entity = target; TargetTrait entity = target;
if(entity instanceof TileEntity && state.is(repair)){ if(entity instanceof TileEntity && state.is(repair) && target.distanceTo(this) < type.range){
float len = 5f; float len = 5f;
Draw.color(Color.BLACK, Color.WHITE, 0.95f + Mathf.absin(Timers.time(), 0.8f, 0.05f)); Draw.color(Color.BLACK, Color.WHITE, 0.95f + Mathf.absin(Timers.time(), 0.8f, 0.05f));
Shapes.laser("beam", "beam-end", Shapes.laser("beam", "beam-end",

View File

@ -206,22 +206,12 @@ public abstract class InputHandler extends InputAdapter{
consumed = true; consumed = true;
showedInventory = true; showedInventory = true;
} }
if(tile.block().consumes.hasAny()){
frag.consume.show(tile);
consumed = true;
showedConsume = true;
}
} }
if(!showedInventory){ if(!showedInventory){
frag.inv.hide(); frag.inv.hide();
} }
if(!showedConsume){
frag.consume.hide();
}
if(!consumed && player.isBuilding()){ if(!consumed && player.isBuilding()){
player.clearBuilding(); player.clearBuilding();
recipe = null; recipe = null;
@ -231,9 +221,7 @@ public abstract class InputHandler extends InputAdapter{
return consumed; return consumed;
} }
/** /**Tries to select the player to drop off items, returns true if successful.*/
* Tries to select the player to drop off items, returns true if successful.
*/
boolean tryTapPlayer(float x, float y){ boolean tryTapPlayer(float x, float y){
if(canTapPlayer(x, y)){ if(canTapPlayer(x, y)){
droppingItem = true; droppingItem = true;
@ -246,9 +234,7 @@ public abstract class InputHandler extends InputAdapter{
return Vector2.dst(x, y, player.x, player.y) <= playerSelectRange && player.inventory.hasItem(); return Vector2.dst(x, y, player.x, player.y) <= playerSelectRange && player.inventory.hasItem();
} }
/** /**Tries to begin mining a tile, returns true if successful.*/
* Tries to begin mining a tile, returns true if successful.
*/
boolean tryBeginMine(Tile tile){ boolean tryBeginMine(Tile tile){
if(canMine(tile)){ if(canMine(tile)){
//if a block is clicked twice, reset it //if a block is clicked twice, reset it

View File

@ -6,10 +6,10 @@ import io.anuke.mindustry.game.Content;
import io.anuke.mindustry.game.UnlockableContent; import io.anuke.mindustry.game.UnlockableContent;
import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.ContentType;
import io.anuke.mindustry.world.meta.StatValue;
import io.anuke.ucore.scene.event.HandCursorListener; import io.anuke.ucore.scene.event.HandCursorListener;
import io.anuke.ucore.scene.ui.Image; import io.anuke.ucore.scene.ui.Image;
import io.anuke.ucore.scene.ui.ScrollPane; import io.anuke.ucore.scene.ui.ScrollPane;
import io.anuke.ucore.scene.ui.Tooltip;
import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.scene.ui.layout.Table;
import io.anuke.ucore.scene.utils.UIUtils; import io.anuke.ucore.scene.utils.UIUtils;
@ -65,10 +65,7 @@ public class UnlocksDialog extends FloatingDialog{
if(control.unlocks.isUnlocked(unlock)){ if(control.unlocks.isUnlocked(unlock)){
image.clicked(() -> Vars.ui.content.show(unlock)); image.clicked(() -> Vars.ui.content.show(unlock));
image.addListener(new Tooltip<>(new Table("clear"){{ StatValue.addToolTip(image, unlock);
add(unlock.localizedName());
margin(4);
}}));
} }
if((++count) % maxWidth == 0){ if((++count) % maxWidth == 0){

View File

@ -12,6 +12,7 @@ import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.consumers.Consume; import io.anuke.mindustry.world.consumers.Consume;
import io.anuke.ucore.core.Graphics; import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.scene.Element;
import io.anuke.ucore.scene.Group; import io.anuke.ucore.scene.Group;
import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.scene.ui.layout.Table;
@ -19,6 +20,7 @@ import static io.anuke.mindustry.Vars.*;
public class BlockConsumeFragment extends Fragment{ public class BlockConsumeFragment extends Fragment{
private Table table; private Table table;
private Tile lastTile;
private boolean visible; private boolean visible;
@Override @Override
@ -26,6 +28,24 @@ public class BlockConsumeFragment extends Fragment{
table = new Table(); table = new Table();
table.visible(() -> !state.is(State.menu) && visible); table.visible(() -> !state.is(State.menu) && visible);
table.setTransform(true); table.setTransform(true);
parent.addChild(new Element(){{update(() -> {
if(!ui.hasMouse()){
Tile tile = world.tileWorld(Graphics.mouseWorld().x, Graphics.mouseWorld().y);
if(tile == null) return;
tile = tile.target();
if(tile != lastTile){
if(tile.block().consumes.hasAny()){
show(tile);
}else if(visible){
hide();
}
lastTile = tile;
}
}
});}});
parent.setTransform(true); parent.setTransform(true);
parent.addChild(table); parent.addChild(table);
} }
@ -66,7 +86,7 @@ public class BlockConsumeFragment extends Fragment{
rebuild(block, entity); rebuild(block, entity);
} }
Vector2 v = Graphics.screen(tile.drawx() - tile.block().size * tilesize / 2f, tile.drawy() + tile.block().size * tilesize / 2f); Vector2 v = Graphics.screen(tile.drawx() - tile.block().size * tilesize / 2f + 0.25f, tile.drawy() + tile.block().size * tilesize / 2f);
table.pack(); table.pack();
table.setPosition(v.x, v.y, Align.topRight); table.setPosition(v.x, v.y, Align.topRight);
}); });
@ -76,8 +96,7 @@ public class BlockConsumeFragment extends Fragment{
public void hide(){ public void hide(){
table.clear(); table.clear();
table.update(() -> { table.update(() -> {});
});
visible = false; visible = false;
} }

View File

@ -101,14 +101,6 @@ public class Tile implements PosTrait, TargetTrait{
return -1; return -1;
} }
public byte sizedRelativeTo(int cx, int cy){
if(x == cx && y == cy - 1 - block().size / 2) return 1;
if(x == cx && y == cy + 1 + block().size / 2) return 3;
if(x == cx - 1 - block().size / 2 && y == cy) return 0;
if(x == cx + 1 + block().size / 2 && y == cy) return 2;
return -1;
}
public <T extends TileEntity> T entity(){ public <T extends TileEntity> T entity(){
return (T) entity; return (T) entity;
} }

View File

@ -14,6 +14,7 @@ import io.anuke.mindustry.graphics.Layer;
import io.anuke.mindustry.graphics.Palette; 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.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;
@ -265,7 +266,8 @@ public class ItemBridge extends Block{
Tile other = world.tile(entity.link); Tile other = world.tile(entity.link);
if(!linkValid(tile, other)){ if(!linkValid(tile, other)){
int i = tile.absoluteRelativeTo(to.x, to.y); Tile edge = Edges.getFacingEdge(to, tile);
int i = tile.absoluteRelativeTo(edge.x, edge.y);
IntSetIterator it = entity.incoming.iterator(); IntSetIterator it = entity.incoming.iterator();

View File

@ -37,27 +37,62 @@ public class PowerGraph{
lastFrameUpdated = threads.getFrameID(); lastFrameUpdated = threads.getFrameID();
boolean charge = false;
float totalInput = 0f; float totalInput = 0f;
float bufferInput = 0f;
for(Tile producer : producers){ for(Tile producer : producers){
totalInput += producer.entity.power.amount; if (producer.block().consumesPower) {
bufferInput += producer.entity.power.amount;
} else {
totalInput += producer.entity.power.amount;
}
} }
float maxOutput = 0f; float maxOutput = 0f;
float bufferOutput = 0f;
for(Tile consumer : consumers){ for(Tile consumer : consumers){
maxOutput += consumer.block().powerCapacity - consumer.entity.power.amount; if (consumer.block().outputsPower) {
bufferOutput += consumer.block().powerCapacity - consumer.entity.power.amount;
} else {
maxOutput += consumer.block().powerCapacity - consumer.entity.power.amount;
}
} }
if (totalInput <= 0.0001f || maxOutput <= 0.0001f) { if (maxOutput < totalInput) {
charge = true;
}
if (totalInput + bufferInput <= 0.0001f || maxOutput + bufferOutput <= 0.0001f) {
return; return;
} }
float inputUsed = Math.min(maxOutput / totalInput, 1f); float bufferUsed = 0;
if (charge) {
bufferUsed = Math.min((totalInput - maxOutput) / bufferOutput, 1f);
} else {
bufferUsed = Math.min((maxOutput - totalInput) / bufferInput, 1f);
}
float inputUsed = charge ? Math.min((maxOutput + bufferOutput) / totalInput, 1f) : 1f;
for(Tile producer : producers){ for(Tile producer : producers){
if (producer.block().consumesPower) {
if (!charge) {
producer.entity.power.amount -= producer.entity.power.amount * bufferUsed;
}
continue;
}
producer.entity.power.amount -= producer.entity.power.amount * inputUsed; producer.entity.power.amount -= producer.entity.power.amount * inputUsed;
} }
float outputSatisfied = Math.min(totalInput / maxOutput, 1f); float outputSatisfied = charge ? 1f : Math.min((totalInput + bufferInput) / maxOutput, 1f);
for(Tile consumer : consumers){ for(Tile consumer : consumers){
if (consumer.block().outputsPower) {
if (charge) {
consumer.entity.power.amount += (consumer.block().powerCapacity - consumer.entity.power.amount) * bufferUsed;
}
continue;
}
consumer.entity.power.amount += (consumer.block().powerCapacity - consumer.entity.power.amount) * outputSatisfied; consumer.entity.power.amount += (consumer.block().powerCapacity - consumer.entity.power.amount) * outputSatisfied;
} }
} }

View File

@ -42,6 +42,7 @@ public class Cultivator extends Drill{
stats.remove(BlockStat.drillTier); stats.remove(BlockStat.drillTier);
stats.add(BlockStat.drillTier, table -> { stats.add(BlockStat.drillTier, table -> {
table.addImage("grass1").size(8 * 3).padBottom(3).padTop(3); table.addImage("grass1").size(8 * 3).padBottom(3).padTop(3);
// TODO: find out localized name and add tool tip
}); });
} }

View File

@ -16,11 +16,14 @@ import io.anuke.mindustry.world.consumers.ConsumeLiquid;
import io.anuke.mindustry.world.meta.BlockGroup; import io.anuke.mindustry.world.meta.BlockGroup;
import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.BlockStat;
import io.anuke.mindustry.world.meta.StatUnit; import io.anuke.mindustry.world.meta.StatUnit;
import io.anuke.mindustry.world.meta.StatValue;
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;
import io.anuke.ucore.core.Graphics; import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.scene.ui.Image;
import io.anuke.ucore.scene.ui.layout.Cell;
import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Threads; import io.anuke.ucore.util.Threads;
@ -133,7 +136,8 @@ public class Drill extends Block{
for(int i = 0; i < list.size; i++){ for(int i = 0; i < list.size; i++){
Item item = list.get(i); Item item = list.get(i);
table.addImage(item.name + "1").size(8 * 3).padRight(2).padLeft(2).padTop(3).padBottom(3); Cell<Image> imageCell = table.addImage(item.name + "1").size(8 * 3).padRight(2).padLeft(2).padTop(3).padBottom(3);
StatValue.addToolTip(imageCell.getElement(), item);
if(i != list.size - 1){ if(i != list.size - 1){
table.add("/"); table.add("/");
} }

View File

@ -64,15 +64,11 @@ public class Pump extends LiquidBlock{
if(isMultiblock()){ if(isMultiblock()){
Liquid last = null; Liquid last = null;
for(Tile other : tile.getLinkedTilesAs(this, drawTiles)){ for(Tile other : tile.getLinkedTilesAs(this, drawTiles)){
if(other == null) return false; if(other.floor().liquidDrop == null)
//can't place pump on block with multiple liquids continue;
if(last != null && other.floor().liquidDrop != last){ if(other.floor().liquidDrop != last && last != null)
return false; return false;
} last = other.floor().liquidDrop;
if(isValid(other)){
last = other.floor().liquidDrop;
}
} }
return last != null; return last != null;
}else{ }else{

View File

@ -81,11 +81,15 @@ public class CommandCenter extends Block{
public void buildTable(Tile tile, Table table){ public void buildTable(Tile tile, Table table){
CommandCenterEntity entity = tile.entity(); CommandCenterEntity entity = tile.entity();
ButtonGroup<ImageButton> group = new ButtonGroup<>(); ButtonGroup<ImageButton> group = new ButtonGroup<>();
Table buttons = new Table();
for(UnitCommand cmd : UnitCommand.values()){ for(UnitCommand cmd : UnitCommand.values()){
table.addImageButton("command-" + cmd.name(), "toggle", 8*3, () -> threads.run(() -> Call.onCommandCenterSet(players[0], tile, cmd))).size(40f, 44f) buttons.addImageButton("command-" + cmd.name(), "toggle", 8*3, () -> threads.run(() -> Call.onCommandCenterSet(players[0], tile, cmd))).size(40f, 44f)
.checked(entity.command == cmd).group(group); .checked(entity.command == cmd).group(group);
} }
table.add(buttons);
table.row();
table.table("button", t -> t.label(() -> entity.command.localized()).center().growX()).growX().padTop(-5);
} }
@Remote(called = Loc.server, forward = true, targets = Loc.both) @Remote(called = Loc.server, forward = true, targets = Loc.both)

View File

@ -1,5 +1,10 @@
package io.anuke.mindustry.world.meta; package io.anuke.mindustry.world.meta;
import io.anuke.mindustry.game.UnlockableContent;
import io.anuke.ucore.scene.Element;
import io.anuke.ucore.scene.ui.Image;
import io.anuke.ucore.scene.ui.Tooltip;
import io.anuke.ucore.scene.ui.layout.Cell;
import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.scene.ui.layout.Table;
/** /**
@ -7,8 +12,38 @@ import io.anuke.ucore.scene.ui.layout.Table;
*/ */
public interface StatValue{ public interface StatValue{
/** /**
* This method should all elements necessary to display this stat to the specified table. * This method should provide all elements necessary to display this stat to the specified table.
* For example, a stat that is just text would add label to the table. * For example, a stat that is just text would add label to the table.
*/ */
void display(Table table); void display(Table table);
/**
* This method adds an icon image together with a tool tip which contains the name of the item.
* @param table the table to add the image cell to.
* @param item The item which provides the tool tip content.
* @return the image cell which was created. The cell is not yet sized or padded.
*/
static Cell<Image> addImageWithToolTip(Table table, UnlockableContent item){
// Create a table cell with a new image as provided by the item
Cell<Image> imageCell = table.addImage(item.getContentIcon());
// Retrieve the image and add a tool tip with the item's name
addToolTip(imageCell.getElement(), item);
// Return the table cell for further processing (sizing, padding, ...)
return imageCell;
}
/**
* Adds a tool tip containing the item's localized name to the given element.
* @param element The element to assign the tool tip to.
* @param item The item which provides the tool tip content.
*/
static void addToolTip(Element element, UnlockableContent item){
element.addListener(new Tooltip<>(new Table("clear"){{
add(item.localizedName());
margin(4);
}}));
}
} }

View File

@ -4,6 +4,8 @@ import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.world.meta.StatValue; import io.anuke.mindustry.world.meta.StatValue;
import io.anuke.ucore.function.Predicate; import io.anuke.ucore.function.Predicate;
import io.anuke.ucore.scene.ui.Image;
import io.anuke.ucore.scene.ui.layout.Cell;
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.*;
@ -24,7 +26,12 @@ public class ItemFilterValue implements StatValue{
for(int i = 0; i < list.size; i++){ for(int i = 0; i < list.size; i++){
Item item = list.get(i); Item item = list.get(i);
table.addImage(item.region).size(8 * 3).padRight(2).padLeft(2);
Cell<Image> imageCell = table.addImage(item.region);
imageCell.size(8 * 3).padRight(2).padLeft(2);
StatValue.addToolTip(imageCell.getElement(), item);
if(i != list.size - 1){ if(i != list.size - 1){
table.add("/"); table.add("/");
} }

View File

@ -5,6 +5,9 @@ import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.ItemStack;
import io.anuke.mindustry.ui.ItemImage; import io.anuke.mindustry.ui.ItemImage;
import io.anuke.mindustry.world.meta.ContentStatValue; import io.anuke.mindustry.world.meta.ContentStatValue;
import io.anuke.mindustry.world.meta.StatValue;
import io.anuke.ucore.scene.ui.Image;
import io.anuke.ucore.scene.ui.layout.Cell;
import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.scene.ui.layout.Table;
public class ItemListValue implements ContentStatValue{ public class ItemListValue implements ContentStatValue{
@ -38,11 +41,17 @@ public class ItemListValue implements ContentStatValue{
public void display(Table table){ public void display(Table table){
if(items != null){ if(items != null){
for(Item item : items){ for(Item item : items){
table.addImage(item.region).size(8 * 3).padRight(5); Cell<Image> imageCell = table.addImage(item.region);
imageCell.size(8 * 3).padRight(5);
StatValue.addToolTip(imageCell.getElement(), item);
} }
}else{ }else{
for(ItemStack stack : stacks){ for(ItemStack stack : stacks){
table.add(new ItemImage(stack)).size(8 * 3).padRight(5); ItemImage image = new ItemImage(stack);
table.add(image).size(8 * 3).padRight(5);
StatValue.addToolTip(image, stack.item);
} }
} }
} }

View File

@ -5,6 +5,7 @@ import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.ItemStack;
import io.anuke.mindustry.ui.ItemImage; import io.anuke.mindustry.ui.ItemImage;
import io.anuke.mindustry.world.meta.ContentStatValue; import io.anuke.mindustry.world.meta.ContentStatValue;
import io.anuke.mindustry.world.meta.StatValue;
import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.scene.ui.layout.Table;
public class ItemValue implements ContentStatValue{ public class ItemValue implements ContentStatValue{
@ -22,6 +23,8 @@ public class ItemValue implements ContentStatValue{
@Override @Override
public void display(Table table){ public void display(Table table){
//TODO better implementation, quantity support //TODO better implementation, quantity support
table.add(new ItemImage(item)).size(8 * 3); ItemImage image = new ItemImage(item);
table.add(image).size(8 * 3);
StatValue.addToolTip(image, item.item);
} }
} }

View File

@ -4,6 +4,9 @@ import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.type.Liquid;
import io.anuke.mindustry.world.meta.StatValue; import io.anuke.mindustry.world.meta.StatValue;
import io.anuke.ucore.function.Predicate; import io.anuke.ucore.function.Predicate;
import io.anuke.ucore.scene.ui.Image;
import io.anuke.ucore.scene.ui.Tooltip;
import io.anuke.ucore.scene.ui.layout.Cell;
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.*;
@ -24,7 +27,10 @@ public class LiquidFilterValue implements StatValue{
for(int i = 0; i < list.size; i++){ for(int i = 0; i < list.size; i++){
Liquid item = list.get(i); Liquid item = list.get(i);
table.addImage(item.getContentIcon()).size(8 * 3).padRight(2).padLeft(2).padTop(2).padBottom(2);
Cell<Image> imageCell = StatValue.addImageWithToolTip(table, item);
imageCell.size(8 * 3).padRight(2).padLeft(2).padTop(2).padBottom(2);
if(i != list.size - 1){ if(i != list.size - 1){
table.add("/"); table.add("/");
} }

View File

@ -3,6 +3,9 @@ package io.anuke.mindustry.world.meta.values;
import io.anuke.mindustry.game.UnlockableContent; import io.anuke.mindustry.game.UnlockableContent;
import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.type.Liquid;
import io.anuke.mindustry.world.meta.ContentStatValue; import io.anuke.mindustry.world.meta.ContentStatValue;
import io.anuke.mindustry.world.meta.StatValue;
import io.anuke.ucore.scene.ui.Image;
import io.anuke.ucore.scene.ui.layout.Cell;
import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.scene.ui.layout.Table;
public class LiquidValue implements ContentStatValue{ public class LiquidValue implements ContentStatValue{
@ -19,6 +22,7 @@ public class LiquidValue implements ContentStatValue{
@Override @Override
public void display(Table table){ public void display(Table table){
table.addImage(liquid.getContentIcon()).size(8 * 3); Cell<Image> imageCell = StatValue.addImageWithToolTip(table, liquid);
imageCell.size(8 * 3);
} }
} }

View File

@ -1,6 +1,7 @@
package io.anuke.mindustry.server; package io.anuke.mindustry.server;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ObjectSet; import com.badlogic.gdx.utils.ObjectSet;
import com.badlogic.gdx.utils.Timer; import com.badlogic.gdx.utils.Timer;
@ -41,12 +42,18 @@ import static io.anuke.ucore.util.Log.*;
public class ServerControl extends Module{ public class ServerControl extends Module{
private static final int roundExtraTime = 12; private static final int roundExtraTime = 12;
//in bytes: 512 kb is max
private static final int maxLogLength = 1024 * 512;
private final CommandHandler handler = new CommandHandler(""); private final CommandHandler handler = new CommandHandler("");
private final FileHandle logFolder = Gdx.files.local("logs/");
private FileHandle currentLogFile;
private int gameOvers; private int gameOvers;
private boolean inExtraRound; private boolean inExtraRound;
private Task lastTask; private Task lastTask;
public ServerControl(String[] args){ public ServerControl(String[] args){
Settings.defaultList( Settings.defaultList(
"shufflemode", "normal", "shufflemode", "normal",
@ -56,7 +63,8 @@ public class ServerControl extends Module{
"sector_y", 1, "sector_y", 1,
"shuffle", true, "shuffle", true,
"crashreport", false, "crashreport", false,
"port", port "port", port,
"logging", true
); );
Log.setLogger(new LogHandler(){ Log.setLogger(new LogHandler(){
@ -64,22 +72,27 @@ public class ServerControl extends Module{
@Override @Override
public void info(String text, Object... args){ public void info(String text, Object... args){
print("&lg&fb" + "[INFO] " + format(text, args)); print("&lg&fb" + "[INFO] " + text, args);
} }
@Override @Override
public void err(String text, Object... args){ public void err(String text, Object... args){
print("&lr&fb" + "[ERR!] " + format(text, args)); print("&lr&fb" + "[ERR!] " + text, args);
} }
@Override @Override
public void warn(String text, Object... args){ public void warn(String text, Object... args){
print("&ly&fb" + "[WARN] " + format(text, args)); print("&ly&fb" + "[WARN] " + text, args);
} }
@Override @Override
public void print(String text, Object... args){ public void print(String text, Object... args){
System.out.println("[" + dateTime.format(LocalDateTime.now()) + "] " + format(text + "&fr", args)); String result = "[" + dateTime.format(LocalDateTime.now()) + "] " + format(text + "&fr", args);
System.out.println(result);
if(Settings.getBool("logging")){
logToFile("[" + dateTime.format(LocalDateTime.now()) + "] " + format(text + "&fr", false, args));
}
} }
}); });
@ -311,7 +324,7 @@ public class ServerControl extends Module{
return; return;
} }
Call.sendMessage("[GRAY][[Server]:[] " + arg[0]); Call.sendMessage("[scarlet][[Server]:[] " + arg[0]);
info("&lyServer: &lb{0}", arg[0]); info("&lyServer: &lb{0}", arg[0]);
}); });
@ -357,6 +370,13 @@ public class ServerControl extends Module{
info("Crash reporting is now {0}.", value ? "on" : "off"); info("Crash reporting is now {0}.", value ? "on" : "off");
}); });
handler.register("logging", "<on/off>", "Disables or enables server logs", arg -> {
boolean value = arg[0].equalsIgnoreCase("on");
Settings.putBool("logging", value);
Settings.save();
info("Logging is now {0}.", value ? "on" : "off");
});
handler.register("strict", "<on/off>", "Disables or enables strict mode", arg -> { handler.register("strict", "<on/off>", "Disables or enables strict mode", arg -> {
boolean value = arg[0].equalsIgnoreCase("on"); boolean value = arg[0].equalsIgnoreCase("on");
netServer.admins.setStrict(value); netServer.admins.setStrict(value);
@ -400,6 +420,7 @@ public class ServerControl extends Module{
Player target = playerGroup.find(p -> p.name.equals(arg[0])); Player target = playerGroup.find(p -> p.name.equals(arg[0]));
if(target != null){ if(target != null){
Call.sendMessage("[scarlet] " + target.name + " has been kicked by the server.");
netServer.kick(target.con.id, KickReason.kick); netServer.kick(target.con.id, KickReason.kick);
info("It is done."); info("It is done.");
}else{ }else{
@ -425,6 +446,13 @@ public class ServerControl extends Module{
}else{ }else{
err("Invalid type."); err("Invalid type.");
} }
for(Player player : playerGroup.all()){
if(netServer.admins.isIDBanned(player.uuid)){
Call.sendMessage("[scarlet] " + player.name + " has been banned.");
netServer.kick(player.con.id, KickReason.banned);
}
}
}); });
handler.register("bans", "List all banned IPs and IDs.", arg -> { handler.register("bans", "List all banned IPs and IDs.", arg -> {
@ -724,4 +752,23 @@ public class ServerControl extends Module{
state.set(State.menu); state.set(State.menu);
} }
} }
private void logToFile(String text){
if(currentLogFile != null && currentLogFile.length() > maxLogLength){
String date = DateTimeFormatter.ofPattern("MM-dd-yyyy | HH:mm:ss").format(LocalDateTime.now());
currentLogFile.writeString("[End of log file. Date: "+ date + "]\n", true);
currentLogFile = null;
}
if(currentLogFile == null){
int i = 0;
while(logFolder.child("log-" + i + ".txt").length() >= maxLogLength){
i ++;
}
currentLogFile = logFolder.child("log-" + i + ".txt");
}
currentLogFile.writeString(text + "\n", true);
}
} }