This commit is contained in:
Anuken
2018-12-14 21:48:34 -05:00
38 changed files with 572 additions and 497 deletions

View File

@@ -107,8 +107,6 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor{
ClassEntry clas = new ClassEntry(callLocation); ClassEntry clas = new ClassEntry(callLocation);
classMap.put(callLocation, clas); classMap.put(callLocation, clas);
classes.add(clas); classes.add(clas);
Utils.messager.printMessage(Kind.NOTE, "Generating class '" + clas.name + "'.");
} }
ClassEntry entry = classMap.get(callLocation); ClassEntry entry = classMap.get(callLocation);

View File

@@ -45,6 +45,7 @@ public class SerializeAnnotationProcessor extends AbstractProcessor{
Set<TypeElement> elements = ElementFilter.typesIn(roundEnv.getElementsAnnotatedWith(Serialize.class)); Set<TypeElement> elements = ElementFilter.typesIn(roundEnv.getElementsAnnotatedWith(Serialize.class));
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC); TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC);
classBuilder.addAnnotation(AnnotationSpec.builder(SuppressWarnings.class).addMember("value", "\"unchecked\"").build());
MethodSpec.Builder method = MethodSpec.methodBuilder("init").addModifiers(Modifier.PUBLIC, Modifier.STATIC); MethodSpec.Builder method = MethodSpec.methodBuilder("init").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
for(TypeElement elem : elements){ for(TypeElement elem : elements){

View File

@@ -1,30 +1,30 @@
buildscript { buildscript{
repositories { repositories{
mavenLocal() mavenLocal()
mavenCentral() mavenCentral()
google() google()
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } maven{ url "https://oss.sonatype.org/content/repositories/snapshots/" }
jcenter() jcenter()
} }
dependencies { dependencies{
classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.0' classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.5'
classpath "com.badlogicgames.gdx:gdx-tools:1.9.9" classpath "com.badlogicgames.gdx:gdx-tools:1.9.9"
} }
} }
allprojects { allprojects{
apply plugin: "idea" apply plugin: "idea"
version = 'release' version = 'release'
ext { ext{
versionNumber = '4' versionNumber = '4'
versionModifier = 'alpha' versionModifier = 'alpha'
if (!project.hasProperty("versionType")) 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 = '5871d2d0385370bc937fed3e5e301d6962a50476' uCoreVersion = '7ffeb2a9c754f4d31ca13e02dd857876b0707dc5'
getVersionString = { getVersionString = {
String buildVersion = getBuildVersion() String buildVersion = getBuildVersion()
@@ -43,7 +43,7 @@ allprojects {
generateLocales = { generateLocales = {
def output = 'en\n' def output = 'en\n'
def bundles = new File(project(':core').projectDir, 'assets/bundles/') def bundles = new File(project(':core').projectDir, 'assets/bundles/')
bundles.listFiles().each { other -> bundles.listFiles().each{ other ->
if(other.name == "bundle.properties") return if(other.name == "bundle.properties") return
output += other.name.substring("bundle".length() + 1, other.name.lastIndexOf('.')) + "\n" output += other.name.substring("bundle".length() + 1, other.name.lastIndexOf('.')) + "\n"
} }
@@ -56,9 +56,9 @@ allprojects {
try{ try{
pfile.createNewFile() pfile.createNewFile()
}catch (Exception ignored){} }catch(Exception ignored){}
if(pfile.exists()) { if(pfile.exists()){
props.load(new FileInputStream(pfile)) props.load(new FileInputStream(pfile))
@@ -74,19 +74,19 @@ allprojects {
} }
} }
repositories { repositories{
mavenLocal() mavenLocal()
mavenCentral() mavenCentral()
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } maven{ url "https://oss.sonatype.org/content/repositories/snapshots/" }
maven { url "https://oss.sonatype.org/content/repositories/releases/" } maven{ url "https://oss.sonatype.org/content/repositories/releases/" }
maven { url 'https://jitpack.io' } maven{ url 'https://jitpack.io' }
} }
} }
project(":desktop") { project(":desktop"){
apply plugin: "java" apply plugin: "java"
dependencies { dependencies{
compile project(":core") compile project(":core")
compile project(":kryonet") compile project(":kryonet")
if(new File(projectDir.parent, '../debug').exists() && System.properties["release"] == null) compile project(":debug") if(new File(projectDir.parent, '../debug').exists() && System.properties["release"] == null) compile project(":debug")
@@ -99,14 +99,14 @@ project(":desktop") {
} }
} }
project(":ios") { project(":ios"){
apply plugin: "java" apply plugin: "java"
apply plugin: "robovm" apply plugin: "robovm"
task copyGen{ task copyGen{
doLast { doLast{
copy { copy{
from("../core/build/classes/java/main/io/anuke/mindustry/gen/") { from("../core/build/classes/java/main/io/anuke/mindustry/gen/"){
include "**/*.java" include "**/*.java"
} }
@@ -134,14 +134,16 @@ 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.containsKey("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)
} }
build.dependsOn(incrementConfig) build.dependsOn(incrementConfig)
build.dependsOn(copyGen) if(file('robovm.properties').exists()){
build.dependsOn(copyGen)
}
dependencies { dependencies{
compile project(":core") compile project(":core")
implementation project(":kryonet") implementation project(":kryonet")
@@ -150,18 +152,17 @@ 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")
} }
} }
project(":core") { project(":core"){
apply plugin: "java" apply plugin: "java"
task finish { task finish{
generateLocales() generateLocales()
} }
dependencies { dependencies{
build.finalizedBy(finish) build.finalizedBy(finish)
def comp = System.properties["release"] == null || System.properties["release"] == "false" def comp = System.properties["release"] == null || System.properties["release"] == "false"
@@ -173,7 +174,7 @@ project(":core") {
compile "com.github.anuken:ucore:$uCoreVersion" compile "com.github.anuken:ucore:$uCoreVersion"
} }
if(new File(projectDir.parent, '../GDXGifRecorder').exists() && comp) { if(new File(projectDir.parent, '../GDXGifRecorder').exists() && comp){
compile project(":GDXGifRecorder") compile project(":GDXGifRecorder")
} }
@@ -186,16 +187,16 @@ project(":core") {
} }
} }
project(":server") { project(":server"){
apply plugin: "java" apply plugin: "java"
configurations { configurations{
if(findProject(":android") != null){ if(findProject(":android") != null){
compile.exclude module: android compile.exclude module: android
} }
} }
dependencies { dependencies{
compile project(":core") compile project(":core")
compile project(":kryonet") compile project(":kryonet")
@@ -207,7 +208,7 @@ project(":server") {
project(":tests"){ project(":tests"){
apply plugin: "java" apply plugin: "java"
dependencies { dependencies{
testImplementation project(":core") testImplementation project(":core")
testImplementation('org.junit.jupiter:junit-jupiter-api:5.1.0') testImplementation('org.junit.jupiter:junit-jupiter-api:5.1.0')
testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.1.0') testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.1.0')
@@ -215,32 +216,32 @@ project(":tests"){
testImplementation "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop" testImplementation "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
} }
test { test{
useJUnitPlatform() useJUnitPlatform()
workingDir = new File("../core/assets") workingDir = new File("../core/assets")
} }
} }
project(":tools") { project(":tools"){
apply plugin: "java" apply plugin: "java"
dependencies { dependencies{
compile project(":core") compile project(":core")
} }
} }
project(":annotations") { project(":annotations"){
apply plugin: "java" apply plugin: "java"
dependencies { dependencies{
compile 'com.squareup:javapoet:1.11.0' compile 'com.squareup:javapoet:1.11.0'
} }
} }
project(":kryonet") { project(":kryonet"){
apply plugin: "java" apply plugin: "java"
dependencies { dependencies{
compile project(":core") compile project(":core")
compile "org.lz4:lz4-java:1.4.1" compile "org.lz4:lz4-java:1.4.1"
compile 'com.github.Anuken:kryonet:53b10247b1' compile 'com.github.Anuken:kryonet:53b10247b1'

View File

@@ -384,6 +384,8 @@ category.multiplayer.name = Multiplayer
command.attack = Attack command.attack = Attack
command.retreat = Retreat command.retreat = Retreat
command.patrol = Patrol command.patrol = Patrol
keybind.gridMode.name = Block Select
keybind.gridModeShift.name = Category Select
keybind.press = Press a key... keybind.press = Press a key...
keybind.press.axis = Press an axis or key... keybind.press.axis = Press an axis or key...
keybind.screenshot.name = Map Screenshot keybind.screenshot.name = Map Screenshot
@@ -406,7 +408,7 @@ keybind.toggle_menus.name = Toggle menus
keybind.chat_history_prev.name = Chat history prev keybind.chat_history_prev.name = Chat history prev
keybind.chat_history_next.name = Chat history next keybind.chat_history_next.name = Chat history next
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
mode.text.help.title = Description of modes mode.text.help.title = Description of modes
mode.waves.name = Waves mode.waves.name = Waves

View File

@@ -7,7 +7,7 @@ text.link.github.description = Code source du jeu
text.link.dev-builds.description = Versions instables de développement text.link.dev-builds.description = Versions instables de développement
text.link.trello.description = Planning Trello officiel pour les fonctionnalités planifiées. text.link.trello.description = Planning Trello officiel pour les fonctionnalités planifiées.
text.link.itch.io.description = Page web itch.io avec les versions ordinateurs téléchargeables et la version web text.link.itch.io.description = Page web itch.io avec les versions ordinateurs téléchargeables et la version web
text.link.google-play.description = Page Google Play Store du jeu text.link.google-play.description = Page Google Play du jeu
text.link.wiki.description = Wiki officiel de Mindustry text.link.wiki.description = Wiki officiel de Mindustry
text.linkfail = L'ouverture du lien a échoué!\nL'URL a été copiée dans votre presse-papier. text.linkfail = L'ouverture du lien a échoué!\nL'URL a été copiée dans votre presse-papier.
text.screenshot = Capture d'écran enregistrée sur {0} text.screenshot = Capture d'écran enregistrée sur {0}
@@ -414,6 +414,8 @@ mode.freebuild.name = Construction libre
mode.freebuild.description = Ressources limitées et pas de compte à rebours pour les vagues. mode.freebuild.description = Ressources limitées et pas de compte à rebours pour les vagues.
mode.pvp.name = PvP mode.pvp.name = PvP
mode.pvp.description = Lutter contre d'autres joueurs pour gagner ! mode.pvp.description = Lutter contre d'autres joueurs pour gagner !
mode.attack.name = Attaque
mode.attack.descrption = Pas de vagues, le but est de détruire la base ennemie.
content.item.name = Objets content.item.name = Objets
content.liquid.name = Liquides content.liquid.name = Liquides
content.unit.name = Unités content.unit.name = Unités

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\n[BLUE]Beryllium
text.credits = Авторы text.credits = Авторы
text.contributors = Переводчики и контрибьюторы text.contributors = Переводчики и контрибьюторы
text.discord = Присоединяйтесь к нашему Discord! text.discord = Присоединяйтесь к нашему Discord!
@@ -23,9 +23,9 @@ text.level.select = Выбор карты
text.level.mode = Режим игры: text.level.mode = Режим игры:
text.construction.desktop = Чтобы отменить выбор блока или остановить строительство, [accent] используйте пробел[]. text.construction.desktop = Чтобы отменить выбор блока или остановить строительство, [accent] используйте пробел[].
text.construction.title = Руководство по размещению блоков text.construction.title = Руководство по размещению блоков
text.construction = Вы только что перешли в режим размещения[accent]блоков[].\n\nЧтобы начать размещение, просто коснитесь подходящего места рядом с вашим мехом.\nПосле того, как вы поставили несколько блоков, нажмите на галочку, чтобы подтвердить, и ваш мех начнет их строительство.\n\n- [accent]Удалите блоки [] из вашего плана строительства, нажав на них.n- [accent]Нажав Shift [] и, удерживая, перетащите любой выбранный блок.\n- [accent]Поместите блоки в линию [], нажимая и удерживая на пустое место, а затем перетаскивая в любом направлении.\n- [accent]Отмените размещение блоков [], нажав X в левом нижнем углу. text.construction = Вы только что перешли в режим размещения[accent]блоков[].\n\nЧтобы начать размещение, просто коснитесь подходящего места рядом с вашим мехом.\nПосле того, как вы поставили несколько блоков, нажмите на галочку, чтобы подтвердить, и ваш мех начнет их строительство.\n\n- [accent]Удалите блоки [] из вашего плана строительства, нажав на них.n- [accent]Нажав Shift [] и, удерживая, перетащите любой выбранный блок.\n- [accent]Поместите блоки в линию [], нажимая и удерживая на пустое место, а затем перетаскивая в любом направлении.\n- [accent]Отмените размещение блоков [], нажав X в нижнем правом углу.
text.deconstruction.title = Руководство по разрушению блоков text.deconstruction.title = Руководство по разрушению блоков
text.deconstruction = Вы только что перешли в режим сноса[accent] блоков.[].\n\nЧтобы начать удалять, просто нажмите на блок рядом с вашим мехом.\nПосле того как вы выбрали несколько блоков, нажмите на галочку, чтобы подтвердить, и ваш мех начнёт их сносить.\n\n- [accent]Уберите блоки [] из вашего выбора, нажав на них.\n- [accent]Удалите блоки в области [], нажав и удерживая на пустом месте, а затем перетаскивая в нужном направлении.\n- [accent]Отменить снос или выбор [] можно нажав X в левом нижнем углу. text.deconstruction = Вы только что перешли в режим сноса[accent] блоков.[].\n\nЧтобы начать удалять, просто нажмите на блок рядом с вашим мехом.\nПосле того как вы выбрали несколько блоков, нажмите на галочку, чтобы подтвердить, и ваш мех начнёт их сносить.\n\n- [accent]Уберите блоки [] из вашего выбора, нажав на них.\n- [accent]Удалите блоки в области [], нажав и удерживая на пустом месте, а затем перетаскивая в нужном направлении.\n- [accent]Отменить снос или выбор [] можно нажав X в нижнем правом углу.
text.showagain = Не показывать снова до следующей сессии text.showagain = Не показывать снова до следующей сессии
text.coreattack = < Ядро находится под атакой! > text.coreattack = < Ядро находится под атакой! >
text.unlocks = Разблокированные text.unlocks = Разблокированные
@@ -39,13 +39,13 @@ text.sector = Выбранный сектор: [LIGHT_GRAY]{0}
text.sector.time = Время: [LIGHT_GRAY]{0} text.sector.time = Время: [LIGHT_GRAY]{0}
text.sector.deploy = Высадиться text.sector.deploy = Высадиться
text.sector.abandon = Отступить text.sector.abandon = Отступить
text.sector.abandon.confirm = Вы уверены, что хотите отступить?\nЭто не может быть отменено! text.sector.abandon.confirm = Вы уверены, что хотите отступить?\nПрогресс на секторе нельзя восстановить!
text.sector.resume = Продолжить text.sector.resume = Продолжить
text.sector.locked = [scarlet][[Не завершён] text.sector.locked = [scarlet][[Не завершён]
text.sector.unexplored = [accent][[Неисследованный] text.sector.unexplored = [accent][[Неисследованный]
text.missions = Миссий:[LIGHT_GRAY] {0} text.missions = Миссий:[LIGHT_GRAY] {0}
text.mission = Миссия:[LIGHT_GRAY] {0} text.mission = Миссия:[LIGHT_GRAY] {0}
text.mission.main = Главная мисия:[LIGHT_GRAY] {0} 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} был завоёван.
@@ -430,12 +430,12 @@ item.titanium.name = Титан
item.titanium.description = Редкий сверхлёгкий металл широко используется в производстве: транспорта, буров и самолётов. item.titanium.description = Редкий сверхлёгкий металл широко используется в производстве: транспорта, буров и самолётов.
item.thorium.name = Торий item.thorium.name = Торий
item.thorium.description = Плотный радиоактивный металл используется в качестве структурной поддержки и ядерного топлива. item.thorium.description = Плотный радиоактивный металл используется в качестве структурной поддержки и ядерного топлива.
item.silicon.name = Кремень item.silicon.name = Кремний
item.silicon.description = Очень полезный полупроводник с применениями в солнечных батареях и множестве сложной электроники. 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 = Биоматерия
@@ -463,7 +463,7 @@ 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 = Защитная
mech.omega-mech.description = Громоздкий и хорошо бронированный мех, сделанный для фронтовых нападений. Его способность брони может блокировать до 90% входящего урона. mech.omega-mech.description = Громоздкий и хорошо бронированный мех, сделанный для фронтовых нападений. Его способность брони может блокировать до 90% входящего урона.
mech.dart-ship.name = Дротик mech.dart-ship.name = Дротик
@@ -655,7 +655,7 @@ tutorial.conveyor = [accent]Конвейеры[] используются для
tutorial.morecopper = Требуется больше меди.\n\nЛибо добудьте её вручную, либо разместите больше буров. tutorial.morecopper = Требуется больше меди.\n\nЛибо добудьте её вручную, либо разместите больше буров.
tutorial.turret = Оборонительные сооружения должны быть созданы, чтобы отразить[LIGHT_GRAY] атаку противника[].Постройте двойную турель рядом с вашей базой. tutorial.turret = Оборонительные сооружения должны быть созданы, чтобы отразить[LIGHT_GRAY] атаку противника[].Постройте двойную турель рядом с вашей базой.
tutorial.drillturret = Двойные турели требуют[accent] патронов из меди[] для стрельбы.\nРазместите бур рядом с турелью, чтобы снабдить её добытой медью. tutorial.drillturret = Двойные турели требуют[accent] патронов из меди[] для стрельбы.\nРазместите бур рядом с турелью, чтобы снабдить её добытой медью.
tutorial.waves = [LIGHT_GRAY]Враг[] приближается.\n\nЗащитите своё ядро от 2-ух волн. Вам может понадобится больше турелей. tutorial.waves = [LIGHT_GRAY]Враг[] приближается.\n\nЗащитите своё ядро от двух волн. Вам может понадобится больше турелей.
tutorial.lead = Осмотритесь! Магическим образом появились новые руды. Добудьте [accent] свинец[].\n\nПеретащите ресурс из своего устройства(юнита) в ядро для переноса ресурсов. tutorial.lead = Осмотритесь! Магическим образом появились новые руды. Добудьте [accent] свинец[].\n\nПеретащите ресурс из своего устройства(юнита) в ядро для переноса ресурсов.
tutorial.smelter = Медь и свинец являются мягкими металлами.\nПревосходный[accent] плотный сплав[] может быть создан в плавильном заводе.\n\nПостройте один плавильный завод. tutorial.smelter = Медь и свинец являются мягкими металлами.\nПревосходный[accent] плотный сплав[] может быть создан в плавильном заводе.\n\nПостройте один плавильный завод.
tutorial.densealloy = Теперь плавильный завод производит плотный сплав.\nСоздайте немного.\nУлучшите производство, если это необходимо. tutorial.densealloy = Теперь плавильный завод производит плотный сплав.\nСоздайте немного.\nУлучшите производство, если это необходимо.
@@ -664,7 +664,7 @@ tutorial.silicondrill = Для производства кремния треб
tutorial.generator = Эта технология требует энергии.\nПостройте [accent] генератор внутреннего сгорания[] для того, чтобы запитать устройство энергией. tutorial.generator = Эта технология требует энергии.\nПостройте [accent] генератор внутреннего сгорания[] для того, чтобы запитать устройство энергией.
tutorial.generatordrill = Генератор внутреннего сгорания нуждается в топливе.\nЗаправьте его углём. tutorial.generatordrill = Генератор внутреннего сгорания нуждается в топливе.\nЗаправьте его углём.
tutorial.node = Энергия требует транспортировки.\nСоздайте [accent] силовой узел[] рядом с генератором внутреннего сгорания для передачи энергии. tutorial.node = Энергия требует транспортировки.\nСоздайте [accent] силовой узел[] рядом с генератором внутреннего сгорания для передачи энергии.
tutorial.nodelink = Энергия может быть передана посредством соприкосновения блоков питания и генераторов или связанных силовых узлов.\n\nСоедините их энергией, нажав на силовой узел и выбрав генератор, а затем кремниевый завод. tutorial.nodelink = Энергия может быть передана посредством соприкосновения блоков питания и генераторов или связанных силовых узлов.\n\nСоедините их, нажав на силовой узел и выбрав генератор, а затем кремниевый завод.
tutorial.silicon = Производство кремния началось. Получите немного.\nРекомендуется улучшить эту систему. tutorial.silicon = Производство кремния началось. Получите немного.\nРекомендуется улучшить эту систему.
tutorial.daggerfactory = Постройте[accent] завод по производству "разведчиков".[]\n\nОн будет производить атакуюших мехов. tutorial.daggerfactory = Постройте[accent] завод по производству "разведчиков".[]\n\nОн будет производить атакуюших мехов.
tutorial.router = Заводы нуждаются в ресурсах для работы.\nСоздайте маршрутизатор для разделения ресурсов конвейера. tutorial.router = Заводы нуждаются в ресурсах для работы.\nСоздайте маршрутизатор для разделения ресурсов конвейера.
@@ -773,8 +773,8 @@ block.bridge-conveyor.description = Улучшенный транспортны
block.alpha-mech-pad.description = Превращает вас в мех [accent] Альфа[]. Требует энергию. block.alpha-mech-pad.description = Превращает вас в мех [accent] Альфа[]. Требует энергию.
block.itemsource.description = Бесконечно выводит предметы. Работает только в песочнице. block.itemsource.description = Бесконечно выводит предметы. Работает только в песочнице.
block.liquidsource.description = Бесконечно выводит жидкости. Работает только в песочнице. block.liquidsource.description = Бесконечно выводит жидкости. Работает только в песочнице.
block.itemvoid.description = Уничтожает любые предметы, которые входят в него, без использования энергии. Работает только в песочнице. block.itemvoid.description = Уничтожает любые предметы, которые входят в него, без использования энергии. Работает только в режиме песочницы.
block.powerinfinite.description = Бесконечность — не предел. Бесконечно выводит энергию. Доступен только в песочнице. block.powerinfinite.description = Бесконечность — не предел. Бесконечно выводит энергию. Доступен только в режиме песочницы.
block.powervoid.description = Энергия просто уходит в пустоту. Присутствует только в песочнице. block.powervoid.description = Энергия просто уходит в пустоту. Присутствует только в песочнице.
liquid.water.description = Намного лучше чем [BLUE]монооксид дигидрогена[].\n\n Для получения воды используйте помпу(насос) на источнике(блоке) или экстрактор воды.\n\n Эту жидкость можно подвести к бурам для ускорения скорости добычи или к турелям для ускорения стрельбы. liquid.water.description = Намного лучше чем [BLUE]монооксид дигидрогена[].\n\n Для получения воды используйте помпу(насос) на источнике(блоке) или экстрактор воды.\n\n Эту жидкость можно подвести к бурам для ускорения скорости добычи или к турелям для ускорения стрельбы.
liquid.lava.description = [accent]Горячо...\nВещество расплавленное из горно-каменных пород. liquid.lava.description = [accent]Горячо...\nВещество расплавленное из горно-каменных пород.

View File

@@ -8,67 +8,69 @@ text.link.trello.description = Planlanan özellikler için resmi Trello Bülteni
text.link.itch.io.description = PC yüklemeleri ve web sürümü ile itch.io sayfası text.link.itch.io.description = PC yüklemeleri ve web sürümü ile itch.io sayfası
text.link.google-play.description = Google Play mağaza sayfası text.link.google-play.description = Google Play mağaza sayfası
text.link.wiki.description = Resmi Mindustry Wikipedi'si text.link.wiki.description = Resmi Mindustry Wikipedi'si
text.linkfail = Bağlantıılamadı! URL, yazı tahtanıza kopyalandı. text.linkfail = Bağlantıılamadı\! URL, yazı tahtanıza kopyalandı.
text.editor.web = Web sürümü editörü desteklemiyor\! Editörü kullanmak için oyunu indirin.
text.web.unsupported = Site versiyonu bunu desteklemiyor\! Oyunu indirip dene.
text.gameover = Çekirdek yok edildi. text.gameover = Çekirdek yok edildi.
text.gameover.pvp = The[accent] {0}[] team is victorious! text.gameover.pvp = [accent] {0}[] takimi kazandi \!
text.sector.gameover = This sector has been lost. Re-deploy? text.sector.gameover = Sektor kaybedildi.
text.sector.retry = Retry text.sector.retry = Tekrar dene
text.highscore = [SARI] Yeni yüksek puan! text.highscore = [SARI] Yeni yüksek puan\!
text.wave.lasted = You lasted until wave [accent]{0}[]. text.wave.lasted = Su dalgaya kadar yasadin: [accent]{0}[].
text.level.highscore = Yüksek Puan: [accent] {0} text.level.highscore = Yüksek Puan\: [accent] {0}
text.level.delete.title = Silmeyi onaylayın text.level.delete.title = Silmeyi onaylayın
text.map.delete = Are you sure you want to delete the map "[accent]{0}[]"? text.map.delete = Su haritayi silmek istedigine emin misin? "[orange]{0}[]"?
text.level.select = Seviye Seç text.level.select = Seviye Seç
text.level.mode = Oyun Modu text.level.mode = Oyun Modu
text.construction.desktop = Desktop controls have been changed.\nTo deselect a block or stop building, [accent]use space[]. text.construction.desktop = Masaustu kontrolleri degisti.\nSecmeyi birakip yapmayi kesmek icin, [accent]bosluga bas[].
text.construction.title = Block Construction Guide text.construction.title = Blok Yapma Ogreticisi
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 = Sen su anda [accent]blok yapma moduna gectin[].\n\nYapmaya baslamak icin, geminin cevresinde uygun bir yere tikla.\nBiraz blok sectikten sonra, onaylamak icin "tik" tusuna bas, ve gemin onlari yapmaya baslayacaktir.\n\n- [accent]Blok kaldirmak[] icin onlari secme yerine gene tikla\n- [accent]Blok secmek icin[] onlara secme yerinde tikla.\n- [accent]Cizgi biciminde koymak icin[] bos bir yere bas, ve bir yere dogru surukle.\n- [accent]Yapma modundan cikmak icin[] alt kosedeki X tusuna bas
text.deconstruction.title = Block Deconstruction Guide text.deconstruction.title = Blok Yikim Ogreticisi
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 = Sen su anda [accent]blok yikim moduna gectin[].\n\nKirmaya baslamak icin, geminin cevresinde bir bloga tikla\nBiraz blok sectikten sonra, "tik" tusuna basarak onayla, ve gemin onlari yikmaya baslayacaktir.\n\n- [accent]Blok kaldirmak[] icin onlari secme yerine gene tikla\n- [accent]Bir alanin icinde blok kirmak icin[] bos bir yere tikla, ve surukle\n- [accent]Yikma modundan cikmak icin[] Kosedeki X tusuna bas
text.showagain = Don't show again next session text.showagain = Bunu gene gosterme
text.coreattack = < Core is under attack! > text.coreattack = < Cekirdek saldiri altinda\! >
text.unlocks = Unlocks text.unlocks = Koleksiyon
text.savegame = Oyunu Kaydet text.savegame = Oyunu Kaydet
text.loadgame = Oyunu yükle text.loadgame = Oyunu yükle
text.joingame = Oyuna katıl text.joingame = Oyuna katıl
text.addplayers = Add/Remove Players text.addplayers = Oyuncu ekle/cikar
text.customgame = Custom Game text.customgame = Ozel oyun
text.sectors = Sectors text.sectors = Sektorler
text.sector = Selected Sector: [LIGHT_GRAY]{0} text.sector = Su sektoru sectin\: [LIGHT_GRAY]{0}
text.sector.time = Time: [LIGHT_GRAY]{0} text.sector.time = Zaman\: [LIGHT_GRAY]{0}
text.sector.deploy = Deploy text.sector.deploy = Basla
text.sector.abandon = Abandon text.sector.abandon = Terk et
text.sector.abandon.confirm = Are you sure you want to abandon all progress at this sector?\nThis cannot be undone! text.sector.abandon.confirm = Buradaki ilerlemeni silmek istedigine emin misin\nBu geri alinamaz\!
text.sector.resume = Resume text.sector.resume = Devam et
text.sector.locked = [scarlet][[Incomplete] text.sector.locked = [scarlet][[Bitirilmedi]
text.sector.unexplored = [accent][[Unexplored] text.sector.unexplored = [accent][[Kesvedilmedş]
text.missions = Missions:[LIGHT_GRAY] {0} text.missions = Gorevler\:[LIGHT_GRAY] {0}
text.mission = Mission:[LIGHT_GRAY] {0} text.mission = Gorev\:[LIGHT_GRAY] {0}
text.mission.main = Main Mission:[LIGHT_GRAY] {0} text.mission.main = Ana gorev\:[LIGHT_GRAY] {0}
text.mission.info = Mission Info text.mission.info = Gorev bilgisi
text.mission.complete = Mission complete! text.mission.complete = Gorev tamamlandi\!
text.mission.complete.body = Sector {0},{1} has been conquered. text.mission.complete.body = Sektor {0},{1} ele gecirildi
text.mission.wave = Survive[accent] {0}/{1} []waves\nWave in {2} text.mission.wave = [accent]{0}[] dalga hayatta kal
text.mission.wave.enemies = Survive[accent] {0}/{1} []waves\n{2} Enemies text.mission.wave.enemies = [accent] {0}/{1} []dalga hayatta kal\n{2} Dusman oldur
text.mission.wave.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy text.mission.wave.enemy = [accent] {0}/{1} []dalga hayatta kal\n{2} Dusman oldur
text.mission.wave.menu = Survive[accent] {0} []waves text.mission.wave.menu = [accent] {0} []dalga hayatta kal
text.mission.battle = Destroy the enemy base. text.mission.battle = Dusman temelini yok et
text.mission.resource.menu = Obtain {0} x{1} text.mission.resource.menu = Sunlari ele gecir {0} x{1}
text.mission.resource = Obtain {0}:\n[accent]{1}/{2}[] text.mission.resource = Sunlari ele gecir {0}\:\n[accent]{1}/{2}[]
text.mission.block = Create {0} text.mission.block = Su kadar yarat {0}
text.mission.unit = Create {0} Unit text.mission.unit = {0} Kadar unit yarat
text.mission.command = Send Command {0} To Units text.mission.command = {0} Unite komut yolla
text.mission.linknode = Link Power Node text.mission.linknode = Guc nodu bagla
text.mission.display = [accent]Mission:\n[LIGHT_GRAY]{0} text.mission.display = [accent]Gorev\:\n[LIGHT_GRAY]{0}
text.mission.mech = Switch to mech[accent] {0}[] text.mission.mech = Su gemiye degis[accent] {0}[]
text.mission.create = Create[accent] {0}[] text.mission.create = Su kadar yarat[accent] {0}[]
text.none = <none> text.none = <none>
text.close = Close text.close = Kapat
text.quit = Çık text.quit = Çık
text.maps = Maps text.maps = Haritalar
text.continue = Continue text.continue = Devam et
text.nextmission = Next Mission text.nextmission = Siradaki gorev
text.maps.none = [LIGHT_GRAY]No maps found! text.maps.none = [LIGHT_GRAY]Harita bulunamadi\!
text.about.button = Hakkında text.about.button = Hakkında
text.name = Adı: text.name = Adı:
text.filename = File Name: text.filename = File Name:

View File

@@ -1,5 +1,6 @@
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 = [ROYAL]Anuken[]製作 - [SKY]anukendev@gmail.com[]
text.credits = 致謝名單 text.credits = 致謝名單
text.contributors = 翻譯員和貢獻者
text.discord = 加入 Mindustry 的 Discord 聊天室! text.discord = 加入 Mindustry 的 Discord 聊天室!
text.link.discord.description = 官方 Mindustry Discord 聊天室 text.link.discord.description = 官方 Mindustry Discord 聊天室
text.link.github.description = 遊戲原始碼 text.link.github.description = 遊戲原始碼
@@ -9,8 +10,9 @@ text.link.itch.io.description = itch.io 電腦版下載與網頁版
text.link.google-play.description = Google Play 商店頁面 text.link.google-play.description = Google Play 商店頁面
text.link.wiki.description = 官方 Mindustry 維基 text.link.wiki.description = 官方 Mindustry 維基
text.linkfail = 無法打開連結!\n我們已將該網址複製到您的剪貼簿。 text.linkfail = 無法打開連結!\n我們已將該網址複製到您的剪貼簿。
text.screenshot = 截圖保存到{0}
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 = [accent]新的高分紀錄! text.highscore = [accent]新的高分紀錄!
@@ -71,6 +73,7 @@ text.nextmission = 下一個任務
text.maps.none = [LIGHT_GRAY]找不到地圖! text.maps.none = [LIGHT_GRAY]找不到地圖!
text.about.button = 關於 text.about.button = 關於
text.name = 名稱: text.name = 名稱:
text.noname = 先選擇一個[accent]玩家名稱[]。
text.filename = 檔案名稱︰ text.filename = 檔案名稱︰
text.unlocked = 新方塊已解鎖! text.unlocked = 新方塊已解鎖!
text.unlocked.plural = 新方塊已解鎖! text.unlocked.plural = 新方塊已解鎖!
@@ -250,7 +253,7 @@ text.menu = 主選單
text.play = 開始 text.play = 開始
text.load = 載入 text.load = 載入
text.save = 儲存 text.save = 儲存
text.fps = 螢幕刷新率{0} text.fps = FPS{0}
text.tps = TPS{0} text.tps = TPS{0}
text.ping = 延遲:{0}ms text.ping = 延遲:{0}ms
text.language.restart = 請重新啟動遊戲以使選取的語言生效。 text.language.restart = 請重新啟動遊戲以使選取的語言生效。
@@ -259,6 +262,7 @@ text.tutorial = 教學
text.editor = 地圖編輯器 text.editor = 地圖編輯器
text.mapeditor = 地圖編輯器 text.mapeditor = 地圖編輯器
text.donate = 贊助 text.donate = 贊助
text.connectfail = [crimson]無法連線到伺服器:[accent]{0} text.connectfail = [crimson]無法連線到伺服器:[accent]{0}
text.error.unreachable = 無法到達伺服器。 text.error.unreachable = 無法到達伺服器。
text.error.invalidaddress = 無效地址。 text.error.invalidaddress = 無效地址。
@@ -267,6 +271,7 @@ text.error.mismatch = 包裹錯誤:\n客戶端/伺服器版本可能不匹配
text.error.alreadyconnected = 已連接。 text.error.alreadyconnected = 已連接。
text.error.mapnotfound = 找不到地圖! text.error.mapnotfound = 找不到地圖!
text.error.any = 未知網絡錯誤。 text.error.any = 未知網絡錯誤。
text.settings.language = 語言 text.settings.language = 語言
text.settings.reset = 重設為預設設定 text.settings.reset = 重設為預設設定
text.settings.rebind = 重新綁定 text.settings.rebind = 重新綁定
@@ -289,7 +294,7 @@ text.error.crashtitle = 發生錯誤
text.blocks.unknown = [LIGHT_GRAY]??? text.blocks.unknown = [LIGHT_GRAY]???
text.blocks.blockinfo = 方塊資訊 text.blocks.blockinfo = 方塊資訊
text.blocks.powercapacity = 蓄電量 text.blocks.powercapacity = 蓄電量
text.blocks.powershot = /射擊 text.blocks.powershot = /射擊
text.blocks.targetsair = 攻擊空中目標 text.blocks.targetsair = 攻擊空中目標
text.blocks.itemspeed = 移動速度 text.blocks.itemspeed = 移動速度
text.blocks.shootrange = 範圍 text.blocks.shootrange = 範圍
@@ -297,13 +302,13 @@ text.blocks.size = 尺寸
text.blocks.liquidcapacity = 液體容量 text.blocks.liquidcapacity = 液體容量
text.blocks.maxitemssecond = 最高產量 text.blocks.maxitemssecond = 最高產量
text.blocks.powerrange = 輸出範圍 text.blocks.powerrange = 輸出範圍
text.blocks.poweruse = 使用 text.blocks.poweruse = 使用
text.blocks.powerdamage = /傷害 text.blocks.powerdamage = /傷害
text.blocks.inputitemcapacity = 最大輸入 text.blocks.inputitemcapacity = 最大輸入
text.blocks.outputitemcapacity = 最大輸出 text.blocks.outputitemcapacity = 最大輸出
text.blocks.itemcapacity = 物品容量 text.blocks.itemcapacity = 物品容量
text.blocks.basepowergeneration = 基本能量生产 text.blocks.basepowergeneration = 基本能量生产
text.blocks.powertransferspeed = 傳輸 text.blocks.powertransferspeed = 傳輸
text.blocks.craftspeed = 產生速度 text.blocks.craftspeed = 產生速度
text.blocks.inputliquid = 輸入液體 text.blocks.inputliquid = 輸入液體
text.blocks.inputliquidaux = 輔助液體 text.blocks.inputliquidaux = 輔助液體
@@ -319,8 +324,8 @@ text.blocks.coolant = 冷卻劑
text.blocks.coolantuse = 使用冷卻劑 text.blocks.coolantuse = 使用冷卻劑
text.blocks.inputliquidfuel = 輸入液體燃料 text.blocks.inputliquidfuel = 輸入液體燃料
text.blocks.liquidfueluse = 使用液體燃料速度 text.blocks.liquidfueluse = 使用液體燃料速度
text.blocks.boostitem = Boost Item text.blocks.boostitem = 強化物品
text.blocks.boostliquid = Boost Liquid text.blocks.boostliquid = 強化液體
text.blocks.health = 耐久度 text.blocks.health = 耐久度
text.blocks.inaccuracy = 誤差 text.blocks.inaccuracy = 誤差
text.blocks.shots = 射擊數 text.blocks.shots = 射擊數
@@ -330,26 +335,27 @@ text.blocks.fuelburntime = 燃燒燃料時間
text.blocks.inputcapacity = 輸入容量 text.blocks.inputcapacity = 輸入容量
text.blocks.outputcapacity = 輸出容量 text.blocks.outputcapacity = 輸出容量
text.unit.blocks = 方塊 text.unit.blocks = 方塊
text.unit.powersecond = 單位/秒 text.unit.powersecond = 單位/秒
text.unit.liquidsecond = 液體單位/秒 text.unit.liquidsecond = 液體單位/秒
text.unit.itemssecond = 物品/秒 text.unit.itemssecond = 物品/秒
text.unit.pixelssecond = 像素/秒 text.unit.pixelssecond = 像素/秒
text.unit.liquidunits = 液體單位 text.unit.liquidunits = 液體單位
text.unit.powerunits = 單位 text.unit.powerunits = 單位
text.unit.degrees = text.unit.degrees =
text.unit.seconds = text.unit.seconds =
text.unit.items = 物品 text.unit.items = 物品
text.category.general = 一般 text.category.general = 一般
text.category.power = text.category.power =
text.category.liquids = 液體 text.category.liquids = 液體
text.category.items = 物品 text.category.items = 物品
text.category.crafting = 合成 text.category.crafting = 合成
text.category.shooting = 射擊 text.category.shooting = 射擊
text.category.optional = Optional Enhancements text.category.optional = 可選的強化
setting.indicators.name = 盟友指標
setting.autotarget.name = 自動射擊 setting.autotarget.name = 自動射擊
setting.fpscap.name = 最大螢幕刷新率 setting.fpscap.name = 最大FPS
setting.fpscap.none = 没有 setting.fpscap.none = 没有
setting.fpscap.text = {0}螢幕刷新率 setting.fpscap.text = {0}FPS
setting.difficulty.training = 訓練 setting.difficulty.training = 訓練
setting.difficulty.easy = 簡單 setting.difficulty.easy = 簡單
setting.difficulty.normal = 普通 setting.difficulty.normal = 普通
@@ -362,7 +368,7 @@ setting.sensitivity.name = 控制器靈敏度
setting.saveinterval.name = 自動存檔間隔 setting.saveinterval.name = 自動存檔間隔
setting.seconds = {0}秒 setting.seconds = {0}秒
setting.fullscreen.name = 全螢幕 setting.fullscreen.name = 全螢幕
setting.fps.name = 顯示螢幕刷新率 setting.fps.name = 顯示FPS
setting.vsync.name = 垂直同步 setting.vsync.name = 垂直同步
setting.lasers.name = 顯示雷射光束 setting.lasers.name = 顯示雷射光束
setting.minimap.name = 顯示小地圖 setting.minimap.name = 顯示小地圖
@@ -370,7 +376,7 @@ setting.musicvol.name = 音樂音量
setting.mutemusic.name = 靜音 setting.mutemusic.name = 靜音
setting.sfxvol.name = 音效音量 setting.sfxvol.name = 音效音量
setting.mutesound.name = 靜音 setting.mutesound.name = 靜音
setting.crashreport.name = Send Anonymous Crash Reports setting.crashreport.name = 發送匿名崩潰報告
text.keybind.title = 重新綁定按鍵 text.keybind.title = 重新綁定按鍵
category.general.name = 一般 category.general.name = 一般
category.view.name = 查看 category.view.name = 查看
@@ -378,8 +384,9 @@ category.multiplayer.name = 多人
command.attack = 攻擊 command.attack = 攻擊
command.retreat = 撤退 command.retreat = 撤退
command.patrol = 巡邏 command.patrol = 巡邏
keybind.press = 按一下鍵 keybind.press = 按一下鍵……
keybind.press.axis = 按一下軸心或鍵 keybind.press.axis = 按一下軸心或鍵……
keybind.screenshot.name = 地圖截圖
keybind.move_x.name = 水平移動 keybind.move_x.name = 水平移動
keybind.move_y.name = 垂直移動 keybind.move_y.name = 垂直移動
keybind.select.name = 選取 keybind.select.name = 選取
@@ -410,6 +417,8 @@ mode.freebuild.name = 自由建造
mode.freebuild.description = 有限的資源,與不倒數計時的波次。 mode.freebuild.description = 有限的資源,與不倒數計時的波次。
mode.pvp.name = 對戰 mode.pvp.name = 對戰
mode.pvp.description = 和其他玩家鬥爭。 mode.pvp.description = 和其他玩家鬥爭。
mode.attack.name = 攻擊
mode.attack.description = 沒有波次,目標是摧毀敵人的基地。
content.item.name = 物品 content.item.name = 物品
content.liquid.name = 液體 content.liquid.name = 液體
content.unit.name = 機組 content.unit.name = 機組
@@ -535,8 +544,8 @@ block.sorter.name = 分類器
block.sorter.description = 對物品進行分類。如果物品與所選種類匹配,則允許其通過。否則,物品將從左邊和右邊輸出。 block.sorter.description = 對物品進行分類。如果物品與所選種類匹配,則允許其通過。否則,物品將從左邊和右邊輸出。
block.overflow-gate.name = 溢流器 block.overflow-gate.name = 溢流器
block.overflow-gate.description = 分離器和分配器的組合。如果前面被擋住,則向從左邊和右邊輸出物品。 block.overflow-gate.description = 分離器和分配器的組合。如果前面被擋住,則向從左邊和右邊輸出物品。
block.smelter.name = block.smelter.name = 煉廠
block.arc-smelter.name = 電弧煉 block.arc-smelter.name = 電弧煉廠
block.silicon-smelter.name = 煉矽廠 block.silicon-smelter.name = 煉矽廠
block.phase-weaver.name = 相織布編織器 block.phase-weaver.name = 相織布編織器
block.pulverizer.name = 粉碎機 block.pulverizer.name = 粉碎機
@@ -546,8 +555,8 @@ block.incinerator.name = 焚化爐
block.biomattercompressor.name = 生物物質壓縮機 block.biomattercompressor.name = 生物物質壓縮機
block.separator.name = 分離機 block.separator.name = 分離機
block.centrifuge.name = 離心機 block.centrifuge.name = 離心機
block.power-node.name = 節點 block.power-node.name = 節點
block.power-node-large.name = 大型能節點 block.power-node-large.name = 大型能節點
block.battery.name = 電池 block.battery.name = 電池
block.battery-large.name = 大型電池 block.battery-large.name = 大型電池
block.combustion-generator.name = 燃燒發電機 block.combustion-generator.name = 燃燒發電機
@@ -568,9 +577,9 @@ block.tau-mech-pad.name = Tau機甲墊
block.conduit.name = 管線 block.conduit.name = 管線
block.mechanical-pump.name = 機械泵 block.mechanical-pump.name = 機械泵
block.itemsource.name = 物品源 block.itemsource.name = 物品源
block.itemvoid.name = 物品 block.itemvoid.name = 物品虚
block.liquidsource.name = 液體源 block.liquidsource.name = 液體源
block.powervoid.name = 空虛 block.powervoid.name = 空虛
block.powerinfinite.name = 無限能量 block.powerinfinite.name = 無限能量
block.unloader.name = 裝卸器 block.unloader.name = 裝卸器
block.vault.name = 存儲庫 block.vault.name = 存儲庫
@@ -578,7 +587,7 @@ block.wave.name = 波浪炮
block.swarmer.name = 群炮 block.swarmer.name = 群炮
block.salvo.name = 齊射炮 block.salvo.name = 齊射炮
block.ripple.name = 波紋炮 block.ripple.name = 波紋炮
block.phase-conveyor.name = 相織傳送帶 block.phase-conveyor.name = 相織傳送帶
block.bridge-conveyor.name = 傳送帶橋 block.bridge-conveyor.name = 傳送帶橋
block.plastanium-compressor.name = 塑料壓縮機 block.plastanium-compressor.name = 塑料壓縮機
block.pyratite-mixer.name = 硫混合器 block.pyratite-mixer.name = 硫混合器
@@ -587,21 +596,21 @@ block.solidifer.name = 凝固器
block.solar-panel.name = 太陽能板 block.solar-panel.name = 太陽能板
block.solar-panel-large.name = 大型太陽能板 block.solar-panel-large.name = 大型太陽能板
block.oil-extractor.name = 石油鑽井 block.oil-extractor.name = 石油鑽井
block.spirit-factory.name = 精神無人機工廠 block.spirit-factory.name = 輕型無人機工廠
block.phantom-factory.name = Phantom Drone Factory block.phantom-factory.name = 幻影無人機工廠
block.wraith-factory.name = Wraith Fighter Factory block.wraith-factory.name = 怨靈戰鬥機工廠
block.ghoul-factory.name = Ghoul Bomber Factory block.ghoul-factory.name = 食屍鬼轟炸機工廠
block.dagger-factory.name = Dagger Mech Factory block.dagger-factory.name = 匕首機甲工廠
block.titan-factory.name = Titan Mech Factory block.titan-factory.name = 泰坦機甲工廠
block.fortress-factory.name = Fortress Mech Factory block.fortress-factory.name = 堡壘機甲工廠
block.revenant-factory.name = Revenant Fighter Factory block.revenant-factory.name = 亡魂戰鬥機工廠
block.repair-point.name = 維修點 block.repair-point.name = 維修點
block.pulse-conduit.name = 脈衝管線 block.pulse-conduit.name = 脈衝管線
block.phase-conduit.name = 相織管線 block.phase-conduit.name = 相織管線
block.liquid-router.name = 液體分配器 block.liquid-router.name = 液體分配器
block.liquid-tank.name = 液體儲罐 block.liquid-tank.name = 液體儲罐
block.liquid-junction.name = 液體連接點 block.liquid-junction.name = 液體連接點
block.bridge-conduit.name = 管橋 block.bridge-conduit.name =
block.rotary-pump.name = 迴旋泵 block.rotary-pump.name = 迴旋泵
block.thorium-reactor.name = 釷反應堆 block.thorium-reactor.name = 釷反應堆
block.command-center.name = 指令中心 block.command-center.name = 指令中心
@@ -619,7 +628,7 @@ block.shock-mine.name = 休克地雷
block.overdrive-projector.name = 超速投影器 block.overdrive-projector.name = 超速投影器
block.force-projector.name = 力牆投影器 block.force-projector.name = 力牆投影器
block.arc.name = 電弧 block.arc.name = 電弧
block.rtg-generator.name = 放射性同位素熱發電機 block.rtg-generator.name = 放射性同位素熱發電機
block.spectre.name = 幽靈炮 block.spectre.name = 幽靈炮
block.meltdown.name = 熔毀炮 block.meltdown.name = 熔毀炮
block.container.name = 容器 block.container.name = 容器
@@ -631,150 +640,150 @@ team.none.name = 灰
team.green.name = team.green.name =
team.purple.name = team.purple.name =
unit.alpha-drone.name = 阿爾法無人機 unit.alpha-drone.name = 阿爾法無人機
unit.spirit.name = 精神無人機 unit.spirit.name = 輕型無人機
unit.spirit.description = The starter drone unit. Spawns in the core by default. Automatically mines ores, collects items and repairs blocks. unit.spirit.description = 起始的無人機。默認在核心產生。自動挖掘礦石、收集物品和修理方塊。
unit.phantom.name = Phantom Drone unit.phantom.name = 幻影無人機
unit.phantom.description = An advanced drone unit. Automatically mines ores, collects items and repairs blocks. Significantly more effective than a drone. unit.phantom.description = 一種高級的無人機。自動挖掘礦石、收集物品和修理方塊。比輕型無人機明顯更有效。
unit.dagger.name = Dagger unit.dagger.name = 匕首
unit.dagger.description = A basic ground unit. Useful in swarms. unit.dagger.description = 一種基本的地面單位。最好一群地使用。
unit.titan.name = Titan unit.titan.name = 泰坦
unit.titan.description = An advanced armored ground unit. Uses carbide as ammo. Attacks both ground and air targets. unit.titan.description = 一種高級的具有裝甲的地面單位。使用碳化物作為彈藥。攻擊地面單位和空中單位。
unit.ghoul.name = Ghoul Bomber unit.ghoul.name = 食屍鬼轟炸機
unit.ghoul.description = A heavy carpet bomber. Uses blast compound or pyratite as ammo. unit.ghoul.description = 一種重型的鋪蓋性的轟炸機。使用爆炸化合物或黃鐵礦作為彈藥。
unit.wraith.name = Wraith Fighter unit.wraith.name = 怨靈戰鬥機
unit.wraith.description = A fast, hit-and-run interceptor unit. unit.wraith.description = 一種快速、打了就跑的攔截機。
unit.fortress.name = Fortress unit.fortress.name = 堡壘
unit.fortress.description = A heavy artillery ground unit. unit.fortress.description = 一種具有重型大砲的地面單位。
unit.revenant.name = Revenant unit.revenant.name = 亡魂
unit.revenant.description = A heavy laser platform. unit.revenant.description = 一種重型的激光平台。
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 = 你的任務是毀滅[LIGHT_GRAY]敵人[]\n\n首先[accent]挖掘銅礦[]。點擊核心附近的銅脈以開始。
tutorial.drill = Mining manually is inefficient.\n[accent]Drills []can mine automatically.\nPlace one on a copper vein. tutorial.drill = 手動挖掘礦石是低效率的。\n[accent]鑽頭[]能夠自動挖掘礦石。\n在銅脈上放置一個鑽頭。
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]輸送帶[]能夠將物品運輸到核心。\n製作一條從鑽頭開始到核心的輸送帶。
tutorial.morecopper = More copper is required.\n\nEither mine it manually, or place more drills. tutorial.morecopper = 需要更多銅。\n\n請手動挖掘銅礦或放置更多鑽頭。
tutorial.turret = Defensive structures must be built to repel the[LIGHT_GRAY] enemy[].\nBuild a duo turret near your base. tutorial.turret = 防禦建築是必須的以擊退[LIGHT_GRAY]敵人[]\n於核心附近建造一個雙炮。
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 = 雙炮需要[accent]銅彈[]以射擊。\n在雙炮旁邊放置一個鑽頭以供應銅。
tutorial.waves = The[LIGHT_GRAY] enemy[] approaches.\n\nDefend your core for 2 waves. Build more turrets. tutorial.waves = [LIGHT_GRAY]敵人[]來臨。\n\n防衛核心2波。建造更多的砲塔以防衛。
tutorial.lead = More ores are available. Explore and mine[accent] lead[].\n\nDrag from your unit to the core to transfer resources. tutorial.lead = 有更多的礦石可用。探索和挖掘[accent][]\n\n點擊您的單位拖動到核心以傳輸資源。
tutorial.smelter = Copper and lead are weak metals.\nSuperior[accent] Dense Alloy[] can be created in a smelter.\n\nBuild one. tutorial.smelter = 銅和鉛是柔軟的金屬。\n優良的[accent]稠密合金[]可以在冶煉廠中生產。\n\n建造一個冶煉廠。
tutorial.densealloy = The smelter will now produce alloy.\nGet some.\nImprove the production if necessary. tutorial.densealloy = 冶煉廠現在將生產稠密合金。\n請獲取更多的稠密合金。\n必要時改善生產系統。
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 = 核心現在將製作一個[accent]輕型無人機[]以挖掘礦石和修理方塊。\n\n製作其他單位的工廠可以使用[accent]矽[]以建造。\n建造一個冶矽廠。
tutorial.silicondrill = Silicon requires[accent] coal[] and[accent] sand[].\nStart by making drills. tutorial.silicondrill = 矽需要[accent]煤[]和[accent]沙[]以製作。\n放置鑽頭以開始。
tutorial.generator = This technology requires power.\nCreate a[accent] combustion generator[] for it. tutorial.generator = 這項技術需要能量。\n建造一個[accent]燃燒發電機[]。
tutorial.generatordrill = Combustion generators need fuel.\nFuel it with coal from a drill. tutorial.generatordrill = 燃燒發電機需要燃料。\n用鑽頭挖的煤為它加燃料。
tutorial.node = Power requires transport.\nCreate a[accent] power node[] next to your combustion generator to transfer its power. tutorial.node = 電源需要運輸。\n在燃燒發電機旁邊建造一個[accent]能量節點[]以傳遞其能量。
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 = 能量可透過接觸的能量方塊和發電機,或者通過連接的能量節點傳遞。\n\n點擊能量節點並選擇發電機和冶矽廠以連接能量。
tutorial.silicon = Silicon is being produced. Get some.\n\nImproving the production system is advised. tutorial.silicon = 正在製作矽。請獲取更多的矽。\n\n建議改善生產系統。
tutorial.daggerfactory = Construct a[accent] dagger mech factory.[]\n\nThis will be used to create attack mechs. tutorial.daggerfactory = 建造一個[accent]匕首機甲工廠[]\n\n這將製作攻擊機甲。
tutorial.router = Factories need resources to function.\nCreate a router to split conveyor resources. tutorial.router = 工廠需要資源以運作。\n建造一個分配器以均分輸送帶的資源。
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 = 連接能量節點至工廠。\n一旦要求滿足將製作一個機甲。\n\n根據需要建造更多鑽頭、發電機和輸送帶。發電機和輸送帶。
tutorial.battle = The[LIGHT_GRAY] enemy[] has revealed their core.\nDestroy it with your unit and dagger mechs. tutorial.battle = [LIGHT_GRAY]敵人[]透露了他們的核心。\n用你的單位和匕首機甲以摧毀它。
block.copper-wall.description = A cheap defensive block.\nUseful for protecting the core and turrets in the first few waves. block.copper-wall.description = 一種便宜的防衛方塊。\n用於前幾波防衛核心和砲塔。
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 = 一種便宜的防衛方塊。\n用於前幾波防衛核心和砲塔\n佔據多個方塊。
block.dense-alloy-wall.description = A standard defensive block.\nAdequate protection from enemies. block.dense-alloy-wall.description = 一種標準的防衛方塊。\n充分地防衛敵人。
block.dense-alloy-wall-large.description = A standard defensive block.\nAdequate protection from enemies.\nSpans multiple tiles. block.dense-alloy-wall-large.description = 一種標準的防衛方塊。\n充分地防衛敵人。\n佔據多個方塊。
block.thorium-wall.description = A strong defensive block.\nGood protection from enemies. block.thorium-wall.description = 一種堅強的防衛方塊。\n良好地防衛敵人。
block.thorium-wall-large.description = A strong defensive block.\nGood protection from enemies.\nSpans multiple tiles. block.thorium-wall-large.description = 一種堅強的防衛方塊。\n良好地防衛敵人。\n佔據多個方塊。
block.phase-wall.description = Not as strong as a thorium wall but will deflect bullets unless they are too powerful. block.phase-wall.description = 沒有釷牆那麼強但會使不太強的子彈偏離。
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佔據多個方塊。
block.surge-wall.description = The strongest defensive block.\nHas a small chance of triggering lightning towards the attacker. block.surge-wall.description = 最強的防衛方塊。\n有小的機會對攻擊者觸發閃電。
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 = 最強的防衛方塊。\n有小的機會對攻擊者觸發閃電。\n佔據多個方塊。
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 = 可以通過點擊打開和關閉的一扇小門。\n如果打開敵人可以穿過它射擊和移動。
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 = 可以通過點擊打開和關閉的一扇大門。\n如果打開敵人可以穿過它射擊和移動。\n佔據多個方塊。
block.mend-projector.description = Periodically heals buildings in its vicinity. block.mend-projector.description = 定期修復附近的建築物。
block.overdrive-projector.description = Increases the speed of nearby buildings like drills and conveyors. block.overdrive-projector.description = 提高附近建築物的速度,如鑽頭和輸送帶。
block.force-projector.description = Creates a hexagonal force field around itself, protecting buildings and units inside from damage through bullets. block.force-projector.description = 在自身周圍形成一個六角形力場,保護內部的建築物和單位免受子彈的傷害。
block.shock-mine.description = Damages enemies stepping on the mine. Nearly invisible to the enemy. block.shock-mine.description = 傷害踩到地雷的敵人。敵人幾乎看不見。
block.duo.description = A small, cheap turret. block.duo.description = 一種小而便宜的砲塔。
block.arc.description = A small turret which shoots electricity in a random arc towards the enemy. block.arc.description = 一種向敵人射出隨機電弧的小砲塔。
block.hail.description = A small artillery turret. block.hail.description = 一種小型火砲。
block.lancer.description = A medium-sized turret which shoots charged electricity beams. block.lancer.description = 一種射出電子束的中型砲塔。
block.wave.description = A medium-sized rapid-fire turret which shoots liquid bubbles. block.wave.description = 一種可以快速射出液體氣泡的中型砲塔。
block.salvo.description = A medium-sized turret which fires shots in salvos. block.salvo.description = 一種齊射的中型砲塔。
block.swarmer.description = A medium-sized turret which shoots burst missiles. block.swarmer.description = 一種射出爆炸導彈的中型砲塔。
block.ripple.description = A large artillery turret which fires several shots simultaneously. block.ripple.description = 一種一次射出幾發子彈的大型火砲。
block.cyclone.description = A large rapid fire turret. block.cyclone.description = 一種快速射擊的大型砲塔。
block.fuse.description = A large turret which shoots powerful short-range beams. block.fuse.description = 一種射出強大的短程射線的大型砲塔。
block.spectre.description = A large turret which shoots two powerful bullets at once. block.spectre.description = 一種一次射出兩顆強大的子彈的大型砲塔。
block.meltdown.description = A large turret which shoots powerful long-range beams. block.meltdown.description = 一種射出強大的遠程光束的大型砲塔。
block.conveyor.description = Basic item transport block. Moved items forward and automatically deposits them into turrets or crafters. Rotatable. block.conveyor.description = 基本物品傳輸方塊。將物品向前移動並自動將它們放入砲塔或機器中。能夠旋轉方向。
block.titanium-conveyor.description = Advanced item transport block. Moves items faster than standard conveyors. block.titanium-conveyor.description = 高級物品傳輸方塊。比標準輸送帶更快地移動物品。
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 = 高級物品傳輸方塊。使用能量將物品傳送到幾個方塊外連接的相織輸送帶。
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 = 作為兩個交叉輸送帶的橋樑。適用於兩條不同輸送帶將不同物品運送到不同位置的情況。
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 = 終極物品運輸方塊。收集幾件物品,然後將它們射向另一個長距離的質量驅動器。
block.smelter.description = Burns coal for smelting copper and lead into dense alloy. block.smelter.description = 燒煤以冶煉銅和鉛成稠密合金。
block.arc-smelter.description = Smelts copper and lead into dense alloy by using an external power source. block.arc-smelter.description = 使用外部能量以冶煉銅和鉛成稠密合金。
block.silicon-smelter.description = Reduces sand with highly pure coke in order to produce silicon. block.silicon-smelter.description = 使用高純度焦炭還原沙子以生產矽。
block.plastanium-compressor.description = Produces plastanium from oil and titanium. block.plastanium-compressor.description = 使用油和鈦以生產塑料。
block.phase-weaver.description = Produces phase fabric from radioactive thorium and high amounts of sand. block.phase-weaver.description = 使用放射性的釷和大量的沙子以生產相織布。
block.alloy-smelter.description = Produces surge alloy from titanium, lead, silicon and copper. block.alloy-smelter.description = 使用鈦、鉛、矽和銅以生產波動合金。
block.pulverizer.description = Crushes stone into sand. Useful when there is a lack of natural sand. block.pulverizer.description = 將石頭壓成沙子。當缺少天然沙子時有用。
block.pyratite-mixer.description = Mixes coal, lead and sand into highly flammable pyratite. block.pyratite-mixer.description = 混合煤、鉛和沙子成為易燃的硫。
block.blast-mixer.description = Uses oil for transforming pyratite into the less flammable but more explosive blast compound. block.blast-mixer.description = 使用油將硫變成比較不易燃但更具爆炸性的爆炸混合器。
block.cryofluidmixer.description = Combines water and titanium into cryofluid which is much more efficient for cooling. block.cryofluidmixer.description = 合水和鈦成冷卻效率更高的冷凍液。
block.solidifer.description = Cools lava to stone at a fast pace. block.solidifer.description = 快速冷卻熔岩至石頭。
block.melter.description = Heats up stone to very high temperatures to obtain lava. block.melter.description = 將石頭加熱到很高的溫度以獲得熔岩。
block.incinerator.description = Gets rid of any excess item or liquid. block.incinerator.description = 清除任何多餘的物品或液體。
block.biomattercompressor.description = Compresses biomatter in order to retrieve oil. block.biomattercompressor.description = 壓縮生物物質以提取油。
block.separator.description = Exposes stone to water pressure in order to obtain various minerals contained in the stone. block.separator.description = 將石頭暴露在水壓下以獲得石頭中的各種礦物質。
block.centrifuge.description = More efficient than the separator, but also more expensive to build and requires power. block.centrifuge.description = 比分離器更有效,但建造更昂貴和需要能量以操作。
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 = 將能量傳輸到連接的節點。最多可連接四個能量來源、接收或節點。節點將從任何相鄰方塊接收能量或向其供能量。
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 = 範圍大於能量節點,最多可連接六個能量來源、接收或節點。
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 = 有能量剩餘時,存儲電力並在能量短缺時提供能量。
block.battery-large.description = Stores much more power than a regular battery. block.battery-large.description = 比普通電池存儲更多的能量。
block.combustion-generator.description = Generates power by burning oil or flammable materials. block.combustion-generator.description = 透過燃燒油或可燃物品以產生能量。
block.turbine-generator.description = More efficient than a combustion generator, but requires additional water. block.turbine-generator.description = 比燃燒發電機更有效,但需要水以操作。
block.thermal-generator.description = Generates a large amount of power from lava. block.thermal-generator.description = 使用熔岩產生大量的能量。
block.solar-panel.description = Provides a small amount of power from the sun. block.solar-panel.description = 透過太陽產生少量的能量。
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 = 比標準太陽能板產生更多的能量,但建造起來昂貴得多。
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 = 從高度放射性釷產生大量能量。需要持續冷卻。如果供應的冷卻劑不足,會劇烈爆炸。
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 = 一種放射性同位素熱發電機,不需要冷卻,但比釷反應堆產生的能量少。
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 = 將物品從容器、存儲庫或核心卸載到傳輸帶上或直接卸載到相鄰的方塊中。透過點擊卸載器來更改要卸載的物品類型。
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 = 存儲少量物品。當物品需求非恆定時,使用它來創建緩衝。使用[LIGHT_GRAY]裝卸器[]以從容器提取物品。
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 = 存儲大量物品。當物品需求非恆定時,使用它來創建緩衝。使用[LIGHT_GRAY]裝卸器[]以從存儲庫提取物品。
block.mechanical-drill.description = A cheap drill. When placed on appropriate tiles, outputs items at a slow pace indefinitely. block.mechanical-drill.description = 一種便宜的鑽頭。當放置在適當的方塊上時,以緩慢的速度無限期地輸出物品。
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 = 一種改進的鑽頭。它挖掘更快,能夠利用氣壓挖掘更硬的材料。
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 = 通過激光技術可以更快地挖掘,但需要能量。此外,這種鑽頭可以挖掘放射性釷。
block.blast-drill.description = The ultimate drill. Requires large amounts of power. block.blast-drill.description = 終極的鑽頭。需要大量能量。
block.water-extractor.description = Extracts water from the ground. Use it when there is no lake nearby. block.water-extractor.description = 從地下提取水。當附近沒有湖泊時使用它。
block.cultivator.description = Cultivates the soil with water in order to obtain biomatter. block.cultivator.description = 用水培養土壤以獲得生物物質。
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 = 使用大量的能量從沙子中提取油。當附近沒有直接的石油來源時使用它。
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 = 離開現有的船隻,換成基本的戰鬥機。\n站在上面雙擊墊以使用它。
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 = 離開現在的船隻,換成具有相當不錯裝甲的重型轟炸機。\n站在上面雙擊墊以使用它。
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 = 離開現在的船隻,換成具有閃電武器、強大而快速的攔截器。\n站在上面雙擊墊以使用它。
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 = 離開現在的船隻,換成具有重裝甲的武裝直升機。\n站在上面雙擊墊以使用它。
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 = 離開現有的船隻,換成可以治愈友好的建築物和單位的支援機甲。\n站在上面雙擊墊以使用它。
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 = 離開現在的船隻,換成快速、具有輕裝甲的機甲,用於打了就跑的攻擊。\n站在上面雙擊墊以使用它。
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 = 離開現在的船隻,換成龐大、具有重裝甲的機甲,用於前線攻擊。\n站在上面雙擊墊以使用它。
block.spirit-factory.description = Produces light drones which mine ore and repair blocks. block.spirit-factory.description = 生產輕型無人機,用於開採礦石和修復方塊。
block.phantom-factory.description = Produces advanced drone units which are significantly more effective than a spirit drone. block.phantom-factory.description = 生產高級的無人機,比輕型無人機明顯更有效。
block.wraith-factory.description = Produces fast, hit-and-run interceptor units. block.wraith-factory.description = 生產快速、打了就跑的攔截機單位。
block.ghoul-factory.description = Produces heavy carpet bombers. block.ghoul-factory.description = 生產重型鋪蓋轟炸機。
block.dagger-factory.description = Produces basic ground units. block.dagger-factory.description = 產生基本地面單位。
block.titan-factory.description = Produces advanced, armored ground units. block.titan-factory.description = 生產具有裝甲的高級地面單位。
block.fortress-factory.description = Produces heavy artillery ground units. block.fortress-factory.description = 生產重型火砲地面單位。
block.revenant-factory.description = Produces heavy laser ground units. block.revenant-factory.description = 生產重型激光地面單位。
block.repair-point.description = Continuously heals the closest damaged unit in its vicinity. block.repair-point.description = 持續治療附近最近的受損單位。
block.command-center.description = Allows changing friendly AI behavior. Currently, attack, retreat and patrol commands are supported. block.command-center.description = 允許更改友好的AI行為。目前支持攻擊、撤退和巡邏命令。
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 = 基本液體運輸方塊。像輸送帶一樣工作,但是液體用的。最適用於提取器、泵或其他管線。
block.pulse-conduit.description = Advanced liquid transport block. Transports liquids faster and stores more than standard conduits. block.pulse-conduit.description = 高級的液體運輸方塊。比標準管線更快地輸送並儲存更多液體。
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 = 高級的液體運輸方塊。使用能量將液體傳送到多個方塊外連接的相織管線。
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 = 接受來自一個方向的液體並將它們平均輸出到最多3個其他方向。可以儲存一定量的液體。用於將液體從一個來源分成多個目標。
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 = 存儲大量液體。當液體需求非恆定時,使用它來創建緩衝或作為冷卻重要方塊的保障。
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 = 作為兩個交叉管線的橋樑。適用於兩條不同管線將不同液體運送到不同位置的情況。
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 = 高級的液體運輸方塊。允許跨過最多3個任何地形或建築物的方塊運輸液體。
block.mechanical-pump.description = A cheap pump with slow output, but no power consumption. block.mechanical-pump.description = 一種便宜的泵,輸出速度慢,但不使用能量。
block.rotary-pump.description = An advanced pump which doubles up speed by using power. block.rotary-pump.description = 高級的泵,透過使用能量使輸出速度加倍。
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 = 終極泵。輸出速度是機械泵的三倍並且是唯一能夠抽熔岩的泵。
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 = 接受來自一個方向的物品並將它們平均輸出到最多3個其他方向。 用於將物品從一個來源分割為多個目標。
block.distributor.description = An advanced router which splits items to up to 7 other directions equally. block.distributor.description = 高級的分配器可將物品均分到最多7個其他方向。
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 = 高級的物品運輸方塊。允許跨過最多3個任何地形或建築物的方塊運輸物品。
block.alpha-mech-pad.description = When given enough power, rebuilds your ship into the[accent] Alpha[] mech. block.alpha-mech-pad.description = 當給予足夠能量時,將你的船重建為[accent]阿爾法[]機甲。
block.itemsource.description = Infinitely outputs items. Sandbox only. block.itemsource.description = 不限地輸出物品。僅限沙盒。
block.liquidsource.description = Infinitely outputs liquids. Sandbox only. block.liquidsource.description = 不限地輸出液體。僅限沙盒。
block.itemvoid.description = Destroys any items which go into it without using power. Sandbox only. block.itemvoid.description = 不使用能量銷毀任何進入它的物品。僅限沙盒。
block.powerinfinite.description = Infinitely outputs power. Sandbox only. block.powerinfinite.description = 不限地輸出能量。僅限沙盒。
block.powervoid.description = Voids all power inputted into it. Sandbox only. block.powervoid.description = 銷毀所有輸入的能量。僅限沙盒。
liquid.water.description = Commonly used for cooling machines and waste processing. liquid.water.description = 常用於冷卻機器和廢物處理。
liquid.lava.description = Can be transformed into[LIGHT_GRAY] stone[], used for generating power or used as ammo for certain turrets. liquid.lava.description = 可以轉換為[LIGHT_GRAY]石頭[]、用於發電或用作某些砲塔的彈藥。
liquid.oil.description = Can be burnt, exploded or used as a coolant. liquid.oil.description = 可以燃燒、爆炸或用作冷卻劑。
liquid.cryofluid.description = The most efficient liquid for cooling things down. liquid.cryofluid.description = 冷卻東西最有效的液體。

View File

@@ -26,7 +26,7 @@ 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},
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: flat-over, up: flat},
discord: {font: default-font, fontColor: white, up: discord-banner}, discord: {font: default-font, fontColor: white, up: discord-banner},
info: {font: default-font, fontColor: white, up: info-banner}, info: {font: default-font, fontColor: white, up: info-banner},
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 },

View File

@@ -1,4 +1,8 @@
apply plugin: "java" apply plugin: "java"
sourceCompatibility = 1.8 sourceCompatibility = 1.8
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8' [compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
sourceSets.main.java.srcDirs = ["src/"] sourceSets.main.java.srcDirs = ["src/"]
compileJava{
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
}

View File

@@ -45,10 +45,9 @@ public class Recipes implements ContentList{
new Recipe(effect, StorageBlocks.container, new ItemStack(Items.densealloy, 200)); 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, StorageBlocks.vault, new ItemStack(Items.densealloy, 500), new ItemStack(Items.thorium, 250));
//core disabled due to being broken
new Recipe(effect, StorageBlocks.core, new Recipe(effect, StorageBlocks.core,
new ItemStack(Items.copper, 2000), new ItemStack(Items.densealloy, 1500), new ItemStack(Items.copper, 2000), new ItemStack(Items.densealloy, 2000),
new ItemStack(Items.silicon, 1500), new ItemStack(Items.thorium, 500), new ItemStack(Items.silicon, 1750), new ItemStack(Items.thorium, 1000),
new ItemStack(Items.surgealloy, 500), new ItemStack(Items.phasefabric, 750) new ItemStack(Items.surgealloy, 500), new ItemStack(Items.phasefabric, 750)
); );

View File

@@ -16,7 +16,8 @@ import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Mathf;
public class Blocks extends BlockList implements ContentList{ public class Blocks extends BlockList implements ContentList{
public static Block air, blockpart, spawn, space, metalfloor, deepwater, water, lava, tar, stone, blackstone, dirt, sand, ice, snow, grass, shrub, rock, icerock, blackrock; public static Block air, blockpart, spawn, space, metalfloor, deepwater, water, lava, tar, stone,
blackstone, dirt, sand, ice, snow, grass, shrub, rock, icerock, blackrock;
@Override @Override
@@ -90,6 +91,7 @@ public class Blocks extends BlockList implements ContentList{
}}; }};
lava = new Floor("lava"){{ lava = new Floor("lava"){{
drownTime = 100f;
liquidColor = Color.valueOf("ed5334"); liquidColor = Color.valueOf("ed5334");
speedMultiplier = 0.2f; speedMultiplier = 0.2f;
damageTaken = 0.5f; damageTaken = 0.5f;
@@ -103,6 +105,7 @@ public class Blocks extends BlockList implements ContentList{
}}; }};
tar = new Floor("tar"){{ tar = new Floor("tar"){{
drownTime = 150f;
liquidColor = Color.valueOf("292929"); liquidColor = Color.valueOf("292929");
status = StatusEffects.tarred; status = StatusEffects.tarred;
statusIntensity = 1f; statusIntensity = 1f;

View File

@@ -1,10 +1,7 @@
package io.anuke.mindustry.core; package io.anuke.mindustry.core;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.TimeUtils;
import io.anuke.mindustry.content.Mechs; import io.anuke.mindustry.content.Mechs;
import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.Player;
@@ -43,17 +40,13 @@ import static io.anuke.mindustry.Vars.*;
* This class is not created in the headless server. * This class is not created in the headless server.
*/ */
public class Control extends Module{ public class Control extends Module{
/** Minimum period of time between the same sound being played.*/
private static final long minSoundPeriod = 100;
public final Saves saves; public final Saves saves;
public final Unlocks unlocks; public final Unlocks unlocks;
private Timer timerRPC= new Timer(), timerUnlock = new Timer(); private Timer timerRPC = new Timer(), timerUnlock = new Timer();
private boolean hiscore = false; private boolean hiscore = false;
private boolean wasPaused = false; private boolean wasPaused = false;
private InputHandler[] inputs = {}; private InputHandler[] inputs = {};
private ObjectMap<Sound, Long> soundMap = new ObjectMap<>();
private Throwable error; private Throwable error;
public Control(){ public Control(){
@@ -78,17 +71,6 @@ public class Control extends Module{
unlocks.load(); unlocks.load();
Sounds.setFalloff(9000f);
Sounds.setPlayer((sound, volume) -> {
long time = TimeUtils.millis();
long value = soundMap.get(sound, 0L);
if(TimeUtils.timeSinceMillis(value) >= minSoundPeriod){
threads.runGraphics(() -> sound.play(volume));
soundMap.put(sound, time);
}
});
DefaultKeybinds.load(); DefaultKeybinds.load();
Settings.defaultList( Settings.defaultList(

View File

@@ -40,7 +40,6 @@ import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Strings; import io.anuke.ucore.util.Strings;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
@@ -96,26 +95,24 @@ public class MapEditorDialog extends Dialog implements Disposable{
t.addImageTextButton("$text.editor.import", "icon-load-map", isize, () -> t.addImageTextButton("$text.editor.import", "icon-load-map", isize, () ->
createDialog("$text.editor.import", createDialog("$text.editor.import",
"$text.editor.importmap", "$text.editor.importmap.description", "icon-load-map", (Runnable) loadDialog::show, "$text.editor.importmap", "$text.editor.importmap.description", "icon-load-map", (Runnable) loadDialog::show,
"$text.editor.importfile", "$text.editor.importfile.description", "icon-file", (Runnable) () -> { "$text.editor.importfile", "$text.editor.importfile.description", "icon-file", (Runnable) () ->
Platform.instance.showFileChooser("$text.loadimage", "Map Files", file -> { Platform.instance.showFileChooser("$text.loadimage", "Map Files", file -> ui.loadGraphics(() -> {
ui.loadGraphics(() -> { try{
try{ DataInputStream stream = new DataInputStream(file.read());
DataInputStream stream = new DataInputStream(file.read());
MapMeta meta = MapIO.readMapMeta(stream); MapMeta meta = MapIO.readMapMeta(stream);
MapTileData data = MapIO.readTileData(stream, meta, false); MapTileData data = MapIO.readTileData(stream, meta, false);
editor.beginEdit(data, meta.tags, false); editor.beginEdit(data, meta.tags, false);
view.clearStack(); view.clearStack();
}catch(Exception e){ }catch(Exception e){
ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false))); ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false)));
Log.err(e); Log.err(e);
} }
}); }), true, mapExtension),
}, true, mapExtension);
}, "$text.editor.importimage", "$text.editor.importimage.description", "icon-file-image", (Runnable)() ->
"$text.editor.importimage", "$text.editor.importimage.description", "icon-file-image", (Runnable)() -> { Platform.instance.showFileChooser("$text.loadimage", "Image Files", file ->
Platform.instance.showFileChooser("$text.loadimage", "Image Files", file -> {
ui.loadGraphics(() -> { ui.loadGraphics(() -> {
try{ try{
MapTileData data = MapIO.readLegacyPixmap(new Pixmap(file)); MapTileData data = MapIO.readLegacyPixmap(new Pixmap(file));
@@ -126,12 +123,11 @@ public class MapEditorDialog extends Dialog implements Disposable{
ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false))); ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false)));
Log.err(e); Log.err(e);
} }
}); }), true, "png")
}, true, "png"); ));
}));
t.addImageTextButton("$text.editor.export", "icon-save-map", isize, () -> createDialog("$text.editor.export", t.addImageTextButton("$text.editor.export", "icon-save-map", isize, () -> createDialog("$text.editor.export",
"$text.editor.exportfile", "$text.editor.exportfile.description", "icon-file", (Runnable) () -> { "$text.editor.exportfile", "$text.editor.exportfile.description", "icon-file", (Runnable) () ->
Platform.instance.showFileChooser("$text.saveimage", "Map Files", file -> { Platform.instance.showFileChooser("$text.saveimage", "Map Files", file -> {
file = file.parent().child(file.nameWithoutExtension() + "." + mapExtension); file = file.parent().child(file.nameWithoutExtension() + "." + mapExtension);
FileHandle result = file; FileHandle result = file;
@@ -147,8 +143,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
Log.err(e); Log.err(e);
} }
}); });
}, false, mapExtension); }, false, mapExtension)));
}));
t.row(); t.row();
@@ -171,8 +166,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
} }
}); });
loadDialog = new MapLoadDialog(map -> { loadDialog = new MapLoadDialog(map ->
ui.loadGraphics(() -> { ui.loadGraphics(() -> {
try(DataInputStream stream = new DataInputStream(map.stream.get())){ try(DataInputStream stream = new DataInputStream(map.stream.get())){
MapMeta meta = MapIO.readMapMeta(stream); MapMeta meta = MapIO.readMapMeta(stream);
@@ -180,12 +174,11 @@ public class MapEditorDialog extends Dialog implements Disposable{
editor.beginEdit(data, meta.tags, false); editor.beginEdit(data, meta.tags, false);
view.clearStack(); view.clearStack();
}catch(IOException e){ }catch(Exception e){
ui.showError(Bundles.format("text.editor.errormapload", Strings.parseException(e, false))); ui.showError(Bundles.format("text.editor.errormapload", Strings.parseException(e, false)));
Log.err(e); Log.err(e);
} }
}); }));
});
setFillParent(true); setFillParent(true);
@@ -261,7 +254,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
* 2) icon name * 2) icon name
* 3) listener * 3) listener
*/ */
private FloatingDialog createDialog(String title, Object... arguments){ private void createDialog(String title, Object... arguments){
FloatingDialog dialog = new FloatingDialog(title); FloatingDialog dialog = new FloatingDialog(title);
float h = 90f; float h = 90f;
@@ -278,18 +271,15 @@ public class MapEditorDialog extends Dialog implements Disposable{
listenable.run(); listenable.run();
dialog.hide(); dialog.hide();
menu.hide(); menu.hide();
}).left().get(); }).left().margin(0).get();
button.clearChildren(); button.clearChildren();
button.table("button", t -> { button.addImage(iconname).size(16 * 3).padLeft(10);
t.addImage(iconname).size(16 * 3);
t.update(() -> t.background(button.getClickListener().isOver() ? "button-over" : "button"));
}).padLeft(-10).padBottom(-3).size(h);
button.table(t -> { button.table(t -> {
t.add(name).growX().wrap(); t.add(name).growX().wrap();
t.row(); t.row();
t.add(description).color(Color.GRAY).growX().wrap(); t.add(description).color(Color.GRAY).growX().wrap();
}).growX().padLeft(8); }).growX().pad(10f).padLeft(5);
button.row(); button.row();
@@ -298,8 +288,6 @@ public class MapEditorDialog extends Dialog implements Disposable{
dialog.addCloseButton(); dialog.addCloseButton();
dialog.show(); dialog.show();
return dialog;
} }
@Override @Override
@@ -562,9 +550,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
ImageButton button = new ImageButton("white", "clear-toggle"); ImageButton button = new ImageButton("white", "clear-toggle");
button.clicked(() -> editor.setDrawBlock(block)); button.clicked(() -> editor.setDrawBlock(block));
button.resizeImage(8 * 4f); button.resizeImage(8 * 4f);
button.getImageCell().setActor(stack); button.replaceImage(stack);
button.addChild(stack);
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(50f); content.add(button).size(50f);

View File

@@ -283,9 +283,9 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
@Override @Override
public void drawShadow(float offsetX, float offsetY){ public void drawShadow(float offsetX, float offsetY){
float x = snappedX(), y = snappedY(); float x = snappedX(), y = snappedY();
float scl = mech.flying ? 1f : boostHeat/2f; float scl = mech.flying ? 1f : boostHeat / 2f;
Draw.rect(mech.iconRegion, x + offsetX*scl, y + offsetY*scl, rotation - 90); Draw.rect(mech.iconRegion, x + offsetX * scl, y + offsetY * scl, rotation - 90);
} }
@Override @Override
@@ -356,9 +356,9 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
float angT = i == 0 ? 0 : Mathf.randomSeedRange(i + 1, 60f); float angT = i == 0 ? 0 : Mathf.randomSeedRange(i + 1, 60f);
float lenT = i == 0 ? 0 : Mathf.randomSeedRange(i + 2, 1f) - 1f; float lenT = i == 0 ? 0 : Mathf.randomSeedRange(i + 2, 1f) - 1f;
Draw.rect(stack.item.region, Draw.rect(stack.item.region,
x + Angles.trnsx(rotation + 180f + angT, backTrns + lenT), x + Angles.trnsx(rotation + 180f + angT, backTrns + lenT),
y + Angles.trnsy(rotation + 180f + angT, backTrns + lenT), y + Angles.trnsy(rotation + 180f + angT, backTrns + lenT),
itemSize, itemSize, rotation); itemSize, itemSize, rotation);
} }
} }
@@ -369,7 +369,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
public void drawStats(){ public void drawStats(){
float x = snappedX(), y = snappedY(); float x = snappedX(), y = snappedY();
Draw.color(Color.BLACK, team.color, healthf() + Mathf.absin(Timers.time(), healthf()*5f, 1f - healthf())); Draw.color(Color.BLACK, team.color, healthf() + Mathf.absin(Timers.time(), healthf() * 5f, 1f - healthf()));
Draw.alpha(hitTime / hitDuration); Draw.alpha(hitTime / hitDuration);
Draw.rect(getPowerCellRegion(), x + Angles.trnsx(rotation, mech.cellTrnsY, 0f), y + Angles.trnsy(rotation, mech.cellTrnsY, 0f), rotation - 90); Draw.rect(getPowerCellRegion(), x + Angles.trnsx(rotation, mech.cellTrnsY, 0f), y + Angles.trnsy(rotation, mech.cellTrnsY, 0f), rotation - 90);
Draw.color(); Draw.color();
@@ -426,7 +426,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
Core.font.setUseIntegerPositions(ints); Core.font.setUseIntegerPositions(ints);
} }
/**Draw all current build requests. Does not draw the beam effect, only the positions.*/ /** Draw all current build requests. Does not draw the beam effect, only the positions. */
public void drawBuildRequests(){ public void drawBuildRequests(){
for(BuildRequest request : getPlaceQueue()){ for(BuildRequest request : getPlaceQueue()){
if(getCurrentRequest() == request) continue; if(getCurrentRequest() == request) continue;
@@ -442,16 +442,16 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
float rad = Mathf.absin(Timers.time(), 7f, 1f) + block.size * tilesize / 2f - 1; float rad = Mathf.absin(Timers.time(), 7f, 1f) + block.size * tilesize / 2f - 1;
Lines.square( Lines.square(
request.x * tilesize + block.offset(), request.x * tilesize + block.offset(),
request.y * tilesize + block.offset() - 1, request.y * tilesize + block.offset() - 1,
rad); rad);
Draw.color(Palette.remove); Draw.color(Palette.remove);
Lines.square( Lines.square(
request.x * tilesize + block.offset(), request.x * tilesize + block.offset(),
request.y * tilesize + block.offset(), request.y * tilesize + block.offset(),
rad); rad);
}else{ }else{
//draw place request //draw place request
Lines.stroke(2f); Lines.stroke(2f);
@@ -461,16 +461,16 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
float rad = Mathf.absin(Timers.time(), 7f, 1f) - 2f + request.recipe.result.size * tilesize / 2f; float rad = Mathf.absin(Timers.time(), 7f, 1f) - 2f + request.recipe.result.size * tilesize / 2f;
Lines.square( Lines.square(
request.x * tilesize + request.recipe.result.offset(), request.x * tilesize + request.recipe.result.offset(),
request.y * tilesize + request.recipe.result.offset() - 1, request.y * tilesize + request.recipe.result.offset() - 1,
rad); rad);
Draw.color(Palette.accent); Draw.color(Palette.accent);
Lines.square( Lines.square(
request.x * tilesize + request.recipe.result.offset(), request.x * tilesize + request.recipe.result.offset(),
request.y * tilesize + request.recipe.result.offset(), request.y * tilesize + request.recipe.result.offset(),
rad); rad);
} }
} }
@@ -605,9 +605,10 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
float xa = Inputs.getAxis(section, "move_x"); float xa = Inputs.getAxis(section, "move_x");
float ya = Inputs.getAxis(section, "move_y"); float ya = Inputs.getAxis(section, "move_y");
if(!Inputs.keyDown("gridMode")){
movement.y += ya * speed; movement.y += ya * speed;
movement.x += xa * speed; movement.x += xa * speed;
}
Vector2 vec = Graphics.world(control.input(playerIndex).getMouseX(), control.input(playerIndex).getMouseY()); Vector2 vec = Graphics.world(control.input(playerIndex).getMouseX(), control.input(playerIndex).getMouseY());
pointerX = vec.x; pointerX = vec.x;
@@ -699,8 +700,8 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
getHitbox(rect); getHitbox(rect);
rect.x -= expansion; rect.x -= expansion;
rect.y -= expansion; rect.y -= expansion;
rect.width += expansion*2f; rect.width += expansion * 2f;
rect.height += expansion*2f; rect.height += expansion * 2f;
isBoosting = EntityQuery.collisions().overlapsTile(rect) || distanceTo(targetX, targetY) > 85f; isBoosting = EntityQuery.collisions().overlapsTile(rect) || distanceTo(targetX, targetY) > 85f;
@@ -737,7 +738,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
if(target != null && distanceTo(target) > getWeapon().getAmmo().getRange()){ if(target != null && distanceTo(target) > getWeapon().getAmmo().getRange()){
target = null; target = null;
}else if(target != null){ }else if(target != null){
target = ((Tile)target).entity; target = ((Tile) target).entity;
} }
} }
@@ -746,14 +747,14 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
} }
} }
}else if(target.isValid() || (target instanceof TileEntity && ((TileEntity) target).damaged() && target.getTeam() == team && }else if(target.isValid() || (target instanceof TileEntity && ((TileEntity) target).damaged() && target.getTeam() == team &&
mech.canHeal && distanceTo(target) < getWeapon().getAmmo().getRange())){ 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);
} }
Vector2 intercept = Vector2 intercept =
Predict.intercept(x, y, target.getX(), target.getY(), target.getVelocity().x - velocity.x, target.getVelocity().y - velocity.y, getWeapon().getAmmo().bullet.speed); Predict.intercept(x, y, target.getX(), target.getY(), target.getVelocity().x - velocity.x, target.getVelocity().y - velocity.y, getWeapon().getAmmo().bullet.speed);
pointerX = intercept.x; pointerX = intercept.x;
pointerY = intercept.y; pointerY = intercept.y;
@@ -764,7 +765,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
}else if(isShooting()){ }else if(isShooting()){
Vector2 vec = Graphics.world(control.input(playerIndex).getMouseX(), Vector2 vec = Graphics.world(control.input(playerIndex).getMouseX(),
control.input(playerIndex).getMouseY()); control.input(playerIndex).getMouseY());
pointerX = vec.x; pointerX = vec.x;
pointerY = vec.y; pointerY = vec.y;
@@ -777,7 +778,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
//region utility methods //region utility methods
/** Resets all values of the player.*/ /** Resets all values of the player. */
public void reset(){ public void reset(){
resetNoAdd(); resetNoAdd();
@@ -791,6 +792,8 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
placeQueue.clear(); placeQueue.clear();
dead = true; dead = true;
trail.clear(); trail.clear();
target = null;
moveTarget = null;
carrier = null; carrier = null;
health = maxHealth(); health = maxHealth();
boostHeat = drownTime = hitTime = 0f; boostHeat = drownTime = hitTime = 0f;

View File

@@ -173,15 +173,19 @@ public interface BuilderTrait extends Entity{
default void updateBuilding(Unit unit){ default void updateBuilding(Unit unit){
//remove already completed build requests //remove already completed build requests
removal.clear(); removal.clear();
for(BuildRequest request : getPlaceQueue()){ for(BuildRequest req : getPlaceQueue()){
if((request.breaking && world.tile(request.x, request.y).block() == Blocks.air) || removal.add(req);
(!request.breaking && world.tile(request.x, request.y).block() == request.recipe.result)){
removal.add(request);
}
} }
for(BuildRequest req : removal){ getPlaceQueue().clear();
getPlaceQueue().removeValue(req, true);
for(BuildRequest request : removal){
if(!((request.breaking && world.tile(request.x, request.y).block() == Blocks.air) ||
(!request.breaking &&
(world.tile(request.x, request.y).getRotation() == request.rotation || !request.recipe.result.rotate)
&& world.tile(request.x, request.y).block() == request.recipe.result))){
getPlaceQueue().addLast(request);
}
} }
BuildRequest current = getCurrentRequest(); BuildRequest current = getCurrentRequest();

View File

@@ -76,7 +76,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
Effects.effect(ExplosionFx.explosion, unit); Effects.effect(ExplosionFx.explosion, unit);
Effects.shake(2f, 2f, unit); Effects.shake(2f, 2f, unit);
//must run afterwards so the unit's group is not null //must run afterwards so the unit's group is not null when sending the removal packet
threads.runDelay(unit::remove); threads.runDelay(unit::remove);
} }

View File

@@ -22,8 +22,7 @@ import java.io.DataInput;
import java.io.DataOutput; import java.io.DataOutput;
import java.io.IOException; import java.io.IOException;
import static io.anuke.mindustry.Vars.headless; import static io.anuke.mindustry.Vars.*;
import static io.anuke.mindustry.Vars.players;
public class AlphaDrone extends FlyingUnit { public class AlphaDrone extends FlyingUnit {
static final float followDistance = 80f; static final float followDistance = 80f;
@@ -62,7 +61,7 @@ public class AlphaDrone extends FlyingUnit {
} }
} }
if(!leader.isShooting && distanceTo(leader) < 8f){ if(!leader.isShooting && distanceTo(leader) < 7f){
Call.onAlphaDroneFade(AlphaDrone.this); Call.onAlphaDroneFade(AlphaDrone.this);
} }
} }
@@ -71,8 +70,9 @@ public class AlphaDrone extends FlyingUnit {
@Remote(called = Loc.server) @Remote(called = Loc.server)
public static void onAlphaDroneFade(BaseUnit drone){ public static void onAlphaDroneFade(BaseUnit drone){
if(drone == null) return; if(drone == null) return;
drone.remove();
Effects.effect(UnitFx.pickup, drone); Effects.effect(UnitFx.pickup, drone);
//must run afterwards so the unit's group is not null when sending the removal packet
threads.runDelay(drone::remove);
} }
@Override @Override

View File

@@ -17,6 +17,8 @@ import io.anuke.ucore.util.Strings;
import io.anuke.ucore.util.ThreadArray; import io.anuke.ucore.util.ThreadArray;
import java.io.IOException; import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
@@ -185,8 +187,12 @@ public class Saves{
return Strings.formatMillis(current == this ? totalPlaytime : meta.timePlayed); return Strings.formatMillis(current == this ? totalPlaytime : meta.timePlayed);
} }
public long getTimestamp(){
return meta.timestamp;
}
public String getDate(){ public String getDate(){
return meta.date; return SimpleDateFormat.getDateTimeInstance().format(new Date(meta.timestamp));
} }
public Map getMap(){ public Map getMap(){

View File

@@ -65,6 +65,7 @@ public class Unlocks{
save(); save();
} }
@SuppressWarnings("unchecked")
public void load(){ public void load(){
unlocked = Settings.getObject("unlockset", ObjectMap.class, ObjectMap::new); unlocked = Settings.getObject("unlockset", ObjectMap.class, ObjectMap::new);
} }

View File

@@ -25,6 +25,8 @@ public class DefaultKeybinds{
"rotate", new Axis(Input.SCROLL), "rotate", new Axis(Input.SCROLL),
"dash", Input.SHIFT_LEFT, "dash", Input.SHIFT_LEFT,
"drop_unit", Input.SHIFT_LEFT, "drop_unit", Input.SHIFT_LEFT,
"gridMode", Input.CONTROL_LEFT,
"gridModeShift", Input.SHIFT_LEFT,
new Category("view"), new Category("view"),
"zoom_hold", Input.CONTROL_LEFT, "zoom_hold", Input.CONTROL_LEFT,
"zoom", new Axis(Input.SCROLL), "zoom", new Axis(Input.SCROLL),

View File

@@ -217,10 +217,10 @@ public class DesktopInput extends InputHandler{
}else if(selected != null){ }else if(selected != null){
//only begin shooting if there's no cursor event //only begin shooting if there's no cursor event
if (!tileTapped(selected) && !tryTapPlayer(Graphics.mouseWorld().x, Graphics.mouseWorld().y) && player.getPlaceQueue().size == 0 && !droppingItem && if (!tileTapped(selected) && !tryTapPlayer(Graphics.mouseWorld().x, Graphics.mouseWorld().y) && player.getPlaceQueue().size == 0 && !droppingItem &&
!tryBeginMine(selected) && player.getMineTile() == null) { !tryBeginMine(selected) && player.getMineTile() == null && !ui.chatfrag.chatOpen()) {
player.isShooting = true; player.isShooting = true;
} }
}else{ //if it's out of bounds, shooting is just fine }else if(!ui.chatfrag.chatOpen()){ //if it's out of bounds, shooting is just fine
player.isShooting = true; player.isShooting = true;
} }
}else if(Inputs.keyTap(section, "deselect") && (recipe != null || mode != none || player.isBuilding()) && }else if(Inputs.keyTap(section, "deselect") && (recipe != null || mode != none || player.isBuilding()) &&

View File

@@ -4,15 +4,12 @@ import io.anuke.mindustry.game.Difficulty;
import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.game.GameMode;
import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.maps.Map;
import java.text.SimpleDateFormat;
import java.util.Date;
import static io.anuke.mindustry.Vars.world; import static io.anuke.mindustry.Vars.world;
public class SaveMeta{ public class SaveMeta{
public int version; public int version;
public int build; public int build;
public String date; public long timestamp;
public long timePlayed; public long timePlayed;
public int sector; public int sector;
public GameMode mode; public GameMode mode;
@@ -20,10 +17,10 @@ public class SaveMeta{
public int wave; public int wave;
public Difficulty difficulty; public Difficulty difficulty;
public SaveMeta(int version, long date, long timePlayed, int build, int sector, int mode, String map, int wave, Difficulty difficulty){ public SaveMeta(int version, long timestamp, long timePlayed, int build, int sector, int mode, String map, int wave, Difficulty difficulty){
this.version = version; this.version = version;
this.build = build; this.build = build;
this.date = SimpleDateFormat.getDateTimeInstance().format(new Date(date)); this.timestamp = timestamp;
this.timePlayed = timePlayed; this.timePlayed = timePlayed;
this.sector = sector; this.sector = sector;
this.mode = GameMode.values()[mode]; this.mode = GameMode.values()[mode];

View File

@@ -86,6 +86,10 @@ public class Sectors{
return grid.get(Bits.getLeftShort(position), Bits.getRightShort(position)); return grid.get(Bits.getLeftShort(position), Bits.getRightShort(position));
} }
public Iterable<Sector> getSectors(){
return grid.values();
}
public Difficulty getDifficulty(Sector sector){ public Difficulty getDifficulty(Sector sector){
if(sector.difficulty == 0){ if(sector.difficulty == 0){
return Difficulty.hard; return Difficulty.hard;
@@ -150,6 +154,7 @@ public class Sectors{
save(); save();
} }
@SuppressWarnings("unchecked")
public void load(){ public void load(){
for(Sector sector : grid.values()){ for(Sector sector : grid.values()){
sector.texture.dispose(); sector.texture.dispose();

View File

@@ -261,6 +261,7 @@ public class Administration{
Settings.save(); Settings.save();
} }
@SuppressWarnings("unchecked")
private void load(){ private void load(){
playerInfo = Settings.getObject("player-info", ObjectMap.class, ObjectMap::new); playerInfo = Settings.getObject("player-info", ObjectMap.class, ObjectMap::new);
bannedIPs = Settings.getObject("banned-ips", Array.class, Array::new); bannedIPs = Settings.getObject("banned-ips", Array.class, Array::new);

View File

@@ -25,11 +25,11 @@ import java.io.IOException;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
@SuppressWarnings("unchecked")
public class Net{ public class Net{
private static boolean server; private static boolean server;
private static boolean active; private static boolean active;
private static boolean clientLoaded; private static boolean clientLoaded;
private static String lastIP;
private static Array<Object> packetQueue = new Array<>(); private static Array<Object> packetQueue = new Array<>();
private static ObjectMap<Class<?>, Consumer> clientListeners = new ObjectMap<>(); private static ObjectMap<Class<?>, Consumer> clientListeners = new ObjectMap<>();
private static ObjectMap<Class<?>, BiConsumer<Integer, Object>> serverListeners = new ObjectMap<>(); private static ObjectMap<Class<?>, BiConsumer<Integer, Object>> serverListeners = new ObjectMap<>();
@@ -106,7 +106,6 @@ public class Net{
*/ */
public static void connect(String ip, int port, Runnable success){ public static void connect(String ip, int port, Runnable success){
try{ try{
lastIP = ip + ":" + port;
if(!active){ if(!active){
clientProvider.connect(ip, port, success); clientProvider.connect(ip, port, success);
active = true; active = true;
@@ -119,11 +118,6 @@ public class Net{
} }
} }
/**Returns the last IP connected to.*/
public static String getLastIP() {
return lastIP;
}
/** /**
* Host a server at an address. * Host a server at an address.
*/ */

View File

@@ -11,7 +11,7 @@ public class ItemImage extends Stack{
public ItemImage(TextureRegion region, Supplier<CharSequence> text){ public ItemImage(TextureRegion region, Supplier<CharSequence> text){
Table t = new Table().left().bottom(); Table t = new Table().left().bottom();
t.label(text); t.label(text).name("item-label");
add(new Image(region)); add(new Image(region));
add(t); add(t);
@@ -22,7 +22,7 @@ public class ItemImage extends Stack{
if(stack.amount != 0){ if(stack.amount != 0){
Table t = new Table().left().bottom(); Table t = new Table().left().bottom();
t.add(stack.amount + ""); t.add(stack.amount + "").name("item-label");
add(t); add(t);
} }
} }

View File

@@ -12,21 +12,15 @@ public class MenuButton extends TextButton{
public MenuButton(String icon, String text, String description, Runnable clicked){ public MenuButton(String icon, String text, String description, Runnable clicked){
super("default"); super("default");
float s = 66f;
clicked(clicked); clicked(clicked);
clearChildren(); clearChildren();
margin(0); margin(0);
table(t -> { table(t -> {
t.addImage(icon).size(14 * 3); t.addImage(icon).size(14 * 3).padLeft(6);
t.update(() -> t.setBackground(getClickListener().isVisualPressed() ? "button-down" : getClickListener().isOver() ? "button-over" : "button"));
}).size(s - 5, s);
table(t -> {
t.add(text).wrap().growX().get().setAlignment(Align.center, Align.left); t.add(text).wrap().growX().get().setAlignment(Align.center, Align.left);
if(description != null){ if(description != null){
t.row(); t.row();

View File

@@ -1,23 +1,22 @@
package io.anuke.mindustry.ui; package io.anuke.mindustry.ui;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import io.anuke.ucore.core.Core; import io.anuke.ucore.core.Core;
import io.anuke.ucore.core.Graphics; import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.scene.Element; import io.anuke.ucore.scene.Element;
import io.anuke.ucore.scene.event.InputEvent; import io.anuke.ucore.scene.event.InputEvent;
import io.anuke.ucore.scene.event.InputListener; import io.anuke.ucore.scene.event.InputListener;
import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.scene.ui.layout.Container;
import static io.anuke.mindustry.Vars.renderer; import static io.anuke.mindustry.Vars.renderer;
public class Minimap extends Table{ public class Minimap extends Container<Element>{
public Minimap(){ public Minimap(){
super("pane"); super(new Element(){
TextureRegion r = new TextureRegion();
margin(5);
Element elem = new Element(){
@Override @Override
public void draw(){ public void draw(){
if(renderer.minimap.getRegion() == null) return; if(renderer.minimap.getRegion() == null) return;
@@ -28,7 +27,12 @@ public class Minimap extends Table{
renderer.minimap.drawEntities(x, y, width, height); renderer.minimap.drawEntities(x, y, width, height);
} }
} }
}; });
background("pane");
size(140f);
margin(5f);
addListener(new InputListener(){ addListener(new InputListener(){
public boolean scrolled(InputEvent event, float x, float y, int amount){ public boolean scrolled(InputEvent event, float x, float y, int amount){
@@ -37,7 +41,7 @@ public class Minimap extends Table{
} }
}); });
elem.update(() -> { update(() -> {
Element e = Core.scene.hit(Graphics.mouse().x, Graphics.mouse().y, true); Element e = Core.scene.hit(Graphics.mouse().x, Graphics.mouse().y, true);
if(e != null && e.isDescendantOf(this)){ if(e != null && e.isDescendantOf(this)){
@@ -46,7 +50,5 @@ public class Minimap extends Table{
Core.scene.setScrollFocus(null); Core.scene.setScrollFocus(null);
} }
}); });
add(elem).size(140f, 140f);
} }
} }

View File

@@ -279,9 +279,7 @@ public class JoinDialog extends FloatingDialog{
button.left(); button.left();
button.row(); button.row();
button.add("[lightgray]" + (host.players != 1 ? Bundles.format("text.players", host.players) : button.add("[lightgray]" + (host.players != 1 ? Bundles.format("text.players", host.players) :
Bundles.format("text.players.single", host.players))); Bundles.format("text.players.single", host.players))).padBottom(5);
button.row();
button.add("[lightgray]" + host.address).pad(4).left();
} }
void connect(String ip, int port){ void connect(String ip, int port){
@@ -310,6 +308,7 @@ public class JoinDialog extends FloatingDialog{
return UIUtils.portrait() ? 350f : 500f; return UIUtils.portrait() ? 350f : 500f;
} }
@SuppressWarnings("unchecked")
private void loadServers(){ private void loadServers(){
servers = Settings.getObject("server-list", Array.class, Array::new); servers = Settings.getObject("server-list", Array.class, Array::new);
} }

View File

@@ -159,6 +159,26 @@ public class SectorsDialog extends FloatingDialog{
}); });
clicked(() -> clicked = true); clicked(() -> clicked = true);
this.focus();
}
private void focus(){
Sector focusSector = null;
long newestTimestamp = 0;
for(Sector sector : world.sectors.getSectors()){
if(sector.hasSave()){
long timestamp = sector.getSave().getTimestamp();
if(timestamp > newestTimestamp){
focusSector = sector;
newestTimestamp = timestamp;
}
}
}
if(focusSector != null) {
panX = (focusSector.x + 0.5f) * sectorSize;
panY = (focusSector.y + 0.5f) * sectorSize;
}
} }
@Override @Override

View File

@@ -109,7 +109,7 @@ public class HudFragment extends Fragment{
} }
cont.update(() -> { cont.update(() -> {
if(Inputs.keyTap("toggle_menus") && !ui.chatfrag.chatOpen()){ if(!Inputs.keyDown("gridMode") && Inputs.keyTap("toggle_menus") && !ui.chatfrag.chatOpen()){
toggleMenus(); toggleMenus();
} }
}); });
@@ -139,7 +139,7 @@ public class HudFragment extends Fragment{
if(Net.hasClient()){ if(Net.hasClient()){
t.label(() -> ping.get(Net.getPing())).visible(Net::client).colspan(2); t.label(() -> ping.get(Net.getPing())).visible(Net::client).colspan(2);
} }
}).size(-1).visible(() -> Settings.getBool("fps")).update(t -> t.setTranslation(0, (!waves.isVisible() ? wavetable.getHeight() : Math.min(wavetable.getTranslation().y, wavetable.getHeight())) )).get(); }).size(-1).visible(() -> Settings.getBool("fps")).update(t -> t.setTranslation(0, (!waves.isVisible() ? wavetable.getHeight() : Math.min(wavetable.getTranslation().y, wavetable.getHeight())))).get();
//make wave box appear below rest of menu //make wave box appear below rest of menu
if(mobile){ if(mobile){
@@ -149,7 +149,7 @@ public class HudFragment extends Fragment{
//minimap //minimap
parent.fill(t -> t.top().right().add(new Minimap()) parent.fill(t -> t.top().right().add(new Minimap())
.visible(() -> !state.is(State.menu) && Settings.getBool("minimap"))); .visible(() -> !state.is(State.menu) && Settings.getBool("minimap")));
//paused table //paused table
parent.fill(t -> { parent.fill(t -> {
@@ -198,7 +198,7 @@ public class HudFragment extends Fragment{
return coreAttackOpacity > 0; return coreAttackOpacity > 0;
}); });
t.table("button", top -> top.add("$text.coreattack").pad(2) t.table("button", top -> top.add("$text.coreattack").pad(2)
.update(label -> label.setColor(Hue.mix(Color.ORANGE, Color.SCARLET, Mathf.absin(Timers.time(), 2f, 1f))))); .update(label -> label.setColor(Hue.mix(Color.ORANGE, Color.SCARLET, Mathf.absin(Timers.time(), 2f, 1f)))));
}); });
//'saving' indicator //'saving' indicator
@@ -218,7 +218,7 @@ public class HudFragment extends Fragment{
} }
}); });
table.margin(12); table.margin(12);
table.addImage("icon-check").size(16*2).pad(3); table.addImage("icon-check").size(16 * 2).pad(3);
table.add(text).wrap().width(280f).get().setAlignment(Align.center, Align.center); table.add(text).wrap().width(280f).get().setAlignment(Align.center, Align.center);
table.pack(); table.pack();
@@ -231,7 +231,7 @@ public class HudFragment extends Fragment{
Actions.run(() -> container.actions(Actions.translateBy(0, table.getPrefHeight(), 1f, Interpolation.fade), Actions.removeActor()))); Actions.run(() -> container.actions(Actions.translateBy(0, table.getPrefHeight(), 1f, Interpolation.fade), Actions.removeActor())));
} }
/**Show unlock notification for a new recipe.*/ /** Show unlock notification for a new recipe. */
public void showUnlock(Recipe recipe){ public void showUnlock(Recipe recipe){
//if there's currently no unlock notification... //if there's currently no unlock notification...
@@ -268,11 +268,11 @@ public class HudFragment extends Fragment{
container.top().add(table); container.top().add(table);
container.setTranslation(0, table.getPrefHeight()); container.setTranslation(0, table.getPrefHeight());
container.actions(Actions.translateBy(0, -table.getPrefHeight(), 1f, Interpolation.fade), Actions.delay(4f), container.actions(Actions.translateBy(0, -table.getPrefHeight(), 1f, Interpolation.fade), Actions.delay(4f),
//nesting actions() calls is necessary so the right prefHeight() is used //nesting actions() calls is necessary so the right prefHeight() is used
Actions.run(() -> container.actions(Actions.translateBy(0, table.getPrefHeight(), 1f, Interpolation.fade), Actions.run(() -> { Actions.run(() -> container.actions(Actions.translateBy(0, table.getPrefHeight(), 1f, Interpolation.fade), Actions.run(() -> {
lastUnlockTable = null; lastUnlockTable = null;
lastUnlockLayout = null; lastUnlockLayout = null;
}), Actions.removeActor()))); }), Actions.removeActor())));
lastUnlockTable = container; lastUnlockTable = container;
lastUnlockLayout = in; lastUnlockLayout = in;

View File

@@ -3,6 +3,7 @@ package io.anuke.mindustry.ui.fragments;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.Interpolation; import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.game.EventType.WorldLoadGraphicsEvent; import io.anuke.mindustry.game.EventType.WorldLoadGraphicsEvent;
@@ -17,6 +18,8 @@ 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;
import io.anuke.ucore.core.Graphics; import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.core.Inputs;
import io.anuke.ucore.input.Input;
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;
@@ -38,6 +41,19 @@ public class PlacementFragment extends Fragment{
boolean shown = true; boolean shown = true;
boolean lastGround; boolean lastGround;
//TODO make this configurable
final Input[] inputGrid = {
Input.NUM_1, Input.NUM_2, Input.NUM_3, Input.NUM_4,
Input.Q, Input.W, Input.E, Input.R,
Input.A, Input.S, Input.D, Input.F,
Input.Z, Input.X, Input.C, Input.V
}, inputCatGrid = {
Input.NUM_1, Input.NUM_2,
Input.Q, Input.W,
Input.A, Input.S,
Input.Z, Input.X, Input.C, Input.V
};
public PlacementFragment(){ public PlacementFragment(){
Events.on(WorldLoadGraphicsEvent.class, event -> { Events.on(WorldLoadGraphicsEvent.class, event -> {
currentCategory = Category.turret; currentCategory = Category.turret;
@@ -47,6 +63,42 @@ public class PlacementFragment extends Fragment{
}); });
} }
boolean gridUpdate(InputHandler input){
if(!Inputs.keyDown("gridMode") || ui.chatfrag.chatOpen()) return false;
if(Inputs.keyDown("gridModeShift")){ //select category
int i = 0;
for(Input key : inputCatGrid){
if(Inputs.keyDown(key)){
input.recipe = Recipe.getByCategory(Category.values()[i]).first();
currentCategory = input.recipe.category;
}
i++;
}
return true;
}else if(Inputs.keyDown("select")){ //mouse eyedropper select
Tile tile = world.tileWorld(Graphics.mouseWorld().x, Graphics.mouseWorld().y);
if(tile != null){
tile = tile.target();
Recipe tryRecipe = Recipe.getByResult(tile.block());
if(tryRecipe != null && control.unlocks.isUnlocked(tryRecipe)){
input.recipe = tryRecipe;
currentCategory = input.recipe.category;
return true;
}
}
}else{ //select block
int i = 0;
Array<Recipe> recipes = Recipe.getByCategory(currentCategory);
for(Input key : inputGrid){
if(Inputs.keyDown(key))
input.recipe = (i < recipes.size && control.unlocks.isUnlocked(recipes.get(i))) ? recipes.get(i) : null;
i++;
}
}
return false;
}
@Override @Override
public void build(Group parent){ public void build(Group parent){
parent.fill(full -> { parent.fill(full -> {
@@ -74,7 +126,7 @@ public class PlacementFragment extends Fragment{
boolean[] unlocked = {false}; boolean[] unlocked = {false};
ImageButton button = blockTable.addImageButton("icon-locked", "select", 8*4, () -> { ImageButton button = blockTable.addImageButton("icon-locked", "select", 8 * 4, () -> {
if(control.unlocks.isUnlocked(recipe)){ if(control.unlocks.isUnlocked(recipe)){
input.recipe = input.recipe == recipe ? null : recipe; input.recipe = input.recipe == recipe ? null : recipe;
} }
@@ -111,8 +163,8 @@ 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() && !lastGround) || if((tileDisplayBlock() == null && lastDisplay == getSelected() && !lastGround) || (tileDisplayBlock() != null && lastDisplay == tileDisplayBlock() && lastGround))
(tileDisplayBlock() != null && lastDisplay == tileDisplayBlock() && lastGround)) return; return;
topTable.clear(); topTable.clear();
topTable.top().left().margin(5); topTable.top().left().margin(5);
@@ -123,14 +175,14 @@ public class PlacementFragment extends Fragment{
if(lastDisplay != null){ //show selected recipe if(lastDisplay != null){ //show selected recipe
topTable.table(header -> { topTable.table(header -> {
header.left(); header.left();
header.add(new ImageStack(lastDisplay.getCompactIcon())).size(8*4); header.add(new ImageStack(lastDisplay.getCompactIcon())).size(8 * 4);
header.labelWrap(() -> header.labelWrap(() ->
!control.unlocks.isUnlocked(Recipe.getByResult(lastDisplay)) ? Bundles.get("text.blocks.unknown") : lastDisplay.formalName) !control.unlocks.isUnlocked(Recipe.getByResult(lastDisplay)) ? Bundles.get("text.blocks.unknown") : lastDisplay.formalName)
.left().width(190f).padLeft(5); .left().width(190f).padLeft(5);
header.add().growX(); header.add().growX();
if(control.unlocks.isUnlocked(Recipe.getByResult(lastDisplay))){ if(control.unlocks.isUnlocked(Recipe.getByResult(lastDisplay))){
header.addButton("?", "clear-partial", () -> ui.content.show(Recipe.getByResult(lastDisplay))) header.addButton("?", "clear-partial", () -> ui.content.show(Recipe.getByResult(lastDisplay)))
.size(8 * 5).padTop(-5).padRight(-5).right().grow(); .size(8 * 5).padTop(-5).padRight(-5).right().grow();
} }
}).growX().left(); }).growX().left();
topTable.row(); topTable.row();
@@ -141,7 +193,7 @@ public class PlacementFragment extends Fragment{
for(ItemStack stack : Recipe.getByResult(lastDisplay).requirements){ for(ItemStack stack : Recipe.getByResult(lastDisplay).requirements){
req.table(line -> { req.table(line -> {
line.left(); line.left();
line.addImage(stack.item.region).size(8*2); line.addImage(stack.item.region).size(8 * 2);
line.add(stack.item.localizedName()).color(Color.LIGHT_GRAY).padLeft(2).left(); line.add(stack.item.localizedName()).color(Color.LIGHT_GRAY).padLeft(2).left();
line.labelWrap(() -> { line.labelWrap(() -> {
TileEntity core = players[0].getClosestCore(); TileEntity core = players[0].getClosestCore();
@@ -159,13 +211,13 @@ public class PlacementFragment extends Fragment{
}else if(tileDisplayBlock() != null){ //show selected tile }else if(tileDisplayBlock() != null){ //show selected tile
lastDisplay = tileDisplayBlock(); lastDisplay = tileDisplayBlock();
topTable.add(new ImageStack(lastDisplay.getDisplayIcon(hoverTile))).size(8*4); topTable.add(new ImageStack(lastDisplay.getDisplayIcon(hoverTile))).size(8 * 4);
topTable.labelWrap(lastDisplay.getDisplayName(hoverTile)).left().width(190f).padLeft(5); topTable.labelWrap(lastDisplay.getDisplayName(hoverTile)).left().width(190f).padLeft(5);
} }
}); });
}).colspan(3).fillX().visible(() -> getSelected() != null || tileDisplayBlock() != null).touchable(Touchable.enabled); }).colspan(3).fillX().visible(() -> getSelected() != null || tileDisplayBlock() != null).touchable(Touchable.enabled);
frame.row(); frame.row();
frame.addImage("blank").color(Palette.accent).colspan(3).height(3*2).growX(); frame.addImage("blank").color(Palette.accent).colspan(3).height(3 * 2).growX();
frame.row(); frame.row();
frame.table("pane-2", blocksSelect -> { frame.table("pane-2", blocksSelect -> {
blocksSelect.margin(4).marginTop(0); blocksSelect.margin(4).marginTop(0);
@@ -181,21 +233,24 @@ public class PlacementFragment extends Fragment{
for(Category cat : Category.values()){ for(Category cat : Category.values()){
if(Recipe.getByCategory(cat).isEmpty()) continue; if(Recipe.getByCategory(cat).isEmpty()) continue;
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).update(i -> i.setChecked(currentCategory == cat)); }).group(group).update(i -> i.setChecked(currentCategory == cat));
if(cat.ordinal() %2 == 1) categories.row(); if(cat.ordinal() % 2 == 1) categories.row();
} }
}).touchable(Touchable.enabled); }).touchable(Touchable.enabled);
rebuildCategory.run(); rebuildCategory.run();
frame.update(() -> {
if(gridUpdate(input)) rebuildCategory.run();
});
}); });
}); });
} }
/**Returns the currently displayed block in the top box.*/ /** Returns the currently displayed block in the top box. */
Block getSelected(){ Block getSelected(){
Block toDisplay = null; Block toDisplay = null;
@@ -226,12 +281,12 @@ public class PlacementFragment extends Fragment{
return toDisplay; return toDisplay;
} }
/**Returns the block currently being hovered over in the world.*/ /** Returns the block currently being hovered over in the world. */
Block tileDisplayBlock(){ Block tileDisplayBlock(){
return hoverTile == null ? null : hoverTile.block().synthetic() ? hoverTile.block() : hoverTile.floor() instanceof OreBlock ? hoverTile.floor() : null; return hoverTile == null ? null : hoverTile.block().synthetic() ? hoverTile.block() : hoverTile.floor() instanceof OreBlock ? hoverTile.floor() : null;
} }
/**Show or hide the placement menu.*/ /** Show or hide the placement menu. */
void toggle(float t, Interpolation ip){ void toggle(float t, Interpolation ip){
toggler.clearActions(); toggler.clearActions();
if(shown){ if(shown){

View File

@@ -101,6 +101,7 @@ public class Tile implements PosTrait, TargetTrait{
return -1; return -1;
} }
@SuppressWarnings("unchecked")
public <T extends TileEntity> T entity(){ public <T extends TileEntity> T entity(){
return (T) entity; return (T) entity;
} }

View File

@@ -35,7 +35,6 @@ public class Conveyor extends Block{
private TextureRegion[][] regions = new TextureRegion[7][4]; private TextureRegion[][] regions = new TextureRegion[7][4];
protected float speed = 0f; protected float speed = 0f;
protected float carryCapacity = 8f;
protected Conveyor(String name){ protected Conveyor(String name){
super(name); super(name);
@@ -342,9 +341,9 @@ public class Conveyor extends Block{
public Array<Object> getDebugInfo(Tile tile){ public Array<Object> getDebugInfo(Tile tile){
ConveyorEntity entity = tile.entity(); ConveyorEntity entity = tile.entity();
Array<Object> arr = super.getDebugInfo(tile); Array<Object> arr = super.getDebugInfo(tile);
arr.addAll(Array.with( arr.addAll(Array.<Object>with(
"clogHeat", entity.clogHeat, "clogHeat", entity.clogHeat,
"sleeping", entity.isSleeping() "sleeping", entity.isSleeping()
)); ));
return arr; return arr;
} }

View File

@@ -87,6 +87,7 @@ public class Consumers{
return map.containsKey(type); return map.containsKey(type);
} }
@SuppressWarnings("unchecked")
public <T extends Consume> T get(Class<T> type){ public <T extends Consume> T get(Class<T> type){
if(!map.containsKey(type)){ if(!map.containsKey(type)){
throw new IllegalArgumentException("Block does not contain consumer of type '" + type + "'!"); throw new IllegalArgumentException("Block does not contain consumer of type '" + type + "'!");

View File

@@ -1,7 +1,7 @@
apply plugin: "java" apply plugin: "java"
sourceCompatibility = 1.8 sourceCompatibility = 1.8
sourceSets.main.java.srcDirs = [ "src/" ] sourceSets.main.java.srcDirs = ["src/"]
project.ext.mainClassName = "io.anuke.mindustry.desktop.DesktopLauncher" project.ext.mainClassName = "io.anuke.mindustry.desktop.DesktopLauncher"
project.ext.assetsDir = new File("../core/assets") project.ext.assetsDir = new File("../core/assets")
@@ -10,25 +10,25 @@ def PACKR_DIR = "$System.env.PACKR_DIR"
def ICON_DIR = new File("core/assets/sprites/icon.icns") def ICON_DIR = new File("core/assets/sprites/icon.icns")
ext.getPlatform = { ext.getPlatform = {
if (project.hasProperty("platform")) { if(project.hasProperty("platform")){
def lc = platform.toLowerCase() def lc = platform.toLowerCase()
if (lc == "windows64") { if(lc == "windows64"){
return "windows64" return "windows64"
} else if (lc == "windows32") { }else if(lc == "windows32"){
return "windows32" return "windows32"
} else if (lc == "linux") { }else if(lc == "linux"){
return "linux64" return "linux64"
} else if (lc == "mac") { }else if(lc == "mac"){
return "mac" return "mac"
} else { }else{
throw new InvalidUserDataException("Invalid platform. Set platform with -Pplatform=windows/linux/mac") throw new InvalidUserDataException("Invalid platform. Set platform with -Pplatform=windows/linux/mac")
} }
} else { }else{
throw new InvalidUserDataException("No platform defined. Set platform with -Pplatform=windows/linux/mac") throw new InvalidUserDataException("No platform defined. Set platform with -Pplatform=windows/linux/mac")
} }
} }
task run(dependsOn: classes, type: JavaExec) { task run(dependsOn: classes, type: JavaExec){
main = project.mainClassName main = project.mainClassName
classpath = sourceSets.main.runtimeClasspath classpath = sourceSets.main.runtimeClasspath
standardInput = System.in standardInput = System.in
@@ -37,7 +37,7 @@ task run(dependsOn: classes, type: JavaExec) {
jvmArgs "-XstartOnFirstThread" jvmArgs "-XstartOnFirstThread"
} }
ignoreExitValue = true ignoreExitValue = true
if (project.hasProperty("args")) { if(project.hasProperty("args")){
args Eval.me(project.getProperties()["args"]) args Eval.me(project.getProperties()["args"])
} }
@@ -46,7 +46,7 @@ task run(dependsOn: classes, type: JavaExec) {
} }
} }
task debug(dependsOn: classes, type: JavaExec) { task debug(dependsOn: classes, type: JavaExec){
main = project.mainClassName main = project.mainClassName
classpath = sourceSets.main.runtimeClasspath classpath = sourceSets.main.runtimeClasspath
standardInput = System.in standardInput = System.in
@@ -55,38 +55,38 @@ task debug(dependsOn: classes, type: JavaExec) {
debug = true debug = true
} }
task dist(type: Jar) { task dist(type: Jar){
dependsOn classes dependsOn classes
writeVersion() writeVersion()
from files(sourceSets.main.output.classesDirs) from files(sourceSets.main.output.classesDirs)
from files(sourceSets.main.output.resourcesDir) from files(sourceSets.main.output.resourcesDir)
from {configurations.compile.collect {zipTree(it)}} from{ configurations.compile.collect{ zipTree(it) } }
from files(project.assetsDir) from files(project.assetsDir)
manifest { manifest{
attributes 'Main-Class': project.mainClassName attributes 'Main-Class': project.mainClassName
} }
} }
task clearOut(type: Delete){ task clearOut(type: Delete){
doLast { doLast{
delete "packr-out/" delete "packr-out/"
} }
} }
//note: call desktop:dist beforehand //note: call desktop:dist beforehand
task packrCmd() { task packrCmd(){
doLast { doLast{
copy { copy{
into PACKR_DIR into PACKR_DIR
from "build/libs/desktop-release.jar" from "build/libs/desktop-release.jar"
} }
exec { exec{
commandLine("java", "-jar", PACKR_DIR + "packr.jar", commandLine("java", "-jar", PACKR_DIR + "packr.jar",
"--verbose", "--verbose",
@@ -104,7 +104,7 @@ task packrCmd() {
} }
} }
task fixMac (type: Copy){ task fixMac(type: Copy){
dependsOn "packrCmd" dependsOn "packrCmd"
into "packr-out/" + appName + ".app/Contents/" into "packr-out/" + appName + ".app/Contents/"
@@ -117,12 +117,12 @@ task fixMac (type: Copy){
} }
} }
task fixWindows32 (type: Copy){ task fixWindows32(type: Copy){
dependsOn "packrCmd" dependsOn "packrCmd"
into "packr-out/jre/bin/" into "packr-out/jre/bin/"
from PACKR_DIR + "zip.dll" from PACKR_DIR + "zip.dll"
rename ("zip.dll", "ojdkbuild_zlib.dll") rename("zip.dll", "ojdkbuild_zlib.dll")
doLast{ doLast{
copy{ copy{
@@ -132,21 +132,21 @@ task fixWindows32 (type: Copy){
} }
} }
task packrZip() { task packrZip(){
dependsOn "packrCmd" dependsOn "packrCmd"
finalizedBy "clearOut" finalizedBy "clearOut"
if(project.hasProperty("platform")) { if(project.hasProperty("platform")){
if (getPlatform() == "mac") { if(getPlatform() == "mac"){
dependsOn "fixMac" dependsOn "fixMac"
} }
if (getPlatform() == "windows32") { if(getPlatform() == "windows32"){
dependsOn "fixWindows32" dependsOn "fixWindows32"
} }
task zip (type: Zip){ task zip(type: Zip){
from "packr-out/" from "packr-out/"
archiveName "$appName-${getPlatform()}-${getVersionString()}.zip" archiveName "$appName-${getPlatform()}-${getVersionString()}.zip"
destinationDir(file("packr-export")) destinationDir(file("packr-export"))

View File

@@ -90,6 +90,8 @@ public class KryoServer implements ServerProvider{
threads.runDelay(() -> { threads.runDelay(() -> {
try{ try{
Net.handleServerReceived(k.id, object); Net.handleServerReceived(k.id, object);
}catch(ValidateException e){
Log.err("Validate failed: {0} ({1})", e.player.name, e.getMessage());
}catch(Exception e){ }catch(Exception e){
e.printStackTrace(); e.printStackTrace();
} }