diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 40a60c9def..d5bd8e3c0c 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -31,6 +31,13 @@ + + + + + + + diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 4065a7c5e1..1960830d9e 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -1454,7 +1454,8 @@ setting.showweather.name = Show Weather Graphics setting.hidedisplays.name = Hide Logic Displays setting.macnotch.name = Adapt interface to display notch setting.macnotch.description = Restart required to apply changes -steam.friendsonly = Friends Only + +steam.friendsonly = Steam Friends Only steam.friendsonly.tooltip = Whether only Steam friends will be able to join your game.\nUnchecking this box will make your game public - anyone can join. setting.maxmagnificationmultiplierpercent.name = Min Camera Distance setting.minmagnificationmultiplierpercent.name = Max Camera Distance @@ -2311,7 +2312,7 @@ ff.arc = :arc: [accent]Arc[] turrets require power to function. Research and pla fungalpass.tutorial1 = Use [accent]units[] to defend buildings and attack the enemy.\nResearch and place a :ground-factory: [accent]ground factory[]. fungalpass.tutorial2 = Select :dagger: [accent]Dagger[] units in the factory.\nProduce 3 units. -frontier.tutorial1 = The :additive-reconstructor: [accent]Additive Reconstructor[]\nupgrades tier 1 units to tier 2\nusing :silicon: silicon and :graphite: graphite.\n\n[accent]Research and reconstruct\na []:dagger:[accent] dagger to a []:mace:[accent] mace. +frontier.tutorial1 = The :additive-reconstructor: [accent]Additive Reconstructor[]\nupgrades tier 1 units to tier 2\nusing :silicon: silicon and :graphite: graphite.\n\n[accent]Reconstruct a []:dagger:[accent] dagger\nto a []:mace:[accent] mace. frontier.tutorial2 = Enemy waves send [accent]infinitely[] until all enemy cores are [unlaunched]destroyed. frontier.tutorial3 = [accent]Attack the enemy base fast to prevent waves from getting too high[]. diff --git a/core/assets/bundles/bundle_be.properties b/core/assets/bundles/bundle_be.properties index 36ff087a7d..a3b56b3fba 100644 --- a/core/assets/bundles/bundle_be.properties +++ b/core/assets/bundles/bundle_be.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Паказаць Анімацыю Надвор'я setting.hidedisplays.name = Схаваць Лагічныя экраны setting.macnotch.name = Адаптуйце інтэрфейс для адлюстравання выемкі setting.macnotch.description = Каб змены ўжыліся патрабуецца перазапуск + steam.friendsonly = Толькі сябры steam.friendsonly.tooltip = Толькі сябры з Steam моргуць зайсці у вашу гульню.\nУбярыце птушачку адсюль і гульня стане публічнай - Кожны зможа зайсці. setting.maxmagnificationmultiplierpercent.name = Мін. дыстанцыя камеры diff --git a/core/assets/bundles/bundle_bg.properties b/core/assets/bundles/bundle_bg.properties index a45395c5c3..cfa1db08a0 100644 --- a/core/assets/bundles/bundle_bg.properties +++ b/core/assets/bundles/bundle_bg.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Показвай графики за климата setting.hidedisplays.name = Скрий логическите екрани setting.macnotch.name = Адаптирайте интерфейса за показване на прорез setting.macnotch.description = За прилагане на промените е необходимо рестартиране + steam.friendsonly = Само приятели steam.friendsonly.tooltip = Дали вашите приятели от Steam ще могат да се включат в играта ви.\nИзключването на тази опция ще направи играта Ви публична и всеки ще може да се присъедини. setting.maxmagnificationmultiplierpercent.name = Min Camera Distance diff --git a/core/assets/bundles/bundle_ca.properties b/core/assets/bundles/bundle_ca.properties index 2bbc2d08c8..a59abf8b9c 100644 --- a/core/assets/bundles/bundle_ca.properties +++ b/core/assets/bundles/bundle_ca.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Mostra l’estat meteorològic setting.hidedisplays.name = Amaga els monitors lògics setting.macnotch.name = Adapta la interfície per a mostrar el notch setting.macnotch.description = Cal reiniciar perquè s’apliquin els canvis + steam.friendsonly = Només amics steam.friendsonly.tooltip = Indica si només els amics de Steam podran unir-se a la vostra partida.\nSi no es selecciona aquesta opció, la vostra partida serà pública i s’hi podrà unir qualsevol jugador. setting.maxmagnificationmultiplierpercent.name = Distància mín. de la càmera diff --git a/core/assets/bundles/bundle_cs.properties b/core/assets/bundles/bundle_cs.properties index fc06c6c07a..15a90dc4f6 100644 --- a/core/assets/bundles/bundle_cs.properties +++ b/core/assets/bundles/bundle_cs.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Zobrazit Grafiku Počasí setting.hidedisplays.name = Skrýt displeje logiky setting.macnotch.name = Přizpůsobte rozhraní zobrazení zářezu setting.macnotch.description = Pro aplikování změn je potřeba restart + steam.friendsonly = Pouze pro přátele steam.friendsonly.tooltip = Určuje, zda bude hra přístupná jen tvým přátelům na Steamu, nebo všem. Odškrtnutí udělá hru veřejnou - připojit se bude moci každý. setting.maxmagnificationmultiplierpercent.name = Minimální vzdálenost kamery diff --git a/core/assets/bundles/bundle_da.properties b/core/assets/bundles/bundle_da.properties index 4ddb3c13ae..aff1cf9c67 100644 --- a/core/assets/bundles/bundle_da.properties +++ b/core/assets/bundles/bundle_da.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Show Weather Graphics setting.hidedisplays.name = Hide Logic Displays setting.macnotch.name = Tilpas grænsefladen til at vise hak setting.macnotch.description = Genstart påkrævet for at anvende ændringer + steam.friendsonly = Friends Only steam.friendsonly.tooltip = Whether only Steam friends will be able to join your game.\nUnchecking this box will make your game public - anyone can join. setting.maxmagnificationmultiplierpercent.name = Min Camera Distance diff --git a/core/assets/bundles/bundle_de.properties b/core/assets/bundles/bundle_de.properties index 5e7b988a5d..9d53e919b3 100644 --- a/core/assets/bundles/bundle_de.properties +++ b/core/assets/bundles/bundle_de.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Wetter anzeigen setting.hidedisplays.name = Logik-Bildschirme verdecken setting.macnotch.name = Benutzeroberfläche an Aussparung anpassen setting.macnotch.description = Neustart erforderlich + steam.friendsonly = Nur Freunde steam.friendsonly.tooltip = Ob nur Steam-Freunde deinem Spiel beitreten können.\nDiese Einstellung zu deaktivieren macht dein Spiel öffentlich - jeder kann beitreten. setting.maxmagnificationmultiplierpercent.name = Min Kameradistanz diff --git a/core/assets/bundles/bundle_es.properties b/core/assets/bundles/bundle_es.properties index df92be85ed..25d00a6366 100644 --- a/core/assets/bundles/bundle_es.properties +++ b/core/assets/bundles/bundle_es.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Efectos visuales climáticos setting.hidedisplays.name = Ocultar pantallas lógicas setting.macnotch.name = Adaptar la interfaz para mostrar la muesca setting.macnotch.description = Es necesario reiniciar para aplicar los cambios + steam.friendsonly = Solo amigos steam.friendsonly.tooltip = Si solo los amigos de Steam podrán unirse a tu partida.\nDesmarcar esta opción hará tu partida pública - cualquiera podrá unirse. setting.maxmagnificationmultiplierpercent.name = Distancia de cámara mínima diff --git a/core/assets/bundles/bundle_et.properties b/core/assets/bundles/bundle_et.properties index 517c84e91a..6b6ab8ff9d 100644 --- a/core/assets/bundles/bundle_et.properties +++ b/core/assets/bundles/bundle_et.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Show Weather Graphics setting.hidedisplays.name = Hide Logic Displays setting.macnotch.name = Kohandage liidest sälku kuvamiseks setting.macnotch.description = Muudatuste rakendamiseks on vaja taaskäivitada + steam.friendsonly = Friends Only steam.friendsonly.tooltip = Whether only Steam friends will be able to join your game.\nUnchecking this box will make your game public - anyone can join. setting.maxmagnificationmultiplierpercent.name = Min Camera Distance diff --git a/core/assets/bundles/bundle_eu.properties b/core/assets/bundles/bundle_eu.properties index a46c305963..828eb2873f 100644 --- a/core/assets/bundles/bundle_eu.properties +++ b/core/assets/bundles/bundle_eu.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Erakutsi eguraldi grafikoak setting.hidedisplays.name = Ezkutatu pantaila logikoak setting.macnotch.name = Egokitu interfazea bistaratzeko setting.macnotch.description = Berrabiarazi behar da aldaketak aplikatzeko + steam.friendsonly = Lagunak bakarrik steam.friendsonly.tooltip = Bai, Steam lagunak bakarrik sartu ahal izango dira zure jokoan.\nKutxa hau desblokeatzeak zure jokoa publiko egingo du. Edonork bat egin dezake. setting.maxmagnificationmultiplierpercent.name = Kameraren distantzia minimoa diff --git a/core/assets/bundles/bundle_fi.properties b/core/assets/bundles/bundle_fi.properties index 1d5c4e5108..a345b47f1a 100644 --- a/core/assets/bundles/bundle_fi.properties +++ b/core/assets/bundles/bundle_fi.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Näytä säägrafiikat setting.hidedisplays.name = Piilota logiikkanäytöt setting.macnotch.name = Mukauta käyttöliittymä näyttämään lovi setting.macnotch.description = Muutosten toteuttaminen vaatii uudelleenkäynnistyksen + steam.friendsonly = Friends Only steam.friendsonly.tooltip = Whether only Steam friends will be able to join your game.\nUnchecking this box will make your game public - anyone can join. setting.maxmagnificationmultiplierpercent.name = Min Camera Distance diff --git a/core/assets/bundles/bundle_fil.properties b/core/assets/bundles/bundle_fil.properties index e90166127f..e3e8fb5b20 100644 --- a/core/assets/bundles/bundle_fil.properties +++ b/core/assets/bundles/bundle_fil.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Show Weather Graphics setting.hidedisplays.name = Hide Logic Displays setting.macnotch.name = Iangkop ang interface upang ipakita ang bingaw setting.macnotch.description = Kinakailangan ang pag-restart upang mailapat ang mga pagbabago + steam.friendsonly = Mga Kaibigan lang steam.friendsonly.tooltip = Whether only Steam friends will be able to join your game.\nUnchecking this box will make your game public - anyone can join. setting.maxmagnificationmultiplierpercent.name = Min Camera Distance diff --git a/core/assets/bundles/bundle_fr.properties b/core/assets/bundles/bundle_fr.properties index 39a048a87b..98f7117221 100644 --- a/core/assets/bundles/bundle_fr.properties +++ b/core/assets/bundles/bundle_fr.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Montrer les Effets météo setting.hidedisplays.name = Cacher les Écrans setting.macnotch.name = Adapter l'interface pour afficher l'encoche setting.macnotch.description = Redémarrage du jeu nécessaire pour appliquer les changements + steam.friendsonly = Amis seulement steam.friendsonly.tooltip = Indique si seuls les amis Steam peuvent rejoindre votre partie.\nSi vous décochez cette case, votre partie deviendra publique et tout le monde pourra la rejoindre. setting.maxmagnificationmultiplierpercent.name = Distance min de la caméra diff --git a/core/assets/bundles/bundle_hu.properties b/core/assets/bundles/bundle_hu.properties index 5c5c421d1b..e2a6e15ec5 100644 --- a/core/assets/bundles/bundle_hu.properties +++ b/core/assets/bundles/bundle_hu.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Időjárás-grafika megjelenítése setting.hidedisplays.name = Logikai kijelzők elrejtése setting.macnotch.name = A felület igazítása a kijelző bevágásához setting.macnotch.description = A változtatások érvénybe lépéséhez újraindítás szükséges + steam.friendsonly = Csak barátok steam.friendsonly.tooltip = Meghatározza, hogy csak a Steam-barátok kapcsolódhassanak-e a játékodhoz.\nHa kikapcsolod, a játékod nyilvános lesz és bárki kapcsolódhat hozzá. setting.maxmagnificationmultiplierpercent.name = Legkisebb kameratávolság diff --git a/core/assets/bundles/bundle_id_ID.properties b/core/assets/bundles/bundle_id_ID.properties index aa7021821c..d611995ffe 100644 --- a/core/assets/bundles/bundle_id_ID.properties +++ b/core/assets/bundles/bundle_id_ID.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Tampilkan Cuaca setting.hidedisplays.name = Sembunyikan Tampilan Logika setting.macnotch.name = Sesuaikan tampilan dengan batas layar setting.macnotch.description = Mulai ulang diperlukan untuk menerapkan perubahan + steam.friendsonly = Hanya Teman steam.friendsonly.tooltip = Mengatur bisa atau tidaknya teman Steam bergabung ke permainanmu.\nMenghapus centang pada kotak ini akan membuat permainan Anda menjadi publik - siapa saja dapat bergabung. setting.maxmagnificationmultiplierpercent.name = Jarak Kamera Minimum diff --git a/core/assets/bundles/bundle_it.properties b/core/assets/bundles/bundle_it.properties index e9abba2576..4a5bc9ba30 100644 --- a/core/assets/bundles/bundle_it.properties +++ b/core/assets/bundles/bundle_it.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Mostra grafica del meteo setting.hidedisplays.name = Nascondi display logici setting.macnotch.name = Adatta l'interfaccia per visualizzare la tacca setting.macnotch.description = Riavvio necessario per applicare le modifiche + steam.friendsonly = Friends Only steam.friendsonly.tooltip = Whether only Steam friends will be able to join your game.\nUnchecking this box will make your game public - anyone can join. setting.maxmagnificationmultiplierpercent.name = Min Camera Distance diff --git a/core/assets/bundles/bundle_ja.properties b/core/assets/bundles/bundle_ja.properties index 0ee9918fac..27b5738c59 100644 --- a/core/assets/bundles/bundle_ja.properties +++ b/core/assets/bundles/bundle_ja.properties @@ -331,10 +331,10 @@ cantconnect = ゲームに参加できませんでした。 ([accent]{0}[]) connecting = [accent]接続中... reconnecting = [accent]再接続中... -connecting.establish = [accent]Establishing connection... -receiving.world = [accent]Receiving world data ({0})... -receiving.assets = [accent]Receiving assets ({0})... -receiving.assets.fail = Error occurred while receiving assets. +connecting.establish = [accent]接続を確立中... +receiving.world = [accent]ワールドデータを受信中 ({0})... +receiving.assets = [accent]アセットを受信中 ({0})... +receiving.assets.fail = アセットの受信中にエラーが発生しました。 server.port = ポート: server.invalidport = 無効なポート番号です! @@ -352,10 +352,10 @@ save.export = エクスポート save.import.invalid = [accent]無効なセーブデータです! save.import.fail = [crimson]セーブデータのインポートに失敗しました: [accent]{0} save.export.fail = [crimson]セーブデータのエクスポートに失敗しました: [accent]{0} -save.export.needsload = [scarlet]⚠ This save contains embedded assets.[]\nLoad into this save before exporting it. -save.assets.missing = Missing Assets -save.assets.missing.list = Asset List... -save.assets.missing.info = [scarlet]⚠ This save contains missing assets![]\n\n[lightgray]This is likely because the save file was not properly exported.\n[lightgray]When sharing saves, only export through the in-game UI. Do not copy save files directly.\n[lightgray]If transferring files is necessary, make sure the [accent]assetCache[] folder is copied as well. +save.export.needsload = [scarlet]⚠ このセーブには埋め込みアセットがあります。[]\nこのセーブに読み込んでからエクスポートしてください。 +save.assets.missing = 欠落アセット +save.assets.missing.list = アセット一覧... +save.assets.missing.info = [scarlet]⚠ このセーブには欠落しているアセットがあります![]\n\n[lightgray]これは、セーブファイルが正しくエクスポートされていないことが原因の可能性があります。\n[lightgray]セーブを共有する際は、必ずゲーム内UIからエクスポートしてください。セーブファイルを直接コピーしないでください。\n[lightgray]ファイルの転送が必要な場合は、[accent]assetCache[] フォルダも必ずコピーしてください。 save.import = インポート save.newslot = セーブ名: save.rename = 名前を変更 @@ -402,7 +402,7 @@ stance.shoot = 指示:発砲 stance.holdfire = 指示:発砲控え stance.pursuetarget = 指示:追撃 stance.patrol = 指示:偵察経路 -stance.holdposition = 指示:位置を保持 +stance.holdposition = 指示:位置を保持 stance.ram = 指示: 突撃\n[lightgray]直線、経路捜索無し stance.boost = ブースト stance.mineauto = 自採掘掘 @@ -542,47 +542,47 @@ patch.fields = {0} フィールド bundle.lines = {0} lines -images = Images -asset.guide = Usage Guide -asset.bundle.exists = A bundle with path '{0}' already exists. -asset.importzip = Import Asset Zip -asset.exportzip = Export Asset Zip -asset.image.importzip = Import Zip -asset.image.exportzip = Export Zip -asset.clearall = Clear All -asset.clearall.confirm = Are you sure that you want to clear [red]all[] assets from this map?\nThis includes images, audio, content, etc. -asset.imports = Import Results -asset.imported = [accent]{0} assets imported. -asset.import.none = No valid asset files found in zip archive. -asset.content.errors = Content Errors -asset.content.add = Add Content +images = 画像 +asset.guide = 使用ガイド +asset.bundle.exists = パスが'{0}'のバンドルはすでに存在します。 +asset.importzip = ZIPアセットをインポート +asset.exportzip = ZIPアセットをエクスポート +asset.image.importzip = ZIPをインポート +asset.image.exportzip = ZIPをエクスポート +asset.clearall = すべてを消去 +asset.clearall.confirm = このマップから[red]すべて[]のアセットを消去してもよろしいですか?\nこれには画像、音声、コンテンツなどが含まれます。 +asset.imports = インポート結果 +asset.imported = [accent]{0} 個のアセットをインポートしました。 +asset.import.none = ZIPアーカイブ内に有効なアセットファイルが見つかりませんでした。 +asset.content.errors = コンテンツエラー +asset.content.add = コンテンツを追加 asset.content.type = Type: -asset.content.exists = [red]Content with that name already exists! -asset.content.badname = [red]Invalid name! Most symbols are not allowed. -asset.content.import.file = Import File -asset.content.import.clipboard = Import From Clipboard -asset.exists = An asset of that type with the same path/name already exists:\n[lightgray]{0} -asset.broken = This asset file could not be located.\nThis can be caused by improper import of data, or an incorrectly exported save. -asset.audio.invalid = Audio file could not be loaded.\nEnsure that it is a valid OGG or MP3 file. -asset.delete.confirm = Are you sure you want to delete this asset? -asset.images = Data Patch Images -asset.image.imports = Import Results -asset.image.imported = [accent]{0} images imported. -asset.image.none = No valid PNG files found in zip archive. -asset.image.error = [red]The following errors were encountered:[] -asset.image.clearall.confirm = Are you certain that you wish to clear all images? -asset.image.info = Image Info -asset.image.toolarge = Image ([lightgray]{0}x{1}[]) is too large. Maximum size is {2}x{3}. -asset.image.exists = An image with that path/name already exists:\n[lightgray]{0} -asset.image.delete.confirm = Are you certain that you wish to delete this image? -asset.image.name = [accent]File Name: [lightgray]{0} -asset.image.region.name = [accent]Region Name: [lightgray]{0} -asset.image.path = [accent]Path: [lightgray]{0} -asset.image.env = [accent]Uses Environment Atlas: [lightgray]{0} -asset.image.size = [accent]Size: [lightgray]{0}x{1} -asset.image.filesize = [accent]File Size: [lightgray]{0} -asset.image.packfailed = [red]⚠ Failed to pack sprite![] -asset.image.packfailed.env = This is likely caused by a lack of space in the environment atlas.\nNote that environment sprites are limited to a 512x512 total area. +asset.content.exists = [red]その名前のコンテンツはすでに存在します! +asset.content.badname = [red]無効な名前です!ほとんどの符号は許可されていません。 +asset.content.import.file = ファイルをインポート +asset.content.import.clipboard = クリップボードからインポート +asset.exists = そのタイプのアセットで、同じパス/名前のものが既に存在します:\n[lightgray]{0} +asset.broken = アセットファイルが見つかりませんでした。\nデータの不適切なインポート、または正しくエクスポートされていない保存ファイルが原因である可能性があります。 +asset.audio.invalid = 音声ファイルを読み込めませんでした。\n有効な OGG または MP3 ファイルであることを確認してください。 +asset.delete.confirm = このアセットを削除してもよろしいですか? +asset.images = データパッチ画像: +asset.image.imports = インポート結果 +asset.image.imported = [accent]{0} 枚の画像をインポートしました。 +asset.image.none = ZIP アーカイブ内に有効な PNG ファイルが見つかりませんでした。 +asset.image.error = [red]以下のエラーが発生しました:[] +asset.image.clearall.confirm = すべての画像を消去してもよろしいですか? +asset.image.info = 画像情報 +asset.image.toolarge = 画像 ([lightgray]{0}x{1}[]) が大きすぎます。最大サイズは {2}x{3}です。 +asset.image.exists = 同じパス/名前の画像が既に存在します:\n[lightgray]{0} +asset.image.delete.confirm = この画像を削除してもよろしいですか? +asset.image.name = [accent]ファイル名: [lightgray]{0} +asset.image.region.name = [accent]リージョン名: [lightgray]{0} +asset.image.path = [accent]パス: [lightgray]{0} +asset.image.env = [accent]環境アトラスの使用: [lightgray]{0} +asset.image.size = [accent]サイズ: [lightgray]{0}x{1} +asset.image.filesize = [accent]ファイルサイズ: [lightgray]{0} +asset.image.packfailed = [red]⚠ スプライトのパックに失敗しました![] +asset.image.packfailed.env = おそらく環境アトラスの空き容量不足が原因です。\n環境スプライトは合計512x512の制限があります。 workshop = ワークショップ waves.title = ウェーブ @@ -1141,7 +1141,7 @@ stat.targetsground = 対地攻撃 stat.crushdamage = クラッシュダメージ stat.legsplashdamage = 踏みつぶしダメージ stat.itemsmoved = 輸送速度 -stat.itemsmoved.info = Throughput is often not linear and tied to FPS/TPS. +stat.itemsmoved.info = スループットは線形とは限らず、FPS/TPSに依存することが多い。 stat.launchtime = 発射の待機時間 stat.shootrange = 範囲 stat.size = 大きさ @@ -1164,8 +1164,8 @@ stat.weapons = 武器 stat.bullet = 弾丸 stat.moduletier = モジュールレベル stat.unittype = ユニット種 -stat.receiverate = Receiving Rate -stat.receiverate.info = Affected by overdrive. Throughput can be increased by placing additional unloaders. +stat.receiverate = 受信速度 +stat.receiverate.info = オーバードライブの影響を受ける。スループットは追加の搬出機を設置することで増加できる。 stat.speedincrease = 速度向上 stat.range = 範囲 stat.drilltier = ドリル @@ -1449,6 +1449,7 @@ setting.showweather.name = 天気のグラフィックを表示 setting.hidedisplays.name = 描画されているロジックディスプレイを非表示 setting.macnotch.name = インターフェイスをノッチ表示に適応させる setting.macnotch.description = 再起動が必要です。 + steam.friendsonly = フレンドのみ steam.friendsonly.tooltip = Steamのフレンドのみがゲームに参加できるようにします。\nこの設定を無効にするとゲームは公開され、誰でも参加できます。 setting.maxmagnificationmultiplierpercent.name = 最低描写距離 @@ -2185,9 +2186,9 @@ block.disperse.name = ディスパーズ block.afflict.name = アフリクト block.lustre.name = ラストル block.scathe.name = スケース -block.scathe.carbide.info = Travels significantly faster.\nModerate damage at any range. -block.scathe.surge-alloy.info = Splits into micro missiles.\nHeavy damage at close distance. -block.scathe.phase-fabric.info = Equipped with a force field.\nLow damage, largest radius. +block.scathe.carbide.info = かなり高速で移動する。\nどの距離でも中程度のダメージ。 +block.scathe.surge-alloy.info = 微小ミサイルに分裂する。\n近距離で高ダメージ。 +block.scathe.phase-fabric.info = フォースフィールドを搭載している。\nダメージは低いが、最大の範囲を持つ。 block.tank-refabricator.name = 戦車再加工工場 block.mech-refabricator.name = メカ再加工工場 block.ship-refabricator.name = 戦艦再加工工場 @@ -2766,7 +2767,7 @@ lst.setprop = ユニットまたは建物のプロパティを設定します。 lst.effect = パーティクルエフェクトを作成します。 lst.sync = ネットワーク経由で変数を同期します。\n最大で1秒間に10回まで呼び出されます。 lst.playsound = サウンドを再生します。\n音量とパンはグローバル値として設定するか、位置に基づいて計算できます。 -lst.playmusic = Plays a music track by name, e.g. [accent]"game1"[].\nIf [accent]interrupt[] is true, the previously playing music will be stopped.\nPlaying with null music and interrupt set to true will stop the current track.\nNote that music from data patches must be prefixed with [accent]dp-[]. +lst.playmusic = 名前で音楽トラックを再生する。例: [accent]"game1"[]。\n[accent]interrupt[] が true の場合、再生中の音楽は停止される。\nnull の音楽を再生し、interrupt を true にすると現在のトラックを停止できる。\ndata patch の音楽を再生する場合は、[accent]dp-[] を接頭辞として付ける必要がある。 lst.makemarker = ワールドに新しいロジックマーカーを作成します。\nこのマーカーを識別するためのIDを指定する必要があります。\nマーカーは現在、1ワールドにつき最大20,000個までです。 lst.setmarker = マーカーのプロパティを設定します。\n使用するIDは"Make Marker"命令で指定したものと同じである必要があります。 lst.localeprint = マップのロケールプロパティの値をテキストバッファに追加します。\nマップエディタでロケールバンドルを設定するには、[accent]Map Info > Locale Bundles[] を確認してください。\nクライアントがモバイルの場合、末尾が ".mobile" のプロパティを優先して出力します。 @@ -2775,8 +2776,8 @@ lst.query = 指定した範囲内のユニット/建物を検索します。結 lglobal.false = 0 lglobal.true = 1 lglobal.null = null -lglobal.@pi = 円周率(π:3.141...)という数学定数 -lglobal.@e = ネイピア数(e:2.718...)という数学定数 +lglobal.@pi = 円周率(π:3.141...)という数学定数 +lglobal.@e = ネイピア数(e:2.718...)という数学定数 lglobal.@degToRad = 度をラジアンに変換するための乗算係数 lglobal.@radToDeg = ラジアンを度に変換するための乗算係数 @@ -2809,13 +2810,13 @@ lglobal.@liquidCount = ゲーム内液体種類数(lookup命令で使用) lglobal.@server = サーバーまたはシングルプレイで実行中なら true、それ以外は false lglobal.@client = クライアント接続中なら true -lglobal.@clientLocale = クライアントの言語設定(例:en_US) +lglobal.@clientLocale = クライアントの言語設定(例: en_US) lglobal.@clientUnit = クライアントが操作しているユニット lglobal.@clientName = クライアントのプレイヤー名 lglobal.@clientTeam = クライアントのチームID lglobal.@clientMobile = クライアントがモバイルなら true、それ以外は false -lenum.type = ユニットや建物の種類を取得します。\n例:任意のルーターに対して、 [accent]@router[] を返します。\n文字列ではありません。 +lenum.type = ユニットや建物の種類を取得します。\n例: 任意のルーターに対して、 [accent]@router[] を返します。\n文字列ではありません。 lenum.shoot = 指定した座標に向かって撃ちます。 lenum.shootp = 任意のユニットや建物を撃ちます。 lenum.config = 建物の設定を取得します。\n例:ソーターに設定されているアイテムなど @@ -2828,7 +2829,7 @@ laccess.controller = ユニットを制御しているものを取得します laccess.dead = ユニットや建物が機能しているかどうか、またはもう有効でないかどうか。 laccess.controlled = ユニットや建物がどのように制御されているのかを取得します。\nプロセッサ制御の場合、 [accent]@ctrlProcessor[] を返します。\nプレイヤー制御の場合、 [accent]@ctrlPlayer[] を返します。\n隊列を組んでいる場合、 [accent]@ctrlFormation[] を返します。\nそれ以外は 0 を返します。 laccess.progress = アクションの進行状況を0〜1で取得します。\n生産、リロード、または建設の進捗状況を返します。 -laccess.speed = ユニットの最高速度を返します。(単位:タイル/秒) +laccess.speed = ユニットの最高速度を返します。(単位: タイル/秒) laccess.size = ユニット/建物の大きさ、または紐の長さ。 laccess.id = ユニット/ブロック/アイテム/液体のID。\nこれは検索操作の逆です。 laccess.displaywidth = 表示ブロックの幅(ピクセル単位) diff --git a/core/assets/bundles/bundle_ko.properties b/core/assets/bundles/bundle_ko.properties index 305b4b5bb3..a86a31a92a 100644 --- a/core/assets/bundles/bundle_ko.properties +++ b/core/assets/bundles/bundle_ko.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = 날씨 그래픽 표시 setting.hidedisplays.name = 로직 디스플레이 숨김 setting.macnotch.name = 노치를 표시하도록 인터페이스 조정 setting.macnotch.description = 적용하려면 재시작이 필요합니다. + steam.friendsonly = 친구 전용 steam.friendsonly.tooltip = 스팀 친구만 게임에 접속할 수 있을지 정합니다.\n체크를 해제하면 누구나 접속할 수 있습니다. setting.maxmagnificationmultiplierpercent.name = 최소 카메라 거리 diff --git a/core/assets/bundles/bundle_lt.properties b/core/assets/bundles/bundle_lt.properties index 5bc265c150..c5d3fcab95 100644 --- a/core/assets/bundles/bundle_lt.properties +++ b/core/assets/bundles/bundle_lt.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Show Weather Graphics setting.hidedisplays.name = Hide Logic Displays setting.macnotch.name = Pritaikykite sąsają, kad būtų rodoma įpjova setting.macnotch.description = Norint pritaikyti pakeitimus, reikia paleisti iš naujo + steam.friendsonly = Friends Only steam.friendsonly.tooltip = Whether only Steam friends will be able to join your game.\nUnchecking this box will make your game public - anyone can join. setting.maxmagnificationmultiplierpercent.name = Min Camera Distance diff --git a/core/assets/bundles/bundle_nl.properties b/core/assets/bundles/bundle_nl.properties index 52e972c726..d096529279 100644 --- a/core/assets/bundles/bundle_nl.properties +++ b/core/assets/bundles/bundle_nl.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Toon Weer Graphics setting.hidedisplays.name = Verberg Logische Displays setting.macnotch.name = Pas de interface aan om de inkeping weer te geven setting.macnotch.description = Herstart vereist om veranderingen door te voeren + steam.friendsonly = Friends Only steam.friendsonly.tooltip = Whether only Steam friends will be able to join your game.\nUnchecking this box will make your game public - anyone can join. setting.maxmagnificationmultiplierpercent.name = Min Camera Distance diff --git a/core/assets/bundles/bundle_nl_BE.properties b/core/assets/bundles/bundle_nl_BE.properties index 7deb8b649c..9fc59c4618 100644 --- a/core/assets/bundles/bundle_nl_BE.properties +++ b/core/assets/bundles/bundle_nl_BE.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Show Weather Graphics setting.hidedisplays.name = Hide Logic Displays setting.macnotch.name = Adapt interface to display notch setting.macnotch.description = Restart required to apply changes + steam.friendsonly = Friends Only steam.friendsonly.tooltip = Whether only Steam friends will be able to join your game.\nUnchecking this box will make your game public - anyone can join. setting.maxmagnificationmultiplierpercent.name = Min Camera Distance diff --git a/core/assets/bundles/bundle_pl.properties b/core/assets/bundles/bundle_pl.properties index f101ae7054..b01ece0452 100644 --- a/core/assets/bundles/bundle_pl.properties +++ b/core/assets/bundles/bundle_pl.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Pokaż pogodę setting.hidedisplays.name = Ukryj wyświetlacze logiczne setting.macnotch.name = Dostosuj interfejs do wyświetlania wycięcia ekranu setting.macnotch.description = Aby zastosować zmiany, wymagane jest ponowne uruchomienie + steam.friendsonly = Tylko Znajomi steam.friendsonly.tooltip = Czy tylko Znajomi ze Steam będą mogli dołączyć do twojej gry?\nOdznaczenie tego okienka ustawi twoją grę na publiczną - każdy może dołączyć. setting.maxmagnificationmultiplierpercent.name = Min. odległość kamery diff --git a/core/assets/bundles/bundle_pt_BR.properties b/core/assets/bundles/bundle_pt_BR.properties index 7a8dc1f087..69d98d8fd3 100644 --- a/core/assets/bundles/bundle_pt_BR.properties +++ b/core/assets/bundles/bundle_pt_BR.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Mostrar Gráficos do Clima setting.hidedisplays.name = Ocultar Displays de Lógicos setting.macnotch.name = Adaptar a interface para exibir o entalhe setting.macnotch.description = Reinicialização necessária para aplicar as alterações + steam.friendsonly = Amigos apenas steam.friendsonly.tooltip = Se apenas amigos do Steam poderão entrar no seu jogo.\nDesmarcar esta caixa tornará seu jogo público - qualquer pessoa pode entrar. setting.maxmagnificationmultiplierpercent.name = Distância Mínima da Câmera diff --git a/core/assets/bundles/bundle_pt_PT.properties b/core/assets/bundles/bundle_pt_PT.properties index 71e8398a61..39b3ffffaa 100644 --- a/core/assets/bundles/bundle_pt_PT.properties +++ b/core/assets/bundles/bundle_pt_PT.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Mostrar Gráficos do Clima setting.hidedisplays.name = Ocultar Ecrãs Lógicos setting.macnotch.name = Adaptar a interface para exibir o entalhe setting.macnotch.description = É necessário reiniciar para aplicar as alterações + steam.friendsonly = Amigos Apenas steam.friendsonly.tooltip = Define se apenas amigos da Steam podem juntar-se ao teu jogo.\nDesativar esta opção fará o teu jogo público - qualquer um pode-se juntar ao teu mapa. setting.maxmagnificationmultiplierpercent.name = Min Camera Distance diff --git a/core/assets/bundles/bundle_ro.properties b/core/assets/bundles/bundle_ro.properties index 439df70f6d..82195b8966 100644 --- a/core/assets/bundles/bundle_ro.properties +++ b/core/assets/bundles/bundle_ro.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Vezi Vremea setting.hidedisplays.name = Hide Logic Displays setting.macnotch.name = Adaptați interfața pentru a afișa notch-ul setting.macnotch.description = Repornire necesară pt a aplica schimbările. + steam.friendsonly = Friends Only steam.friendsonly.tooltip = Whether only Steam friends will be able to join your game.\nUnchecking this box will make your game public - anyone can join. setting.maxmagnificationmultiplierpercent.name = Min Camera Distance diff --git a/core/assets/bundles/bundle_ru.properties b/core/assets/bundles/bundle_ru.properties index 6084e84cc1..19abbcbe97 100644 --- a/core/assets/bundles/bundle_ru.properties +++ b/core/assets/bundles/bundle_ru.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Отображать погоду setting.hidedisplays.name = Скрыть логические дисплеи setting.macnotch.name = Адаптировать интерфейс к вырезу на экране setting.macnotch.description = Для вступления изменений в силу требуется перезагрузка игры + steam.friendsonly = Только друзья steam.friendsonly.tooltip = Только ли друзья из Steam могут присоединяться к вашей игре.\nУбрав эту галочку, вы сделаете вашу игру публичной - присоединиться сможет любой желающий. setting.maxmagnificationmultiplierpercent.name = Минимальная дистанция камеры diff --git a/core/assets/bundles/bundle_sr.properties b/core/assets/bundles/bundle_sr.properties index 454ced6d1f..e159bc5436 100644 --- a/core/assets/bundles/bundle_sr.properties +++ b/core/assets/bundles/bundle_sr.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Prikazuj Grafiku Vremena setting.hidedisplays.name = Sakrij Logičke Displeje setting.macnotch.name = Prilagodi interfejs da prikaže zarez setting.macnotch.description = Restartovanje je zahtevano da bi se učitale promene + steam.friendsonly = Friends Only steam.friendsonly.tooltip = Whether only Steam friends will be able to join your game.\nUnchecking this box will make your game public - anyone can join. setting.maxmagnificationmultiplierpercent.name = Min Camera Distance diff --git a/core/assets/bundles/bundle_sv.properties b/core/assets/bundles/bundle_sv.properties index 4e82433e6e..45df1031e4 100644 --- a/core/assets/bundles/bundle_sv.properties +++ b/core/assets/bundles/bundle_sv.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Show Weather Graphics setting.hidedisplays.name = Hide Logic Displays setting.macnotch.name = Anpassa gränssnittet för att visa skåra setting.macnotch.description = Omstart krävs för att tillämpa ändringar + steam.friendsonly = Friends Only steam.friendsonly.tooltip = Whether only Steam friends will be able to join your game.\nUnchecking this box will make your game public - anyone can join. setting.maxmagnificationmultiplierpercent.name = Min Camera Distance diff --git a/core/assets/bundles/bundle_th.properties b/core/assets/bundles/bundle_th.properties index e64197ae4a..e26d856916 100644 --- a/core/assets/bundles/bundle_th.properties +++ b/core/assets/bundles/bundle_th.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = แสดงกราฟิกสภาพอาก setting.hidedisplays.name = ซ่อนหน้าจอลอจิก setting.macnotch.name = ปรับอินเตอร์เฟซให้เข้ากับติ่งหน้าจอ setting.macnotch.description = อาจจะต้องรีสตาร์ทเพื่อใช้งานการเปลี่ยนแปลง + steam.friendsonly = เพื่อนเท่านั้น steam.friendsonly.tooltip = ว่าจะให้แค่เพื่อนเท่านั้นหรือไม่ที่จะสามารถเข้าร่วมเกมของคุณได้\nหากคุณติ๊กช่องนี้ออกนั้นจะทำให้เกมของคุณเปิดเป็นสาธารณะ - ใครๆก็จะสามารถเข้าร่วมเกมของคุณได้ setting.maxmagnificationmultiplierpercent.name = ระยะห่างกล้องต่ำสุด diff --git a/core/assets/bundles/bundle_tk.properties b/core/assets/bundles/bundle_tk.properties index 79a9c6282d..d765dec1f5 100644 --- a/core/assets/bundles/bundle_tk.properties +++ b/core/assets/bundles/bundle_tk.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Show Weather Graphics setting.hidedisplays.name = Hide Logic Displays setting.macnotch.name = Kesgitlemek üçin interfeýsi uýgunlaşdyryň setting.macnotch.description = Üýtgeşmeleri ulanmak üçin täzeden başlaň + steam.friendsonly = Friends Only steam.friendsonly.tooltip = Whether only Steam friends will be able to join your game.\nUnchecking this box will make your game public - anyone can join. setting.maxmagnificationmultiplierpercent.name = Min Camera Distance diff --git a/core/assets/bundles/bundle_tr.properties b/core/assets/bundles/bundle_tr.properties index 3627a94246..47368844a0 100644 --- a/core/assets/bundles/bundle_tr.properties +++ b/core/assets/bundles/bundle_tr.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Hava Durumu Grafiklerini Göster setting.hidedisplays.name = İşlemci İpuçlarını Gizle setting.macnotch.name = Arayüzü çentik gösterecek şekilde uyarlayın setting.macnotch.description = Değişikleri uygulamak için yeniden başlatma gerekli + steam.friendsonly = Arkadaşlara özel steam.friendsonly.tooltip = Sadece Steam arkadaşlarının katılıp katılabilemeyeceğini belirler.\nBu kutudan tiki kaldırmak oyununuzu herkese açık yapacaktır. setting.maxmagnificationmultiplierpercent.name = Min Camera Distance diff --git a/core/assets/bundles/bundle_uk_UA.properties b/core/assets/bundles/bundle_uk_UA.properties index 28b0103676..5fbf68a938 100644 --- a/core/assets/bundles/bundle_uk_UA.properties +++ b/core/assets/bundles/bundle_uk_UA.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Показувати погоду setting.hidedisplays.name = Приховувати логічні дисплеї setting.macnotch.name = Адаптувати інтерфейс для показу виїмки setting.macnotch.description = Потрібен перезапуск для застосування змін + steam.friendsonly = Лише друзі steam.friendsonly.tooltip = Чи лише друзі Steam зможуть приєднатися до вашої гри. Якщо зняти цей прапорець, ваша гра стане загальнодоступною – будь-хто зможе приєднатися. setting.maxmagnificationmultiplierpercent.name = Мінімальна відстань камери diff --git a/core/assets/bundles/bundle_vi.properties b/core/assets/bundles/bundle_vi.properties index 9047615664..53280ea418 100644 --- a/core/assets/bundles/bundle_vi.properties +++ b/core/assets/bundles/bundle_vi.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = Hiện đồ họa thời tiết setting.hidedisplays.name = Ẩn hiển thị logic setting.macnotch.name = Giao diện phù hợp với hiển thị tai thỏ setting.macnotch.description = Cần khởi động lại để áp dụng các thay đổi + steam.friendsonly = Chỉ bạn bè steam.friendsonly.tooltip = Liệu chỉ bạn bè trên Steam mới có thể tham gia trò chơi của bạn hay không.\nBỏ chọn ô này sẽ làm trò chơi của bạn công khai - mọi người có thể tham gia. setting.maxmagnificationmultiplierpercent.name = Tầm xa tối thiểu của máy quay diff --git a/core/assets/bundles/bundle_zh_CN.properties b/core/assets/bundles/bundle_zh_CN.properties index 30d7eabd6d..f00d032363 100644 --- a/core/assets/bundles/bundle_zh_CN.properties +++ b/core/assets/bundles/bundle_zh_CN.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = 显示天气效果 setting.hidedisplays.name = 不显示逻辑绘图 setting.macnotch.name = 适应刘海显示 setting.macnotch.description = 需要重启才能应用更改 + steam.friendsonly = 仅限好友 steam.friendsonly.tooltip = 是否只有 Steam 好友才能加入你的游戏。\n取消选中该选项将使你的游戏公开 - 任何人都可以加入。 setting.maxmagnificationmultiplierpercent.name = 最小视距 diff --git a/core/assets/bundles/bundle_zh_TW.properties b/core/assets/bundles/bundle_zh_TW.properties index 333ec82640..ab17856cc1 100644 --- a/core/assets/bundles/bundle_zh_TW.properties +++ b/core/assets/bundles/bundle_zh_TW.properties @@ -1449,6 +1449,7 @@ setting.showweather.name = 顯示天氣動畫 setting.hidedisplays.name = 隱藏邏輯顯示 setting.macnotch.name = 使界面適應顯示槽口 setting.macnotch.description = 需要重新啟動遊戲以更改大小 + steam.friendsonly = 僅限好友 steam.friendsonly.tooltip = 是否只有 Steam 好友可以加入您的遊戲。\n取消勾選後,遊戲為公開的,任何人都可以加入。 setting.maxmagnificationmultiplierpercent.name = Min Camera Distance diff --git a/core/assets/maps/serpulo/hidden/13.msav b/core/assets/maps/serpulo/hidden/13.msav index b48ee33243..6e97fea22d 100644 Binary files a/core/assets/maps/serpulo/hidden/13.msav and b/core/assets/maps/serpulo/hidden/13.msav differ diff --git a/core/assets/maps/serpulo/hidden/263.msav b/core/assets/maps/serpulo/hidden/263.msav index d5e967c7a3..9302fd3c7c 100644 Binary files a/core/assets/maps/serpulo/hidden/263.msav and b/core/assets/maps/serpulo/hidden/263.msav differ diff --git a/core/src/mindustry/ai/RtsAI.java b/core/src/mindustry/ai/RtsAI.java index e006e4303d..bf34924ae0 100644 --- a/core/src/mindustry/ai/RtsAI.java +++ b/core/src/mindustry/ai/RtsAI.java @@ -11,6 +11,7 @@ import mindustry.ai.types.*; import mindustry.content.*; import mindustry.core.*; import mindustry.entities.*; +import mindustry.entities.comp.*; import mindustry.game.EventType.*; import mindustry.game.Teams.*; import mindustry.gen.*; @@ -160,7 +161,7 @@ public class RtsAI{ ay /= units.size; if(debug){ - Vars.ui.showLabel("Squad: " + units.size, -1, 2f, ax, ay); + Vars.ui.showLabel("Squad: " + units.size, -1, 2f, ax, ay, WorldLabel.flagBackground | WorldLabel.flagAutoscale); } Building defend = null; @@ -192,7 +193,7 @@ public class RtsAI{ defend = best; if(debug){ - Vars.ui.showLabel("Defend, dst = " + (int)(best.dst(ax, ay)), -1, 8f, best.x, best.y); + Vars.ui.showLabel("Defend, dst = " + (int)(best.dst(ax, ay)), -1, 8f, best.x, best.y, WorldLabel.flagBackground | WorldLabel.flagAutoscale); } if(best instanceof CoreBuild){ diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 014e18dd9a..4c4226ddb6 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -1503,7 +1503,7 @@ public class Blocks{ }}; smallHeatRedirector = new HeatConductor("small-heat-redirector"){{ - requirements(Category.crafting, with(Items.surgeAlloy, 8, Items.graphite, 8)); + requirements(Category.crafting, with(Items.surgeAlloy, 3, Items.graphite, 8)); researchCostMultiplier = 2f; researchCostMultipliers.put(Items.graphite, 7f); diff --git a/core/src/mindustry/content/Planets.java b/core/src/mindustry/content/Planets.java index 36a4021031..d362d3d719 100644 --- a/core/src/mindustry/content/Planets.java +++ b/core/src/mindustry/content/Planets.java @@ -142,6 +142,7 @@ public class Planets{ r.waveTeam = Team.crux; r.placeRangeCheck = false; r.hideSpawns = true; + r.derelictRepair = true; r.coreDestroyClear = true; }; showRtsAIRule = true; diff --git a/core/src/mindustry/content/SerpuloTechTree.java b/core/src/mindustry/content/SerpuloTechTree.java index af9b296ebe..fc4b1bdfed 100644 --- a/core/src/mindustry/content/SerpuloTechTree.java +++ b/core/src/mindustry/content/SerpuloTechTree.java @@ -41,8 +41,8 @@ public class SerpuloTechTree{ node(itemBridge, () -> { node(titaniumConveyor, Seq.with(new SectorComplete(crateredBattleground)), () -> { - node(phaseConveyor, () -> { - node(massDriver, Seq.with(new SectorComplete(tarFields)), () -> { + node(massDriver, Seq.with(new SectorComplete(tarFields)), () -> { + node(phaseConveyor, () -> { }); }); @@ -53,8 +53,8 @@ public class SerpuloTechTree{ }); }); - node(armoredConveyor, () -> { - node(plastaniumConveyor, () -> { + node(plastaniumConveyor, () -> { + node(armoredConveyor, () -> { }); }); diff --git a/core/src/mindustry/core/NetClient.java b/core/src/mindustry/core/NetClient.java index ba27671c81..7a72b558d7 100644 --- a/core/src/mindustry/core/NetClient.java +++ b/core/src/mindustry/core/NetClient.java @@ -373,7 +373,7 @@ public class NetClient implements ApplicationListener{ @Remote(called = Loc.client, variants = Variant.one) public static void connect(String ip, int port){ - if(!steam && ip.startsWith("steam:")) return; + if(!steam && (ip.startsWith("steam:") || ip.startsWith("steamserver:"))) return; netClient.disconnectQuietly(); logic.reset(); diff --git a/core/src/mindustry/core/UI.java b/core/src/mindustry/core/UI.java index 202d8315d9..6623f147de 100644 --- a/core/src/mindustry/core/UI.java +++ b/core/src/mindustry/core/UI.java @@ -89,7 +89,7 @@ public class UI implements ApplicationListener, Loadable{ /** Maps popups to ids so that they can be removed or updated by id. */ private final ObjectMap popups = new ObjectMap<>(); /** Maps labels to ids so that they can be removed or updated by id. */ - private final IntMap labels = new IntMap<>(); + private final IntMap labels = new IntMap<>(); public UI(){ Fonts.loadFonts(); @@ -437,34 +437,20 @@ public class UI implements ApplicationListener, Loadable{ } /** Shows a label in the world. This label is behind everything. Does not fade. */ - public void showLabel(@Nullable String info, int id, float duration, float worldx, float worldy){ + public void showLabel(@Nullable String info, int id, float duration, float worldx, float worldy, int flags){ if(info == null){ // null info allows deletion of old labels provided they have ids - var table = labels.remove(id); - if(table != null) table.remove(); + var label = labels.remove(id); + if(label != null) label.remove(); return; } - var table = new Table(Styles.black3).margin(4); - if(id != -1){ - Table old = labels.put(id, table); - if(old != null) old.remove(); - } - table.touchable = Touchable.disabled; - table.update(() -> { - if(state.isMenu()){ - table.remove(); - if(id != -1) labels.remove(id); - } - Vec2 v = Core.camera.project(worldx, worldy); - table.setPosition(v.x, v.y, Align.center); - }); - table.actions(Actions.delay(duration), Actions.remove(), Actions.run(() -> { if(id != -1) labels.remove(id); })); - table.add(info).style(Styles.outlineLabel); - table.pack(); - table.act(0f); - //make sure it's at the back - Core.scene.root.addChildAt(0, table); - table.getChildren().first().act(0f); + var label = labels.get(id, WorldLabel::create); // todo: pool? + label.x = worldx; + label.y = worldy; + label.text = info; + label.flags = (byte)flags; // flag | flag2 at call site turns it into an int so the flags param here has to be int or casting has to be done at every call site + label.duration = duration; + label.add(); } public void showInfo(String info){ diff --git a/core/src/mindustry/editor/data/MapImagesView.java b/core/src/mindustry/editor/data/MapImagesView.java index 4bedecb0eb..eb70b01c49 100644 --- a/core/src/mindustry/editor/data/MapImagesView.java +++ b/core/src/mindustry/editor/data/MapImagesView.java @@ -45,7 +45,7 @@ public class MapImagesView implements AssetView{ if(width > DataPatcher.maxImageSize || height > DataPatcher.maxImageSize){ ui.showErrorMessage(Core.bundle.format("asset.image.toolarge", width, height, DataPatcher.maxImageSize, DataPatcher.maxImageSize)); - return; + continue; } String name = result.nameWithoutExtension(); @@ -53,7 +53,7 @@ public class MapImagesView implements AssetView{ var other = images.find(p -> p.path.equalsIgnoreCase(path) || p.name.equalsIgnoreCase(name)); if(other != null){ ui.showErrorMessage(Core.bundle.format("asset.image.exists", other.name + " (" + other.path + ")")); - return; + continue; } byte[] hash = assetCache.add(bytes); diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index 2d231b9f4e..150b32ec6e 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -1283,8 +1283,15 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, } public void payloadDraw(){ - if(block.isAir()) return; - draw(); + float z = Draw.z(); + if(block.drawCached){ + Draw.z(block.buildingCacheLayer.layer); + drawCached(); + } + if(block.drawDynamic){ + Draw.z(z); + draw(); + } } public void drawTeamTop(){ @@ -1793,6 +1800,11 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, if(power != null && updatePower){ var oldGraph = power.graph; + for(var other : proximity){ + if(other != null && other.team != team && other.power != null && other.power.graph == oldGraph){ + new PowerGraph().reflow(other); + } + } for(int i = 0; i < power.links.size; i++){ var other = world.build(power.links.items[i]); diff --git a/core/src/mindustry/entities/comp/WorldLabelComp.java b/core/src/mindustry/entities/comp/WorldLabelComp.java index e58325ffe8..2942f2757d 100644 --- a/core/src/mindustry/entities/comp/WorldLabelComp.java +++ b/core/src/mindustry/entities/comp/WorldLabelComp.java @@ -32,12 +32,22 @@ public abstract class WorldLabelComp implements Posc, Drawc, Syncc{ public byte flags = flagBackground | flagOutline; /** If not null, this label gets set to the parent position with x, y used as offsets. */ public @Nullable Posc parent; + /** Duration in seconds. Ignored if zero or negative. */ + public transient float duration; @Replace public float clipSize(){ return text.length() * 10f * fontSize; } + @Override + public void update(){ + if(duration > 0){ + duration -= Time.delta / 60f; + if(duration <= 0) hide(); + } + } + @Override public void draw(){ float x = this.x, y = this.y; diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index 3c95e5adc5..9199d94aea 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -1424,7 +1424,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ overlappingPlayer= player; } - plan.animScale = Mathf.lerpDelta(plan.animScale, 1f, 0.2f * Time.delta); + plan.animScale = Mathf.lerpDelta(plan.animScale, 1f, 0.2f); plan.block.drawOtherPlayerPlan(plan, player.planEachable, overlappingPlan == plan ? 0.7f : 0.25f); }); }); diff --git a/core/src/mindustry/io/TypeIO.java b/core/src/mindustry/io/TypeIO.java index 001791450a..c96c4cf0f4 100644 --- a/core/src/mindustry/io/TypeIO.java +++ b/core/src/mindustry/io/TypeIO.java @@ -630,12 +630,7 @@ public class TypeIO{ int x = read.us(); int y = read.us(); Block block = Vars.content.block(read.us()); - if(block == null){ - // Skip unrecognised block IDs (e.g. from a modded client) - read.b(); // consume rotation byte - readClientPlanConfig(read); // consume config - continue; - } + if(block == null) throw new ArcRuntimeException("Invalid block ID in block plans! Client is likely using an incorrectly configured mod."); int rotation = (block.rotate ? read.b() : 0); Object config = readClientPlanConfig(read); BuildPlan plan = new BuildPlan(x, y, rotation, block, config); diff --git a/core/src/mindustry/logic/LExecutor.java b/core/src/mindustry/logic/LExecutor.java index f66c075d52..dfc7243b2a 100644 --- a/core/src/mindustry/logic/LExecutor.java +++ b/core/src/mindustry/logic/LExecutor.java @@ -1558,7 +1558,7 @@ public class LExecutor{ public void run(LExecutor exec){ if(net.client()) return; - Tile tile = world.tile(x.numi(), y.numi()); + Tile tile = world.tile(Mathf.round(x.numf()), Mathf.round(y.numf())); if(tile != null && block.obj() instanceof Block b){ switch(layer){ case ore -> { diff --git a/core/src/mindustry/logic/LStatements.java b/core/src/mindustry/logic/LStatements.java index 71012e3f4b..5bc81a58e6 100644 --- a/core/src/mindustry/logic/LStatements.java +++ b/core/src/mindustry/logic/LStatements.java @@ -1574,7 +1574,7 @@ public class LStatements{ }).size(80f, 40f).pad(4f).color(table.color); if(statusNames == null){ - statusNames = content.statusEffects().select(s -> !s.isHidden()).map(s -> s.name).toArray(String.class); + statusNames = content.statusEffects().map(s -> s.name).toArray(String.class); } table.button(b -> { diff --git a/core/src/mindustry/net/SteamAdmin.java b/core/src/mindustry/net/SteamAdmin.java index e867dde24a..4c67853d01 100644 --- a/core/src/mindustry/net/SteamAdmin.java +++ b/core/src/mindustry/net/SteamAdmin.java @@ -63,7 +63,8 @@ public class SteamAdmin{ } public static boolean isBanned(String id){ - if(!id.startsWith("steam:")) return false; + //bans are ignored with private lobbies + if(!id.startsWith("steam:") || !Core.settings.getBool("steampublichost2")) return false; return data.bans.contains(id.substring("steam:".length())); } diff --git a/core/src/mindustry/ui/Menus.java b/core/src/mindustry/ui/Menus.java index 3f01a18f54..4881b63be6 100644 --- a/core/src/mindustry/ui/Menus.java +++ b/core/src/mindustry/ui/Menus.java @@ -141,9 +141,19 @@ public class Menus{ infoPopup(message, duration, align, top, left, bottom, right); } + @Remote(variants = Variant.both, unreliable = true) + public static void label(@Nullable String message, int id, float duration, float worldx, float worldy, int flags){ + ui.showLabel(message, id, duration, worldx, worldy, flags); + } + + @Remote(variants = Variant.both) + public static void labelReliable(@Nullable String message, int id, float duration, float worldx, float worldy, int flags){ + label(message, id, duration, worldx, worldy, flags); + } + @Remote(variants = Variant.both, unreliable = true) public static void label(@Nullable String message, int id, float duration, float worldx, float worldy){ - ui.showLabel(message, id, duration, worldx, worldy); + label(message, id, duration, worldx, worldy, WorldLabel.flagBackground | WorldLabel.flagAutoscale | WorldLabel.flagOutline); } @Remote(variants = Variant.both) diff --git a/core/src/mindustry/ui/dialogs/HostDialog.java b/core/src/mindustry/ui/dialogs/HostDialog.java index 050b6141cf..f6b7099a2b 100644 --- a/core/src/mindustry/ui/dialogs/HostDialog.java +++ b/core/src/mindustry/ui/dialogs/HostDialog.java @@ -43,7 +43,7 @@ public class HostDialog extends BaseDialog{ cont.add().width(65f); - cont.check("@steam.friendsonly", !Core.settings.getBool("steampublichost"), val -> Core.settings.put("steampublichost", !val)).colspan(2).left() + cont.check("@steam.friendsonly", !Core.settings.getBool("steampublichost2"), val -> Core.settings.put("steampublichost2", !val)).colspan(2).left() .with(c -> ui.addDescTooltip(c, "@steam.friendsonly.tooltip")).padBottom(15f).row(); } @@ -98,9 +98,9 @@ public class HostDialog extends BaseDialog{ player.admin = true; Events.fire(new HostEvent()); - if(steam && Core.settings.getBool("steampublichost")){ + if(steam && Core.settings.getBool("steampublichost2")){ if(Version.modifier.contains("beta") || Version.modifier.contains("alpha")){ - Core.settings.put("steampublichost", false); + Core.settings.put("steampublichost2", false); platform.updateLobby(); Core.settings.getBoolOnce("betapublic", () -> ui.showInfo("@public.beta")); } diff --git a/core/src/mindustry/ui/dialogs/PausedDialog.java b/core/src/mindustry/ui/dialogs/PausedDialog.java index 8136ebbe78..b555d0544e 100644 --- a/core/src/mindustry/ui/dialogs/PausedDialog.java +++ b/core/src/mindustry/ui/dialogs/PausedDialog.java @@ -58,6 +58,14 @@ public class PausedDialog extends BaseDialog{ }); if(!mobile){ + if(steam){ + cont.check("@steam.friendsonly", !Core.settings.getBool("steampublichost2"), val -> { + Core.settings.put("steampublichost2", !val); + platform.updateLobby(); + }).colspan(2).left().with(c -> ui.addDescTooltip(c, "@steam.friendsonly.tooltip")).width(440f) + .visible(() -> net.server()).center().colspan(2).fillX().padBottom(10f).row(); + } + float dw = 220f; cont.defaults().width(dw).height(55).pad(5f); diff --git a/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java b/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java index 901cea8752..eaa12d70de 100644 --- a/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java +++ b/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java @@ -419,12 +419,6 @@ public class SettingsMenuDialog extends BaseDialog{ platform.updateLobby(); return i + ""; }); - - if(!Version.modifier.contains("beta")){ - game.checkPref("steampublichost", false, i -> { - platform.updateLobby(); - }); - } } game.checkPref("console", false); diff --git a/core/src/mindustry/ui/fragments/HudFragment.java b/core/src/mindustry/ui/fragments/HudFragment.java index 84a837d48c..eb149b3587 100644 --- a/core/src/mindustry/ui/fragments/HudFragment.java +++ b/core/src/mindustry/ui/fragments/HudFragment.java @@ -56,6 +56,7 @@ public class HudFragment{ private Seq blocksOut = new Seq<>(); private Table hudLabel; + private float coreAttackTime; private static ObjectSet favoriteBlocks = new ObjectSet<>(); private static String lastFavorited = null; @@ -592,9 +593,11 @@ public class HudFragment{ c.top().collapser(coreItems, () -> Core.settings.getBool("coreitems") && !mobile && shown).fillX().row(); float notifDuration = 240f; - float[] coreAttackTime = {0}; - Events.run(Trigger.teamCoreDamage, () -> coreAttackTime[0] = notifDuration); + Events.run(Trigger.teamCoreDamage, () -> coreAttackTime = notifDuration); + Events.on(ResetEvent.class, e -> { + coreAttackTime = 0f; + }); //'core is under attack' table c.collapser(top -> top.background(Styles.black6).add("@coreattack").pad(8) @@ -608,13 +611,13 @@ public class HudFragment{ }) .update(label -> label.color.set(Color.orange).lerp(Color.scarlet, Mathf.absin(Time.time, 2f, 1f))), true, () -> { - if(!shown || state.isPaused()) return false; if(state.isMenu() || !player.team().data().hasCore()){ - coreAttackTime[0] = 0f; + coreAttackTime = 0f; return false; } + if(!shown || state.isPaused()) return false; - return (coreAttackTime[0] -= Time.delta) > 0; + return (coreAttackTime -= Time.delta) > 0; }) .touchable(Touchable.disabled) .fillX().row(); diff --git a/core/src/mindustry/ui/fragments/PlayerListFragment.java b/core/src/mindustry/ui/fragments/PlayerListFragment.java index 58d82ae32d..30379f944e 100644 --- a/core/src/mindustry/ui/fragments/PlayerListFragment.java +++ b/core/src/mindustry/ui/fragments/PlayerListFragment.java @@ -190,8 +190,6 @@ public class PlayerListFragment{ var teamSelect = new BaseDialog(Core.bundle.get("player.team") + ": " + user.name); teamSelect.setFillParent(false); - var group = new ButtonGroup<>(); - int i = 0; for(Team team : Team.baseTeams){ @@ -203,7 +201,7 @@ public class PlayerListFragment{ Call.adminRequest(user, AdminAction.switchTeam, team); teamSelect.hide(); }); - teamSelect.cont.add(b).size(50f).checked(a -> user.team() == team).group(group); + teamSelect.cont.add(b).size(50f).checked(a -> user.team() == team); if(i++ % 3 == 2) teamSelect.cont.row(); } diff --git a/core/src/mindustry/world/blocks/defense/BaseShield.java b/core/src/mindustry/world/blocks/defense/BaseShield.java index 8ceaf66026..e279f7b7e2 100644 --- a/core/src/mindustry/world/blocks/defense/BaseShield.java +++ b/core/src/mindustry/world/blocks/defense/BaseShield.java @@ -62,6 +62,7 @@ public class BaseShield extends Block{ hasPower = true; update = solid = true; rebuildable = false; + canPickup = true; } @Override diff --git a/core/src/mindustry/world/blocks/logic/LogicBlock.java b/core/src/mindustry/world/blocks/logic/LogicBlock.java index 31c86b1bd2..7872afbca5 100644 --- a/core/src/mindustry/world/blocks/logic/LogicBlock.java +++ b/core/src/mindustry/world/blocks/logic/LogicBlock.java @@ -523,11 +523,6 @@ public class LogicBlock extends Block{ l.trySet(executor, null); //always clear old variable, it may get a new name if(valid){ - //this prevents conflicts - l.name = ""; - //finds a new matching name after toggling - l.name = findLinkName(cur.block); - //remove redundant links links.removeAll(o -> { boolean remove = world.build(o.x, o.y) == cur && o != l; diff --git a/core/src/mindustry/world/blocks/logic/TileableLogicDisplay.java b/core/src/mindustry/world/blocks/logic/TileableLogicDisplay.java index f17afd3168..44d87eb932 100644 --- a/core/src/mindustry/world/blocks/logic/TileableLogicDisplay.java +++ b/core/src/mindustry/world/blocks/logic/TileableLogicDisplay.java @@ -32,6 +32,7 @@ public class TileableLogicDisplay extends LogicDisplay{ super(name); displaySize = 32; + allowRectanglePlacement = true; } public static void linkDisplays(TileableLogicDisplayBuild start){ diff --git a/core/src/mindustry/world/blocks/units/UnitAssembler.java b/core/src/mindustry/world/blocks/units/UnitAssembler.java index 62d39ee38e..c021cc6972 100644 --- a/core/src/mindustry/world/blocks/units/UnitAssembler.java +++ b/core/src/mindustry/world/blocks/units/UnitAssembler.java @@ -166,8 +166,9 @@ public class UnitAssembler extends PayloadBlock{ @Override public void afterPatch(){ - initCapacities(); super.afterPatch(); + + initCapacities(); } public void initCapacities(){ @@ -705,6 +706,13 @@ public class UnitAssembler extends PayloadBlock{ return super.sense(sensor); } + @Override + public boolean acceptUnitPayload(Unit unit){ + var plan = plan(); + return plan.requirements.contains(b -> b.item == unit.type() && + blocks.get(unit.type()) < Mathf.round(b.amount * state.rules.unitCost(team))); + } + @Override public PayloadSeq getPayloads(){ return blocks; diff --git a/core/src/mindustry/world/meta/StatValues.java b/core/src/mindustry/world/meta/StatValues.java index 5ef77b6beb..2c6598cf48 100644 --- a/core/src/mindustry/world/meta/StatValues.java +++ b/core/src/mindustry/world/meta/StatValues.java @@ -656,7 +656,7 @@ public class StatValues{ if(blockName != null && t instanceof UnlockableContent){ UnlockableContent content = (UnlockableContent) t; String key = "block." + blockName + "." + content.name + ".info"; - if(Core.bundle.has(key)){ + if(Core.bundle.has(key) && !Vars.headless){ bt.table(desc -> { desc.image(Icon.info.getRegion()).size(20).color(Color.lightGray).scaling(Scaling.fit).padRight(8).padLeft(12); desc.add("[lightgray]" + Core.bundle.get(key)); @@ -872,7 +872,7 @@ public class StatValues{ private static Cell note(Table table, String text){ table.row(); return table.table(t -> { - t.image(Icon.arrowNoteSmall.getRegion()).size(15).color(Pal.stat).scaling(Scaling.fit).padRight(6).padLeft(12); + if(!Vars.headless) t.image(Icon.arrowNoteSmall.getRegion()).size(15).color(Pal.stat).scaling(Scaling.fit).padRight(6).padLeft(12); t.add(text); }); } diff --git a/desktop/src/mindustry/desktop/steam/SNet.java b/desktop/src/mindustry/desktop/steam/SNet.java index 588d6e4f07..2086794469 100644 --- a/desktop/src/mindustry/desktop/steam/SNet.java +++ b/desktop/src/mindustry/desktop/steam/SNet.java @@ -133,6 +133,38 @@ public class SNet implements SteamNetworkingCallback, SteamMatchmakingCallback, }catch(NumberFormatException e){ throw new IOException("Invalid Steam ID: " + lobbyname); } + }else if (ip.startsWith("steamserver:")){ + String server = ip.substring("steamserver:".length()); + try{ + SteamID serverID = SteamID.createFromNativeHandle(Long.parseLong(server)); + if(!serverID.isValid()) throw new IOException("Invalid Steam ID structure: " + server); + + Core.app.post(() -> { + currentLobby = null; + currentServer = serverID; + + // Run success + if(success != null) success.run(); + + // Connect + Connect con = new Connect(); + con.addressTCP = "steam:" + currentServer.getAccountID(); + + net.setClientConnected(); + net.handleClientReceived(con); + Core.app.post(() -> { // TODO: This gets hidden and I can't figure out how to not do so. + ui.loadfrag.show("@connecting"); + ui.loadfrag.setButton(() -> { + ui.loadfrag.hide(); + netClient.disconnectQuietly(); + }); + }); + + Log.info("Initiated direct Steam P2P connection to server: @", currentServer.getAccountID()); + }); + }catch(NumberFormatException e){ + throw new IOException("Failed to parse server Steam ID: " + server); + } }else{ provider.connectClient(ip, port, success); } @@ -165,13 +197,11 @@ public class SNet implements SteamNetworkingCallback, SteamMatchmakingCallback, @Override public void disconnectClient(){ if(isSteamClient()){ - if(currentLobby != null){ - smat.leaveLobby(currentLobby); - snet.closeP2PSessionWithUser(currentServer); - currentServer = null; - currentLobby = null; - net.handleClientReceived(new Disconnect()); - } + if(currentLobby != null) smat.leaveLobby(currentLobby); + snet.closeP2PSessionWithUser(currentServer); + currentServer = null; + currentLobby = null; + net.handleClientReceived(new Disconnect()); }else{ provider.disconnectClient(); } @@ -196,14 +226,14 @@ public class SNet implements SteamNetworkingCallback, SteamMatchmakingCallback, @Override public void hostServer(int port) throws IOException{ provider.hostServer(port); - smat.createLobby(Core.settings.getBool("steampublichost") ? LobbyType.Public : LobbyType.FriendsOnly, Core.settings.getInt("playerlimit")); + smat.createLobby(Core.settings.getBool("steampublichost2") ? LobbyType.Public : LobbyType.FriendsOnly, Core.settings.getInt("playerlimit")); Core.app.post(() -> Core.app.post(() -> Core.app.post(() -> Log.info("Server: @\nClient: @\nActive: @", net.server(), net.client(), net.active())))); } public void updateLobby(){ if(currentLobby != null && net.server()){ - smat.setLobbyType(currentLobby, Core.settings.getBool("steampublichost") ? LobbyType.Public : LobbyType.FriendsOnly); + smat.setLobbyType(currentLobby, Core.settings.getBool("steampublichost2") ? LobbyType.Public : LobbyType.FriendsOnly); smat.setLobbyMemberLimit(currentLobby, Core.settings.getInt("playerlimit")); } } @@ -411,6 +441,13 @@ public class SNet implements SteamNetworkingCallback, SteamMatchmakingCallback, }else if(steamIDRemote.equals(currentServer)){ Log.info("Disconnected! @: @", steamIDRemote.getAccountID(), sessionError); net.handleClientReceived(new Disconnect()); + + Core.app.post(() -> { + ui.loadfrag.hide(); + ui.showErrorMessage(Core.bundle.format("cantconnect", sessionError.name())); + net.handleClientReceived(new Disconnect()); + currentServer = null; + }); } } diff --git a/ios/Info.plist.xml b/ios/Info.plist.xml index fb8380a787..abd5e7339a 100644 --- a/ios/Info.plist.xml +++ b/ios/Info.plist.xml @@ -13,7 +13,7 @@ CFBundleInfoDictionaryVersion 6.0 MinimumOSVersion - 12.0.0 + 13.0.0 CFBundleName ${app.name} CFBundlePackageType