mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-07-27 08:07:56 +07:00
Added ukranian lang, updated uCore, minor fixes
This commit is contained in:
@ -25,7 +25,7 @@ allprojects {
|
|||||||
appName = 'Mindustry'
|
appName = 'Mindustry'
|
||||||
gdxVersion = '1.9.8'
|
gdxVersion = '1.9.8'
|
||||||
aiVersion = '1.8.1'
|
aiVersion = '1.8.1'
|
||||||
uCoreVersion = '39939f7'
|
uCoreVersion = '9503bcb'
|
||||||
|
|
||||||
getVersionString = {
|
getVersionString = {
|
||||||
String buildVersion = getBuildVersion()
|
String buildVersion = getBuildVersion()
|
||||||
|
@ -263,7 +263,7 @@ setting.sensitivity.name=Controller Sensitivity
|
|||||||
setting.saveinterval.name=Autosave Interval
|
setting.saveinterval.name=Autosave Interval
|
||||||
setting.seconds={0} Seconds
|
setting.seconds={0} Seconds
|
||||||
setting.fullscreen.name=Fullscreen
|
setting.fullscreen.name=Fullscreen
|
||||||
setting.multithread.name=Multithreading [scarlet](unstable!)
|
setting.multithread.name=Multithreading
|
||||||
setting.fps.name=Show FPS
|
setting.fps.name=Show FPS
|
||||||
setting.vsync.name=VSync
|
setting.vsync.name=VSync
|
||||||
setting.lasers.name=Show Power Lasers
|
setting.lasers.name=Show Power Lasers
|
||||||
|
500
core/assets/bundles/bundle_uk_UA.properties
Normal file
500
core/assets/bundles/bundle_uk_UA.properties
Normal file
@ -0,0 +1,500 @@
|
|||||||
|
text.about = Створено [ROYAL] Anuken. []\nСпочатку запис у [orange] GDL [] MM Jam.\nТворці:\n- SFX зроблено з [YELLOW] bfxr []\n- Музика зроблена [GREEN] RoccoW [] / Знайдено на [lime] FreeMusicArchive.org [] \nОсоблива подяка:\n- [coral] MitchellFJN []: екстенсивне тестування та відгуки\n- [sky] Luxray5474 []: робота з вікі, вклади коду\n- Всі бета-тестери на itch.io та Google Play\n
|
||||||
|
text.discord = Приєднуйтесь до нашого Discord!
|
||||||
|
text.changes = [SCARLET] Увага! \n[] Деякі важливі механіки гри були змінені.\n- [accent] Телепорти [] тепер використовують електроенергію. \n- [accent] Домінна піч [] та [accent] Тиглі [] тепер мають ліміт. \n- [accent] Тиглі [] зараз вимагають вугілля як паливо.
|
||||||
|
text.gameover = Ядро було зруйновано.
|
||||||
|
text.highscore = [YELLOW] Новий рекорд!
|
||||||
|
text.lasted = Ви тримались до хвилі
|
||||||
|
text.level.highscore = Рекорд: [accent] {0}
|
||||||
|
text.level.delete.title = Підтвердьте видалення
|
||||||
|
text.level.delete = Ви впевнені, що хочете видалити карту \"[orange] {0} \"?
|
||||||
|
text.level.select = Вибір рівня
|
||||||
|
text.level.mode = Ігровий режим
|
||||||
|
text.savegame = Зберегти гру
|
||||||
|
text.loadgame = Завантажити гру
|
||||||
|
text.joingame = Приєднатися\nдо гри
|
||||||
|
text.newgame=Нова гра
|
||||||
|
text.quit = Вийти
|
||||||
|
text.about.button = Про
|
||||||
|
text.name = Назва:
|
||||||
|
text.public = Публічний
|
||||||
|
text.players = {0} гравців онлайн
|
||||||
|
text.server.player.host = {0} (host)
|
||||||
|
text.players.single = {0} гравців онлайн
|
||||||
|
text.server.mismatch = Пакетна помилка: невідповідність версії версії клієнта / сервера. Переконайтеся, що ви та хост мають останню версію Mindustry!
|
||||||
|
text.server.closing = [accent] Закриття сервера ...
|
||||||
|
text.server.kicked.kick = Ви були вигнані з сервера!
|
||||||
|
text.server.kicked.invalidPassword = Невірний пароль!
|
||||||
|
text.server.kicked.clientOutdated = Застарілий клієнт! Оновіть свою гру!
|
||||||
|
text.server.kicked.serverOutdated = Застарілий сервер! Попросіть хост оновити!
|
||||||
|
text.server.connected = {0} приєднався.
|
||||||
|
text.server.disconnected = {0} від'єднано.
|
||||||
|
text.nohost = Неможливо розмістити сервер на власній карті!
|
||||||
|
text.hostserver = Хост-сервер
|
||||||
|
text.host = Хост
|
||||||
|
text.hosting = [accent] Відкриття сервера ...
|
||||||
|
text.hosts.refresh = Оновити
|
||||||
|
text.hosts.discovering = Знайомство з мережевими іграми
|
||||||
|
text.server.refreshing = Оновити сервери
|
||||||
|
text.hosts.none = [lightgray] Ніяких ігор у мережі не знайдено!
|
||||||
|
text.host.invalid = [scarlet] Неможливо підключитися до хосту.
|
||||||
|
text.server.friendlyfire = Дружній вогонь
|
||||||
|
text.server.add = Додати сервер
|
||||||
|
text.server.delete = Ви впевнені, що хочете видалити цей сервер?
|
||||||
|
text.server.hostname = Хост: {0}
|
||||||
|
text.server.edit = Редагувати сервер
|
||||||
|
text.joingame.byip = [] Приєднатися по IP ...[]
|
||||||
|
text.joingame.title = Приєднатися до гри
|
||||||
|
text.joingame.ip = IP
|
||||||
|
text.disconnect = Роз'єднано
|
||||||
|
text.connecting = [accent] Підключення ...
|
||||||
|
text.connecting.data = [accent] Завантаження світових даних ...
|
||||||
|
text.connectfail = [crimson] Не вдалося підключитися до сервера: [orange] {0}
|
||||||
|
text.server.port = Порт
|
||||||
|
text.server.addressinuse = Адреса вже використовується!
|
||||||
|
text.server.invalidport = Недійсний номер порту.
|
||||||
|
text.server.error = [crimson] Помилка хостингу сервера: [orange] {0}
|
||||||
|
text.tutorial.back = < Попер.
|
||||||
|
text.tutorial.next = Далі >
|
||||||
|
text.save.new = Нове збереження
|
||||||
|
text.save.overwrite = Ви впевнені, що хочете перезаписати цей слот для збереження?
|
||||||
|
text.overwrite = Перезаписати
|
||||||
|
text.save.none = Не знайдено жодних збережень!
|
||||||
|
text.saveload = [accent] Збереження ...
|
||||||
|
text.savefail = Не вдалося зберегти гру!
|
||||||
|
text.save.delete.confirm = Ви впевнені, що хочете видалити це збереження?
|
||||||
|
text.save.delete = Видалити
|
||||||
|
text.save.export = Експорт збереження
|
||||||
|
text.save.import.invalid = [orange] Це збереження недійсне!
|
||||||
|
text.save.import.fail = [crimson] Не вдалося імпортувати збереження: [orange] {0}
|
||||||
|
text.save.export.fail = [crimson] Не вдалося експортувати збереження: [orange] {0}
|
||||||
|
text.save.import = Імпортувати збереження
|
||||||
|
text.save.newslot = Назва збереження:
|
||||||
|
text.save.rename = Переіменувати
|
||||||
|
text.save.rename.text = Нова назва:
|
||||||
|
text.selectslot = Виберіть збереження.
|
||||||
|
text.slot = [accent] слот {0}
|
||||||
|
text.save.corrupted = [orange] Збережений файл пошкоджений або він невірний!
|
||||||
|
text.empty = <порожньо>
|
||||||
|
text.on = Увімкнути
|
||||||
|
text.off = Вимкнути
|
||||||
|
text.save.autosave = Автозбереження: {0}
|
||||||
|
text.save.map = Карта
|
||||||
|
text.save.wave = Хвиля {0}
|
||||||
|
text.save.difficulty = Складність
|
||||||
|
text.save.date = Останнє збережено: {0}
|
||||||
|
text.confirm = Підтвердити
|
||||||
|
text.delete = Видалити
|
||||||
|
text.ok = ОК
|
||||||
|
text.open = Відкрити
|
||||||
|
text.cancel = Скасувати
|
||||||
|
text.openlink = Відкрити посилання
|
||||||
|
text.back = Назад
|
||||||
|
text.quit.confirm = Ти впевнений що хочеш піти?
|
||||||
|
text.loading = [accent] Завантаження ...
|
||||||
|
text.wave = [orange] хвиля {0}
|
||||||
|
text.wave.waiting = Хвиля через {0}
|
||||||
|
text.waiting = Очікування…
|
||||||
|
text.enemies = {0} Вороги
|
||||||
|
text.enemies.single = Противник
|
||||||
|
text.loadimage = Завантажити зображення
|
||||||
|
text.saveimage = Зберегти зображення
|
||||||
|
text.oregen = Генерація руд
|
||||||
|
text.editor.badsize = [orange] Недійсні розміри зображення! [] Дійсні розміри карти: {0}
|
||||||
|
text.editor.errorimageload = Помилка завантаження файлу зображень: [orange] {0}
|
||||||
|
text.editor.errorimagesave = Помилка збереження файлу зображення: [orange] {0}
|
||||||
|
text.editor.generate = Генератор
|
||||||
|
text.editor.resize = Змінити розмір
|
||||||
|
text.editor.loadmap = // Завантажити карту
|
||||||
|
text.editor.savemap = Зберегти карту
|
||||||
|
text.editor.loadimage = Завантажити зображення
|
||||||
|
text.editor.saveimage = Зберегти зображення
|
||||||
|
text.editor.unsaved = [scarlet] У вас є незбережені зміни! [] Ви впевнені, що хочете вийти?
|
||||||
|
text.editor.brushsize = Розмір пензля: {0}
|
||||||
|
text.editor.noplayerspawn = Ця карта не має ігрового поля для гравця!
|
||||||
|
text.editor.manyplayerspawns = Карти не можуть мати більше одного ігрового поля для гравців!
|
||||||
|
text.editor.manyenemyspawns = Не може бути більше ніж {0} ворожих точок!
|
||||||
|
text.editor.resizemap = Змінити розмір карти
|
||||||
|
text.editor.resizebig = [scarlet] Попередження! [] Карти, розмір яких перевищує 256 одиниць, можуть виснути і можуть бути нестабільними.
|
||||||
|
text.editor.mapname = Назва карти:
|
||||||
|
text.editor.overwrite = [accent] Попередження! Це перезаписує існуючу карту.
|
||||||
|
text.editor.failoverwrite = [crimson] Неможливо перезаписати карту за замовчуванням!
|
||||||
|
text.editor.selectmap = Виберіть карту для завантаження:
|
||||||
|
text.width = Ширина
|
||||||
|
text.height = Висота
|
||||||
|
text.randomize = Рандомізувати
|
||||||
|
text.apply = Застосувати
|
||||||
|
text.update = Оновити
|
||||||
|
text.menu = Меню
|
||||||
|
text.play = Відтворити
|
||||||
|
text.load = Завантаження
|
||||||
|
text.save = Зберегти
|
||||||
|
text.language.restart = Будь ласка, перезапустіть свою гру, щоб налаштування мови набули чинності.
|
||||||
|
text.settings.language = Мова
|
||||||
|
text.settings = Налаштування
|
||||||
|
text.tutorial = Навчальний\nпосібник
|
||||||
|
text.editor = Редактор
|
||||||
|
text.mapeditor = Редактор карт
|
||||||
|
text.donate = Підтримати проект
|
||||||
|
text.settings.reset = Скинути до стандартних
|
||||||
|
text.settings.controls = Елементи управління
|
||||||
|
text.settings.game = Гра
|
||||||
|
text.settings.sound = Звук
|
||||||
|
text.settings.graphics = Графіка
|
||||||
|
text.upgrades = Оновлення
|
||||||
|
text.purchased = [LIME] Створено!
|
||||||
|
text.weapons = Зброя
|
||||||
|
text.paused = Пауза
|
||||||
|
text.respawn = Відновлення за
|
||||||
|
text.info.title = [accent] інформація
|
||||||
|
text.error.title = [crimson] Виникла помилка
|
||||||
|
text.error.crashmessage = [SCARLET] Виникла несподівана помилка, що призвела до збою. [] Будь ласка, повідомте про конкретні обставини, розробнику: [ORANGE] anukendev@gmail.com []
|
||||||
|
text.error.crashtitle = Виникла помилка
|
||||||
|
text.mode.break = Режим зносу: {0}
|
||||||
|
text.mode.place = Режим будівництва: {0}
|
||||||
|
placemode.hold.name = Лінія
|
||||||
|
placemode.areadelete.name = Площа
|
||||||
|
placemode.touchdelete.name = Дотик
|
||||||
|
placemode.holddelete.name = Утримування.
|
||||||
|
placemode.none.name = (None)
|
||||||
|
placemode.touch.name = Дотик
|
||||||
|
placemode.cursor.name = курсор
|
||||||
|
text.blocks.extrainfo = [accent] додатковий інформаційний блок:
|
||||||
|
text.blocks.blockinfo = Блокування інформації
|
||||||
|
text.blocks.powercapacity = Потужність
|
||||||
|
text.blocks.powershot = Потужність / постріл
|
||||||
|
text.blocks.powersecond = Потужність / секунда
|
||||||
|
text.blocks.powerdraindamage = Потужність дренажу / пошкодження
|
||||||
|
text.blocks.shieldradius = Радіус щита
|
||||||
|
text.blocks.itemspeedsecond = Швидкість / секунда
|
||||||
|
text.blocks.range = Радіус
|
||||||
|
text.blocks.size = Розмір
|
||||||
|
text.blocks.powerliquid = Потужність / Рідина
|
||||||
|
text.blocks.maxliquidsecond = Макс. Рідина / секунда
|
||||||
|
text.blocks.liquidcapacity = Ємкість рідини
|
||||||
|
text.blocks.liquidsecond = Рідина / секунда
|
||||||
|
text.blocks.damageshot = Пошкодження / постріл
|
||||||
|
text.blocks.ammocapacity = Місткість боєприпасів
|
||||||
|
text.blocks.ammo = Набої
|
||||||
|
text.blocks.ammoitem = Боєприпаси / предмет
|
||||||
|
text.blocks.maxitemssecond = Макс. Елементи / секунду
|
||||||
|
text.blocks.powerrange = Радіус потужності
|
||||||
|
text.blocks.lasertilerange = Радіус лазерних плиток
|
||||||
|
text.blocks.capacity = Ємкість
|
||||||
|
text.blocks.itemcapacity = Ємкість предмету
|
||||||
|
text.blocks.maxpowergenerationsecond = Максимальна потужність / секунда
|
||||||
|
text.blocks.powergenerationsecond = Потужність / секунда
|
||||||
|
text.blocks.generationsecondsitem = Генерація за секунду / предмет
|
||||||
|
text.blocks.input = Ввід
|
||||||
|
text.blocks.inputliquid = Ввід речовини
|
||||||
|
text.blocks.inputitem = Вхідний матеріал
|
||||||
|
text.blocks.output = Вивід
|
||||||
|
text.blocks.secondsitem = Секунда / предмет
|
||||||
|
text.blocks.maxpowertransfersecond = Максимальна передача потужності / секунда
|
||||||
|
text.blocks.explosive = Вибухонебезпечний!
|
||||||
|
text.blocks.repairssecond = Ремонт / секунда
|
||||||
|
text.blocks.health = Здоров'я
|
||||||
|
text.blocks.inaccuracy = Неточність
|
||||||
|
text.blocks.shots = Постріли
|
||||||
|
text.blocks.shotssecond = Постріли / секунду
|
||||||
|
text.blocks.fuel = Паливо:
|
||||||
|
text.blocks.fuelduration = Тривалість палива
|
||||||
|
text.blocks.maxoutputsecond = Макс. Вихід / секунду
|
||||||
|
text.blocks.inputcapacity = Вхідна ємність
|
||||||
|
text.blocks.outputcapacity = Випускна ємність
|
||||||
|
text.blocks.poweritem = Потужність / виріб
|
||||||
|
text.placemode = Місцевий режим
|
||||||
|
text.breakmode = Перерваний режим
|
||||||
|
text.health = Здоров'я
|
||||||
|
setting.difficulty.easy = Легкий
|
||||||
|
setting.difficulty.normal = Нормальний
|
||||||
|
setting.difficulty.hard = Важкий
|
||||||
|
setting.difficulty.insane = Божевільний
|
||||||
|
setting.difficulty.purge = Очистити
|
||||||
|
setting.difficulty.name = Складність
|
||||||
|
setting.screenshake.name = Тряска екрана
|
||||||
|
setting.smoothcam.name = Гладка камера
|
||||||
|
setting.indicators.name = Індикатори ворога
|
||||||
|
setting.effects.name = Ефекти відображення
|
||||||
|
setting.sensitivity.name = Чутливість контролера
|
||||||
|
setting.saveinterval.name = Інтервал автозбереження
|
||||||
|
setting.seconds = {0} секунд
|
||||||
|
setting.fullscreen.name = Повноекранний
|
||||||
|
setting.multithread.name = Багатопотоковий [scarlet] (нестабільний!)
|
||||||
|
setting.fps.name = Показати FPS
|
||||||
|
setting.vsync.name = VSunc
|
||||||
|
setting.lasers.name = Показати енергетичні лазери
|
||||||
|
setting.healthbars.name = Показати здоров'я
|
||||||
|
setting.pixelate.name = Пікселяція екрану
|
||||||
|
setting.musicvol.name = Гучність музики
|
||||||
|
setting.mutemusic.name = Вимкнути музику
|
||||||
|
setting.sfxvol.name = Гучність ефектів
|
||||||
|
setting.mutesound.name = Вимкнути звук
|
||||||
|
map.maze.name = Лабіринт
|
||||||
|
map.fortress.name = Фортеця
|
||||||
|
map.sinkhole.name = Свердловина
|
||||||
|
map.caves.name = Печери
|
||||||
|
map.volcano.name = Вулкан
|
||||||
|
map.caldera.name = Кальдера
|
||||||
|
map.scorch.name = Мертва земля
|
||||||
|
map.desert.name = Пустеля
|
||||||
|
map.island.name = Острів
|
||||||
|
map.grassland.name = Пасовища
|
||||||
|
map.tundra.name = Тундра
|
||||||
|
map.spiral.name = Спіраль
|
||||||
|
map.tutorial.name = Навчання
|
||||||
|
tutorial.intro.text = [yellow] Ласкаво просимо до підручника. [] Для початку натисніть \"далі\".
|
||||||
|
tutorial.moveDesktop.text = Для переміщення використовуйте клавіші [orange] [[WASD] []. Утримуйте [orange] SHIFT[], для прискорення. Утримуйте [orange] CTRL [], використовуючи [orange] колесо прокручування [] для збільшення або зменшення.
|
||||||
|
tutorial.shoot.text = Використовуйте мишу, щоб націлитись, утримуйте [orange] ліву кнопку миші [], щоб стріляти. Попрактикуйтесь на [yellow] мішені [].
|
||||||
|
tutorial.moveAndroid.text = Щоб перетягнути панораму, перетягніть один палець по екрану. Використовуйте два пальця, щоб збільшити чи зменшити маштаб.
|
||||||
|
tutorial.placeSelect.text = Спробуйте вибрати [yellow] конвеєр [] у меню блоку внизу справа.
|
||||||
|
tutorial.placeConveyorDesktop.text = Використовуйте [orange] [[колесико миші] [], щоб повернути конвеєр [orange] вперед [], а потім помістіть його в [yellow] позначене місце [], використовуючи [orange] [[ліву кнопку миші] [].
|
||||||
|
tutorial.placeConveyorAndroid.text = Використовуйте [orange] [[кнопку оберту] [], щоб обернути конвеєр [оранжевий] вперед [], перетягуйте його одним пальцем, а потім помістіть його в [yellow] позначене місце [], використовуючи [orange] [[галочка][].
|
||||||
|
tutorial.placeConveyorAndroidInfo.text = Крім того, ви можете натиснути піктограму перехрестя внизу ліворуч, щоб переключитися на [orange] [[сенсорний режим]] [], і помістити блоки, натиснувши на екран. У сенсорному режимі блоки можна повертати зі стрілкою внизу ліворуч. Натисніть [yellow] наступний [], щоб спробувати.
|
||||||
|
tutorial.placeDrill.text = Тепер виберіть та розмістіть [yellow] кам'яне свердло [] у зазначеному місці.
|
||||||
|
tutorial.blockInfo.text = Якщо ви хочете дізнатись більше про блок, ви можете торкнутися [orange] знак питання [] у верхньому правому куті, щоб прочитати його опис.
|
||||||
|
tutorial.deselectDesktop.text = Ви можете вимкнути блок, використовуючи [orange] [[клацання правою кнопкою миші] [].
|
||||||
|
tutorial.deselectAndroid.text = Ви можете скасувати вибір блоку, натиснувши кнопку [orange] X [].
|
||||||
|
tutorial.drillPlaced.text = Дриль тепер видобуває [yellow] камінь, [] та виведе його на конвеєр, а потім переміщає його в [yellow] ядро [].
|
||||||
|
tutorial.drillInfo.text = Різні руди потребують різних дрилі. Камінь вимагає кам'яні свердла, залізо вимагає залізні свердла та ін
|
||||||
|
tutorial.drillPlaced2.text = Переміщення елементів у ядро вказує їх у ваш [yellow] предметний інвентар [] у верхньому лівому куті. Розміщення блоків використовує предмети з вашого інвентарю.
|
||||||
|
tutorial.moreDrills.text = Ви можете пов'язати багато свердлів і конвеєрів разом в одну гілку конвеєра.
|
||||||
|
tutorial.deleteBlock.text = Ви можете видалити блоки, натиснувши правою клавішею [orange] правою кнопкою миші [] по блоці, який ви хочете видалити. Спробуйте видалити цей конвеєр.
|
||||||
|
tutorial.deleteBlockAndroid.text = Ви можете видалити блоки за допомогою [orange], перехрестя [] в меню [mode] зламу [orange] у нижньому лівому куті та натиснувши на блок. Спробуйте видалити цей конвеєр.
|
||||||
|
tutorial.placeTurret.text = Тепер виділіть та розмістіть [yellow] турель [] у [yellow] позначеному місці [].
|
||||||
|
tutorial.placedTurretAmmo.text = Ця турель тепер приймає [yellow] боєприпас [] з конвеєра. Ви можете побачити, скільки боєприпасів вона має, натискаючи на неї і перевіряючи [green] зелену полоску [].
|
||||||
|
tutorial.turretExplanation.text = Турелі будуть автоматично стріляти у найближчого ворога, якщо вони мають достатню кількість боєприпасів.
|
||||||
|
tutorial.waves.text = Кожні [yellow] 60 [] секунд, хвиля [coral] ворогів [] буде виникати в певних місцях і намагатися знищити ядро.
|
||||||
|
tutorial.coreDestruction.text = Ваша мета полягає в тому, щоб [yellow] захищати ядро []. Якщо ядро знищено, ви [coral] програєте[].
|
||||||
|
tutorial.pausingDesktop.text = Якщо вам коли-небудь потрібно зробити перерву, натисніть кнопку [orange] паузи [] у верхньому лівому куті або на кнопку [orange] пропуск [], щоб призупинити гру. Ви можете вибрати і розмістити блоки під час призупинення, але не можете переміщатися чи стріляти.
|
||||||
|
tutorial.pausingAndroid.text = Якщо вам коли-небудь потрібно зробити перерву, натисніть кнопку [orange] пауза [] у верхньому лівому куті, щоб призупинити гру. Ти можеш ще знищувати та будувати блоки під час призупинення.
|
||||||
|
tutorial.purchaseWeapons.text = Ви можете придбати нову [yellow] зброю [] для вашого механізму, відкривши меню оновлення в лівому нижньому кутку.
|
||||||
|
tutorial.switchWeapons.text = Перемикати зброю будь-яким натисканням його піктограми внизу ліворуч або за допомогою цифр [orange] [[1-9] [].
|
||||||
|
tutorial.spawnWave.text = Ось хвиля зараз. Знищи їх
|
||||||
|
tutorial.pumpDesc.text = У пізніших хвилях, можливо, доведеться використовувати [yellow] насоси [] для розподілу рідин для генераторів або екстракторів.
|
||||||
|
tutorial.pumpPlace.text = Насоси працюють аналогічно свердлам, за винятком того, що вони виробляють рідини замість предметів. Спробуйте встановити насос на [yellow] призначене мастило [].
|
||||||
|
tutorial.conduitUse.text = Тепер покладіть [orange] трубопровід [], віддаляючись від насоса.
|
||||||
|
tutorial.conduitUse2.text = І ще кілька ...
|
||||||
|
tutorial.conduitUse3.text = І ще кілька ...
|
||||||
|
tutorial.generator.text = Тепер, помістіть блок [orange] базовий генератор енергії [] в кінці каналу.
|
||||||
|
tutorial.generatorExplain.text = Цей генератор тепер створить [yellow] енергію [] від масла.
|
||||||
|
tutorial.lasers.text = Потужність розподіляється за допомогою [yellow] лазерів потужності []. Поверніть і помістіть його тут.
|
||||||
|
tutorial.laserExplain.text = Тепер генератор переведе енергію в лазерний блок. Промінь [yellow] непрозорий [] означає, що в даний час він передає потужність, а промінь [yellow] прозорий [] означає, що це не так.
|
||||||
|
tutorial.laserMore.text = Ви можете перевірити, скільки енергії в блоку, наведіть курсор миші на нього і перевірте [yellow] жовту стрічку [] у верхній частині екрана.
|
||||||
|
tutorial.healingTurret.text = Цей лазер може бути використаний для живлення турелі для ремонту [lime] []. Помістіть одну тут.
|
||||||
|
tutorial.healingTurretExplain.text = Поки вона має енергію, ця турель може [lime] відремонтувати блоки. [] Під час гри постарайтеся збудувати одну таку чим швидше!
|
||||||
|
tutorial.smeltery.text = Для багатьох блоків потрібна [orange] сталь [], для цього потрібна[orange] доминна піч [] . Місце тут.
|
||||||
|
tutorial.smelterySetup.text = Ця піч буде тепер виробляти [orange] сталь [] із вхідного заліза, використовуючи вугілля як паливо.
|
||||||
|
tutorial.tunnelExplain.text = Також зауважте, що елементи проходять через [yellow] тунельний блок [] і з'являються з іншого боку, проходячи через кам'яний блок. Майте на увазі, що тунелі можуть проходити лише до 2 блоків.
|
||||||
|
tutorial.end.text = Ви завершили підручник! Удачі!
|
||||||
|
text.keybind.title = Ключ перемотки
|
||||||
|
keybind.move_x.name = move_x
|
||||||
|
keybind.move_y.name = move_y
|
||||||
|
keybind.select.name = Вибрати
|
||||||
|
keybind.break.name = {0}break{/0}{1}; {/1}
|
||||||
|
keybind.shoot.name = Постріл
|
||||||
|
keybind.zoom_hold.name = zoom_hold
|
||||||
|
keybind.zoom.name = Збільшити
|
||||||
|
keybind.block_info.name = Інформація про блок
|
||||||
|
keybind.menu.name = Меню
|
||||||
|
keybind.pause.name = Пауза
|
||||||
|
keybind.dash.name = Тире
|
||||||
|
keybind.chat.name = Чат
|
||||||
|
keybind.player_list.name = Список гравців
|
||||||
|
keybind.console.name = // Консоль 1
|
||||||
|
keybind.rotate_alt.name = rotate_alt
|
||||||
|
keybind.rotate.name = Повернути
|
||||||
|
keybind.weapon_1.name = Зброя!
|
||||||
|
keybind.weapon_2.name = Зброя!
|
||||||
|
keybind.weapon_3.name = Зброя!
|
||||||
|
keybind.weapon_4.name = Зброя!
|
||||||
|
keybind.weapon_5.name = Зброя!
|
||||||
|
keybind.weapon_6.name = Зброя!
|
||||||
|
mode.waves.name = Хвилі
|
||||||
|
mode.sandbox.name = Пісочниця
|
||||||
|
mode.freebuild.name = Вільний режим
|
||||||
|
upgrade.standard.name = Стандартний
|
||||||
|
upgrade.standard.description = Стандартний механ.
|
||||||
|
upgrade.blaster.name = Бластер
|
||||||
|
upgrade.blaster.description = Стріляє повільно, слабкі кулі.
|
||||||
|
upgrade.triblaster.name = Трипластер
|
||||||
|
upgrade.triblaster.description = Вистрілює 3 кулі в розповсюдженні.
|
||||||
|
upgrade.clustergun.name = Касетна гармата
|
||||||
|
upgrade.clustergun.description = Вистрілює неточними вибуховими гранатами.
|
||||||
|
upgrade.beam.name = Пушечна гармата
|
||||||
|
upgrade.beam.description = Вистрілює далекобійним,пробірний лазерний промінь.
|
||||||
|
upgrade.vulcan.name = Вулкан
|
||||||
|
upgrade.vulcan.description = Вистрілює шквал швидких куль.
|
||||||
|
upgrade.shockgun.name = Шок-пушка
|
||||||
|
upgrade.shockgun.description = Стріляє руйнівним вибухом заряженої шрапнелі.
|
||||||
|
item.stone.name = Камінь
|
||||||
|
item.iron.name = Залізо
|
||||||
|
item.coal.name = Вугівалля
|
||||||
|
item.steel.name = Сталь
|
||||||
|
item.titanium.name = Титан
|
||||||
|
item.dirium.name = Дириум
|
||||||
|
item.uranium.name = Уран
|
||||||
|
item.sand.name = Пісок
|
||||||
|
liquid.water.name = Вода
|
||||||
|
liquid.plasma.name = Плазма
|
||||||
|
liquid.lava.name = Лава
|
||||||
|
liquid.oil.name = Нафта
|
||||||
|
block.weaponfactory.name = Фабрика зброї
|
||||||
|
block.weaponfactory.fulldescription = Використовується для створення зброї для гравця mech. Натисніть, щоб використати. Автоматично приймає ресурси з основного ядра.
|
||||||
|
block.air.name = Повітря
|
||||||
|
block.blockpart.name = Блокчастина
|
||||||
|
block.deepwater.name = Глибока вода
|
||||||
|
block.water.name = Вода
|
||||||
|
block.lava.name = Лава
|
||||||
|
block.oil.name = Нафта
|
||||||
|
block.stone.name = Камінь
|
||||||
|
block.blackstone.name = Чорний камінь
|
||||||
|
block.iron.name = Залізо
|
||||||
|
block.coal.name = Вугілля
|
||||||
|
block.titanium.name = Титан
|
||||||
|
block.uranium.name = Уран
|
||||||
|
block.dirt.name = Бруд
|
||||||
|
block.sand.name = Пісок
|
||||||
|
block.ice.name = Лід
|
||||||
|
block.snow.name = Сніг
|
||||||
|
block.grass.name = Трава
|
||||||
|
block.sandblock.name = Блок піску
|
||||||
|
block.snowblock.name = Блок снігу
|
||||||
|
block.stoneblock.name = Блок камню
|
||||||
|
block.blackstoneblock.name = Блок чорного камню
|
||||||
|
block.grassblock.name = Блок бруду
|
||||||
|
block.mossblock.name = Моссблок
|
||||||
|
block.shrub.name = Чагарник
|
||||||
|
block.rock.name = Камень
|
||||||
|
block.icerock.name = Ледяний камень
|
||||||
|
block.blackrock.name = Чорний камінь
|
||||||
|
block.dirtblock.name = Блок землі
|
||||||
|
block.stonewall.name = Кам'яна стіна
|
||||||
|
block.stonewall.fulldescription = Недорогий захисний блок. Корисно для захисту ядра та турелі в перші кілька хвиль.
|
||||||
|
block.ironwall.name = Залізна стіна
|
||||||
|
block.ironwall.fulldescription = Основний захисний блок. Забезпечує захист від ворогів.
|
||||||
|
block.steelwall.name = Сталева стіна
|
||||||
|
block.steelwall.fulldescription = Стандартний захисний блок. адекватний захист від ворогів.
|
||||||
|
block.titaniumwall.name = Титанова стіна
|
||||||
|
block.titaniumwall.fulldescription = Сильний захисний блок. Забезпечує захист від ворогів.
|
||||||
|
block.duriumwall.name = Діріумова стіна
|
||||||
|
block.duriumwall.fulldescription = Дуже сильний захисний блок. Забезпечує захист від ворогів.
|
||||||
|
block.compositewall.name = Композитна стіна
|
||||||
|
block.steelwall-large.name = Велика сталева стіна
|
||||||
|
block.steelwall-large.fulldescription = Стандартний захисний блок. Поєднує в собі кілька блоків.
|
||||||
|
block.titaniumwall-large.name = Велика титанова стіна
|
||||||
|
block.titaniumwall-large.fulldescription = Сильний захисний блок. Поєднує в собі кілька блоків.
|
||||||
|
block.duriumwall-large.name = Велика дирмітова стіна
|
||||||
|
block.duriumwall-large.fulldescription = Дуже сильний захисний блок.Поєднує в собі кілька блоків.
|
||||||
|
block.titaniumshieldwall.name = Стіна з щитом
|
||||||
|
block.titaniumshieldwall.fulldescription = Сильний захисний блок з додатковим вбудованим щитом. Потрібна енергія. Використовує енергію для поглинання ворожих куль. Рекомендується використовувати силові пристосування для забезпечення енергії цього блоку.
|
||||||
|
block.repairturret.name = Ремонтна турель
|
||||||
|
block.repairturret.fulldescription = Ремонтує недалекі пошкодженні блоки.Повільний темп. Використовує невелику кількість енергії.
|
||||||
|
block.megarepairturret.name = Ремонтна турель II
|
||||||
|
block.megarepairturret.fulldescription = Ремонтує недалекі пошкодженні блоки.Збільшений радіус та швидший темп ремонту . Використовує багато енергії.
|
||||||
|
block.shieldgenerator.name = Генератор щиту
|
||||||
|
block.shieldgenerator.fulldescription = Передовий захисний блок. Захищає всі блоки в радіусі від нападу. Не вкористовує енергію при бездіяльності, але швидко витрачає енергію на захист від куль.
|
||||||
|
block.door.name = Двері
|
||||||
|
block.door.fulldescription = Блок, який можна відкрити та закрити, торкнувшись його.
|
||||||
|
block.door-large.name = Великі двері
|
||||||
|
block.door-large.fulldescription = Блок, який можна відкрити та закрити, торкнувшись його.
|
||||||
|
block.conduit.name = Трубопровід
|
||||||
|
block.conduit.fulldescription = Основний транспортний блок. Працює як конвеєр, але з рідинами. Найкраще використовується з насосами або іншими трубопроводами. Може використовуватися як міст через рідини для ворогів та гравців.
|
||||||
|
block.pulseconduit.name = Імпульсний канал
|
||||||
|
block.pulseconduit.fulldescription = Покращенний блок перевезення рідин. Транспортує рідини швидше і зберігає більше стандартних каналів.
|
||||||
|
block.liquidrouter.name = маршрутизатор для рідини
|
||||||
|
block.liquidrouter.fulldescription = Працює аналогічно маршрутизатору. Приймає рідину ввід з одного боку і виводить його на інші сторони. Корисний для розщеплення рідини з одного каналу на кілька інших трубопроводів.
|
||||||
|
block.conveyor.name = Конвеєр
|
||||||
|
block.conveyor.fulldescription = Базовий транспортний блок. Переміщує предмети вперед і автоматично вкладає їх у турелі або ремісники. Поворотний Може використовуватися як міст через рідину для ворогів та гравців.
|
||||||
|
block.steelconveyor.name = Сталевий конвеєр
|
||||||
|
block.steelconveyor.fulldescription = Розширений блок транспортування предметів. Переміщення елементів швидше, ніж стандартні конвеєри.
|
||||||
|
block.poweredconveyor.name = Імпульсний конвеєр
|
||||||
|
block.poweredconveyor.fulldescription = Кінцевий транспортний блок. Переміщення елементів швидше, ніж сталеві конвеєри.
|
||||||
|
block.router.name = Маршрутизатор
|
||||||
|
block.router.fulldescription = Приймає елементи з одного напрямку і виводить їх на 3 інших напрямках. Можна також зберігати певну кількість предметів. Використовується для розщеплення матеріалів з одного свердла на декілька башточок.
|
||||||
|
block.junction.name = Міст
|
||||||
|
block.junction.fulldescription = Виступає як міст для двох перехресних конвеєрних стрічок. Корисне у ситуаціях з двома різними конвеєрами, що несуть різні матеріали в різних місцях.
|
||||||
|
block.conveyortunnel.name = Конвеєрний тунель
|
||||||
|
block.conveyortunnel.fulldescription = Транспортує предмети під блоками. Щоб використати, помістіть один тунель, що веде у блок, щоб бути підсвіченим, а один - з іншого боку. Переконайтеся, що обидва тунелі стикаються з протилежними напрямками, тобто до блоків, які вони вводять або виводять.
|
||||||
|
block.liquidjunction.name = Міст для рідини
|
||||||
|
block.liquidjunction.fulldescription = Діє як міст для двох перехресних трубопроводів. Корисно в ситуаціях з двома різними трубами, що несуть різні рідини в різних місцях.
|
||||||
|
block.liquiditemjunction.name = Перехрестя рідкого пункту
|
||||||
|
block.liquiditemjunction.fulldescription = Виступає як міст для перетину трубопроводів і конвеєрів.
|
||||||
|
block.powerbooster.name = Підсилювач потужності
|
||||||
|
block.powerbooster.fulldescription = Поширює енергію на всі блоки в межах його радіуса.
|
||||||
|
block.powerlaser.name = Енергетичний лазер
|
||||||
|
block.powerlaser.fulldescription = Створює лазер, який передає енергію блоку перед ним. Не створює жодної сили сама. Найкраще використовується з генераторами або іншими лазерами.
|
||||||
|
block.powerlaserrouter.name = Лазерний маршрутизатор
|
||||||
|
block.powerlaserrouter.fulldescription = Лазер, який розподіляє енергію у три напрямки одночасно. Корисно в ситуаціях, коли потрібно живити кілька блоків від одного генератора.
|
||||||
|
block.powerlasercorner.name = Лазерний кут
|
||||||
|
block.powerlasercorner.fulldescription = Лазер, який розподіляє енергію одночасно на два напрямки. Корисно в ситуаціях, коли потрібно живити кілька блоків від одного генератора, а маршрутизатор неточний.
|
||||||
|
block.teleporter.name = Телепорт
|
||||||
|
block.teleporter.fulldescription = Продвинутий блок транспортування предметів.Щоб телепортувати предмети з одного місця в інше потрібно збудувати 2 телепорти і назначити на них одинаковий колір. Використовує енергію. Натисніть, щоб змінити колір.
|
||||||
|
block.sorter.name = Сортувальник
|
||||||
|
block.sorter.fulldescription = Сортує предмети за типом матеріалу. Матеріал для прийняття позначається кольором у блоці. Всі елементи, що відповідають матеріалу сортування, виводяться вперед, а все інше виводить ліворуч і праворуч.
|
||||||
|
block.core.name = Ядро
|
||||||
|
block.pump.name = Насос
|
||||||
|
block.pump.fulldescription = Насоси рідини з вихідного блоку - зазвичай вода, лава чи олія. Виводить рідину в сусідні трубопроводи.
|
||||||
|
block.fluxpump.name = Флюсовий насос
|
||||||
|
block.fluxpump.fulldescription = Розширений варіант насоса. Зберігає більше рідини та перекачує швидше.
|
||||||
|
block.smelter.name = Плавильня
|
||||||
|
block.smelter.fulldescription = Основний ремісничий блок. Коли вводиться 1 залізо та 1 вугілля в якості палива, виводить одну сталь. Рекомендується вводити залізо та вугілля на різних поясах, щоб запобігти засміченню.
|
||||||
|
block.crucible.name = Тигель
|
||||||
|
block.crucible.fulldescription = Розширений блок обробки. При введенні 1 титану, 1 сталі та 1 вугілля в якості пального, виводить один дирний. Рекомендується вводити вугілля, сталь та титан на різних поясах, щоб запобігти засміченню.
|
||||||
|
block.coalpurifier.name = вугільний екстрактор
|
||||||
|
block.coalpurifier.fulldescription = Основний екстрактор. Виходить вугілля при постачанні великої кількості води та каменю.
|
||||||
|
block.titaniumpurifier.name = Титановий екстрактор
|
||||||
|
block.titaniumpurifier.fulldescription = Стандартний блок екстрактора. Виходить титан при постачанні великої кількості води та заліза.
|
||||||
|
block.oilrefinery.name = Нафтопереробний завод
|
||||||
|
block.oilrefinery.fulldescription = Очищує велику кількість нафти і перетворює на вугілля. Корисний для заправки вугільних башточок, коли вугільні родовища є дефіцитними.
|
||||||
|
block.stoneformer.name = Кам'янний екстрактор
|
||||||
|
block.stoneformer.fulldescription = Здавлюється рідка лава в камінь. Корисно для виготовлення великої кількості каменю для очищувачів вугілля.
|
||||||
|
block.lavasmelter.name = Лавовий завод
|
||||||
|
block.lavasmelter.fulldescription = Використовує лаву для перетворення залізо на сталь. Альтернатива плавильні. Корисно в ситуаціях, коли вугілля є дефіцитним.
|
||||||
|
block.stonedrill.name = Кам'янна свердловина
|
||||||
|
block.stonedrill.fulldescription = Основна свердловина.Розміщюється на кам'яній плитці виводить камінь повільними темпами.
|
||||||
|
block.irondrill.name = Залізна свердловина
|
||||||
|
block.irondrill.fulldescription = Базова свердловина.Розміщюється на родовищі залізної руди, випускає залізо в повільному темпі.
|
||||||
|
block.coaldrill.name = Вугільна свердловина
|
||||||
|
block.coaldrill.fulldescription = Базова свердловина.Розміщюється на родовищі вугільної руди ,видобуває вугілля повільними темпами.
|
||||||
|
block.uraniumdrill.name = Уранова свердловина
|
||||||
|
block.uraniumdrill.fulldescription = Продвинута свердловина. Розміщюється на родовищі уранової руди.Видобуток урану відбувається повільними темпами.
|
||||||
|
block.titaniumdrill.name = Титанова свердловина
|
||||||
|
block.titaniumdrill.fulldescription = Продвинута свердловина.Розміщюється на родовищі титанової руди, Видобуток титану відбувається повільним темпом.
|
||||||
|
block.omnidrill.name = Убер свердловина
|
||||||
|
block.omnidrill.fulldescription = Кінцева свердловина.Дуже швидко видобуває будь-який вид руди.
|
||||||
|
block.coalgenerator.name = Вугільний генератор
|
||||||
|
block.coalgenerator.fulldescription = Основний генератор. Генерує енергію з вугілля. Виводиться потужність лазерів на 4 сторони.
|
||||||
|
block.thermalgenerator.name = Теплогенератор
|
||||||
|
block.thermalgenerator.fulldescription = Генерує енергію від лави. Виводиться потужність лазерів на 4 сторони.
|
||||||
|
block.combustiongenerator.name = Генератор горіння
|
||||||
|
block.combustiongenerator.fulldescription = Генерує енергію з нафти. Виводиться потужність лазерів на 4 сторони.
|
||||||
|
block.rtgenerator.name = RTG генератор
|
||||||
|
block.rtgenerator.fulldescription = Генерує невелику кількість енергії з радіоактивного розпаду урану. Виводиться потужність лазерів на 4 сторони.
|
||||||
|
block.nuclearreactor.name = Ядерний реактор
|
||||||
|
block.nuclearreactor.fulldescription = Розширений варіант RTG Generator і кінцевий генератор електроенергії. Генерує енергію з урану. Потребує постійного водяного охолодження.Сильно вибухне якщо не буде постачання води у великії кількості
|
||||||
|
block.turret.name = Турель
|
||||||
|
block.turret.fulldescription = Базова, дешева турель. Використовує камінь для боєприпасів. Має трохи більше діапазону, ніж подвійна турель.
|
||||||
|
block.doubleturret.name = Подвійна турель
|
||||||
|
block.doubleturret.fulldescription = Дещо потужна версія турель. Використовує камінь для боєприпасів. Значно більший урон, але менший діапазон. Вистрілює дві кулі.
|
||||||
|
block.machineturret.name = Кулеметна турель
|
||||||
|
block.machineturret.fulldescription = Стандартна всеосяжна турель. Використовує залізо для боєприпасів. Має швидку швидкість пострілу і гідну шкоду.
|
||||||
|
block.shotgunturret.name = Розріджуюча турель
|
||||||
|
block.shotgunturret.fulldescription = Стандартна турель. Використовує залізо для боєприпасів. Вистрілює 7 куль навколо себе.Наносить значних ушкоджень,звісно якщо поцілить :)
|
||||||
|
block.flameturret.name = Вогнемет
|
||||||
|
block.flameturret.fulldescription = Продвинута турель ближнього діапазону. Використовує вугілля для боєприпасів. Має дуже низький радіус, але дуже високий збиток. Добре для близьких дистанцій. Рекомендується використовувати за стінами.
|
||||||
|
block.sniperturret.name = Лазерна турель.
|
||||||
|
block.sniperturret.fulldescription = Продвинута далекобійна турель. Використовує сталь для боєприпасів. Дуже високий збиток, але низький рівень урону. Дорогі для використання, але можуть бути розташовані далеко від ліній ворога через його радіус.
|
||||||
|
block.mortarturret.name = Флак турель
|
||||||
|
block.mortarturret.fulldescription = Продвинута,неточна турель. Використовує вугілля для боєприпасів. Стріляє кулями, що вибухають у шрапнеллв. Корисне для великих натовпів ворогів.
|
||||||
|
block.laserturret.name = Лазерна турель
|
||||||
|
block.laserturret.fulldescription = Продвинута однопушечна турель. Використовує енергію. Хороша на середніх дистанціях. Ніколи не пропускає.
|
||||||
|
block.waveturret.name = Тесла
|
||||||
|
block.waveturret.fulldescription = Передова багатоцільова турель. Використовує енергію. Середній радіус. Ніколи не пропускає. Активно знижує, але може вражати декількох ворогів одночасно з ланцюговим освітленням.
|
||||||
|
block.plasmaturret.name = Плазмова турель
|
||||||
|
block.plasmaturret.fulldescription = Дуже продвинута версія Вогнеметної турелі. Використовує вугілля як боєприпаси. Дуже високий урон, від близької до середньої дистанції.
|
||||||
|
block.chainturret.name = Уранова турель
|
||||||
|
block.chainturret.fulldescription = Остаточна швидкістна вежа. Використовує уран як боєприпаси. Вистрілює великі кулі при високій швидкості вогню. Середній радіус. Промінь кілька плиток. Надзвичайно жорсткий.
|
||||||
|
block.titancannon.name = Титанова гармата
|
||||||
|
block.titancannon.fulldescription = Найбільш далекобійна турель. Використовує уран як боєприпаси. Вистрілює великі снаряди. Далекобійний. Промінь кілька плиток. Надзвичайно жорсткий.
|
||||||
|
block.playerspawn.name = Спавн Гравця
|
||||||
|
block.enemyspawn.name = Спавн ворогів
|
@ -70,10 +70,13 @@ char id=98 x=204 y=102 width=22 height=22 xoffset=-1 yoffset=15 x
|
|||||||
char id=99 x=226 y=102 width=22 height=22 xoffset=-1 yoffset=15 xadvance=24 page=0 chnl=0
|
char id=99 x=226 y=102 width=22 height=22 xoffset=-1 yoffset=15 xadvance=24 page=0 chnl=0
|
||||||
char id=100 x=248 y=102 width=22 height=22 xoffset=-1 yoffset=15 xadvance=24 page=0 chnl=0
|
char id=100 x=248 y=102 width=22 height=22 xoffset=-1 yoffset=15 xadvance=24 page=0 chnl=0
|
||||||
char id=101 x=270 y=102 width=22 height=22 xoffset=-1 yoffset=15 xadvance=24 page=0 chnl=0
|
char id=101 x=270 y=102 width=22 height=22 xoffset=-1 yoffset=15 xadvance=24 page=0 chnl=0
|
||||||
|
char id=1108 x=270 y=102 width=22 height=22 xoffset=-1 yoffset=15 xadvance=24 page=0 chnl=0
|
||||||
char id=102 x=292 y=102 width=22 height=22 xoffset=-1 yoffset=15 xadvance=24 page=0 chnl=0
|
char id=102 x=292 y=102 width=22 height=22 xoffset=-1 yoffset=15 xadvance=24 page=0 chnl=0
|
||||||
char id=103 x=314 y=102 width=22 height=22 xoffset=-1 yoffset=15 xadvance=24 page=0 chnl=0
|
char id=103 x=314 y=102 width=22 height=22 xoffset=-1 yoffset=15 xadvance=24 page=0 chnl=0
|
||||||
char id=104 x=336 y=102 width=22 height=22 xoffset=-1 yoffset=15 xadvance=24 page=0 chnl=0
|
char id=104 x=336 y=102 width=22 height=22 xoffset=-1 yoffset=15 xadvance=24 page=0 chnl=0
|
||||||
char id=105 x=358 y=102 width=14 height=22 xoffset=-1 yoffset=15 xadvance=16 page=0 chnl=0
|
char id=105 x=358 y=102 width=14 height=22 xoffset=-1 yoffset=15 xadvance=16 page=0 chnl=0
|
||||||
|
char id=1110 x=358 y=102 width=14 height=22 xoffset=-1 yoffset=15 xadvance=16 page=0 chnl=0
|
||||||
|
char id=1111 x=358 y=102 width=14 height=22 xoffset=-1 yoffset=15 xadvance=16 page=0 chnl=0
|
||||||
char id=106 x=372 y=102 width=22 height=22 xoffset=-1 yoffset=15 xadvance=24 page=0 chnl=0
|
char id=106 x=372 y=102 width=22 height=22 xoffset=-1 yoffset=15 xadvance=24 page=0 chnl=0
|
||||||
char id=107 x=394 y=102 width=22 height=22 xoffset=-1 yoffset=15 xadvance=24 page=0 chnl=0
|
char id=107 x=394 y=102 width=22 height=22 xoffset=-1 yoffset=15 xadvance=24 page=0 chnl=0
|
||||||
char id=108 x=416 y=102 width=22 height=22 xoffset=-1 yoffset=15 xadvance=24 page=0 chnl=0
|
char id=108 x=416 y=102 width=22 height=22 xoffset=-1 yoffset=15 xadvance=24 page=0 chnl=0
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#Autogenerated file. Do not modify.
|
#Autogenerated file. Do not modify.
|
||||||
#Fri Mar 16 22:39:48 EDT 2018
|
#Mon Mar 19 20:46:00 EDT 2018
|
||||||
version=release
|
version=release
|
||||||
androidBuildCode=446
|
androidBuildCode=449
|
||||||
name=Mindustry
|
name=Mindustry
|
||||||
code=3.4
|
code=3.4
|
||||||
build=custom build
|
build=custom build
|
||||||
|
@ -92,7 +92,7 @@ public class Vars{
|
|||||||
|
|
||||||
public static final int tilesize = 8;
|
public static final int tilesize = 8;
|
||||||
|
|
||||||
public static final Locale[] locales = {new Locale("en"), new Locale("fr", "FR"), new Locale("ru"), new Locale("pl", "PL"),
|
public static final Locale[] locales = {new Locale("en"), new Locale("fr", "FR"), new Locale("ru"), new Locale("uk", "UA"), new Locale("pl", "PL"),
|
||||||
new Locale("de"), new Locale("es", "LA"), new Locale("pt", "BR"), new Locale("ko"), new Locale("in", "ID")};
|
new Locale("de"), new Locale("es", "LA"), new Locale("pt", "BR"), new Locale("ko"), new Locale("in", "ID")};
|
||||||
|
|
||||||
public static final Color[] playerColors = {
|
public static final Color[] playerColors = {
|
||||||
|
@ -122,6 +122,8 @@ public class Control extends Module{
|
|||||||
"lastBuild", 0
|
"lastBuild", 0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Log.info("{0}", (int)'ї');
|
||||||
|
|
||||||
KeyBinds.load();
|
KeyBinds.load();
|
||||||
|
|
||||||
for(Map map : world.maps().list()){
|
for(Map map : world.maps().list()){
|
||||||
|
@ -12,6 +12,7 @@ import io.anuke.mindustry.net.Net;
|
|||||||
import io.anuke.mindustry.net.Net.SendMode;
|
import io.anuke.mindustry.net.Net.SendMode;
|
||||||
import io.anuke.mindustry.net.NetworkIO;
|
import io.anuke.mindustry.net.NetworkIO;
|
||||||
import io.anuke.mindustry.net.Packets.*;
|
import io.anuke.mindustry.net.Packets.*;
|
||||||
|
import io.anuke.mindustry.net.TraceInfo;
|
||||||
import io.anuke.mindustry.resource.*;
|
import io.anuke.mindustry.resource.*;
|
||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
import io.anuke.mindustry.world.Placement;
|
import io.anuke.mindustry.world.Placement;
|
||||||
@ -65,8 +66,7 @@ public class NetServer extends Module{
|
|||||||
|
|
||||||
String ip = Net.getConnection(id).address;
|
String ip = Net.getConnection(id).address;
|
||||||
|
|
||||||
admins.setKnownName(ip, packet.name);
|
admins.updatePlayerJoined(uuid, ip, packet.name);
|
||||||
admins.setKnownIP(uuid, ip);
|
|
||||||
admins.getTrace(ip).uuid = uuid;
|
admins.getTrace(ip).uuid = uuid;
|
||||||
admins.getTrace(ip).android = packet.android;
|
admins.getTrace(ip).android = packet.android;
|
||||||
|
|
||||||
@ -150,6 +150,7 @@ public class NetServer extends Module{
|
|||||||
Net.send(dc, SendMode.tcp);
|
Net.send(dc, SendMode.tcp);
|
||||||
|
|
||||||
Platform.instance.updateRPC();
|
Platform.instance.updateRPC();
|
||||||
|
admins.save();
|
||||||
});
|
});
|
||||||
|
|
||||||
Net.handleServer(PositionPacket.class, (id, packet) -> {
|
Net.handleServer(PositionPacket.class, (id, packet) -> {
|
||||||
@ -161,6 +162,22 @@ public class NetServer extends Module{
|
|||||||
});
|
});
|
||||||
|
|
||||||
Net.handleServer(ShootPacket.class, (id, packet) -> {
|
Net.handleServer(ShootPacket.class, (id, packet) -> {
|
||||||
|
TraceInfo info = admins.getTrace(Net.getConnection(id).address);
|
||||||
|
Weapon weapon = (Weapon)Upgrade.getByID(packet.weaponid);
|
||||||
|
|
||||||
|
float wtrc = 45f;
|
||||||
|
|
||||||
|
if(!Timers.get(info.ip + "-weapontrace", wtrc)){
|
||||||
|
info.fastShots ++;
|
||||||
|
}else{
|
||||||
|
|
||||||
|
if(info.fastShots - 2 > (int)(wtrc / (weapon.getReload() / 2f))){
|
||||||
|
Net.kickConnection(id, KickReason.kick);
|
||||||
|
}
|
||||||
|
|
||||||
|
info.fastShots = 0;
|
||||||
|
}
|
||||||
|
|
||||||
packet.playerid = connections.get(id).id;
|
packet.playerid = connections.get(id).id;
|
||||||
Net.sendExcept(id, packet, SendMode.udp);
|
Net.sendExcept(id, packet, SendMode.udp);
|
||||||
});
|
});
|
||||||
@ -182,6 +199,7 @@ public class NetServer extends Module{
|
|||||||
|
|
||||||
admins.getTrace(Net.getConnection(id).address).lastBlockPlaced = block;
|
admins.getTrace(Net.getConnection(id).address).lastBlockPlaced = block;
|
||||||
admins.getTrace(Net.getConnection(id).address).totalBlocksPlaced ++;
|
admins.getTrace(Net.getConnection(id).address).totalBlocksPlaced ++;
|
||||||
|
admins.getInfo(admins.getTrace(Net.getConnection(id).address).uuid).totalBlockPlaced ++;
|
||||||
|
|
||||||
Net.send(packet, SendMode.tcp);
|
Net.send(packet, SendMode.tcp);
|
||||||
});
|
});
|
||||||
@ -196,6 +214,7 @@ public class NetServer extends Module{
|
|||||||
if(block != null) {
|
if(block != null) {
|
||||||
admins.getTrace(Net.getConnection(id).address).lastBlockBroken = block;
|
admins.getTrace(Net.getConnection(id).address).lastBlockBroken = block;
|
||||||
admins.getTrace(Net.getConnection(id).address).totalBlocksBroken++;
|
admins.getTrace(Net.getConnection(id).address).totalBlocksBroken++;
|
||||||
|
admins.getInfo(admins.getTrace(Net.getConnection(id).address).uuid).totalBlocksBroken ++;
|
||||||
if (block.update || block.destructible)
|
if (block.update || block.destructible)
|
||||||
admins.getTrace(Net.getConnection(id).address).structureBlocksBroken++;
|
admins.getTrace(Net.getConnection(id).address).structureBlocksBroken++;
|
||||||
}
|
}
|
||||||
|
@ -7,177 +7,224 @@ import io.anuke.ucore.core.Settings;
|
|||||||
|
|
||||||
public class Administration {
|
public class Administration {
|
||||||
private Json json = new Json();
|
private Json json = new Json();
|
||||||
|
/**All player info. Maps UUIDs to info. This persists throughout restarts.*/
|
||||||
|
private ObjectMap<String, PlayerInfo> playerInfo = new ObjectMap<>();
|
||||||
|
/**Maps UUIDs to trace infos. This is wiped when a player logs off.*/
|
||||||
|
private ObjectMap<String, TraceInfo> traceInfo = new ObjectMap<>();
|
||||||
private Array<String> bannedIPs = new Array<>();
|
private Array<String> bannedIPs = new Array<>();
|
||||||
private Array<String> bannedIDs = new Array<>();
|
|
||||||
private Array<String> admins = new Array<>();
|
|
||||||
private ObjectMap<String, String> ipNames = new ObjectMap<>();
|
|
||||||
private ObjectMap<String, String> idIPs = new ObjectMap<>();
|
|
||||||
private ObjectMap<String, TraceInfo> traces = new ObjectMap<>();
|
|
||||||
|
|
||||||
public Administration(){
|
public Administration(){
|
||||||
Settings.defaultList(
|
Settings.defaults("playerInfo", "{}");
|
||||||
"bans", "{}",
|
Settings.defaults("bannedIPs", "{}");
|
||||||
"bannedIDs", "{}",
|
|
||||||
"admins", "{}",
|
|
||||||
"knownIPs", "{}",
|
|
||||||
"knownIDs", "{}"
|
|
||||||
);
|
|
||||||
|
|
||||||
load();
|
load();
|
||||||
}
|
}
|
||||||
|
|
||||||
public TraceInfo getTrace(String ip){
|
/**Call when a player joins to update their information here.*/
|
||||||
if(!traces.containsKey(ip)) traces.put(ip, new TraceInfo(ip));
|
public void updatePlayerJoined(String id, String ip, String name){
|
||||||
|
PlayerInfo info = getCreateInfo(id);
|
||||||
|
info.lastName = name;
|
||||||
|
info.lastIP = ip;
|
||||||
|
info.timesJoined ++;
|
||||||
|
if(!info.names.contains(name, false)) info.names.add(name);
|
||||||
|
if(!info.ips.contains(ip, false)) info.ips.add(ip);
|
||||||
|
}
|
||||||
|
|
||||||
return traces.get(ip);
|
/**Returns trace info by IP.*/
|
||||||
|
public TraceInfo getTrace(String ip){
|
||||||
|
if(!traceInfo.containsKey(ip)) traceInfo.put(ip, new TraceInfo(ip));
|
||||||
|
|
||||||
|
return traceInfo.get(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearTraces(){
|
public void clearTraces(){
|
||||||
traces.clear();
|
traceInfo.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Sets last known name for an IP.*/
|
/**Bans a player by IP; returns whether this player was already banned.
|
||||||
public void setKnownName(String ip, String name){
|
* If there are players who at any point had this IP, they will be UUID banned as well.*/
|
||||||
ipNames.put(ip, name);
|
|
||||||
saveKnown();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**Sets last known UUID for an IP.*/
|
|
||||||
public void setKnownIP(String id, String ip){
|
|
||||||
idIPs.put(id, ip);
|
|
||||||
saveKnown();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**Returns the last known name for an IP. Returns 'unknown' if this IP has an unknown username.*/
|
|
||||||
public String getLastName(String ip){
|
|
||||||
return ipNames.get(ip, "unknown");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**Returns the last known IP for a UUID. Returns 'unknown' if this IP has an unknown IP.*/
|
|
||||||
public String getLastIP(String id){
|
|
||||||
return idIPs.get(id, "unknown");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**Return the last known device ID associated with an IP. Returns 'unknown' if this IP has an unknown device.*/
|
|
||||||
public String getLastID(String ip){
|
|
||||||
for(String id : idIPs.keys()){
|
|
||||||
if(idIPs.get(id).equals(ip)){
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "unknown";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**Returns list of banned IPs.*/
|
|
||||||
public Array<String> getBanned(){
|
|
||||||
return bannedIPs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**Returns list of banned IDs.*/
|
|
||||||
public Array<String> getBannedIDs(){
|
|
||||||
return bannedIDs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**Bans a player by IP; returns whether this player was already banned.*/
|
|
||||||
public boolean banPlayerIP(String ip){
|
public boolean banPlayerIP(String ip){
|
||||||
if(bannedIPs.contains(ip, false))
|
if(bannedIPs.contains(ip, false))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
for(PlayerInfo info : playerInfo.values()){
|
||||||
|
if(info.ips.contains(ip, false)){
|
||||||
|
info.banned = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bannedIPs.add(ip);
|
bannedIPs.add(ip);
|
||||||
saveBans();
|
save();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Bans a player by UUID.*/
|
/**Bans a player by UUID; returns whether this player was already banned.*/
|
||||||
public boolean banPlayerID(String id){
|
public boolean banPlayerID(String id){
|
||||||
if(bannedIDs.contains(id, false))
|
if(playerInfo.containsKey(id) && playerInfo.get(id).banned)
|
||||||
return false;
|
return false;
|
||||||
bannedIDs.add(id);
|
|
||||||
saveBans();
|
getCreateInfo(id).banned = true;
|
||||||
|
|
||||||
|
save();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Unbans a player by IP; returns whether this player was banned in the first place..*/
|
/**Unbans a player by IP; returns whether this player was banned in the first place.
|
||||||
|
* This method also unbans any player that was banned and had this IP.*/
|
||||||
public boolean unbanPlayerIP(String ip){
|
public boolean unbanPlayerIP(String ip){
|
||||||
if(!bannedIPs.contains(ip, false))
|
boolean found = bannedIPs.contains(ip, false);
|
||||||
return false;
|
|
||||||
|
for(PlayerInfo info : playerInfo.values()){
|
||||||
|
if(info.ips.contains(ip, false)){
|
||||||
|
info.banned = false;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bannedIPs.removeValue(ip, false);
|
bannedIPs.removeValue(ip, false);
|
||||||
saveBans();
|
|
||||||
|
|
||||||
return true;
|
if(found) save();
|
||||||
|
|
||||||
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Unbans a player by IP; returns whether this player was banned in the first place..*/
|
/**Unbans a player by ID; returns whether this player was banned in the first place.
|
||||||
public boolean unbanPlayerID(String ip){
|
* This also unbans all IPs the player used.*/
|
||||||
if(!bannedIDs.contains(ip, false))
|
public boolean unbanPlayerID(String id){
|
||||||
|
PlayerInfo info = getCreateInfo(id);
|
||||||
|
|
||||||
|
if(!info.banned)
|
||||||
return false;
|
return false;
|
||||||
bannedIDs.removeValue(ip, false);
|
|
||||||
saveBans();
|
info.banned = false;
|
||||||
|
bannedIPs.removeAll(info.ips, false);
|
||||||
|
save();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Returns list of banned IPs.*/
|
/**Returns list of all players with admin status*/
|
||||||
public Array<String> getAdmins(){
|
public Array<PlayerInfo> getAdmins(){
|
||||||
return admins;
|
Array<PlayerInfo> result = new Array<>();
|
||||||
|
for(PlayerInfo info : playerInfo.values()){
|
||||||
|
if(info.admin){
|
||||||
|
result.add(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**Returns list of all players with admin status*/
|
||||||
|
public Array<PlayerInfo> getBanned(){
|
||||||
|
Array<PlayerInfo> result = new Array<>();
|
||||||
|
for(PlayerInfo info : playerInfo.values()){
|
||||||
|
if(info.banned){
|
||||||
|
result.add(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**Returns all banned IPs. This does not include the IPs of ID-banned players.*/
|
||||||
|
public Array<String> getBannedIPs(){
|
||||||
|
return bannedIPs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Makes a player an admin. Returns whether this player was already an admin.*/
|
/**Makes a player an admin. Returns whether this player was already an admin.*/
|
||||||
public boolean adminPlayer(String ip){
|
public boolean adminPlayer(String id){
|
||||||
if(admins.contains(ip, false))
|
PlayerInfo info = getCreateInfo(id);
|
||||||
|
|
||||||
|
if(info.admin)
|
||||||
return false;
|
return false;
|
||||||
admins.add(ip);
|
|
||||||
saveAdmins();
|
info.admin = true;
|
||||||
|
save();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Makes a player no longer an admin. Returns whether this player was an admin in the first place.*/
|
/**Makes a player no longer an admin. Returns whether this player was an admin in the first place.*/
|
||||||
public boolean unAdminPlayer(String ip){
|
public boolean unAdminPlayer(String id){
|
||||||
if(!admins.contains(ip, false))
|
PlayerInfo info = getCreateInfo(id);
|
||||||
|
|
||||||
|
if(!info.admin)
|
||||||
return false;
|
return false;
|
||||||
admins.removeValue(ip, false);
|
|
||||||
saveAdmins();
|
info.admin = false;
|
||||||
|
save();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isIPBanned(String ip){
|
public boolean isIPBanned(String ip){
|
||||||
return bannedIPs.contains(ip, false);
|
return bannedIPs.contains(ip, false) || (findByIP(ip) != null && findByIP(ip).banned);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isIDBanned(String uuid){
|
public boolean isIDBanned(String uuid){
|
||||||
return bannedIDs.contains(uuid, false);
|
return getCreateInfo(uuid).banned;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAdmin(String ip){
|
public boolean isAdmin(String id){
|
||||||
return admins.contains(ip, false);
|
return getCreateInfo(id).admin;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveKnown(){
|
public PlayerInfo getInfo(String id){
|
||||||
Settings.putString("knownIPs", json.toJson(ipNames));
|
return getCreateInfo(id);
|
||||||
Settings.putString("knownIDs", json.toJson(idIPs));
|
|
||||||
Settings.save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveBans(){
|
public PlayerInfo getInfoOptional(String id){
|
||||||
Settings.putString("bans", json.toJson(bannedIPs));
|
return playerInfo.get(id);
|
||||||
Settings.putString("bannedIDs", json.toJson(bannedIDs));
|
|
||||||
Settings.save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveAdmins(){
|
public PlayerInfo findByIP(String ip){
|
||||||
Settings.putString("admins", json.toJson(admins));
|
for(PlayerInfo info : playerInfo.values()){
|
||||||
|
if(info.ips.contains(ip, false)){
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PlayerInfo getCreateInfo(String id){
|
||||||
|
if(playerInfo.containsKey(id)){
|
||||||
|
return playerInfo.get(id);
|
||||||
|
}else{
|
||||||
|
PlayerInfo info = new PlayerInfo(id);
|
||||||
|
playerInfo.put(id, info);
|
||||||
|
save();
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(){
|
||||||
|
Settings.putString("playerInfo", json.toJson(playerInfo));
|
||||||
|
Settings.putString("bannedIPs", json.toJson(bannedIPs));
|
||||||
Settings.save();
|
Settings.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void load(){
|
private void load(){
|
||||||
bannedIPs = json.fromJson(Array.class, Settings.getString("bans"));
|
playerInfo = json.fromJson(ObjectMap.class, Settings.getString("playerInfo"));
|
||||||
bannedIDs = json.fromJson(Array.class, Settings.getString("bannedIDs"));
|
bannedIPs = json.fromJson(Array.class, Settings.getString("bannedIPs"));
|
||||||
admins = json.fromJson(Array.class, Settings.getString("admins"));
|
}
|
||||||
ipNames = json.fromJson(ObjectMap.class, Settings.getString("knownIPs"));
|
|
||||||
idIPs = json.fromJson(ObjectMap.class, Settings.getString("knownIDs"));
|
public static class PlayerInfo{
|
||||||
|
public String id;
|
||||||
|
public String lastName = "<unknown>", lastIP = "<unknown>";
|
||||||
|
public Array<String> ips = new Array<>();
|
||||||
|
public Array<String> names = new Array<>();
|
||||||
|
public int timesKicked; //TODO not implemented!
|
||||||
|
public int timesJoined;
|
||||||
|
public int totalBlockPlaced;
|
||||||
|
public int totalBlocksBroken;
|
||||||
|
public boolean banned, admin;
|
||||||
|
|
||||||
|
PlayerInfo(String id){
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PlayerInfo(){}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@ public class TraceInfo {
|
|||||||
public boolean modclient;
|
public boolean modclient;
|
||||||
public boolean android;
|
public boolean android;
|
||||||
|
|
||||||
|
public int fastShots;
|
||||||
|
|
||||||
public int totalBlocksBroken;
|
public int totalBlocksBroken;
|
||||||
public int structureBlocksBroken;
|
public int structureBlocksBroken;
|
||||||
public Block lastBlockBroken = Blocks.air;
|
public Block lastBlockBroken = Blocks.air;
|
||||||
|
@ -117,6 +117,10 @@ public class Weapon extends Upgrade{
|
|||||||
Effects.sound(shootsound, x, y);
|
Effects.sound(shootsound, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float getReload(){
|
||||||
|
return reload;
|
||||||
|
}
|
||||||
|
|
||||||
public void shoot(Player p, float x, float y, float angle){
|
public void shoot(Player p, float x, float y, float angle){
|
||||||
shootInternal(p, x, y, angle);
|
shootInternal(p, x, y, angle);
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package io.anuke.mindustry.ui.dialogs;
|
package io.anuke.mindustry.ui.dialogs;
|
||||||
|
|
||||||
import io.anuke.mindustry.entities.Player;
|
import io.anuke.mindustry.entities.Player;
|
||||||
|
import io.anuke.mindustry.net.Administration.PlayerInfo;
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.mindustry.net.NetConnection;
|
import io.anuke.mindustry.net.NetConnection;
|
||||||
import io.anuke.mindustry.net.NetEvents;
|
import io.anuke.mindustry.net.NetEvents;
|
||||||
@ -36,15 +37,15 @@ public class AdminsDialog extends FloatingDialog {
|
|||||||
table.add("$text.server.admins.none");
|
table.add("$text.server.admins.none");
|
||||||
}
|
}
|
||||||
|
|
||||||
for(String ip : netServer.admins.getAdmins()){
|
for(PlayerInfo info : netServer.admins.getAdmins()){
|
||||||
Table res = new Table("button");
|
Table res = new Table("button");
|
||||||
res.margin(14f);
|
res.margin(14f);
|
||||||
|
|
||||||
res.labelWrap("[LIGHT_GRAY]" + netServer.admins.getLastName(ip)).width(w - h - 24f);
|
res.labelWrap("[LIGHT_GRAY]" + info.lastName).width(w - h - 24f);
|
||||||
res.add().growX();
|
res.add().growX();
|
||||||
res.addImageButton("icon-cancel", 14*3, () -> {
|
res.addImageButton("icon-cancel", 14*3, () -> {
|
||||||
ui.showConfirm("$text.confirm", "$text.confirmunadmin", () -> {
|
ui.showConfirm("$text.confirm", "$text.confirmunadmin", () -> {
|
||||||
netServer.admins.unAdminPlayer(ip);
|
netServer.admins.unAdminPlayer(info.id);
|
||||||
for(Player player : playerGroup.all()){
|
for(Player player : playerGroup.all()){
|
||||||
NetConnection c = Net.getConnection(player.clientid);
|
NetConnection c = Net.getConnection(player.clientid);
|
||||||
if(c != null){
|
if(c != null){
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package io.anuke.mindustry.ui.dialogs;
|
package io.anuke.mindustry.ui.dialogs;
|
||||||
|
|
||||||
|
import io.anuke.mindustry.net.Administration.PlayerInfo;
|
||||||
import io.anuke.ucore.scene.ui.ScrollPane;
|
import io.anuke.ucore.scene.ui.ScrollPane;
|
||||||
import io.anuke.ucore.scene.ui.layout.Table;
|
import io.anuke.ucore.scene.ui.layout.Table;
|
||||||
|
|
||||||
@ -33,15 +34,15 @@ public class BansDialog extends FloatingDialog {
|
|||||||
table.add("$text.server.bans.none");
|
table.add("$text.server.bans.none");
|
||||||
}
|
}
|
||||||
|
|
||||||
for(String ip : netServer.admins.getBanned()){
|
for(PlayerInfo info : netServer.admins.getBanned()){
|
||||||
Table res = new Table("button");
|
Table res = new Table("button");
|
||||||
res.margin(14f);
|
res.margin(14f);
|
||||||
|
|
||||||
res.labelWrap("IP: [LIGHT_GRAY]" + ip + "\n[]Name: [LIGHT_GRAY]" + netServer.admins.getLastName(ip)).width(w - h - 24f);
|
res.labelWrap("IP: [LIGHT_GRAY]" + info.lastIP + "\n[]Name: [LIGHT_GRAY]" + info.lastName).width(w - h - 24f);
|
||||||
res.add().growX();
|
res.add().growX();
|
||||||
res.addImageButton("icon-cancel", 14*3, () -> {
|
res.addImageButton("icon-cancel", 14*3, () -> {
|
||||||
ui.showConfirm("$text.confirm", "$text.confirmunban", () -> {
|
ui.showConfirm("$text.confirm", "$text.confirmunban", () -> {
|
||||||
netServer.admins.unbanPlayerIP(ip);
|
netServer.admins.unbanPlayerID(info.id);
|
||||||
setup();
|
setup();
|
||||||
});
|
});
|
||||||
}).size(h).pad(-14f);
|
}).size(h).pad(-14f);
|
||||||
|
@ -10,6 +10,7 @@ import io.anuke.mindustry.game.EventType.GameOverEvent;
|
|||||||
import io.anuke.mindustry.game.GameMode;
|
import io.anuke.mindustry.game.GameMode;
|
||||||
import io.anuke.mindustry.io.SaveIO;
|
import io.anuke.mindustry.io.SaveIO;
|
||||||
import io.anuke.mindustry.io.Version;
|
import io.anuke.mindustry.io.Version;
|
||||||
|
import io.anuke.mindustry.net.Administration.PlayerInfo;
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.mindustry.net.NetConnection;
|
import io.anuke.mindustry.net.NetConnection;
|
||||||
import io.anuke.mindustry.net.NetEvents;
|
import io.anuke.mindustry.net.NetEvents;
|
||||||
@ -126,7 +127,7 @@ public class ServerControl extends Module {
|
|||||||
Log.info("Stopped server.");
|
Log.info("Stopped server.");
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.register("host", "<mapname> <mode>", "Open the server with a specific map.", arg -> {
|
handler.register("host", "<mapname> [mode]", "Open the server with a specific map.", arg -> {
|
||||||
if(state.is(State.playing)){
|
if(state.is(State.playing)){
|
||||||
err("Already hosting. Type 'stop' to stop hosting first.");
|
err("Already hosting. Type 'stop' to stop hosting first.");
|
||||||
return;
|
return;
|
||||||
@ -146,7 +147,7 @@ public class ServerControl extends Module {
|
|||||||
|
|
||||||
GameMode mode = null;
|
GameMode mode = null;
|
||||||
try{
|
try{
|
||||||
mode = GameMode.valueOf(arg[1]);
|
mode = arg.length < 2 ? GameMode.waves : GameMode.valueOf(arg[1]);
|
||||||
}catch (IllegalArgumentException e){
|
}catch (IllegalArgumentException e){
|
||||||
err("No gamemode '{0}' found.", arg[1]);
|
err("No gamemode '{0}' found.", arg[1]);
|
||||||
return;
|
return;
|
||||||
@ -306,26 +307,26 @@ public class ServerControl extends Module {
|
|||||||
});
|
});
|
||||||
|
|
||||||
handler.register("bans", "List all banned IPs and IDs.", arg -> {
|
handler.register("bans", "List all banned IPs and IDs.", arg -> {
|
||||||
Array<String> bans = netServer.admins.getBanned();
|
Array<PlayerInfo> bans = netServer.admins.getBanned();
|
||||||
|
|
||||||
if(bans.size == 0){
|
if(bans.size == 0){
|
||||||
Log.info("No IP-banned players have been found.");
|
|
||||||
}else{
|
|
||||||
Log.info("&lyBanned players [IP]:");
|
|
||||||
for(String string : bans){
|
|
||||||
Log.info(" &ly {0} / Last known name: '{1}'", string, netServer.admins.getLastName(string));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Array<String> idbans = netServer.admins.getBannedIDs();
|
|
||||||
|
|
||||||
if(idbans.size == 0){
|
|
||||||
Log.info("No ID-banned players have been found.");
|
Log.info("No ID-banned players have been found.");
|
||||||
}else{
|
}else{
|
||||||
Log.info("&lmBanned players [ID]:");
|
Log.info("&lyBanned players [ID]:");
|
||||||
for(String string : idbans){
|
for(PlayerInfo info : bans){
|
||||||
Log.info(" &lm '{0}' / Last known name: '{1}' / Last known IP: '{2}'", string,
|
Log.info(" &ly {0} / Last known name: '{1}'", info.id, info.lastName);
|
||||||
netServer.admins.getLastName(netServer.admins.getLastIP(string)), netServer.admins.getLastIP(string));
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Array<String> ipbans = netServer.admins.getBannedIPs();
|
||||||
|
|
||||||
|
if(ipbans.size == 0){
|
||||||
|
Log.info("No IP-banned players have been found.");
|
||||||
|
}else{
|
||||||
|
Log.info("&lmBanned players [IP]:");
|
||||||
|
for(String string : ipbans){
|
||||||
|
PlayerInfo info = netServer.admins.findByIP(string);
|
||||||
|
Log.info(" &lm '{0}' / Last known name: '{1}' / ID: '{2}'", string, info.lastName, info.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -363,12 +364,6 @@ public class ServerControl extends Module {
|
|||||||
handler.register("unbanip", "<ip>", "Completely unban a person by IP.", arg -> {
|
handler.register("unbanip", "<ip>", "Completely unban a person by IP.", arg -> {
|
||||||
if(netServer.admins.unbanPlayerIP(arg[0])) {
|
if(netServer.admins.unbanPlayerIP(arg[0])) {
|
||||||
info("Unbanned player by IP: {0}.", arg[0]);
|
info("Unbanned player by IP: {0}.", arg[0]);
|
||||||
for(String s : netServer.admins.getBannedIDs()){
|
|
||||||
if(netServer.admins.getLastIP(s).equals(arg[0])){
|
|
||||||
netServer.admins.unbanPlayerID(s);
|
|
||||||
Log.info("Also unbanned UUID '{0}' as it corresponds to this IP.", s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else{
|
}else{
|
||||||
err("That IP is not banned!");
|
err("That IP is not banned!");
|
||||||
}
|
}
|
||||||
@ -377,11 +372,6 @@ public class ServerControl extends Module {
|
|||||||
handler.register("unbanid", "<id>", "Completely unban a person by ID.", arg -> {
|
handler.register("unbanid", "<id>", "Completely unban a person by ID.", arg -> {
|
||||||
if(netServer.admins.unbanPlayerID(arg[0])) {
|
if(netServer.admins.unbanPlayerID(arg[0])) {
|
||||||
info("&lmUnbanned player by ID: {0}.", arg[0]);
|
info("&lmUnbanned player by ID: {0}.", arg[0]);
|
||||||
String ip = netServer.admins.getLastIP(arg[0]);
|
|
||||||
if(!ip.equals("unknown")) {
|
|
||||||
netServer.admins.unbanPlayerIP(ip);
|
|
||||||
Log.info("Also unbanned IP '{0}' as it corresponds to this ID.", ip);
|
|
||||||
}
|
|
||||||
}else{
|
}else{
|
||||||
err("That IP is not banned!");
|
err("That IP is not banned!");
|
||||||
}
|
}
|
||||||
@ -403,10 +393,10 @@ public class ServerControl extends Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(target != null){
|
if(target != null){
|
||||||
String ip = Net.getConnection(target.clientid).address;
|
String id = netServer.admins.getTrace(Net.getConnection(target.clientid).address).uuid;
|
||||||
netServer.admins.adminPlayer(ip);
|
netServer.admins.adminPlayer(id);
|
||||||
NetEvents.handleAdminSet(target, true);
|
NetEvents.handleAdminSet(target, true);
|
||||||
info("Admin-ed player by IP: {0} / {1}", ip, arg[0]);
|
info("Admin-ed player by ID: {0} / {1}", id, arg[0]);
|
||||||
}else{
|
}else{
|
||||||
info("Nobody with that name could be found.");
|
info("Nobody with that name could be found.");
|
||||||
}
|
}
|
||||||
@ -428,24 +418,24 @@ public class ServerControl extends Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(target != null){
|
if(target != null){
|
||||||
String ip = Net.getConnection(target.clientid).address;
|
String id = netServer.admins.getTrace(Net.getConnection(target.clientid).address).uuid;
|
||||||
netServer.admins.unAdminPlayer(ip);
|
netServer.admins.unAdminPlayer(id);
|
||||||
NetEvents.handleAdminSet(target, false);
|
NetEvents.handleAdminSet(target, false);
|
||||||
info("Un-admin-ed player by IP: {0} / {1}", ip, arg[0]);
|
info("Un-admin-ed player by ID: {0} / {1}", id, arg[0]);
|
||||||
}else{
|
}else{
|
||||||
info("Nobody with that name could be found.");
|
info("Nobody with that name could be found.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.register("admins", "List all admins.", arg -> {
|
handler.register("admins", "List all admins.", arg -> {
|
||||||
Array<String> admins = netServer.admins.getAdmins();
|
Array<PlayerInfo> admins = netServer.admins.getAdmins();
|
||||||
|
|
||||||
if(admins.size == 0){
|
if(admins.size == 0){
|
||||||
Log.info("No admins have been found.");
|
Log.info("No admins have been found.");
|
||||||
}else{
|
}else{
|
||||||
Log.info("&lyAdmins:");
|
Log.info("&lyAdmins:");
|
||||||
for(String string : admins){
|
for(PlayerInfo info : admins){
|
||||||
Log.info(" &luy {0} / Name: '{1}'", string, netServer.admins.getLastName(string));
|
Log.info(" &luy {0} / ID: '{1}' / IP: '{2}'", info.lastName, info.id, info.lastIP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -509,7 +499,7 @@ public class ServerControl extends Module {
|
|||||||
info("Core destroyed.");
|
info("Core destroyed.");
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.register("info", "Print debug info", arg -> {
|
handler.register("debug", "Print debug info", arg -> {
|
||||||
info(DebugFragment.debugInfo());
|
info(DebugFragment.debugInfo());
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -540,6 +530,23 @@ public class ServerControl extends Module {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
handler.register("info", "<UUID>", "Get global info for a player's UUID.", arg -> {
|
||||||
|
PlayerInfo info = netServer.admins.getInfoOptional(arg[0]);
|
||||||
|
|
||||||
|
if(info != null){
|
||||||
|
Log.info("&lcTrace info for player '{0}':", info.lastName);
|
||||||
|
Log.info(" &lyall names used: {0}", info.names);
|
||||||
|
Log.info(" &lyIP: {0}", info.lastIP);
|
||||||
|
Log.info(" &lyall IPs used: {0}", info.ips);
|
||||||
|
Log.info(" &lytimes joined: {0}", info.timesJoined);
|
||||||
|
Log.info("");
|
||||||
|
Log.info(" &lytotal blocks broken: {0}", info.totalBlocksBroken);
|
||||||
|
Log.info(" &lytotal blocks placed: {0}", info.totalBlockPlaced);
|
||||||
|
}else{
|
||||||
|
info("Nobody with that UUID could be found.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
handler.register("trace", "<username...>", "Trace a player's actions", arg -> {
|
handler.register("trace", "<username...>", "Trace a player's actions", arg -> {
|
||||||
if(!state.is(State.playing)) {
|
if(!state.is(State.playing)) {
|
||||||
err("Open the server first.");
|
err("Open the server first.");
|
||||||
|
Reference in New Issue
Block a user