mirror of
https://github.com/imayushsaini/Bombsquad-Ballistica-Modded-Server.git
synced 2025-10-20 00:00:39 +00:00
1.7.5 master sync
This commit is contained in:
parent
421c488c6a
commit
62103ea678
61 changed files with 2001 additions and 1364 deletions
27
dist/ba_data/data/langdata.json
vendored
27
dist/ba_data/data/langdata.json
vendored
|
|
@ -50,6 +50,7 @@
|
||||||
"5PH3X",
|
"5PH3X",
|
||||||
"99",
|
"99",
|
||||||
"@sametsunal",
|
"@sametsunal",
|
||||||
|
"_DraXX",
|
||||||
"_Fami",
|
"_Fami",
|
||||||
"Omar a",
|
"Omar a",
|
||||||
"Bruno A.",
|
"Bruno A.",
|
||||||
|
|
@ -75,7 +76,7 @@
|
||||||
"adan",
|
"adan",
|
||||||
"Adeel (AdeZ {@adez_})",
|
"Adeel (AdeZ {@adez_})",
|
||||||
"Adel",
|
"Adel",
|
||||||
"Rio adi",
|
"Rio Adi",
|
||||||
"Rayhan Adiansyah",
|
"Rayhan Adiansyah",
|
||||||
"Yonas Adiel",
|
"Yonas Adiel",
|
||||||
"admin",
|
"admin",
|
||||||
|
|
@ -194,6 +195,7 @@
|
||||||
"Arin",
|
"Arin",
|
||||||
"Arroz",
|
"Arroz",
|
||||||
"ARSHAD",
|
"ARSHAD",
|
||||||
|
"ArshiyDLn",
|
||||||
"Artem",
|
"Artem",
|
||||||
"Valentino Artizzu",
|
"Valentino Artizzu",
|
||||||
"Arxyma",
|
"Arxyma",
|
||||||
|
|
@ -237,6 +239,7 @@
|
||||||
"Bank",
|
"Bank",
|
||||||
"Ibrahim Baraka",
|
"Ibrahim Baraka",
|
||||||
"Kamil Barański",
|
"Kamil Barański",
|
||||||
|
"Leonan Barcelos",
|
||||||
"Bardiaghasedipour",
|
"Bardiaghasedipour",
|
||||||
"William Barnak",
|
"William Barnak",
|
||||||
"William Barnakk",
|
"William Barnakk",
|
||||||
|
|
@ -248,6 +251,7 @@
|
||||||
"Bashkot",
|
"Bashkot",
|
||||||
"Matthias Bastron",
|
"Matthias Bastron",
|
||||||
"Ralph Bathmann",
|
"Ralph Bathmann",
|
||||||
|
"Bato",
|
||||||
"Florian Bauernfeind",
|
"Florian Bauernfeind",
|
||||||
"David BAUMANN",
|
"David BAUMANN",
|
||||||
"bayanus",
|
"bayanus",
|
||||||
|
|
@ -273,6 +277,7 @@
|
||||||
"Anton Bang Berner",
|
"Anton Bang Berner",
|
||||||
"Felix Bernhard",
|
"Felix Bernhard",
|
||||||
"Davide Bigotto",
|
"Davide Bigotto",
|
||||||
|
"bilibili@Medic药",
|
||||||
"Bima",
|
"Bima",
|
||||||
"Biytremni",
|
"Biytremni",
|
||||||
"Blackcat2960",
|
"Blackcat2960",
|
||||||
|
|
@ -316,6 +321,7 @@
|
||||||
"Buskebam",
|
"Buskebam",
|
||||||
"Buto11",
|
"Buto11",
|
||||||
"ByAdrianYT",
|
"ByAdrianYT",
|
||||||
|
"Semih Byzts",
|
||||||
"Mohamad Hossein BZ",
|
"Mohamad Hossein BZ",
|
||||||
"Christoffer Bünner",
|
"Christoffer Bünner",
|
||||||
"mvp aka cactus",
|
"mvp aka cactus",
|
||||||
|
|
@ -382,6 +388,7 @@
|
||||||
"D",
|
"D",
|
||||||
"Dada",
|
"Dada",
|
||||||
"Daivaras",
|
"Daivaras",
|
||||||
|
"Dajo6596YT",
|
||||||
"Dakkat",
|
"Dakkat",
|
||||||
"Mikkel Damgaard",
|
"Mikkel Damgaard",
|
||||||
"Danco",
|
"Danco",
|
||||||
|
|
@ -398,6 +405,7 @@
|
||||||
"Dasto",
|
"Dasto",
|
||||||
"David",
|
"David",
|
||||||
"Davide",
|
"Davide",
|
||||||
|
"DavidPlayzLol",
|
||||||
"DavidPlayzloll",
|
"DavidPlayzloll",
|
||||||
"DaymanLP",
|
"DaymanLP",
|
||||||
"Ddávid",
|
"Ddávid",
|
||||||
|
|
@ -445,6 +453,7 @@
|
||||||
"Dustin",
|
"Dustin",
|
||||||
"Paul Duvernay",
|
"Paul Duvernay",
|
||||||
"Emir İslam Dündar",
|
"Emir İslam Dündar",
|
||||||
|
"E.R.A.L",
|
||||||
"Ebutahapro07tr",
|
"Ebutahapro07tr",
|
||||||
"Edson",
|
"Edson",
|
||||||
"Glen Edwards",
|
"Glen Edwards",
|
||||||
|
|
@ -458,6 +467,7 @@
|
||||||
"Rezk ElAdawy",
|
"Rezk ElAdawy",
|
||||||
"ElCatCaesar",
|
"ElCatCaesar",
|
||||||
"ElderLink",
|
"ElderLink",
|
||||||
|
"elfree",
|
||||||
"Elian",
|
"Elian",
|
||||||
"Elsans320_YT",
|
"Elsans320_YT",
|
||||||
"Elskoser",
|
"Elskoser",
|
||||||
|
|
@ -466,6 +476,7 @@
|
||||||
"Emil",
|
"Emil",
|
||||||
"Kürti Emil",
|
"Kürti Emil",
|
||||||
"Muhammed emir",
|
"Muhammed emir",
|
||||||
|
"Muhammet Emir",
|
||||||
"EmirSametEr",
|
"EmirSametEr",
|
||||||
"emm",
|
"emm",
|
||||||
"EnderDust123",
|
"EnderDust123",
|
||||||
|
|
@ -686,8 +697,9 @@
|
||||||
"Tobias Dencker Israelsen",
|
"Tobias Dencker Israelsen",
|
||||||
"Kegyes István",
|
"Kegyes István",
|
||||||
"Itamar",
|
"Itamar",
|
||||||
"ivan",
|
"Ivan",
|
||||||
"iViietZ",
|
"iViietZ",
|
||||||
|
"JaaJ",
|
||||||
"Al jabbar",
|
"Al jabbar",
|
||||||
"Jacek",
|
"Jacek",
|
||||||
"Jack556",
|
"Jack556",
|
||||||
|
|
@ -729,6 +741,7 @@
|
||||||
"joke",
|
"joke",
|
||||||
"Jonatas",
|
"Jonatas",
|
||||||
"Jop",
|
"Jop",
|
||||||
|
"JoseANG3L",
|
||||||
"Joseetion",
|
"Joseetion",
|
||||||
"Joseph",
|
"Joseph",
|
||||||
"Joshep",
|
"Joshep",
|
||||||
|
|
@ -771,6 +784,7 @@
|
||||||
"Mani kelidari",
|
"Mani kelidari",
|
||||||
"Kelmine",
|
"Kelmine",
|
||||||
"Kenjie",
|
"Kenjie",
|
||||||
|
"Kerfix",
|
||||||
"Kerim",
|
"Kerim",
|
||||||
"Khaild1717",
|
"Khaild1717",
|
||||||
"muh khairul",
|
"muh khairul",
|
||||||
|
|
@ -852,8 +866,10 @@
|
||||||
"Linux44313",
|
"Linux44313",
|
||||||
"LiteBalt",
|
"LiteBalt",
|
||||||
"LittleNyanCat",
|
"LittleNyanCat",
|
||||||
|
"Lizz",
|
||||||
"Lizzetc",
|
"Lizzetc",
|
||||||
"Lkham",
|
"Lkham",
|
||||||
|
"Lobinhofs",
|
||||||
"Loex",
|
"Loex",
|
||||||
"Loko",
|
"Loko",
|
||||||
"Longkencok",
|
"Longkencok",
|
||||||
|
|
@ -871,6 +887,7 @@
|
||||||
"Ludicrouswizard",
|
"Ludicrouswizard",
|
||||||
"satrio ludji",
|
"satrio ludji",
|
||||||
"Ludovico",
|
"Ludovico",
|
||||||
|
"Luis (GalaxyM4)",
|
||||||
"Jose Luis",
|
"Jose Luis",
|
||||||
"luislinares",
|
"luislinares",
|
||||||
"luispro25",
|
"luispro25",
|
||||||
|
|
@ -933,6 +950,7 @@
|
||||||
"Ihsan Maulana ( @ihsanm27)",
|
"Ihsan Maulana ( @ihsanm27)",
|
||||||
"Federico Mazzone",
|
"Federico Mazzone",
|
||||||
"Andrea Mazzucchelli",
|
"Andrea Mazzucchelli",
|
||||||
|
"Medic",
|
||||||
"Medic别闹我有药",
|
"Medic别闹我有药",
|
||||||
"German Medin",
|
"German Medin",
|
||||||
"Martin Medina",
|
"Martin Medina",
|
||||||
|
|
@ -1104,12 +1122,14 @@
|
||||||
"pett",
|
"pett",
|
||||||
"Petulakulina",
|
"Petulakulina",
|
||||||
"Pez",
|
"Pez",
|
||||||
|
"PGIGM",
|
||||||
"Đào Xuân Phi",
|
"Đào Xuân Phi",
|
||||||
"Philip",
|
"Philip",
|
||||||
"Philipp",
|
"Philipp",
|
||||||
"piga",
|
"piga",
|
||||||
"Stefano Pigozzi",
|
"Stefano Pigozzi",
|
||||||
"Mario Donato Pilla",
|
"Mario Donato Pilla",
|
||||||
|
"Pinchidino",
|
||||||
"Danilo \"Logan\" Pirrone",
|
"Danilo \"Logan\" Pirrone",
|
||||||
"PivotStickfigure12",
|
"PivotStickfigure12",
|
||||||
"Pixelcube",
|
"Pixelcube",
|
||||||
|
|
@ -1321,6 +1341,7 @@
|
||||||
"sun.4810",
|
"sun.4810",
|
||||||
"Samet Sunal",
|
"Samet Sunal",
|
||||||
"sundar",
|
"sundar",
|
||||||
|
"Suprcat",
|
||||||
"Indo sus",
|
"Indo sus",
|
||||||
"Sven",
|
"Sven",
|
||||||
"Shannon Sy",
|
"Shannon Sy",
|
||||||
|
|
@ -1329,6 +1350,7 @@
|
||||||
"Sz™",
|
"Sz™",
|
||||||
"Jorge Luis Sánchez",
|
"Jorge Luis Sánchez",
|
||||||
"Daniel Sýkora",
|
"Daniel Sýkora",
|
||||||
|
"Aleksandar Tadic",
|
||||||
"Arung Taftazani",
|
"Arung Taftazani",
|
||||||
"taha",
|
"taha",
|
||||||
"Rasim Eren TAHMAZ",
|
"Rasim Eren TAHMAZ",
|
||||||
|
|
@ -1394,6 +1416,7 @@
|
||||||
"Kontantin Tsvetkov",
|
"Kontantin Tsvetkov",
|
||||||
"Tudikk",
|
"Tudikk",
|
||||||
"Jan Tymll",
|
"Jan Tymll",
|
||||||
|
"Zacker Tz",
|
||||||
"Zoltán Tóth",
|
"Zoltán Tóth",
|
||||||
"uDinnoo",
|
"uDinnoo",
|
||||||
"Cristian Ugalde",
|
"Cristian Ugalde",
|
||||||
|
|
|
||||||
49
dist/ba_data/data/languages/arabic.json
vendored
49
dist/ba_data/data/languages/arabic.json
vendored
|
|
@ -327,6 +327,7 @@
|
||||||
"achievementsRemainingText": "الإنجازات المتبقية",
|
"achievementsRemainingText": "الإنجازات المتبقية",
|
||||||
"achievementsText": "الإنجازات",
|
"achievementsText": "الإنجازات",
|
||||||
"achievementsUnavailableForOldSeasonsText": "المعذرة، الإنجازات للمواسم القديمة غير متوفرة",
|
"achievementsUnavailableForOldSeasonsText": "المعذرة، الإنجازات للمواسم القديمة غير متوفرة",
|
||||||
|
"activatedText": "${THING} تم تفعيله.",
|
||||||
"addGameWindow": {
|
"addGameWindow": {
|
||||||
"getMoreGamesText": "الحصول على المزيد من الألعاب",
|
"getMoreGamesText": "الحصول على المزيد من الألعاب",
|
||||||
"titleText": "إضافة لعبة"
|
"titleText": "إضافة لعبة"
|
||||||
|
|
@ -625,7 +626,9 @@
|
||||||
"epicDescriptionFilterText": "${DESCRIPTION} بحركة ملحمية بطيئة",
|
"epicDescriptionFilterText": "${DESCRIPTION} بحركة ملحمية بطيئة",
|
||||||
"epicNameFilterText": "الملحمي ${NAME}",
|
"epicNameFilterText": "الملحمي ${NAME}",
|
||||||
"errorAccessDeniedText": "تم الرفض",
|
"errorAccessDeniedText": "تم الرفض",
|
||||||
|
"errorDeviceTimeIncorrectText": "توقف وقت جهازك بمقدار ${HOURS} ساعة.\nهذا قد يتسبب بمشاكل.\nمن فضلك قم بالتحقق من اعدادات الوقت.",
|
||||||
"errorOutOfDiskSpaceText": "انتهت مساحة التخزين",
|
"errorOutOfDiskSpaceText": "انتهت مساحة التخزين",
|
||||||
|
"errorSecureConnectionFailText": "تعذر انشاء اتصال سحابي أمن; قد تفشل وظائف الشبكة.",
|
||||||
"errorText": "خطا",
|
"errorText": "خطا",
|
||||||
"errorUnknownText": "خطا غير معروف",
|
"errorUnknownText": "خطا غير معروف",
|
||||||
"exitGameText": "هل تريد الخروج من ${APP_NAME}؟",
|
"exitGameText": "هل تريد الخروج من ${APP_NAME}؟",
|
||||||
|
|
@ -788,7 +791,7 @@
|
||||||
"ticketPack4Text": "جمبو تذكرة حزمة",
|
"ticketPack4Text": "جمبو تذكرة حزمة",
|
||||||
"ticketPack5Text": "ماموث تذكرة حزمة",
|
"ticketPack5Text": "ماموث تذكرة حزمة",
|
||||||
"ticketPack6Text": "تذكرة حزمة هائلة",
|
"ticketPack6Text": "تذكرة حزمة هائلة",
|
||||||
"ticketsFromASponsorText": "احصل على تذاكر ${COUNT}\nمن مقدم مشروع القرار",
|
"ticketsFromASponsorText": "شاهد اعلانا\nمن التذاكر ${COUNT} للحصول على",
|
||||||
"ticketsText": "${COUNT} بطاقات",
|
"ticketsText": "${COUNT} بطاقات",
|
||||||
"titleText": "أحصل على تذاكر",
|
"titleText": "أحصل على تذاكر",
|
||||||
"unavailableLinkAccountText": "عذرا، لا تتوفر عمليات الشراء على هذا النظام الأساسي.\nوكحل بديل، يمكنك ربط هذا الحساب بحساب في\nمنصة أخرى وجعل عمليات الشراء هناك.",
|
"unavailableLinkAccountText": "عذرا، لا تتوفر عمليات الشراء على هذا النظام الأساسي.\nوكحل بديل، يمكنك ربط هذا الحساب بحساب في\nمنصة أخرى وجعل عمليات الشراء هناك.",
|
||||||
|
|
@ -799,6 +802,7 @@
|
||||||
"youHaveText": "لديك ${COUNT} تذاكر"
|
"youHaveText": "لديك ${COUNT} تذاكر"
|
||||||
},
|
},
|
||||||
"googleMultiplayerDiscontinuedText": "عذرًا ، خدمة جوجل متعددة اللاعبين لم تعد متاحة.\n أنا أعمل على بديل بأسرع وقت ممكن.\n حتى ذلك الحين ، يرجى تجربة طريقة اتصال أخرى.\n -إريك",
|
"googleMultiplayerDiscontinuedText": "عذرًا ، خدمة جوجل متعددة اللاعبين لم تعد متاحة.\n أنا أعمل على بديل بأسرع وقت ممكن.\n حتى ذلك الحين ، يرجى تجربة طريقة اتصال أخرى.\n -إريك",
|
||||||
|
"googlePlayPurchasesNotAvailableText": "عمليات شراء جوجل بلاي غير متوفرة.\nقد تحتاج لتحديث تطبيق المتجر.",
|
||||||
"googlePlayText": "جوجل بلاي",
|
"googlePlayText": "جوجل بلاي",
|
||||||
"graphicsSettingsWindow": {
|
"graphicsSettingsWindow": {
|
||||||
"alwaysText": "دائما",
|
"alwaysText": "دائما",
|
||||||
|
|
@ -1109,7 +1113,10 @@
|
||||||
"playlistsText": "قائمة العب",
|
"playlistsText": "قائمة العب",
|
||||||
"pleaseRateText": "يرجى اتخاذ لحظة وتقييمه ${APP_NAME} اذا كنت تستمتع بلعبة\nاو كتابة مراجعة فهاذا يوفر معلومات مفيدة ويوفر التطوير\nفي المستقبل\n\n!شكرًا\nاريك—",
|
"pleaseRateText": "يرجى اتخاذ لحظة وتقييمه ${APP_NAME} اذا كنت تستمتع بلعبة\nاو كتابة مراجعة فهاذا يوفر معلومات مفيدة ويوفر التطوير\nفي المستقبل\n\n!شكرًا\nاريك—",
|
||||||
"pleaseWaitText": "الرجاء الانتظار . . .",
|
"pleaseWaitText": "الرجاء الانتظار . . .",
|
||||||
"pluginsDetectedText": "تم العتور على اضافات جديدة. فعلها او عدلها في الاعدادات",
|
"pluginClassLoadErrorText": "فشل في تشغيل الاضافة '${PLUGIN}': ${ERROR}",
|
||||||
|
"pluginInitErrorText": "خطأ في بدء الاضافة '${PLUGIN}: ${ERROR}",
|
||||||
|
"pluginsDetectedText": "تم العثور على اضافات جديدة. اعد التشغيل لتفعيلها، او قم بتخصيصها في الاعدادات.",
|
||||||
|
"pluginsRemovedText": "${NUM} لم تعد الاضافة موجودة.",
|
||||||
"pluginsText": "اضافات",
|
"pluginsText": "اضافات",
|
||||||
"practiceText": "تدريب",
|
"practiceText": "تدريب",
|
||||||
"pressAnyButtonPlayAgainText": "اضغط اي زر للعب مجددا...",
|
"pressAnyButtonPlayAgainText": "اضغط اي زر للعب مجددا...",
|
||||||
|
|
@ -1296,8 +1303,8 @@
|
||||||
"comingSoonText": "قريبا...",
|
"comingSoonText": "قريبا...",
|
||||||
"extrasText": "إضافات",
|
"extrasText": "إضافات",
|
||||||
"freeBombSquadProText": "فرقة القنبلة الآن أصبحت مجانية، لكن بما أنك اشتريتها\nبطاقات كشكر لك ${COUNT} ستتلقى فرقة القنبلة القنبلة للمحترفين و\n!استمتع بالميزات الجديدة، وشكرًا لدعمك\n-إيريك",
|
"freeBombSquadProText": "فرقة القنبلة الآن أصبحت مجانية، لكن بما أنك اشتريتها\nبطاقات كشكر لك ${COUNT} ستتلقى فرقة القنبلة القنبلة للمحترفين و\n!استمتع بالميزات الجديدة، وشكرًا لدعمك\n-إيريك",
|
||||||
"holidaySpecialText": "عطلة خاصة",
|
"holidaySpecialText": "خاص بالعطل",
|
||||||
"howToSwitchCharactersText": "(انتقل إلى \"${SETTINGS} -> ${PLAYER_PROFILES}\" لتعيين وتخصيص الأحرف)",
|
"howToSwitchCharactersText": "(توجه الى \"${SETTINGS} -> ${PLAYER_PROFILES}\" لتخصيص الشخصيات)",
|
||||||
"howToUseIconsText": "(إنشاء ملفات تعريف لاعب العالمية (في إطار الحساب) لاستخدام هذه)",
|
"howToUseIconsText": "(إنشاء ملفات تعريف لاعب العالمية (في إطار الحساب) لاستخدام هذه)",
|
||||||
"howToUseMapsText": "(استخدم هذه الخرائط في فرقك الخاصة / قوائم التشغيل المجانية للجميع)",
|
"howToUseMapsText": "(استخدم هذه الخرائط في فرقك الخاصة / قوائم التشغيل المجانية للجميع)",
|
||||||
"iconsText": "رموز",
|
"iconsText": "رموز",
|
||||||
|
|
@ -1321,7 +1328,7 @@
|
||||||
"winterSpecialText": "عرض الشتاء",
|
"winterSpecialText": "عرض الشتاء",
|
||||||
"youOwnThisText": "- انت تملك هذا -"
|
"youOwnThisText": "- انت تملك هذا -"
|
||||||
},
|
},
|
||||||
"storeDescriptionText": "8 لاعب حفله لعبة الجنون!\n\nتفجير أصدقائك (أو الكمبيوتر) في البطولة من الألعاب المصغرة المتفجرة مثل القبض على العلم، منفذها هوكي، وملحمة بطيئة الحركة الموت الموت!\n\nضوابط بسيطة ودعم وحدة تحكم واسعة تجعل من السهل لمدة تصل إلى 8 أشخاص للحصول على في العمل. يمكنك حتى استخدام الأجهزة النقالة الخاصة بك عن طريق التحكم عن طريق الحرة 'بومبسكاد البعيد' التطبيق!\n\nالقنابل بعيدا!\n\nتحقق من www.froemling.net/bombsquad لمزيد من المعلومات.",
|
"storeDescriptionText": "لعبة لأكثر من 8 لاعبين!\n\nالعب مع اصدقائك (او الحاسوب) في بطولات من الميني جيمز المتفجرة كــإمساك بالعلم، الهوكي و المعركة البطيئة!\n\nتحكم بسيط و لعب باجهزة تحكم يجعلها سهلة لأكثر من 8 لاعبين ليدخلو المعركة; تستطيع ايضا استعمال اجهزة الهاتف كاجهزة تحكم من خلال التطبيق المجاني 'BombSquad Remote' !\n\nوقت رمي القنابل!\n\nتفقد www.froemling.net/bombsquad للمزيد من المعلومات.",
|
||||||
"storeDescriptions": {
|
"storeDescriptions": {
|
||||||
"blowUpYourFriendsText": ".فجر أصدقائك",
|
"blowUpYourFriendsText": ".فجر أصدقائك",
|
||||||
"competeInMiniGamesText": "تنافس في الألعاب المصغرة بدءا من السباق للطيران.",
|
"competeInMiniGamesText": "تنافس في الألعاب المصغرة بدءا من السباق للطيران.",
|
||||||
|
|
@ -1364,31 +1371,31 @@
|
||||||
"translations": {
|
"translations": {
|
||||||
"characterNames": {
|
"characterNames": {
|
||||||
"Agent Johnson": "العميل جونسون",
|
"Agent Johnson": "العميل جونسون",
|
||||||
"B-9000": "الآلي الخارق",
|
"B-9000": "B-9000",
|
||||||
"Bernard": "الدب القطبي",
|
"Bernard": "بيرنارد",
|
||||||
"Bones": "هيكل عظمي",
|
"Bones": "هيكل عظمي",
|
||||||
"Butch": "بوتش",
|
"Butch": "بوتش",
|
||||||
"Easter Bunny": "أرنوب",
|
"Easter Bunny": "أرنب عيد الفصح",
|
||||||
"Flopsy": "فلوبسي",
|
"Flopsy": "فلوبسي",
|
||||||
"Frosty": "مُقاتل ثلجي",
|
"Frosty": "فروستي",
|
||||||
"Gretel": "جريتل",
|
"Gretel": "جريتل",
|
||||||
"Grumbledorf": "المشعوذ",
|
"Grumbledorf": "الساحر",
|
||||||
"Jack Morgan": "خير الدين بارباروسا",
|
"Jack Morgan": "جاك مورجان (قرصان)",
|
||||||
"Kronk": "عدنان",
|
"Kronk": "كرونك",
|
||||||
"Lee": "لي",
|
"Lee": "لي",
|
||||||
"Lucky": "سعيد الحظ",
|
"Lucky": "سعيد الحظ",
|
||||||
"Mel": "الطباخ",
|
"Mel": "ميل",
|
||||||
"Middle-Man": "الرجل المتوسط",
|
"Middle-Man": "الرجل المتوسط",
|
||||||
"Minimus": "أدنى لا",
|
"Minimus": "أدنى لا",
|
||||||
"Pascal": "البطريق الكبير",
|
"Pascal": "پاسكال",
|
||||||
"Pixel": "حسناء",
|
"Pixel": "بيكسل",
|
||||||
"Sammy Slam": "سامي سلام",
|
"Sammy Slam": "سامي سلام",
|
||||||
"Santa Claus": "الشيخ",
|
"Santa Claus": "سانتا كلوس",
|
||||||
"Snake Shadow": "مُحارب في الصحراء",
|
"Snake Shadow": "نينجا",
|
||||||
"Spaz": "Spaz",
|
"Spaz": "سپاز",
|
||||||
"Taobao Mascot": "التميمه تاوباو",
|
"Taobao Mascot": "ماسكوت تاوباو",
|
||||||
"Todd McBurton": "تود بيرتون",
|
"Todd McBurton": "تود بيرتون",
|
||||||
"Zoe": "ليلى",
|
"Zoe": "زوي",
|
||||||
"Zola": "زولا"
|
"Zola": "زولا"
|
||||||
},
|
},
|
||||||
"coopLevelNames": {
|
"coopLevelNames": {
|
||||||
|
|
@ -1843,6 +1850,8 @@
|
||||||
"winsPlayerText": "${NAME} !يفوز",
|
"winsPlayerText": "${NAME} !يفوز",
|
||||||
"winsTeamText": "${NAME} !يفوز فريق",
|
"winsTeamText": "${NAME} !يفوز فريق",
|
||||||
"winsText": "${NAME} !يفوز",
|
"winsText": "${NAME} !يفوز",
|
||||||
|
"workspaceSyncErrorText": "فشل في مزامنة ${WORKSPACE}. القي نظرة على السجل للتفاصيل.",
|
||||||
|
"workspaceSyncReuseText": "لا يمكن مزامنة ${WORKSPACE}. اعادة استخدام النسخة المتزامنة السابقة.",
|
||||||
"worldScoresUnavailableText": "(النتيجة العالمية غير متوفرة (اتصل بالانترنت",
|
"worldScoresUnavailableText": "(النتيجة العالمية غير متوفرة (اتصل بالانترنت",
|
||||||
"worldsBestScoresText": "افضل نتيجة للعالم",
|
"worldsBestScoresText": "افضل نتيجة للعالم",
|
||||||
"worldsBestTimesText": "افضل اوقات العالم",
|
"worldsBestTimesText": "افضل اوقات العالم",
|
||||||
|
|
|
||||||
11
dist/ba_data/data/languages/chinese.json
vendored
11
dist/ba_data/data/languages/chinese.json
vendored
|
|
@ -330,6 +330,7 @@
|
||||||
"achievementsRemainingText": "未完成成就:",
|
"achievementsRemainingText": "未完成成就:",
|
||||||
"achievementsText": "成就",
|
"achievementsText": "成就",
|
||||||
"achievementsUnavailableForOldSeasonsText": "抱歉,往届的成就细节不可用。",
|
"achievementsUnavailableForOldSeasonsText": "抱歉,往届的成就细节不可用。",
|
||||||
|
"activatedText": "${THING} 已激活",
|
||||||
"addGameWindow": {
|
"addGameWindow": {
|
||||||
"getMoreGamesText": "获取更多游戏模式…",
|
"getMoreGamesText": "获取更多游戏模式…",
|
||||||
"titleText": "添加比赛"
|
"titleText": "添加比赛"
|
||||||
|
|
@ -629,7 +630,9 @@
|
||||||
"epicDescriptionFilterText": "史诗级慢动作 ${DESCRIPTION}。",
|
"epicDescriptionFilterText": "史诗级慢动作 ${DESCRIPTION}。",
|
||||||
"epicNameFilterText": "史诗级${NAME}",
|
"epicNameFilterText": "史诗级${NAME}",
|
||||||
"errorAccessDeniedText": "访问被拒绝",
|
"errorAccessDeniedText": "访问被拒绝",
|
||||||
|
"errorDeviceTimeIncorrectText": "您的系统时间与服务器时间相差了${HOURS}小时\n这可能会出现一些问题\n请检查您的系统时间或时区",
|
||||||
"errorOutOfDiskSpaceText": "磁盘空间不足",
|
"errorOutOfDiskSpaceText": "磁盘空间不足",
|
||||||
|
"errorSecureConnectionFailText": "无法建立安全的云链接,网络可能会连接失败",
|
||||||
"errorText": "错误",
|
"errorText": "错误",
|
||||||
"errorUnknownText": "未知错误",
|
"errorUnknownText": "未知错误",
|
||||||
"exitGameText": "退出${APP_NAME}?",
|
"exitGameText": "退出${APP_NAME}?",
|
||||||
|
|
@ -795,7 +798,7 @@
|
||||||
"ticketPack4Text": "巨型点券包",
|
"ticketPack4Text": "巨型点券包",
|
||||||
"ticketPack5Text": "猛犸象点券包",
|
"ticketPack5Text": "猛犸象点券包",
|
||||||
"ticketPack6Text": "终极点券包",
|
"ticketPack6Text": "终极点券包",
|
||||||
"ticketsFromASponsorText": "从赞助商处\n获得${COUNT}点券",
|
"ticketsFromASponsorText": "观看广告\n白嫖${COUNT}个点券",
|
||||||
"ticketsText": "${COUNT}点券",
|
"ticketsText": "${COUNT}点券",
|
||||||
"titleText": "获得点券",
|
"titleText": "获得点券",
|
||||||
"unavailableLinkAccountText": "对不起,该平台上不可进行购买。\n您可将此帐户链接到另一个\n平台,以进行购买。",
|
"unavailableLinkAccountText": "对不起,该平台上不可进行购买。\n您可将此帐户链接到另一个\n平台,以进行购买。",
|
||||||
|
|
@ -806,6 +809,7 @@
|
||||||
"youHaveText": "你拥有${COUNT}点券"
|
"youHaveText": "你拥有${COUNT}点券"
|
||||||
},
|
},
|
||||||
"googleMultiplayerDiscontinuedText": "抱歉,Google的多人游戏服务已不可用。\n我将尽快更换新的替代服务。\n在此之前,请尝试其他连接方法。\n-Eric",
|
"googleMultiplayerDiscontinuedText": "抱歉,Google的多人游戏服务已不可用。\n我将尽快更换新的替代服务。\n在此之前,请尝试其他连接方法。\n-Eric",
|
||||||
|
"googlePlayPurchasesNotAvailableText": "Google商店购买不可用!\n请安装谷歌框架或更新Google服务。",
|
||||||
"googlePlayText": "Google Play",
|
"googlePlayText": "Google Play",
|
||||||
"graphicsSettingsWindow": {
|
"graphicsSettingsWindow": {
|
||||||
"alwaysText": "总是",
|
"alwaysText": "总是",
|
||||||
|
|
@ -1122,7 +1126,10 @@
|
||||||
"playlistsText": "列表",
|
"playlistsText": "列表",
|
||||||
"pleaseRateText": "如果你喜欢 ${APP_NAME},请考虑花一点时间\n来评价一下它或为它写一篇评论。这将为我们提供\n有用的反馈建议,为游戏的未来开发给予支持。\n\n感谢您!\n-eric",
|
"pleaseRateText": "如果你喜欢 ${APP_NAME},请考虑花一点时间\n来评价一下它或为它写一篇评论。这将为我们提供\n有用的反馈建议,为游戏的未来开发给予支持。\n\n感谢您!\n-eric",
|
||||||
"pleaseWaitText": "请稍等...",
|
"pleaseWaitText": "请稍等...",
|
||||||
|
"pluginClassLoadErrorText": "加载'${PLUGIN}'插件时出错了耶: ${ERROR}",
|
||||||
|
"pluginInitErrorText": "初始化'${PLUGIN}'插件失败了啦: ${ERROR}",
|
||||||
"pluginsDetectedText": "新插件安装成功,请重启游戏或在设置中设置它们~",
|
"pluginsDetectedText": "新插件安装成功,请重启游戏或在设置中设置它们~",
|
||||||
|
"pluginsRemovedText": "有${NUM}个插件被删除了...",
|
||||||
"pluginsText": "插件",
|
"pluginsText": "插件",
|
||||||
"practiceText": "练习",
|
"practiceText": "练习",
|
||||||
"pressAnyButtonPlayAgainText": "按任意按钮再玩一次...",
|
"pressAnyButtonPlayAgainText": "按任意按钮再玩一次...",
|
||||||
|
|
@ -1863,6 +1870,8 @@
|
||||||
"winsPlayerText": "${NAME}获胜!",
|
"winsPlayerText": "${NAME}获胜!",
|
||||||
"winsTeamText": "${NAME}获胜!",
|
"winsTeamText": "${NAME}获胜!",
|
||||||
"winsText": "${NAME}获胜!",
|
"winsText": "${NAME}获胜!",
|
||||||
|
"workspaceSyncErrorText": "同步${WORKSPACE}出错了啦,详情见日志文件",
|
||||||
|
"workspaceSyncReuseText": "同步${WORKSPACE}时出错,正在使用以前同步的数据....",
|
||||||
"worldScoresUnavailableText": "全球得分不可用。",
|
"worldScoresUnavailableText": "全球得分不可用。",
|
||||||
"worldsBestScoresText": "全球最高得分",
|
"worldsBestScoresText": "全球最高得分",
|
||||||
"worldsBestTimesText": "全球最佳时间",
|
"worldsBestTimesText": "全球最佳时间",
|
||||||
|
|
|
||||||
|
|
@ -324,6 +324,7 @@
|
||||||
"achievementsRemainingText": "未完成的成就",
|
"achievementsRemainingText": "未完成的成就",
|
||||||
"achievementsText": "成就",
|
"achievementsText": "成就",
|
||||||
"achievementsUnavailableForOldSeasonsText": "抱歉,往屆成就細節不可用",
|
"achievementsUnavailableForOldSeasonsText": "抱歉,往屆成就細節不可用",
|
||||||
|
"activatedText": "${THING}已激活",
|
||||||
"addGameWindow": {
|
"addGameWindow": {
|
||||||
"getMoreGamesText": "獲取更多比賽模式",
|
"getMoreGamesText": "獲取更多比賽模式",
|
||||||
"titleText": "新增比賽"
|
"titleText": "新增比賽"
|
||||||
|
|
@ -621,7 +622,9 @@
|
||||||
"epicDescriptionFilterText": "史詩級慢動作${DESCRIPTION}",
|
"epicDescriptionFilterText": "史詩級慢動作${DESCRIPTION}",
|
||||||
"epicNameFilterText": "史詩級${NAME}",
|
"epicNameFilterText": "史詩級${NAME}",
|
||||||
"errorAccessDeniedText": "訪問被拒絕",
|
"errorAccessDeniedText": "訪問被拒絕",
|
||||||
|
"errorDeviceTimeIncorrectText": "您的系統時間與BS伺服器相差了${HOURS}小時\n這可能會出現一些問題\n請檢查你的系統時間或時區",
|
||||||
"errorOutOfDiskSpaceText": "磁盤空間不足",
|
"errorOutOfDiskSpaceText": "磁盤空間不足",
|
||||||
|
"errorSecureConnectionFailText": "無法安全的連接到伺服器,網絡功能可能會失效",
|
||||||
"errorText": "錯誤",
|
"errorText": "錯誤",
|
||||||
"errorUnknownText": "未知錯誤",
|
"errorUnknownText": "未知錯誤",
|
||||||
"exitGameText": "退出${APP_NAME}?",
|
"exitGameText": "退出${APP_NAME}?",
|
||||||
|
|
@ -1105,7 +1108,10 @@
|
||||||
"playlistsText": "遊戲列表",
|
"playlistsText": "遊戲列表",
|
||||||
"pleaseRateText": "如果你喜歡${APP_NAME},請考慮花一些時間\n為Bombsquad寫一篇評論。這將為我們\n提供一些有用的反饋建議,為遊戲的未來開發給予支持\n\nThanks!\n-Eric",
|
"pleaseRateText": "如果你喜歡${APP_NAME},請考慮花一些時間\n為Bombsquad寫一篇評論。這將為我們\n提供一些有用的反饋建議,為遊戲的未來開發給予支持\n\nThanks!\n-Eric",
|
||||||
"pleaseWaitText": "請稍等....",
|
"pleaseWaitText": "請稍等....",
|
||||||
"pluginsDetectedText": "檢測到新插件。 在設置中啟用/配置它們。",
|
"pluginClassLoadErrorText": "加載插件類'${PLUGIN}'時出錯:${ERROR}",
|
||||||
|
"pluginInitErrorText": "初始化插件'${PLUGIN}'時出錯:${ERROR}",
|
||||||
|
"pluginsDetectedText": "檢測到新插件。重新啓動以激活,或在設置中配置這些插件",
|
||||||
|
"pluginsRemovedText": "${NUM}個插件已丟失",
|
||||||
"pluginsText": "外掛程式",
|
"pluginsText": "外掛程式",
|
||||||
"practiceText": "練習",
|
"practiceText": "練習",
|
||||||
"pressAnyButtonPlayAgainText": "按任意鍵再玩一次...",
|
"pressAnyButtonPlayAgainText": "按任意鍵再玩一次...",
|
||||||
|
|
@ -1839,6 +1845,8 @@
|
||||||
"winsPlayerText": "${NAME}贏了!",
|
"winsPlayerText": "${NAME}贏了!",
|
||||||
"winsTeamText": "${NAME}贏了!",
|
"winsTeamText": "${NAME}贏了!",
|
||||||
"winsText": "${NAME}贏了!",
|
"winsText": "${NAME}贏了!",
|
||||||
|
"workspaceSyncErrorText": "同步${WORKSPACE}時出錯,詳情日志已輸出",
|
||||||
|
"workspaceSyncReuseText": "無法同步${WORKSPACE},重複使用以前的同步版本",
|
||||||
"worldScoresUnavailableText": "無法讀入全球分數",
|
"worldScoresUnavailableText": "無法讀入全球分數",
|
||||||
"worldsBestScoresText": "全球最佳分數",
|
"worldsBestScoresText": "全球最佳分數",
|
||||||
"worldsBestTimesText": "全球最佳時間",
|
"worldsBestTimesText": "全球最佳時間",
|
||||||
|
|
|
||||||
6
dist/ba_data/data/languages/croatian.json
vendored
6
dist/ba_data/data/languages/croatian.json
vendored
|
|
@ -329,6 +329,7 @@
|
||||||
"achievementsRemainingText": "Preostala Postignuća:",
|
"achievementsRemainingText": "Preostala Postignuća:",
|
||||||
"achievementsText": "Postignuća",
|
"achievementsText": "Postignuća",
|
||||||
"achievementsUnavailableForOldSeasonsText": "Žao nam je,postignuća pojedinosti nisu dostupni za stare sezone.",
|
"achievementsUnavailableForOldSeasonsText": "Žao nam je,postignuća pojedinosti nisu dostupni za stare sezone.",
|
||||||
|
"activatedText": "${THING} uključeno.",
|
||||||
"addGameWindow": {
|
"addGameWindow": {
|
||||||
"getMoreGamesText": "Još igara...",
|
"getMoreGamesText": "Još igara...",
|
||||||
"titleText": "Dodaj igru"
|
"titleText": "Dodaj igru"
|
||||||
|
|
@ -1117,7 +1118,10 @@
|
||||||
"playlistsText": "Liste igara",
|
"playlistsText": "Liste igara",
|
||||||
"pleaseRateText": "Ako ti se sviđa ${APP_NAME}, molim te razmisli o tome\nda ga ocijeniš ili napišeš recenziju.\nOvako šalješ korisnu povratnu informaciju koja pomaže u daljnjem razvoju.\n\nHvala!\n-eric",
|
"pleaseRateText": "Ako ti se sviđa ${APP_NAME}, molim te razmisli o tome\nda ga ocijeniš ili napišeš recenziju.\nOvako šalješ korisnu povratnu informaciju koja pomaže u daljnjem razvoju.\n\nHvala!\n-eric",
|
||||||
"pleaseWaitText": "Molimo sačekajte...",
|
"pleaseWaitText": "Molimo sačekajte...",
|
||||||
|
"pluginClassLoadErrorText": "Pogreška učitavanja dodatka klase '${PLUGIN}': ${ERROR}",
|
||||||
|
"pluginInitErrorText": "Pogreška iniciranja dodatka '${PLUGIN}': ${ERROR}",
|
||||||
"pluginsDetectedText": "Novi dodatak(ci) detektiran(i) Resetiraj da ih ukljućiš ili ih konfiguriraj u postavkima",
|
"pluginsDetectedText": "Novi dodatak(ci) detektiran(i) Resetiraj da ih ukljućiš ili ih konfiguriraj u postavkima",
|
||||||
|
"pluginsRemovedText": "${NUM} dodatak/ci više nisu pronađeni.",
|
||||||
"pluginsText": "Dodatci",
|
"pluginsText": "Dodatci",
|
||||||
"practiceText": "Vježba",
|
"practiceText": "Vježba",
|
||||||
"pressAnyButtonPlayAgainText": "Pritisni bilo koju tipku za ponovnu igru...",
|
"pressAnyButtonPlayAgainText": "Pritisni bilo koju tipku za ponovnu igru...",
|
||||||
|
|
@ -1858,6 +1862,8 @@
|
||||||
"winsPlayerText": "${NAME} pobjeđuje!",
|
"winsPlayerText": "${NAME} pobjeđuje!",
|
||||||
"winsTeamText": "${NAME} pobjeđuju!",
|
"winsTeamText": "${NAME} pobjeđuju!",
|
||||||
"winsText": "${NAME} pobjeđuje!",
|
"winsText": "${NAME} pobjeđuje!",
|
||||||
|
"workspaceSyncErrorText": "Pogreška sinkroniziranja ${WORKSPACE}. Pogledaj log za više detalja.",
|
||||||
|
"workspaceSyncReuseText": "Nemoguće sinkronizirati ${WORKSPACE}. Ponovno korištenje stare verzije",
|
||||||
"worldScoresUnavailableText": "Svjetski rezultati nedostupni.",
|
"worldScoresUnavailableText": "Svjetski rezultati nedostupni.",
|
||||||
"worldsBestScoresText": "Najbolji svjetski rezultati",
|
"worldsBestScoresText": "Najbolji svjetski rezultati",
|
||||||
"worldsBestTimesText": "Najbolja svjetska prolazna vremena",
|
"worldsBestTimesText": "Najbolja svjetska prolazna vremena",
|
||||||
|
|
|
||||||
10
dist/ba_data/data/languages/czech.json
vendored
10
dist/ba_data/data/languages/czech.json
vendored
|
|
@ -331,6 +331,7 @@
|
||||||
"achievementsRemainingText": "Achievementů Zbývá:",
|
"achievementsRemainingText": "Achievementů Zbývá:",
|
||||||
"achievementsText": "Achievementy",
|
"achievementsText": "Achievementy",
|
||||||
"achievementsUnavailableForOldSeasonsText": "Promiňte, ale detaily úspěchu nejsou pro starší sezóny zpřístupněny.",
|
"achievementsUnavailableForOldSeasonsText": "Promiňte, ale detaily úspěchu nejsou pro starší sezóny zpřístupněny.",
|
||||||
|
"activatedText": "${THING} aktivováno.",
|
||||||
"addGameWindow": {
|
"addGameWindow": {
|
||||||
"getMoreGamesText": "Získat Více Her...",
|
"getMoreGamesText": "Získat Více Her...",
|
||||||
"titleText": "Přidat Hru"
|
"titleText": "Přidat Hru"
|
||||||
|
|
@ -633,7 +634,9 @@
|
||||||
"epicDescriptionFilterText": "${DESCRIPTION} V epickém slow motionu",
|
"epicDescriptionFilterText": "${DESCRIPTION} V epickém slow motionu",
|
||||||
"epicNameFilterText": "Epické ${NAME}",
|
"epicNameFilterText": "Epické ${NAME}",
|
||||||
"errorAccessDeniedText": "přístup zamítnut",
|
"errorAccessDeniedText": "přístup zamítnut",
|
||||||
|
"errorDeviceTimeIncorrectText": "Čas vašeho zařízení je mimo o ${HOURS} h.\nTo pravděpodobně způsobí problémy.\nProsím zkontrolujte nastavení času a časového pásma.",
|
||||||
"errorOutOfDiskSpaceText": "není místo na disku",
|
"errorOutOfDiskSpaceText": "není místo na disku",
|
||||||
|
"errorSecureConnectionFailText": "Unable to establish secure cloud connection; network functionality may fail.",
|
||||||
"errorText": "Chyba",
|
"errorText": "Chyba",
|
||||||
"errorUnknownText": "neznámá chyba",
|
"errorUnknownText": "neznámá chyba",
|
||||||
"exitGameText": "Ukončit ${APP_NAME} ???",
|
"exitGameText": "Ukončit ${APP_NAME} ???",
|
||||||
|
|
@ -1123,7 +1126,10 @@
|
||||||
"playlistsText": "Playlisty",
|
"playlistsText": "Playlisty",
|
||||||
"pleaseRateText": "Jestliže Vás ${APP_NAME} baví, zvažte prosím, jestli si nechcete udělat\nchvilku na ohodnocení nebo napsání recenze. Poskytuje to užitečnou\nzpětnou vazbu a pomáhá podporovat budoucí vývoj.\n\nDíky!\n-eric",
|
"pleaseRateText": "Jestliže Vás ${APP_NAME} baví, zvažte prosím, jestli si nechcete udělat\nchvilku na ohodnocení nebo napsání recenze. Poskytuje to užitečnou\nzpětnou vazbu a pomáhá podporovat budoucí vývoj.\n\nDíky!\n-eric",
|
||||||
"pleaseWaitText": "Prosím čekejte...",
|
"pleaseWaitText": "Prosím čekejte...",
|
||||||
"pluginsDetectedText": "Nové plugin(y) nalezeny. Zapněte/konfigurujte je v nastavení.",
|
"pluginClassLoadErrorText": "Chyba při načítání třídy pluginu '${PLUGIN}': ${ERROR}",
|
||||||
|
"pluginInitErrorText": "Chyba při inicializaci pluginu '${PLUGIN}': ${ERROR}",
|
||||||
|
"pluginsDetectedText": "Nové plugin(y) nalezeny. Pro aktivaci restartujte, nebo konfigurujte v nastavení.",
|
||||||
|
"pluginsRemovedText": "${NUM} plugin(y) nenalezeny.",
|
||||||
"pluginsText": "Pluginy",
|
"pluginsText": "Pluginy",
|
||||||
"practiceText": "Cvičení",
|
"practiceText": "Cvičení",
|
||||||
"pressAnyButtonPlayAgainText": "Stiskněte libovolné tlačítko pro opakování hry...",
|
"pressAnyButtonPlayAgainText": "Stiskněte libovolné tlačítko pro opakování hry...",
|
||||||
|
|
@ -1864,6 +1870,8 @@
|
||||||
"winsPlayerText": "${NAME} Vyhrál!",
|
"winsPlayerText": "${NAME} Vyhrál!",
|
||||||
"winsTeamText": "${NAME} Vyhrál!",
|
"winsTeamText": "${NAME} Vyhrál!",
|
||||||
"winsText": "${NAME} Vyhrál!",
|
"winsText": "${NAME} Vyhrál!",
|
||||||
|
"workspaceSyncErrorText": "Chyba synchronizace ${WORKSPACE}. Podrobnosti v logu.",
|
||||||
|
"workspaceSyncReuseText": "Nelze synchronizovat ${WORKSPACE}. Opětovné použití předchozí synchronizované verze.",
|
||||||
"worldScoresUnavailableText": "Světové skóre nepřístupné.",
|
"worldScoresUnavailableText": "Světové skóre nepřístupné.",
|
||||||
"worldsBestScoresText": "Světové nejlepší skóre",
|
"worldsBestScoresText": "Světové nejlepší skóre",
|
||||||
"worldsBestTimesText": "Světové nejlepší časy",
|
"worldsBestTimesText": "Světové nejlepší časy",
|
||||||
|
|
|
||||||
5
dist/ba_data/data/languages/english.json
vendored
5
dist/ba_data/data/languages/english.json
vendored
|
|
@ -624,7 +624,9 @@
|
||||||
"epicDescriptionFilterText": "${DESCRIPTION} In epic slow motion.",
|
"epicDescriptionFilterText": "${DESCRIPTION} In epic slow motion.",
|
||||||
"epicNameFilterText": "Epic ${NAME}",
|
"epicNameFilterText": "Epic ${NAME}",
|
||||||
"errorAccessDeniedText": "access denied",
|
"errorAccessDeniedText": "access denied",
|
||||||
|
"errorDeviceTimeIncorrectText": "Your device's time is off by ${HOURS} hours.\nThis is likely to cause problems.\nPlease check your time and time-zone settings.",
|
||||||
"errorOutOfDiskSpaceText": "out of disk space",
|
"errorOutOfDiskSpaceText": "out of disk space",
|
||||||
|
"errorSecureConnectionFailText": "Unable to establish secure cloud connection; network functionality may fail.",
|
||||||
"errorText": "Error",
|
"errorText": "Error",
|
||||||
"errorUnknownText": "unknown error",
|
"errorUnknownText": "unknown error",
|
||||||
"exitGameText": "Exit ${APP_NAME}?",
|
"exitGameText": "Exit ${APP_NAME}?",
|
||||||
|
|
@ -787,7 +789,7 @@
|
||||||
"ticketPack4Text": "Jumbo Ticket Pack",
|
"ticketPack4Text": "Jumbo Ticket Pack",
|
||||||
"ticketPack5Text": "Mammoth Ticket Pack",
|
"ticketPack5Text": "Mammoth Ticket Pack",
|
||||||
"ticketPack6Text": "Ultimate Ticket Pack",
|
"ticketPack6Text": "Ultimate Ticket Pack",
|
||||||
"ticketsFromASponsorText": "Get ${COUNT} tickets\nfrom a sponsor",
|
"ticketsFromASponsorText": "Watch an ad\nfor ${COUNT} tickets",
|
||||||
"ticketsText": "${COUNT} Tickets",
|
"ticketsText": "${COUNT} Tickets",
|
||||||
"titleText": "Get Tickets",
|
"titleText": "Get Tickets",
|
||||||
"unavailableLinkAccountText": "Sorry, purchases are not available on this platform.\nAs a workaround, you can link this account to an account on\nanother platform and make purchases there.",
|
"unavailableLinkAccountText": "Sorry, purchases are not available on this platform.\nAs a workaround, you can link this account to an account on\nanother platform and make purchases there.",
|
||||||
|
|
@ -798,6 +800,7 @@
|
||||||
"youHaveText": "you have ${COUNT} tickets"
|
"youHaveText": "you have ${COUNT} tickets"
|
||||||
},
|
},
|
||||||
"googleMultiplayerDiscontinuedText": "Sorry, Google’s multiplayer service is no longer available.\nI am working on a replacement as fast as possible.\nUntil then, please try another connection method.\n-Eric",
|
"googleMultiplayerDiscontinuedText": "Sorry, Google’s multiplayer service is no longer available.\nI am working on a replacement as fast as possible.\nUntil then, please try another connection method.\n-Eric",
|
||||||
|
"googlePlayPurchasesNotAvailableText": "Google Play purchases are not available.\nYou may need to update your store app.",
|
||||||
"googlePlayText": "Google Play",
|
"googlePlayText": "Google Play",
|
||||||
"graphicsSettingsWindow": {
|
"graphicsSettingsWindow": {
|
||||||
"alwaysText": "Always",
|
"alwaysText": "Always",
|
||||||
|
|
|
||||||
23
dist/ba_data/data/languages/filipino.json
vendored
23
dist/ba_data/data/languages/filipino.json
vendored
|
|
@ -325,6 +325,7 @@
|
||||||
"achievementsRemainingText": "Ang Mga Natitirang Nakamtan:",
|
"achievementsRemainingText": "Ang Mga Natitirang Nakamtan:",
|
||||||
"achievementsText": "Achievements",
|
"achievementsText": "Achievements",
|
||||||
"achievementsUnavailableForOldSeasonsText": "Pasensya na, hindi available ang mga detalye ng achievements para sa mga lumang seasons.",
|
"achievementsUnavailableForOldSeasonsText": "Pasensya na, hindi available ang mga detalye ng achievements para sa mga lumang seasons.",
|
||||||
|
"activatedText": "Na-aktibo ang ${THING}.",
|
||||||
"addGameWindow": {
|
"addGameWindow": {
|
||||||
"getMoreGamesText": "Kukuha ng higit pang mga laro…",
|
"getMoreGamesText": "Kukuha ng higit pang mga laro…",
|
||||||
"titleText": "Magdagdag Ng Laro"
|
"titleText": "Magdagdag Ng Laro"
|
||||||
|
|
@ -623,9 +624,11 @@
|
||||||
"epicDescriptionFilterText": "${DESCRIPTION} sa isang epic na slow motion.",
|
"epicDescriptionFilterText": "${DESCRIPTION} sa isang epic na slow motion.",
|
||||||
"epicNameFilterText": "Epikong ${NAME}",
|
"epicNameFilterText": "Epikong ${NAME}",
|
||||||
"errorAccessDeniedText": "walang pahintulot",
|
"errorAccessDeniedText": "walang pahintulot",
|
||||||
|
"errorDeviceTimeIncorrectText": "Ang oras ng iyong device ay naka-off nang ${HOURS} na oras.\nIto ay malamang na magdulot ng mga iba’t ibang problema.\nPakisuri ang iyong mga setting ng oras at time-zone.",
|
||||||
"errorOutOfDiskSpaceText": "Wala sa puwang ng disk",
|
"errorOutOfDiskSpaceText": "Wala sa puwang ng disk",
|
||||||
|
"errorSecureConnectionFailText": "Hindi mapatunayan ng secure na “cloud connection”; maaaring mabigo ang pagpapagana ng network.",
|
||||||
"errorText": "Error",
|
"errorText": "Error",
|
||||||
"errorUnknownText": "hindi batid na error",
|
"errorUnknownText": "error na ‘di malaman",
|
||||||
"exitGameText": "Exit mula sa ${APP_NAME}?",
|
"exitGameText": "Exit mula sa ${APP_NAME}?",
|
||||||
"exportSuccessText": "Na-export ang '${NAME}'.",
|
"exportSuccessText": "Na-export ang '${NAME}'.",
|
||||||
"externalStorageText": "External na Storage",
|
"externalStorageText": "External na Storage",
|
||||||
|
|
@ -786,7 +789,7 @@
|
||||||
"ticketPack4Text": "Malaking Pakete Ng Tiket",
|
"ticketPack4Text": "Malaking Pakete Ng Tiket",
|
||||||
"ticketPack5Text": "Mas Malaking Pakete Ng Tiket",
|
"ticketPack5Text": "Mas Malaking Pakete Ng Tiket",
|
||||||
"ticketPack6Text": "Pinakamalaking Pakete Ng Tiket",
|
"ticketPack6Text": "Pinakamalaking Pakete Ng Tiket",
|
||||||
"ticketsFromASponsorText": "Kumuha ng ${COUNT} na tiket\nmula sa isang sponsor",
|
"ticketsFromASponsorText": "Manood ng Ad\npara makuha ang ${COUNT} na tiket",
|
||||||
"ticketsText": "${COUNT} Tiket",
|
"ticketsText": "${COUNT} Tiket",
|
||||||
"titleText": "Kumuha Ng Tiket",
|
"titleText": "Kumuha Ng Tiket",
|
||||||
"unavailableLinkAccountText": "Pasensya na, hindi available ang pagbili sa platform na ito.\nBilang isang solusyon, maaari mong i-link ang account na ito sa isang account na nasa\nisa pang platform at bumili doon.",
|
"unavailableLinkAccountText": "Pasensya na, hindi available ang pagbili sa platform na ito.\nBilang isang solusyon, maaari mong i-link ang account na ito sa isang account na nasa\nisa pang platform at bumili doon.",
|
||||||
|
|
@ -797,6 +800,7 @@
|
||||||
"youHaveText": "mayroon kang ${COUNT} na tiket"
|
"youHaveText": "mayroon kang ${COUNT} na tiket"
|
||||||
},
|
},
|
||||||
"googleMultiplayerDiscontinuedText": "Pasensya na, hindi na available ang multiplayer na serbisyo ng Google.\nGumagawa ako ng kapalit sa lalong madaling panahon.\nHanggang doon, mangyaring sumubok ng ibang paraan ng koneksyon.\n-Eric",
|
"googleMultiplayerDiscontinuedText": "Pasensya na, hindi na available ang multiplayer na serbisyo ng Google.\nGumagawa ako ng kapalit sa lalong madaling panahon.\nHanggang doon, mangyaring sumubok ng ibang paraan ng koneksyon.\n-Eric",
|
||||||
|
"googlePlayPurchasesNotAvailableText": "Hindi puwede ang mga pagbili sa Google Play nito.\nMaaaring kailanganin mong i-update ang iyong store app.",
|
||||||
"googlePlayText": "Google Play",
|
"googlePlayText": "Google Play",
|
||||||
"graphicsSettingsWindow": {
|
"graphicsSettingsWindow": {
|
||||||
"alwaysText": "Palagi",
|
"alwaysText": "Palagi",
|
||||||
|
|
@ -836,11 +840,11 @@
|
||||||
"pickUpInfoTextScale": 0.5,
|
"pickUpInfoTextScale": 0.5,
|
||||||
"powerupBombDescriptionText": "Payagan kang maglabas ng tatlong bomba\nsa isang hilera sa halip na isa lamang.",
|
"powerupBombDescriptionText": "Payagan kang maglabas ng tatlong bomba\nsa isang hilera sa halip na isa lamang.",
|
||||||
"powerupBombNameText": "Tatlong-Bomba",
|
"powerupBombNameText": "Tatlong-Bomba",
|
||||||
"powerupCurseDescriptionText": "Malamang na gusto mong iwasan ang mga ito.\n ...o ikaw?",
|
"powerupCurseDescriptionText": "Malamang na gusto mong iwasan ang mga ganito.\n ...o sige lang?",
|
||||||
"powerupCurseNameText": "Sumpa",
|
"powerupCurseNameText": "Sumpa",
|
||||||
"powerupHealthDescriptionText": "Ibangon ka sa buong kalusugan.\nHindi mo naisip nito.",
|
"powerupHealthDescriptionText": "Ibangon ka sa buong kalusugan.\nHindi mo naisip nito.",
|
||||||
"powerupHealthNameText": "Medikal-Pakete",
|
"powerupHealthNameText": "Medikal-Pakete",
|
||||||
"powerupIceBombsDescriptionText": "Mas mahina kaysa sa mga normal na bomba\nngunit nagyelo ang iyong mga kalaban\nat partikular na malutong.",
|
"powerupIceBombsDescriptionText": "Mas mahina kaysa sa mga normal na bomba\nngunit nagyelo ang iyong mga kalaban\nat partikular na mabasag.",
|
||||||
"powerupIceBombsNameText": "Bombang-Yelo",
|
"powerupIceBombsNameText": "Bombang-Yelo",
|
||||||
"powerupImpactBombsDescriptionText": "Medyo mahina kaysa sa regular\nbomba, ngunit sumasabog ito kapag nabagsak.",
|
"powerupImpactBombsDescriptionText": "Medyo mahina kaysa sa regular\nbomba, ngunit sumasabog ito kapag nabagsak.",
|
||||||
"powerupImpactBombsNameText": "Gatilyong-Bomba",
|
"powerupImpactBombsNameText": "Gatilyong-Bomba",
|
||||||
|
|
@ -1089,7 +1093,7 @@
|
||||||
"titleText": "Maglaro",
|
"titleText": "Maglaro",
|
||||||
"twoToEightPlayersText": "2-8 na manlalaro"
|
"twoToEightPlayersText": "2-8 na manlalaro"
|
||||||
},
|
},
|
||||||
"playerCountAbbreviatedText": "${COUNT}n.m",
|
"playerCountAbbreviatedText": "${COUNT}p",
|
||||||
"playerDelayedJoinText": "Papasok si ${PLAYER} sa simula ng susunod na round.",
|
"playerDelayedJoinText": "Papasok si ${PLAYER} sa simula ng susunod na round.",
|
||||||
"playerInfoText": "Impormasyon ng Manlalaro",
|
"playerInfoText": "Impormasyon ng Manlalaro",
|
||||||
"playerLeftText": "Umalis si ${PLAYER} sa laro.",
|
"playerLeftText": "Umalis si ${PLAYER} sa laro.",
|
||||||
|
|
@ -1110,7 +1114,10 @@
|
||||||
"playlistsText": "Mga Playlist",
|
"playlistsText": "Mga Playlist",
|
||||||
"pleaseRateText": "Kung nae-enjoy mo ang ${APP_NAME}, mangyaring isaalang-alang ang \npagkuha na sandali lang at i-rate ito o pagsulat ng isang pagsusuri. Nagbibigay ito ngkapaki-pakinabang na feedback at \ntumutulong sa pagsuporta sa pag-unlad sa hinaharap.\n\nsalamat!\n-eric",
|
"pleaseRateText": "Kung nae-enjoy mo ang ${APP_NAME}, mangyaring isaalang-alang ang \npagkuha na sandali lang at i-rate ito o pagsulat ng isang pagsusuri. Nagbibigay ito ngkapaki-pakinabang na feedback at \ntumutulong sa pagsuporta sa pag-unlad sa hinaharap.\n\nsalamat!\n-eric",
|
||||||
"pleaseWaitText": "Hintay lang…",
|
"pleaseWaitText": "Hintay lang…",
|
||||||
|
"pluginClassLoadErrorText": "Error sa paglo-load ang '${PLUGIN}' na klaseng plugin : ${ERROR}",
|
||||||
|
"pluginInitErrorText": "Error sa pagsisimula ang '${PLUGIN}' na plugin: ${ERROR}",
|
||||||
"pluginsDetectedText": "May nakitang bagong (mga) plugin. I-restart para i-activate ang mga ito, o i-configure ang mga ito sa mga setting.",
|
"pluginsDetectedText": "May nakitang bagong (mga) plugin. I-restart para i-activate ang mga ito, o i-configure ang mga ito sa mga setting.",
|
||||||
|
"pluginsRemovedText": "Hindi na nahanapan ang ${NUM} ng (mga) plugin.",
|
||||||
"pluginsText": "Mga Plugin",
|
"pluginsText": "Mga Plugin",
|
||||||
"practiceText": "Pagsasagawa",
|
"practiceText": "Pagsasagawa",
|
||||||
"pressAnyButtonPlayAgainText": "Pindutin ang anumang button para maglaro muli...",
|
"pressAnyButtonPlayAgainText": "Pindutin ang anumang button para maglaro muli...",
|
||||||
|
|
@ -1453,7 +1460,7 @@
|
||||||
"kill ${ARG1} enemies": "patayin ang ${ARG1} na mga kalaban.",
|
"kill ${ARG1} enemies": "patayin ang ${ARG1} na mga kalaban.",
|
||||||
"last one standing wins": "kung sino ang huling nakatayo ang siyang mananalo",
|
"last one standing wins": "kung sino ang huling nakatayo ang siyang mananalo",
|
||||||
"last team standing wins": "kung sino ang huling katayuan ng team ang siyang mananalo",
|
"last team standing wins": "kung sino ang huling katayuan ng team ang siyang mananalo",
|
||||||
"return ${ARG1} flags": "ibalik ang ${ARG1} na mga bandera",
|
"return ${ARG1} flags": "Magnakaw ng ${ARG1} na mga bandera",
|
||||||
"return 1 flag": "ibalik ang 1 bandila",
|
"return 1 flag": "ibalik ang 1 bandila",
|
||||||
"run ${ARG1} laps": "Tumakbo ng ${ARG1} ikot",
|
"run ${ARG1} laps": "Tumakbo ng ${ARG1} ikot",
|
||||||
"run 1 lap": "tumakbo ng 1 ikot",
|
"run 1 lap": "tumakbo ng 1 ikot",
|
||||||
|
|
@ -1774,7 +1781,7 @@
|
||||||
"randomName3Text": "Stephen",
|
"randomName3Text": "Stephen",
|
||||||
"randomName4Text": "Joshua",
|
"randomName4Text": "Joshua",
|
||||||
"randomName5Text": "Villar",
|
"randomName5Text": "Villar",
|
||||||
"skipConfirmText": "Sure ka na i-skip ang tutorial? Tap o pindutin para ma i-confirm.",
|
"skipConfirmText": "Sure ka ba na i-skip ang tutorial? Tap o pindutin para ma i-confirm.",
|
||||||
"skipVoteCountText": "${COUNT}/${TOTAL} boto na gustong laktawan",
|
"skipVoteCountText": "${COUNT}/${TOTAL} boto na gustong laktawan",
|
||||||
"skippingText": "Nilalaktawan ang tutorial",
|
"skippingText": "Nilalaktawan ang tutorial",
|
||||||
"toSkipPressAnythingText": "(i-tap o pindutin ang anuman para laktawan ang tutorial)"
|
"toSkipPressAnythingText": "(i-tap o pindutin ang anuman para laktawan ang tutorial)"
|
||||||
|
|
@ -1844,6 +1851,8 @@
|
||||||
"winsPlayerText": "Nanalo si ${NAME}!",
|
"winsPlayerText": "Nanalo si ${NAME}!",
|
||||||
"winsTeamText": "Nanalo ang ${NAME}!",
|
"winsTeamText": "Nanalo ang ${NAME}!",
|
||||||
"winsText": "${NAME} Nanalo!",
|
"winsText": "${NAME} Nanalo!",
|
||||||
|
"workspaceSyncErrorText": "Error sa pag-sync ng ${WORKSPACE}. Tingnan ang log para sa mga detalye.",
|
||||||
|
"workspaceSyncReuseText": "Hindi ma-sync ang ${WORKSPACE}. Muling paggamit ng nakaraang naka-sync na bersyon.",
|
||||||
"worldScoresUnavailableText": "Ang scores sa buong mundo ay hindi pa handa",
|
"worldScoresUnavailableText": "Ang scores sa buong mundo ay hindi pa handa",
|
||||||
"worldsBestScoresText": "Pinakamahusay na Iskor ng Mundo",
|
"worldsBestScoresText": "Pinakamahusay na Iskor ng Mundo",
|
||||||
"worldsBestTimesText": "Pinakamahusay na Oras sa Mundo",
|
"worldsBestTimesText": "Pinakamahusay na Oras sa Mundo",
|
||||||
|
|
|
||||||
6
dist/ba_data/data/languages/gibberish.json
vendored
6
dist/ba_data/data/languages/gibberish.json
vendored
|
|
@ -661,7 +661,9 @@
|
||||||
"epicDescriptionFilterText": "${DESCRIPTION} Ín ípic slúw mztíon.",
|
"epicDescriptionFilterText": "${DESCRIPTION} Ín ípic slúw mztíon.",
|
||||||
"epicNameFilterText": "${NAME} Epícz",
|
"epicNameFilterText": "${NAME} Epícz",
|
||||||
"errorAccessDeniedText": "acczlr dnfflz",
|
"errorAccessDeniedText": "acczlr dnfflz",
|
||||||
|
"errorDeviceTimeIncorrectText": "Yowruc cowier oowefjwoefj ${HOURS} horewif.\noitwocweojowerjiowejjjfwoef.\nPefjwe wehapeocjjgwghwe w e weofwoefjwe.",
|
||||||
"errorOutOfDiskSpaceText": "orz of dkzk spzlfz",
|
"errorOutOfDiskSpaceText": "orz of dkzk spzlfz",
|
||||||
|
"errorSecureConnectionFailText": "Uweorcjwoef ojcowe werryyeoi nowe; jcnwoeroidfowdffdj.dfsdf.",
|
||||||
"errorText": "Errórz",
|
"errorText": "Errórz",
|
||||||
"errorUnknownText": "unknznlz errzzz",
|
"errorUnknownText": "unknznlz errzzz",
|
||||||
"exitGameText": "$Excej ${APP_NAME}",
|
"exitGameText": "$Excej ${APP_NAME}",
|
||||||
|
|
@ -749,6 +751,7 @@
|
||||||
"getFriendInviteCodeText": "Gz Frjor Infivo Cdz",
|
"getFriendInviteCodeText": "Gz Frjor Infivo Cdz",
|
||||||
"googlePlayDescriptionText": "Invlt Gglglz Plzlz plzlfer tz yzr prtaryz:",
|
"googlePlayDescriptionText": "Invlt Gglglz Plzlz plzlfer tz yzr prtaryz:",
|
||||||
"googlePlayInviteText": "Invtlzz",
|
"googlePlayInviteText": "Invtlzz",
|
||||||
|
"googlePlayPurchasesNotAvailableText": "JGowej eo owe weoirjweorjf\nYou we r wcowehpaw ecowjeoiwjrperpp.",
|
||||||
"googlePlayReInviteText": "Tnz arzs ${COUNT} Gflf Plzz Plalfjdsf oin weojf wfeoyowiufe\nwhiz ewofij woijdoisoic o asodf wfiawje;aoew aoiwfj.\nTIncowjf oweofjao wotonwei oiacoiw eotijweto tat.",
|
"googlePlayReInviteText": "Tnz arzs ${COUNT} Gflf Plzz Plalfjdsf oin weojf wfeoyowiufe\nwhiz ewofij woijdoisoic o asodf wfiawje;aoew aoiwfj.\nTIncowjf oweofjao wotonwei oiacoiw eotijweto tat.",
|
||||||
"googlePlaySeeInvitesText": "Szz Invtlfz",
|
"googlePlaySeeInvitesText": "Szz Invtlfz",
|
||||||
"googlePlayText": "Gzzlg Plz",
|
"googlePlayText": "Gzzlg Plz",
|
||||||
|
|
@ -841,7 +844,7 @@
|
||||||
"ticketPack4Text": "Jmfpmf Tkckf CPkf",
|
"ticketPack4Text": "Jmfpmf Tkckf CPkf",
|
||||||
"ticketPack5Text": "Mmthf Tckff Pckc",
|
"ticketPack5Text": "Mmthf Tckff Pckc",
|
||||||
"ticketPack6Text": "Ulzjtla Tkckdf Pck",
|
"ticketPack6Text": "Ulzjtla Tkckdf Pck",
|
||||||
"ticketsFromASponsorText": "Gzt ${COUNT} tkckjtz\nfzn a sobfhrkz",
|
"ticketsFromASponsorText": "woejwoe c woeijweo\ncowjeo ${COUNT} weocjw",
|
||||||
"ticketsText": "${COUNT} Tckrtzz",
|
"ticketsText": "${COUNT} Tckrtzz",
|
||||||
"titleText": "Gtz Tckrtz",
|
"titleText": "Gtz Tckrtz",
|
||||||
"unavailableLinkAccountText": "Srryrc, cpofj caodn oiwrj coi weo joweijwoief.\nIf wc woiejf w, cocwi eoiaoth aciw jeojfow iejoijwef\npcoj weo faona omowio wejfowijerwe.",
|
"unavailableLinkAccountText": "Srryrc, cpofj caodn oiwrj coi weo joweijwoief.\nIf wc woiejf w, cocwi eoiaoth aciw jeojfow iejoijwef\npcoj weo faona omowio wejfowijerwe.",
|
||||||
|
|
@ -852,6 +855,7 @@
|
||||||
"youHaveText": "yz hv ${COUNT} tickrrz"
|
"youHaveText": "yz hv ${COUNT} tickrrz"
|
||||||
},
|
},
|
||||||
"googleMultiplayerDiscontinuedText": "Sowoer Gojf wel wouwen weoioc long wf won.\nI wow oe wefwjr pif g wfpawouja c oeij fw ocjaoiejowr.\nUntil. cowier oa j fapefij cpoypt ao coonnec awoiery.\n-Ercff",
|
"googleMultiplayerDiscontinuedText": "Sowoer Gojf wel wouwen weoioc long wf won.\nI wow oe wefwjr pif g wfpawouja c oeij fw ocjaoiejowr.\nUntil. cowier oa j fapefij cpoypt ao coonnec awoiery.\n-Ercff",
|
||||||
|
"googlePlayPurchasesNotAvailableText": "Weofiiwj woe woerd wieofjwe\ncome foe rj eofiaj cpwoe jrowjer..dd",
|
||||||
"googlePlayText": "Gzzggl Plzz",
|
"googlePlayText": "Gzzggl Plzz",
|
||||||
"graphicsSettingsWindow": {
|
"graphicsSettingsWindow": {
|
||||||
"alwaysText": "Azlwáys",
|
"alwaysText": "Azlwáys",
|
||||||
|
|
|
||||||
6
dist/ba_data/data/languages/italian.json
vendored
6
dist/ba_data/data/languages/italian.json
vendored
|
|
@ -332,6 +332,7 @@
|
||||||
"achievementsRemainingText": "Trofei rimasti:",
|
"achievementsRemainingText": "Trofei rimasti:",
|
||||||
"achievementsText": "Trofei",
|
"achievementsText": "Trofei",
|
||||||
"achievementsUnavailableForOldSeasonsText": "Mi dispiace, ma gli obbiettivi non sono disponibili per le stagioni vecchie.",
|
"achievementsUnavailableForOldSeasonsText": "Mi dispiace, ma gli obbiettivi non sono disponibili per le stagioni vecchie.",
|
||||||
|
"activatedText": "${THING} attivato.",
|
||||||
"addGameWindow": {
|
"addGameWindow": {
|
||||||
"getMoreGamesText": "Ottieni Giochi...",
|
"getMoreGamesText": "Ottieni Giochi...",
|
||||||
"titleText": "Aggiungi Partita"
|
"titleText": "Aggiungi Partita"
|
||||||
|
|
@ -1162,7 +1163,10 @@
|
||||||
"playlistsText": "Scalette",
|
"playlistsText": "Scalette",
|
||||||
"pleaseRateText": "Se ti sta piacendo ${APP_NAME}, prenditi\nun momento per valutarlo o scriverci su una recensione.\nQuesto aiuterà a supportare futuri sviluppi.\n\nGrazie!\n-eric",
|
"pleaseRateText": "Se ti sta piacendo ${APP_NAME}, prenditi\nun momento per valutarlo o scriverci su una recensione.\nQuesto aiuterà a supportare futuri sviluppi.\n\nGrazie!\n-eric",
|
||||||
"pleaseWaitText": "Attendi...",
|
"pleaseWaitText": "Attendi...",
|
||||||
|
"pluginClassLoadErrorText": "Errore nel caricamento di plugin classe '${PLUGIN}': ${ERROR}",
|
||||||
|
"pluginInitErrorText": "Errore inizializzazione plugin '${PLUGIN}': ${ERROR}",
|
||||||
"pluginsDetectedText": "nuovo/i plugin rilevato. Riavvia per attivarli, o configurali nelle impostazioni.",
|
"pluginsDetectedText": "nuovo/i plugin rilevato. Riavvia per attivarli, o configurali nelle impostazioni.",
|
||||||
|
"pluginsRemovedText": "${NUM} plugin non trovati.",
|
||||||
"pluginsText": "Plugin",
|
"pluginsText": "Plugin",
|
||||||
"practiceText": "Allenamento",
|
"practiceText": "Allenamento",
|
||||||
"pressAnyButtonPlayAgainText": "Premi un pulsante qualunque per rigiocare...",
|
"pressAnyButtonPlayAgainText": "Premi un pulsante qualunque per rigiocare...",
|
||||||
|
|
@ -1943,6 +1947,8 @@
|
||||||
"winsPlayerText": "${NAME} Ha Vinto!",
|
"winsPlayerText": "${NAME} Ha Vinto!",
|
||||||
"winsTeamText": "${NAME} Ha Vinto!",
|
"winsTeamText": "${NAME} Ha Vinto!",
|
||||||
"winsText": "${NAME} vince!",
|
"winsText": "${NAME} vince!",
|
||||||
|
"workspaceSyncErrorText": "Errore nella sincronizzazione di ${WORKSPACE}. Controlla il registro per dettagli.",
|
||||||
|
"workspaceSyncReuseText": "Impossibile sincronizzare ${WORKSPACE}. Riutilizzo della versione sincronizzata precedente.",
|
||||||
"worldScoresUnavailableText": "Punteggi mondiali non disponibili.",
|
"worldScoresUnavailableText": "Punteggi mondiali non disponibili.",
|
||||||
"worldsBestScoresText": "I punteggi migliori del mondo",
|
"worldsBestScoresText": "I punteggi migliori del mondo",
|
||||||
"worldsBestTimesText": "I tempi migliori del mondo",
|
"worldsBestTimesText": "I tempi migliori del mondo",
|
||||||
|
|
|
||||||
12
dist/ba_data/data/languages/persian.json
vendored
12
dist/ba_data/data/languages/persian.json
vendored
|
|
@ -326,6 +326,7 @@
|
||||||
"achievementsRemainingText": "دستاورد های باقیمانده:",
|
"achievementsRemainingText": "دستاورد های باقیمانده:",
|
||||||
"achievementsText": "دستاوردها",
|
"achievementsText": "دستاوردها",
|
||||||
"achievementsUnavailableForOldSeasonsText": "ببخشید، دستاوردهای مخصوص فصل گذشته در دسترس نیستند",
|
"achievementsUnavailableForOldSeasonsText": "ببخشید، دستاوردهای مخصوص فصل گذشته در دسترس نیستند",
|
||||||
|
"activatedText": "${THING} فعال شد.",
|
||||||
"addGameWindow": {
|
"addGameWindow": {
|
||||||
"getMoreGamesText": "...بازی های بیشتر",
|
"getMoreGamesText": "...بازی های بیشتر",
|
||||||
"titleText": "افزودن بازی"
|
"titleText": "افزودن بازی"
|
||||||
|
|
@ -625,7 +626,9 @@
|
||||||
"epicDescriptionFilterText": "در حماسهٔ حرکت آهسته ${DESCRIPTION}",
|
"epicDescriptionFilterText": "در حماسهٔ حرکت آهسته ${DESCRIPTION}",
|
||||||
"epicNameFilterText": "${NAME} حماسهٔ",
|
"epicNameFilterText": "${NAME} حماسهٔ",
|
||||||
"errorAccessDeniedText": "دسترسی رد شد",
|
"errorAccessDeniedText": "دسترسی رد شد",
|
||||||
|
"errorDeviceTimeIncorrectText": "ساعت گوشی ${HOURS} ساعت خاموش بودهاست.\nممکن است مشکل بهوجود بیاید.\nلطفاً ساعت و منطقهٔ زمانی گوشیتان را بررسی کنید.",
|
||||||
"errorOutOfDiskSpaceText": "حافظه جا ندارد",
|
"errorOutOfDiskSpaceText": "حافظه جا ندارد",
|
||||||
|
"errorSecureConnectionFailText": "قادر به ایجاد اتصال ابری امن نیست. عملکرد شبکه ممکن است خراب شود.",
|
||||||
"errorText": "خطا",
|
"errorText": "خطا",
|
||||||
"errorUnknownText": "خطای ناشناخته",
|
"errorUnknownText": "خطای ناشناخته",
|
||||||
"exitGameText": "؟${APP_NAME} خروج از",
|
"exitGameText": "؟${APP_NAME} خروج از",
|
||||||
|
|
@ -788,7 +791,7 @@
|
||||||
"ticketPack4Text": "پک خیلی بزرگ بلیط",
|
"ticketPack4Text": "پک خیلی بزرگ بلیط",
|
||||||
"ticketPack5Text": "پک ماموتی بلیط",
|
"ticketPack5Text": "پک ماموتی بلیط",
|
||||||
"ticketPack6Text": "پک نهایی بلیط",
|
"ticketPack6Text": "پک نهایی بلیط",
|
||||||
"ticketsFromASponsorText": "بلیط از${COUNT}\nیه اسپانسر بگیرید",
|
"ticketsFromASponsorText": "در ازای ${COUNT} بلیت\nیک آگهی ببینید",
|
||||||
"ticketsText": "بلیط${COUNT}",
|
"ticketsText": "بلیط${COUNT}",
|
||||||
"titleText": "بلیط بگیرید",
|
"titleText": "بلیط بگیرید",
|
||||||
"unavailableLinkAccountText": ".ببخشید،خرید به وسیله ی این دستگاه در دسترس نمیباشد\nمیتوانید حسابتان بر روی این دستگاه را به حسابی در دستگاهی\n.دیگر متصل کنید و آنجا خرید خود را انجام دهید",
|
"unavailableLinkAccountText": ".ببخشید،خرید به وسیله ی این دستگاه در دسترس نمیباشد\nمیتوانید حسابتان بر روی این دستگاه را به حسابی در دستگاهی\n.دیگر متصل کنید و آنجا خرید خود را انجام دهید",
|
||||||
|
|
@ -1109,7 +1112,10 @@
|
||||||
"playlistsText": "لیست بازی ها",
|
"playlistsText": "لیست بازی ها",
|
||||||
"pleaseRateText": "خوشتان آمده، لطفاً چند لحظهای وقت بگذارید و ${APP_NAME} اگر از\nآن را رتبهبندی کنید یا مروری بر آن بنویسید. این کار بازخوردهای مفیدی\n.را به همراه دارد و به پشتیبانی از توسعهها در آینده کمک خواهد کرد\n\n!با تشکر\nاریک—",
|
"pleaseRateText": "خوشتان آمده، لطفاً چند لحظهای وقت بگذارید و ${APP_NAME} اگر از\nآن را رتبهبندی کنید یا مروری بر آن بنویسید. این کار بازخوردهای مفیدی\n.را به همراه دارد و به پشتیبانی از توسعهها در آینده کمک خواهد کرد\n\n!با تشکر\nاریک—",
|
||||||
"pleaseWaitText": "…لطفاً صبر کنید",
|
"pleaseWaitText": "…لطفاً صبر کنید",
|
||||||
"pluginsDetectedText": ".افزونه(ها)ی جدید شناسایی شد. آنها را در تنظیمات فعال/پیکربندی کنید",
|
"pluginClassLoadErrorText": "${ERROR} :«${PLUGIN}» خطا در بارگیری دستهبندی افزونهٔ",
|
||||||
|
"pluginInitErrorText": "${ERROR} :«${PLUGIN}» خطا در راهاندازی افزونهٔ",
|
||||||
|
"pluginsDetectedText": "افزونه(ها)ی جدید شناسایی شد. آنها را در تنظیمات فعال، یا پیکربندی کنید.",
|
||||||
|
"pluginsRemovedText": "${NUM} افزونه دیگر یافت نمیشود.",
|
||||||
"pluginsText": "افزونهها",
|
"pluginsText": "افزونهها",
|
||||||
"practiceText": "تمرین",
|
"practiceText": "تمرین",
|
||||||
"pressAnyButtonPlayAgainText": "…فشردن هر دکمهای برای بازی دوباره",
|
"pressAnyButtonPlayAgainText": "…فشردن هر دکمهای برای بازی دوباره",
|
||||||
|
|
@ -1847,6 +1853,8 @@
|
||||||
"winsPlayerText": "${NAME} برنده شد",
|
"winsPlayerText": "${NAME} برنده شد",
|
||||||
"winsTeamText": "${NAME} برنده شد",
|
"winsTeamText": "${NAME} برنده شد",
|
||||||
"winsText": "${NAME} برنده شد",
|
"winsText": "${NAME} برنده شد",
|
||||||
|
"workspaceSyncErrorText": "خطا در همگامسازی ${WORKSPACE}. برای جزئیات به لاگ مراجعه کنید.",
|
||||||
|
"workspaceSyncReuseText": "نمیتوان ${WORKSPACE} را همگامسازی کرد. استفادهٔ مجدد از نسخهٔ همگامسازیشده قبلی.",
|
||||||
"worldScoresUnavailableText": "امتیاز های جهانی قابل دسترس نیستند.",
|
"worldScoresUnavailableText": "امتیاز های جهانی قابل دسترس نیستند.",
|
||||||
"worldsBestScoresText": "بهترین امتیازهای جهانی",
|
"worldsBestScoresText": "بهترین امتیازهای جهانی",
|
||||||
"worldsBestTimesText": "بهترین زمان های جهانی",
|
"worldsBestTimesText": "بهترین زمان های جهانی",
|
||||||
|
|
|
||||||
11
dist/ba_data/data/languages/portuguese.json
vendored
11
dist/ba_data/data/languages/portuguese.json
vendored
|
|
@ -331,6 +331,7 @@
|
||||||
"achievementsRemainingText": "Conquistas restantes:",
|
"achievementsRemainingText": "Conquistas restantes:",
|
||||||
"achievementsText": "Conquistas",
|
"achievementsText": "Conquistas",
|
||||||
"achievementsUnavailableForOldSeasonsText": "Desculpe, algumas conquistas não estão disponíveis em temporadas antigas.",
|
"achievementsUnavailableForOldSeasonsText": "Desculpe, algumas conquistas não estão disponíveis em temporadas antigas.",
|
||||||
|
"activatedText": "${THING} foi ativado.",
|
||||||
"addGameWindow": {
|
"addGameWindow": {
|
||||||
"getMoreGamesText": "Mais jogos...",
|
"getMoreGamesText": "Mais jogos...",
|
||||||
"titleText": "Adicionar jogo"
|
"titleText": "Adicionar jogo"
|
||||||
|
|
@ -657,7 +658,9 @@
|
||||||
"epicDescriptionFilterText": "${DESCRIPTION} em câmera lenta épica.",
|
"epicDescriptionFilterText": "${DESCRIPTION} em câmera lenta épica.",
|
||||||
"epicNameFilterText": "${NAME} épico(a)",
|
"epicNameFilterText": "${NAME} épico(a)",
|
||||||
"errorAccessDeniedText": "acesso negado",
|
"errorAccessDeniedText": "acesso negado",
|
||||||
|
"errorDeviceTimeIncorrectText": "A hora do seu dispositivo está atrasada/adiantada em ${HOURS} horas.\nIsso poderá causar problemas.\nPor favor cheque as suas configurações de hora e fuso horário.",
|
||||||
"errorOutOfDiskSpaceText": "pouco espaço em disco",
|
"errorOutOfDiskSpaceText": "pouco espaço em disco",
|
||||||
|
"errorSecureConnectionFailText": "Não foi possível estabelecer uma conexão segura à nuvem; a funcionalidade da rede pode falhar.",
|
||||||
"errorText": "Erro",
|
"errorText": "Erro",
|
||||||
"errorUnknownText": "erro desconhecido",
|
"errorUnknownText": "erro desconhecido",
|
||||||
"exitGameText": "Sair do ${APP_NAME}?",
|
"exitGameText": "Sair do ${APP_NAME}?",
|
||||||
|
|
@ -832,7 +835,7 @@
|
||||||
"ticketPack4Text": "Pacote jumbo de bilhetes",
|
"ticketPack4Text": "Pacote jumbo de bilhetes",
|
||||||
"ticketPack5Text": "Pacote mamute de bilhete",
|
"ticketPack5Text": "Pacote mamute de bilhete",
|
||||||
"ticketPack6Text": "Pacote ultimate de bilhetes",
|
"ticketPack6Text": "Pacote ultimate de bilhetes",
|
||||||
"ticketsFromASponsorText": "Ganhe ${COUNT} bilhetes\nde um patrocinador",
|
"ticketsFromASponsorText": "Assista a um anúncio \ne ganhe ${COUNT} bilhetes",
|
||||||
"ticketsText": "${COUNT} bilhetes",
|
"ticketsText": "${COUNT} bilhetes",
|
||||||
"titleText": "Obter bilhetes",
|
"titleText": "Obter bilhetes",
|
||||||
"unavailableLinkAccountText": "Desculpe, as compras não estão disponíveis nesta plataforma.\nComo solução alternativa, você pode vincular esta conta para\noutra conta de outra plataforma e fazer compras lá.",
|
"unavailableLinkAccountText": "Desculpe, as compras não estão disponíveis nesta plataforma.\nComo solução alternativa, você pode vincular esta conta para\noutra conta de outra plataforma e fazer compras lá.",
|
||||||
|
|
@ -843,6 +846,7 @@
|
||||||
"youHaveText": "você possui ${COUNT} bilhetes"
|
"youHaveText": "você possui ${COUNT} bilhetes"
|
||||||
},
|
},
|
||||||
"googleMultiplayerDiscontinuedText": "Desculpe, o serviço multijogador do Google não está mais disponível.\nEstou trabalhando em uma substituição o mais rápido possível.\nAté lá, tente outro método de conexão.\n-Eric",
|
"googleMultiplayerDiscontinuedText": "Desculpe, o serviço multijogador do Google não está mais disponível.\nEstou trabalhando em uma substituição o mais rápido possível.\nAté lá, tente outro método de conexão.\n-Eric",
|
||||||
|
"googlePlayPurchasesNotAvailableText": "Compras pela Google Play não estão disponíveis.\nTalvez seja necessário atualizar sua loja para isso.",
|
||||||
"googlePlayText": "Google Play",
|
"googlePlayText": "Google Play",
|
||||||
"graphicsSettingsWindow": {
|
"graphicsSettingsWindow": {
|
||||||
"alwaysText": "Sempre",
|
"alwaysText": "Sempre",
|
||||||
|
|
@ -1183,7 +1187,10 @@
|
||||||
"playlistsText": "Playlists",
|
"playlistsText": "Playlists",
|
||||||
"pleaseRateText": "Se você está curtindo ${APP_NAME}, por favor, dê um tempinho\npara avaliar e comentar. Isso nos dá uma opinião útil\ne ajuda no desenvolvimento do jogo.\n\nobrigado!\n-eric",
|
"pleaseRateText": "Se você está curtindo ${APP_NAME}, por favor, dê um tempinho\npara avaliar e comentar. Isso nos dá uma opinião útil\ne ajuda no desenvolvimento do jogo.\n\nobrigado!\n-eric",
|
||||||
"pleaseWaitText": "Por favor, aguarde...",
|
"pleaseWaitText": "Por favor, aguarde...",
|
||||||
|
"pluginClassLoadErrorText": "Erro ao carregar a classe de um plugin '${PLUGIN}': ${ERROR}",
|
||||||
|
"pluginInitErrorText": "Erro ao inicializar plugin '${PLUGIN}': ${ERROR}",
|
||||||
"pluginsDetectedText": "Novo(s) plugin(s) detetados. Reinicie o jogo para ativá-los ou configure-os nas configurações.",
|
"pluginsDetectedText": "Novo(s) plugin(s) detetados. Reinicie o jogo para ativá-los ou configure-os nas configurações.",
|
||||||
|
"pluginsRemovedText": "${NUM} plugin(s) não foram encontrados.",
|
||||||
"pluginsText": "Plugins",
|
"pluginsText": "Plugins",
|
||||||
"practiceText": "Praticar",
|
"practiceText": "Praticar",
|
||||||
"pressAnyButtonPlayAgainText": "Aperte qualquer botão para jogar novamente...",
|
"pressAnyButtonPlayAgainText": "Aperte qualquer botão para jogar novamente...",
|
||||||
|
|
@ -1970,6 +1977,8 @@
|
||||||
"winsPlayerText": "${NAME} venceu!",
|
"winsPlayerText": "${NAME} venceu!",
|
||||||
"winsTeamText": "${NAME} venceu!",
|
"winsTeamText": "${NAME} venceu!",
|
||||||
"winsText": "${NAME} ganhou!",
|
"winsText": "${NAME} ganhou!",
|
||||||
|
"workspaceSyncErrorText": "Erro ao sincronizar ${WORKSPACE}. Veja o log para mais detalhes.",
|
||||||
|
"workspaceSyncReuseText": "Não pôde sincronizar ${WORKSPACE}. Reusando uma versão anterior sincronizada.",
|
||||||
"worldScoresUnavailableText": "Pontuações mundiais indisponíveis.",
|
"worldScoresUnavailableText": "Pontuações mundiais indisponíveis.",
|
||||||
"worldsBestScoresText": "Melhores pontuações do mundo",
|
"worldsBestScoresText": "Melhores pontuações do mundo",
|
||||||
"worldsBestTimesText": "Melhores tempos do mundo",
|
"worldsBestTimesText": "Melhores tempos do mundo",
|
||||||
|
|
|
||||||
43
dist/ba_data/data/languages/romanian.json
vendored
43
dist/ba_data/data/languages/romanian.json
vendored
|
|
@ -330,6 +330,7 @@
|
||||||
"achievementsRemainingText": "Realizări Rămase:",
|
"achievementsRemainingText": "Realizări Rămase:",
|
||||||
"achievementsText": "Realizări",
|
"achievementsText": "Realizări",
|
||||||
"achievementsUnavailableForOldSeasonsText": "Scuze, dar detaliile realizărilor din sezoanele trecute sunt indisponibile.",
|
"achievementsUnavailableForOldSeasonsText": "Scuze, dar detaliile realizărilor din sezoanele trecute sunt indisponibile.",
|
||||||
|
"activatedText": "${THING} a fost activat(ă).",
|
||||||
"addGameWindow": {
|
"addGameWindow": {
|
||||||
"getMoreGamesText": "Ia mai multe MiniJocuri...",
|
"getMoreGamesText": "Ia mai multe MiniJocuri...",
|
||||||
"titleText": "Adaugă un joc"
|
"titleText": "Adaugă un joc"
|
||||||
|
|
@ -349,14 +350,14 @@
|
||||||
"autoText": "Automat",
|
"autoText": "Automat",
|
||||||
"backText": "Înapoi",
|
"backText": "Înapoi",
|
||||||
"banThisPlayerText": "Interzice Accesul Acestui Jucător",
|
"banThisPlayerText": "Interzice Accesul Acestui Jucător",
|
||||||
"bestOfFinalText": "Finala Primul-La-${COUNT}",
|
"bestOfFinalText": "Finala Cel-Mai-Bun-Din-${COUNT}",
|
||||||
"bestOfSeriesText": "Seriile Primul-La-${COUNT}:",
|
"bestOfSeriesText": "Seriile Cel-Mai-Bun-Din-${COUNT}:",
|
||||||
"bestOfUseFirstToInstead": 1,
|
"bestOfUseFirstToInstead": 0,
|
||||||
"bestRankText": "Cea mai bună poziție a ta este: #${RANK}",
|
"bestRankText": "Cea mai bună poziție a ta este: #${RANK}",
|
||||||
"bestRatingText": "Cea mai bună notă a ta este ${RATING}",
|
"bestRatingText": "Cea mai bună notă a ta este ${RATING}",
|
||||||
"bombBoldText": "BOMBĂ",
|
"bombBoldText": "BOMBĂ",
|
||||||
"bombText": "Bombă",
|
"bombText": "Bombă",
|
||||||
"boostText": "Crește-ți",
|
"boostText": "Crește",
|
||||||
"bsRemoteConfigureInAppText": "${REMOTE_APP_NAME} este configurat în aplicația în sine.",
|
"bsRemoteConfigureInAppText": "${REMOTE_APP_NAME} este configurat în aplicația în sine.",
|
||||||
"buttonText": "buton",
|
"buttonText": "buton",
|
||||||
"canWeDebugText": "Ai vrea ca BombSquad să trimită automat bug-uri,\ncrash-uri și informații de bază programatorului jocului?\n\nAceste informații nu conțin date personale, ci doar\najută la îmbunătățirea jocului.",
|
"canWeDebugText": "Ai vrea ca BombSquad să trimită automat bug-uri,\ncrash-uri și informații de bază programatorului jocului?\n\nAceste informații nu conțin date personale, ci doar\najută la îmbunătățirea jocului.",
|
||||||
|
|
@ -629,7 +630,9 @@
|
||||||
"epicDescriptionFilterText": "${DESCRIPTION} În slow motion epic.",
|
"epicDescriptionFilterText": "${DESCRIPTION} În slow motion epic.",
|
||||||
"epicNameFilterText": "${NAME} Epic",
|
"epicNameFilterText": "${NAME} Epic",
|
||||||
"errorAccessDeniedText": "acces respins",
|
"errorAccessDeniedText": "acces respins",
|
||||||
|
"errorDeviceTimeIncorrectText": "Ceasul dispozitivului tău este dat înainte sau înapoi cu ${HOURS} ore.\nAcestu lucru ar putea cauza niște probleme.\nTe rog să verifici setările ceasului și ale fusului orar.",
|
||||||
"errorOutOfDiskSpaceText": "ai rămas fără memorie",
|
"errorOutOfDiskSpaceText": "ai rămas fără memorie",
|
||||||
|
"errorSecureConnectionFailText": "Nu s-a putut stabili o conexiune sigură cloud; funcționalitatea internetului ar putea eșua.",
|
||||||
"errorText": "Eroare",
|
"errorText": "Eroare",
|
||||||
"errorUnknownText": "eroare necunoscută",
|
"errorUnknownText": "eroare necunoscută",
|
||||||
"exitGameText": "Ieși din ${APP_NAME}?",
|
"exitGameText": "Ieși din ${APP_NAME}?",
|
||||||
|
|
@ -705,10 +708,10 @@
|
||||||
"friendHasSentPromoCodeText": "${COUNT} Bilete pe ${APP_NAME} de la ${NAME}",
|
"friendHasSentPromoCodeText": "${COUNT} Bilete pe ${APP_NAME} de la ${NAME}",
|
||||||
"friendPromoCodeAwardText": "Vei primi ${COUNT} de bilete de fiecare dată când este folosit.",
|
"friendPromoCodeAwardText": "Vei primi ${COUNT} de bilete de fiecare dată când este folosit.",
|
||||||
"friendPromoCodeExpireText": "Codul va expira în ${EXPIRE_HOURS} de ore şi este valabil doar pentru jucătorii noi.",
|
"friendPromoCodeExpireText": "Codul va expira în ${EXPIRE_HOURS} de ore şi este valabil doar pentru jucătorii noi.",
|
||||||
"friendPromoCodeInstructionsText": "Pentru a-l utiliza, deschide ${APP_NAME} și accesează „Setări-> Avansat-> Introdu codul”.\nConsultă bombsquadgame.com pentru linkuri de descărcare pentru toate platformele acceptate.",
|
"friendPromoCodeInstructionsText": "Pentru a-l utiliza, deschide ${APP_NAME} și accesează „Setări-> Avansat-> Introdu un cod”.\nConsultă bombsquadgame.com pentru linkuri de descărcare pentru toate platformele acceptate.",
|
||||||
"friendPromoCodeRedeemLongText": "Poate fi introdus pentru ${COUNT} de bilete gratuite de către un maxim de ${MAX_USES} de persoane.",
|
"friendPromoCodeRedeemLongText": "Poate fi introdus pentru ${COUNT} de bilete gratuite de către un maxim de ${MAX_USES} de persoane.",
|
||||||
"friendPromoCodeRedeemShortText": "Poate fi introdus în joc pentru ${COUNT} de bilete.",
|
"friendPromoCodeRedeemShortText": "Poate fi introdus în joc pentru ${COUNT} de bilete.",
|
||||||
"friendPromoCodeWhereToEnterText": "(în „Setări-> Avansat-> Introdu codul”)",
|
"friendPromoCodeWhereToEnterText": "(în \"Setări-> Avansat-> Introdu un cod\")",
|
||||||
"getFriendInviteCodeText": "Cere un Cod pentru Prieteni",
|
"getFriendInviteCodeText": "Cere un Cod pentru Prieteni",
|
||||||
"googlePlayDescriptionText": "Invită jucători Google Play la petrecerea ta:",
|
"googlePlayDescriptionText": "Invită jucători Google Play la petrecerea ta:",
|
||||||
"googlePlayInviteText": "Invită",
|
"googlePlayInviteText": "Invită",
|
||||||
|
|
@ -794,7 +797,7 @@
|
||||||
"ticketPack4Text": "Super-Pachet de Bilete",
|
"ticketPack4Text": "Super-Pachet de Bilete",
|
||||||
"ticketPack5Text": "Pachet de Bilete MAMUT",
|
"ticketPack5Text": "Pachet de Bilete MAMUT",
|
||||||
"ticketPack6Text": "Pachet de Bilete Suprem",
|
"ticketPack6Text": "Pachet de Bilete Suprem",
|
||||||
"ticketsFromASponsorText": "Ia ${COUNT} bilete\nde la un sponsor",
|
"ticketsFromASponsorText": "Vizionează o reclamă\npentru ${COUNT} bilete",
|
||||||
"ticketsText": "${COUNT} de Bilete",
|
"ticketsText": "${COUNT} de Bilete",
|
||||||
"titleText": "Ia Bilete",
|
"titleText": "Ia Bilete",
|
||||||
"unavailableLinkAccountText": "Scuze, dar achizițiile nu sunt disponibile pe această platformă.\nCa soluție, poți conecta acest cont la un alt cont de pe\no altă platformă și să faci cumpărături acolo.",
|
"unavailableLinkAccountText": "Scuze, dar achizițiile nu sunt disponibile pe această platformă.\nCa soluție, poți conecta acest cont la un alt cont de pe\no altă platformă și să faci cumpărături acolo.",
|
||||||
|
|
@ -805,6 +808,7 @@
|
||||||
"youHaveText": "ai ${COUNT} (de) bilete"
|
"youHaveText": "ai ${COUNT} (de) bilete"
|
||||||
},
|
},
|
||||||
"googleMultiplayerDiscontinuedText": "Ne pare rău, serviciul multiplayer de pe Google nu mai este disponibil.\nLucrez la un înlocuitor cât mai repede posibil.\nPână atunci, te rog să încerci o altă metodă de conectare.\n-Eric",
|
"googleMultiplayerDiscontinuedText": "Ne pare rău, serviciul multiplayer de pe Google nu mai este disponibil.\nLucrez la un înlocuitor cât mai repede posibil.\nPână atunci, te rog să încerci o altă metodă de conectare.\n-Eric",
|
||||||
|
"googlePlayPurchasesNotAvailableText": "Achizițiile de pe Google Play nu sunt disponibile.\nÎncearcă să actualizezi Magazin Play și să încerci din nou.",
|
||||||
"googlePlayText": "Google Play",
|
"googlePlayText": "Google Play",
|
||||||
"graphicsSettingsWindow": {
|
"graphicsSettingsWindow": {
|
||||||
"alwaysText": "Întotdeauna",
|
"alwaysText": "Întotdeauna",
|
||||||
|
|
@ -881,7 +885,7 @@
|
||||||
"buttonText": "buton",
|
"buttonText": "buton",
|
||||||
"cantKickHostError": "Nu poți da afară hostul server-ului.",
|
"cantKickHostError": "Nu poți da afară hostul server-ului.",
|
||||||
"chatBlockedText": "${NAME} este blocat în chat timp de ${TIME} (de) secunde.",
|
"chatBlockedText": "${NAME} este blocat în chat timp de ${TIME} (de) secunde.",
|
||||||
"connectedToGameText": "a intrat în „${NAME}”",
|
"connectedToGameText": "Ai intrat în '${NAME}'",
|
||||||
"connectedToPartyText": "Ai intrat în server-ul lui ${NAME}!",
|
"connectedToPartyText": "Ai intrat în server-ul lui ${NAME}!",
|
||||||
"connectingToPartyText": "Se conectează...",
|
"connectingToPartyText": "Se conectează...",
|
||||||
"connectionFailedHostAlreadyInPartyText": "Conexiunea a eşuat; hostul este în alt joc.",
|
"connectionFailedHostAlreadyInPartyText": "Conexiunea a eşuat; hostul este în alt joc.",
|
||||||
|
|
@ -915,7 +919,7 @@
|
||||||
"kickIdlePlayersKickedText": "${NAME} a fost dat afară deoarece era inactiv.",
|
"kickIdlePlayersKickedText": "${NAME} a fost dat afară deoarece era inactiv.",
|
||||||
"kickIdlePlayersWarning1Text": "${NAME} va fi dat afară în următoarele ${COUNT} secunde dacă continuă să fie inactiv.",
|
"kickIdlePlayersWarning1Text": "${NAME} va fi dat afară în următoarele ${COUNT} secunde dacă continuă să fie inactiv.",
|
||||||
"kickIdlePlayersWarning2Text": "(Poți dezactiva această setare în Setări -> Avansat)",
|
"kickIdlePlayersWarning2Text": "(Poți dezactiva această setare în Setări -> Avansat)",
|
||||||
"leftGameText": "A ieșit din ${NAME}",
|
"leftGameText": "Ai ieșit din '${NAME}'",
|
||||||
"leftPartyText": "Ai ieşit din server-ul lui ${NAME}.",
|
"leftPartyText": "Ai ieşit din server-ul lui ${NAME}.",
|
||||||
"noMusicFilesInFolderText": "Folder-ul nu conține niciun fişier de muzică.",
|
"noMusicFilesInFolderText": "Folder-ul nu conține niciun fişier de muzică.",
|
||||||
"playerJoinedPartyText": "${NAME} a intrat în joc!",
|
"playerJoinedPartyText": "${NAME} a intrat în joc!",
|
||||||
|
|
@ -1026,9 +1030,9 @@
|
||||||
"modeArcadeText": "Mod Pentru Arcade",
|
"modeArcadeText": "Mod Pentru Arcade",
|
||||||
"modeClassicText": "Modul Clasic",
|
"modeClassicText": "Modul Clasic",
|
||||||
"modeDemoText": "Modul Demonstrativ",
|
"modeDemoText": "Modul Demonstrativ",
|
||||||
"mostValuablePlayerText": "Cel mai valoros jucător este:",
|
"mostValuablePlayerText": "Cel mai valoros jucător este",
|
||||||
"mostViolatedPlayerText": "Cel mai ucis jucător este:",
|
"mostViolatedPlayerText": "Cel mai ucis jucător este",
|
||||||
"mostViolentPlayerText": "Cel mai violent jucător este:",
|
"mostViolentPlayerText": "Cel mai violent jucător este",
|
||||||
"moveText": "Te miști din",
|
"moveText": "Te miști din",
|
||||||
"multiKillText": "${COUNT} ucideri!!!",
|
"multiKillText": "${COUNT} ucideri!!!",
|
||||||
"multiPlayerCountText": "${COUNT} jucători",
|
"multiPlayerCountText": "${COUNT} jucători",
|
||||||
|
|
@ -1119,7 +1123,10 @@
|
||||||
"playlistsText": "Liste de Jocuri",
|
"playlistsText": "Liste de Jocuri",
|
||||||
"pleaseRateText": "Dacă îți place ${APP_NAME}, te rog să stai\no clipă și să evaluezi jocul, scriind o recenzie pentru acesta.\nAceasta furnizează feedback folositor și ajută la dezvoltarea jocului în viitor.\n\nmulțumesc!\n-Eric",
|
"pleaseRateText": "Dacă îți place ${APP_NAME}, te rog să stai\no clipă și să evaluezi jocul, scriind o recenzie pentru acesta.\nAceasta furnizează feedback folositor și ajută la dezvoltarea jocului în viitor.\n\nmulțumesc!\n-Eric",
|
||||||
"pleaseWaitText": "Te rog să aștepți...",
|
"pleaseWaitText": "Te rog să aștepți...",
|
||||||
|
"pluginClassLoadErrorText": "Nu s-a putut încărca plugin-ul '${PLUGIN}': ${ERROR}",
|
||||||
|
"pluginInitErrorText": "Nu s-a putut iniția plugin-ul '${PLUGIN}': ${ERROR}",
|
||||||
"pluginsDetectedText": "Plugin(uri) noi detectate. Restartează jocul pentru a le activa / configura în setări.",
|
"pluginsDetectedText": "Plugin(uri) noi detectate. Restartează jocul pentru a le activa / configura în setări.",
|
||||||
|
"pluginsRemovedText": "${NUM} plugin(uri) nu mai există.",
|
||||||
"pluginsText": "Plugin-uri",
|
"pluginsText": "Plugin-uri",
|
||||||
"practiceText": "Antrenament",
|
"practiceText": "Antrenament",
|
||||||
"pressAnyButtonPlayAgainText": "Apasă orice buton pentru a juca din nou...",
|
"pressAnyButtonPlayAgainText": "Apasă orice buton pentru a juca din nou...",
|
||||||
|
|
@ -1134,7 +1141,7 @@
|
||||||
"pressToSelectProfileText": "apasă ${BUTTONS} pentru a-ți selecta profilul",
|
"pressToSelectProfileText": "apasă ${BUTTONS} pentru a-ți selecta profilul",
|
||||||
"pressToSelectTeamText": "apasă ${BUTTONS} pentru a-ți selecta echipa",
|
"pressToSelectTeamText": "apasă ${BUTTONS} pentru a-ți selecta echipa",
|
||||||
"promoCodeWindow": {
|
"promoCodeWindow": {
|
||||||
"codeText": "Codul:",
|
"codeText": "Codul",
|
||||||
"codeTextDescription": "Cod Promoțional",
|
"codeTextDescription": "Cod Promoțional",
|
||||||
"enterText": "Trimite-l"
|
"enterText": "Trimite-l"
|
||||||
},
|
},
|
||||||
|
|
@ -1246,7 +1253,7 @@
|
||||||
"disableThisNotice": "(Poți dezactiva această notificare în setările avansate)",
|
"disableThisNotice": "(Poți dezactiva această notificare în setările avansate)",
|
||||||
"enablePackageModsDescriptionText": "Permite mai multe capabilități pentru modare, dar dezactivează net-play-ul)",
|
"enablePackageModsDescriptionText": "Permite mai multe capabilități pentru modare, dar dezactivează net-play-ul)",
|
||||||
"enablePackageModsText": "Activează Moduri cu Pachete Locale",
|
"enablePackageModsText": "Activează Moduri cu Pachete Locale",
|
||||||
"enterPromoCodeText": "Codul:",
|
"enterPromoCodeText": "Introdu un cod",
|
||||||
"forTestingText": "Notă: aceste valori sunt doar pentru teste şi vor fi resetate când jocul va fi închis.",
|
"forTestingText": "Notă: aceste valori sunt doar pentru teste şi vor fi resetate când jocul va fi închis.",
|
||||||
"helpTranslateText": "Translațiile din ${APP_NAME} sunt un efort depus de comunitate.\nDacă ai dori să te implici la translatarea/corectarea unei limbi,\nurmează linkul de mai jos. Mulțumiri anticipate!",
|
"helpTranslateText": "Translațiile din ${APP_NAME} sunt un efort depus de comunitate.\nDacă ai dori să te implici la translatarea/corectarea unei limbi,\nurmează linkul de mai jos. Mulțumiri anticipate!",
|
||||||
"kickIdlePlayersText": "Dă Afară Jucătorii Inactivi",
|
"kickIdlePlayersText": "Dă Afară Jucătorii Inactivi",
|
||||||
|
|
@ -1713,12 +1720,12 @@
|
||||||
"Don't run all the time. Really. You will fall off cliffs.": "Nu fugi tot timpul. Pe bune. Vei cădea de pe hărți.",
|
"Don't run all the time. Really. You will fall off cliffs.": "Nu fugi tot timpul. Pe bune. Vei cădea de pe hărți.",
|
||||||
"Don't spin for too long; you'll become dizzy and fall.": "Nu te învârti prea mult timp; vei ameți și vei fi pus la pământ.",
|
"Don't spin for too long; you'll become dizzy and fall.": "Nu te învârti prea mult timp; vei ameți și vei fi pus la pământ.",
|
||||||
"Hold any button to run. (Trigger buttons work well if you have them)": "Ține apăsat orice buton pentru a fugi. (Butoanele 'Trigger' funcționează bine şi ele dacă le ai)",
|
"Hold any button to run. (Trigger buttons work well if you have them)": "Ține apăsat orice buton pentru a fugi. (Butoanele 'Trigger' funcționează bine şi ele dacă le ai)",
|
||||||
"Hold down any button to run. You'll get places faster\nbut won't turn very well, so watch out for cliffs.": "Pentru a fugi,ține apăsat orice buton. Vei ajunge mai repede unde vrei,\ndar nu vei lua curba prea bine, așa că ai grijă să nu cazi de pe hărți.",
|
"Hold down any button to run. You'll get places faster\nbut won't turn very well, so watch out for cliffs.": "Pentru a fugi, ține apăsat orice buton. Vei ajunge mai repede unde vrei,\ndar nu vei lua curba prea bine, așa că ai grijă să nu cazi de pe hărți.",
|
||||||
"Ice bombs are not very powerful, but they freeze\nwhoever they hit, leaving them vulnerable to shattering.": "Bombele de gheață nu sunt foarte puternice, dar îngheață\npe oricine lovesc, lăsând victimele vulnerabile la spargere.",
|
"Ice bombs are not very powerful, but they freeze\nwhoever they hit, leaving them vulnerable to shattering.": "Bombele de gheață nu sunt foarte puternice, dar îngheață\npe oricine lovesc, lăsând victimele vulnerabile la spargere.",
|
||||||
"If someone picks you up, punch them and they'll let go.\nThis works in real life too.": "Dacă cineva te ia pe sus, dă-i un pumn și îți va da drumul.\n (Apropo, merge și în viața reală)",
|
"If someone picks you up, punch them and they'll let go.\nThis works in real life too.": "Dacă cineva te ia pe sus, dă-i un pumn și îți va da drumul.\n (Apropo, merge și în viața reală)",
|
||||||
"If you are short on controllers, install the '${REMOTE_APP_NAME}' app\non your mobile devices to use them as controllers.": "Dacă nu ai destule controllere, instalează aplicația '${REMOTE_APP_NAME}' \npe dispozitivele tale mobile pentru a le folosi drept controllere.",
|
"If you are short on controllers, install the '${REMOTE_APP_NAME}' app\non your mobile devices to use them as controllers.": "Dacă nu ai destule controllere, instalează aplicația '${REMOTE_APP_NAME}' \npe dispozitivele tale mobile pentru a le folosi drept controllere.",
|
||||||
"If you are short on controllers, install the 'BombSquad Remote' app\non your iOS or Android devices to use them as controllers.": "Dacă nu ai destule controllere, instalează 'BombSquad Remote' pe\nun dispozitiv Android sau iOS pentru a-l folosi ca pe un controller.",
|
"If you are short on controllers, install the 'BombSquad Remote' app\non your iOS or Android devices to use them as controllers.": "Dacă nu ai destule controllere, instalează 'BombSquad Remote' pe\nun dispozitiv Android sau iOS pentru a-l folosi ca pe un controller.",
|
||||||
"If you get a sticky-bomb stuck to you, jump around and spin in circles. You might\nshake the bomb off, or if nothing else your last moments will be entertaining.": "Dacă o bombă lipicioasă se lipește de tine, sari și rotește-te în cercuri. S-ar putea \nsă scapi de aceasta, dar dacă nu, vei face un spectacol minunat din ultimele tale momente rămase în viață.",
|
"If you get a sticky-bomb stuck to you, jump around and spin in circles. You might\nshake the bomb off, or if nothing else your last moments will be entertaining.": "Dacă se atinge vreodată o bombă lipicioasă de tine, sari și rotește-te în cercuri. S-ar putea \nsă scapi de aceasta, dar dacă nu, vei face un spectacol minunat din ultimele tale momente rămase în viață.",
|
||||||
"If you kill an enemy in one hit you get double points for it.": "Dacă omori un inamic dintr-o singură lovitură vei primi puncte duble.",
|
"If you kill an enemy in one hit you get double points for it.": "Dacă omori un inamic dintr-o singură lovitură vei primi puncte duble.",
|
||||||
"If you pick up a curse, your only hope for survival is to\nfind a health powerup in the next few seconds.": "Dacă atingi un blestem, singura ta şansă de a trăi este să\nprinzi o trusă de prim-ajutor în următoarele 5 secunde.",
|
"If you pick up a curse, your only hope for survival is to\nfind a health powerup in the next few seconds.": "Dacă atingi un blestem, singura ta şansă de a trăi este să\nprinzi o trusă de prim-ajutor în următoarele 5 secunde.",
|
||||||
"If you stay in one place, you're toast. Run and dodge to survive..": "Dacă stai într-un singur loc, vei muri ca un fraier. Ferește-te și aleargă din loc în loc pentru a supraviețui..",
|
"If you stay in one place, you're toast. Run and dodge to survive..": "Dacă stai într-un singur loc, vei muri ca un fraier. Ferește-te și aleargă din loc în loc pentru a supraviețui..",
|
||||||
|
|
@ -1863,6 +1870,8 @@
|
||||||
"winsPlayerText": "${NAME} Câștigă!",
|
"winsPlayerText": "${NAME} Câștigă!",
|
||||||
"winsTeamText": "${NAME} Câștigă!",
|
"winsTeamText": "${NAME} Câștigă!",
|
||||||
"winsText": "${NAME} Câștigă!",
|
"winsText": "${NAME} Câștigă!",
|
||||||
|
"workspaceSyncErrorText": "Nu s-a putut sincroniza ${WORKSPACE}. Vezi jurnalul de activități pentru detalii.",
|
||||||
|
"workspaceSyncReuseText": "Nu se poate sincroniza ${WORKSPACE}. Se va folosi ultima versiune sincronizată.",
|
||||||
"worldScoresUnavailableText": "Scorurile globale sunt indisponibile.",
|
"worldScoresUnavailableText": "Scorurile globale sunt indisponibile.",
|
||||||
"worldsBestScoresText": "Top Scoruri Mondiale",
|
"worldsBestScoresText": "Top Scoruri Mondiale",
|
||||||
"worldsBestTimesText": "Top Timpi Mondiali",
|
"worldsBestTimesText": "Top Timpi Mondiali",
|
||||||
|
|
|
||||||
105
dist/ba_data/data/languages/russian.json
vendored
105
dist/ba_data/data/languages/russian.json
vendored
|
|
@ -39,7 +39,7 @@
|
||||||
"testAccountWarningCardboardText": "Внимание: вы подписываете в с \"тест\" счета.\nЭти данные будут заменены со счетами Google сразу\nони становятся поддерживается в картонные приложений.\n\nСейчас вы будете зарабатывать все билеты в игре.\n(вы , тем не менее , получить Pro обновление BombSquad бесплатно )",
|
"testAccountWarningCardboardText": "Внимание: вы подписываете в с \"тест\" счета.\nЭти данные будут заменены со счетами Google сразу\nони становятся поддерживается в картонные приложений.\n\nСейчас вы будете зарабатывать все билеты в игре.\n(вы , тем не менее , получить Pro обновление BombSquad бесплатно )",
|
||||||
"testAccountWarningOculusText": "Внимание: вы входите под акканутом \"test\".\nОни будут заменены аккаунтами Oculus позже в этом\nгоду, что позволит совершать покупки билетов и многое другое.\n\nНа данный момент вам придется зарабатывать билеты в игре.\n(однако, вы получаете обновление BombSquad Pro бесплатно)",
|
"testAccountWarningOculusText": "Внимание: вы входите под акканутом \"test\".\nОни будут заменены аккаунтами Oculus позже в этом\nгоду, что позволит совершать покупки билетов и многое другое.\n\nНа данный момент вам придется зарабатывать билеты в игре.\n(однако, вы получаете обновление BombSquad Pro бесплатно)",
|
||||||
"testAccountWarningText": "Внимание: вы заходите под аккаунтом \"test\".\nЭтот аккаунт привязан к конкретному устройству и может\nпериодически сбрасываться. (так что лучше особо\nне тратить время на сбор/разблокировку добра в нем)\n\nЧтобы использовать настоящий аккаунт (Game-Center,\nGoogle Plus и т.д.), запустите платную версию. Это также\nпозволит сохранять свой прогресс в облаке и делать его\nдоступным для разных устройств.",
|
"testAccountWarningText": "Внимание: вы заходите под аккаунтом \"test\".\nЭтот аккаунт привязан к конкретному устройству и может\nпериодически сбрасываться. (так что лучше особо\nне тратить время на сбор/разблокировку добра в нем)\n\nЧтобы использовать настоящий аккаунт (Game-Center,\nGoogle Plus и т.д.), запустите платную версию. Это также\nпозволит сохранять свой прогресс в облаке и делать его\nдоступным для разных устройств.",
|
||||||
"ticketsText": "Билетов: ${COUNT}",
|
"ticketsText": "Количество билетов: ${COUNT}",
|
||||||
"titleText": "Аккаунт",
|
"titleText": "Аккаунт",
|
||||||
"unlinkAccountsInstructionsText": "Выберите аккаунт, который хотите отвязать",
|
"unlinkAccountsInstructionsText": "Выберите аккаунт, который хотите отвязать",
|
||||||
"unlinkAccountsText": "Отвязать аккаунты",
|
"unlinkAccountsText": "Отвязать аккаунты",
|
||||||
|
|
@ -49,14 +49,14 @@
|
||||||
"youAreSignedInAsText": "Вы вошли как:"
|
"youAreSignedInAsText": "Вы вошли как:"
|
||||||
},
|
},
|
||||||
"achievementChallengesText": "Достижения",
|
"achievementChallengesText": "Достижения",
|
||||||
"achievementText": "Медаль",
|
"achievementText": "Достижение",
|
||||||
"achievements": {
|
"achievements": {
|
||||||
"Boom Goes the Dynamite": {
|
"Boom Goes the Dynamite": {
|
||||||
"description": "Убейте 3 плохих парней с помощью TNT",
|
"description": "Убейте 3 плохих парней с помощью TNT",
|
||||||
"descriptionComplete": "С помощью TNT убито 3 плохих парней",
|
"descriptionComplete": "С помощью TNT убито 3 плохих парней",
|
||||||
"descriptionFull": "Убейте 3 плохих парней с помощью TNT на уровне ${LEVEL}",
|
"descriptionFull": "Убейте 3 плохих парней с помощью TNT на уровне ${LEVEL}",
|
||||||
"descriptionFullComplete": "3 плохих парней убито с помощью TNT на уровне ${LEVEL}",
|
"descriptionFullComplete": "3 плохих парней убито с помощью TNT на уровне ${LEVEL}",
|
||||||
"name": "Сейчас бабахнет"
|
"name": "Динамит сейчас взорвётся!"
|
||||||
},
|
},
|
||||||
"Boxer": {
|
"Boxer": {
|
||||||
"description": "Победите без использования бомб",
|
"description": "Победите без использования бомб",
|
||||||
|
|
@ -134,7 +134,7 @@
|
||||||
"descriptionComplete": "С карты сброшено 3 негодяя",
|
"descriptionComplete": "С карты сброшено 3 негодяя",
|
||||||
"descriptionFull": "Сбросьте 3 негодяев с карты на уровне ${LEVEL}",
|
"descriptionFull": "Сбросьте 3 негодяев с карты на уровне ${LEVEL}",
|
||||||
"descriptionFullComplete": "3 негодяя сброшено с карты на уровне ${LEVEL}",
|
"descriptionFullComplete": "3 негодяя сброшено с карты на уровне ${LEVEL}",
|
||||||
"name": "Давай отсюда"
|
"name": "Пора учится летать"
|
||||||
},
|
},
|
||||||
"Onslaught God": {
|
"Onslaught God": {
|
||||||
"description": "Наберите 5000 очков",
|
"description": "Наберите 5000 очков",
|
||||||
|
|
@ -180,7 +180,7 @@
|
||||||
},
|
},
|
||||||
"Pro Football Shutout": {
|
"Pro Football Shutout": {
|
||||||
"description": "Победите в сухую",
|
"description": "Победите в сухую",
|
||||||
"descriptionComplete": "Победил в сухую",
|
"descriptionComplete": "Уровень был пройден в сухую",
|
||||||
"descriptionFull": "Выиграйте матч ${LEVEL} в сухую",
|
"descriptionFull": "Выиграйте матч ${LEVEL} в сухую",
|
||||||
"descriptionFullComplete": "Победа в матче ${LEVEL} в сухую",
|
"descriptionFullComplete": "Победа в матче ${LEVEL} в сухую",
|
||||||
"name": "${LEVEL} в сухую"
|
"name": "${LEVEL} в сухую"
|
||||||
|
|
@ -194,9 +194,9 @@
|
||||||
},
|
},
|
||||||
"Pro Onslaught Victory": {
|
"Pro Onslaught Victory": {
|
||||||
"description": "Победите все волны",
|
"description": "Победите все волны",
|
||||||
"descriptionComplete": "Побеждены все волны",
|
"descriptionComplete": "Пройдены все волны",
|
||||||
"descriptionFull": "Победите все волны на уровне ${LEVEL}",
|
"descriptionFull": "Победите все волны на уровне ${LEVEL}",
|
||||||
"descriptionFullComplete": "Побеждены все волны на уровне ${LEVEL}",
|
"descriptionFullComplete": "Пройдены все волны на ${LEVEL}",
|
||||||
"name": "Победа на уровне ${LEVEL}"
|
"name": "Победа на уровне ${LEVEL}"
|
||||||
},
|
},
|
||||||
"Pro Runaround Victory": {
|
"Pro Runaround Victory": {
|
||||||
|
|
@ -215,7 +215,7 @@
|
||||||
},
|
},
|
||||||
"Rookie Football Victory": {
|
"Rookie Football Victory": {
|
||||||
"description": "Выиграйте матч",
|
"description": "Выиграйте матч",
|
||||||
"descriptionComplete": "Матч выигран",
|
"descriptionComplete": "Матч пройден в вашу пользу",
|
||||||
"descriptionFull": "Выиграйте матч ${LEVEL}",
|
"descriptionFull": "Выиграйте матч ${LEVEL}",
|
||||||
"descriptionFullComplete": "Выигран матч ${LEVEL}",
|
"descriptionFullComplete": "Выигран матч ${LEVEL}",
|
||||||
"name": "Победа в матче ${LEVEL}"
|
"name": "Победа в матче ${LEVEL}"
|
||||||
|
|
@ -250,7 +250,7 @@
|
||||||
},
|
},
|
||||||
"Sharing is Caring": {
|
"Sharing is Caring": {
|
||||||
"descriptionFull": "Успешно поделиться игрой с другом",
|
"descriptionFull": "Успешно поделиться игрой с другом",
|
||||||
"descriptionFullComplete": "Игра успешно поделена с другом",
|
"descriptionFullComplete": "Игра успешно передана другу",
|
||||||
"name": "Делиться - значит заботиться"
|
"name": "Делиться - значит заботиться"
|
||||||
},
|
},
|
||||||
"Stayin' Alive": {
|
"Stayin' Alive": {
|
||||||
|
|
@ -309,7 +309,7 @@
|
||||||
},
|
},
|
||||||
"Uber Football Victory": {
|
"Uber Football Victory": {
|
||||||
"description": "Выиграйте матч",
|
"description": "Выиграйте матч",
|
||||||
"descriptionComplete": "Матч выигран",
|
"descriptionComplete": "Матч пройден в вашу пользу",
|
||||||
"descriptionFull": "Выиграйте матч ${LEVEL}",
|
"descriptionFull": "Выиграйте матч ${LEVEL}",
|
||||||
"descriptionFullComplete": "Выигран матч ${LEVEL}",
|
"descriptionFullComplete": "Выигран матч ${LEVEL}",
|
||||||
"name": "Победа в матче ${LEVEL}"
|
"name": "Победа в матче ${LEVEL}"
|
||||||
|
|
@ -329,9 +329,10 @@
|
||||||
"name": "Победа на уровне ${LEVEL}"
|
"name": "Победа на уровне ${LEVEL}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"achievementsRemainingText": "Оставшиеся медали:",
|
"achievementsRemainingText": "Осталось достижений:",
|
||||||
"achievementsText": "Медали",
|
"achievementsText": "Достижения",
|
||||||
"achievementsUnavailableForOldSeasonsText": "К сожалению, подробности достижений не доступны для старых сезонов.",
|
"achievementsUnavailableForOldSeasonsText": "К сожалению, подробности достижений не доступны для старых сезонов.",
|
||||||
|
"activatedText": "${THING} активировано.",
|
||||||
"addGameWindow": {
|
"addGameWindow": {
|
||||||
"getMoreGamesText": "Еще игр...",
|
"getMoreGamesText": "Еще игр...",
|
||||||
"titleText": "Добавить игру"
|
"titleText": "Добавить игру"
|
||||||
|
|
@ -340,7 +341,7 @@
|
||||||
"alreadySignedInText": "На вашем аккаунте играют на другом устройстве;\nпожалуйста зайдите с другого аккаунта или закройте\nигру на другом устройстве и попытайтесь снова.",
|
"alreadySignedInText": "На вашем аккаунте играют на другом устройстве;\nпожалуйста зайдите с другого аккаунта или закройте\nигру на другом устройстве и попытайтесь снова.",
|
||||||
"apiVersionErrorText": "Невозможно загрузить модуль ${NAME}; он предназначен для API версии ${VERSION_USED}; здесь требуется версия ${VERSION_REQUIRED}.",
|
"apiVersionErrorText": "Невозможно загрузить модуль ${NAME}; он предназначен для API версии ${VERSION_USED}; здесь требуется версия ${VERSION_REQUIRED}.",
|
||||||
"audioSettingsWindow": {
|
"audioSettingsWindow": {
|
||||||
"headRelativeVRAudioInfoText": "(Режим \"Авто\" включает его только когда подключены наушники)",
|
"headRelativeVRAudioInfoText": "(Режим \"Авто\" активируется только при подключении наушников)",
|
||||||
"headRelativeVRAudioText": "Позиционно-зависимое ВР-аудио",
|
"headRelativeVRAudioText": "Позиционно-зависимое ВР-аудио",
|
||||||
"musicVolumeText": "Громкость музыки",
|
"musicVolumeText": "Громкость музыки",
|
||||||
"soundVolumeText": "Громкость звука",
|
"soundVolumeText": "Громкость звука",
|
||||||
|
|
@ -374,37 +375,37 @@
|
||||||
"completeThisLevelToProceedText": "Чтобы продолжить, нужно\nпройти этот уровень!",
|
"completeThisLevelToProceedText": "Чтобы продолжить, нужно\nпройти этот уровень!",
|
||||||
"completionBonusText": "Бонус за прохождение",
|
"completionBonusText": "Бонус за прохождение",
|
||||||
"configControllersWindow": {
|
"configControllersWindow": {
|
||||||
"configureControllersText": "Настройка контроллеров",
|
"configureControllersText": "Настройка геймпада",
|
||||||
"configureGamepadsText": "Настройка контроллеров",
|
"configureGamepadsText": "Настройка контроллеров",
|
||||||
"configureKeyboard2Text": "Настройка клавиатуры P2",
|
"configureKeyboard2Text": "Настройка клавиатуры P2",
|
||||||
"configureKeyboardText": "Настройка клавиатуры",
|
"configureKeyboardText": "Настройка клавиатуры",
|
||||||
"configureMobileText": "Мобильные устройства как контроллеры",
|
"configureMobileText": "Использовать мобильные устройства в качестве геймпадов",
|
||||||
"configureTouchText": "Настройка сенсорного экрана",
|
"configureTouchText": "Настройка сенсорного экрана",
|
||||||
"ps3Text": "Контроллеры PS3",
|
"ps3Text": "Геймпады PS3™",
|
||||||
"titleText": "Контроллеры",
|
"titleText": "Геймпады",
|
||||||
"wiimotesText": "Контроллеры Wii",
|
"wiimotesText": "Пульт Wii™",
|
||||||
"xbox360Text": "Контроллеры Xbox 360"
|
"xbox360Text": "Геймпады Xbox 360™"
|
||||||
},
|
},
|
||||||
"configGamepadSelectWindow": {
|
"configGamepadSelectWindow": {
|
||||||
"androidNoteText": "Внимание: поддержка контроллеров различается в зависимости от устройства и версии Android.",
|
"androidNoteText": "Внимание: поддержка геймпада различается в зависимости от устройства и версии Android.",
|
||||||
"pressAnyButtonText": "Нажмите любую кнопку на контроллере,\n который хотите настроить...",
|
"pressAnyButtonText": "Нажмите любую кнопку на геймпаде,\n которую хотите настроить...",
|
||||||
"titleText": "Настроить контроллер"
|
"titleText": "Настроить геймпад"
|
||||||
},
|
},
|
||||||
"configGamepadWindow": {
|
"configGamepadWindow": {
|
||||||
"advancedText": "Дополнительно",
|
"advancedText": "Дополнительно",
|
||||||
"advancedTitleText": "Дополнительные настройки контроллера",
|
"advancedTitleText": "Дополнительные настройки геймпада",
|
||||||
"analogStickDeadZoneDescriptionText": "(Включите, если персонаж продолжает двигаться после того, как стик отпущен)",
|
"analogStickDeadZoneDescriptionText": "(Включите, если персонаж продолжает двигаться после того, как стик отпущен)",
|
||||||
"analogStickDeadZoneText": "Мертвая зона аналогового стика",
|
"analogStickDeadZoneText": "Мертвая зона аналогового стика",
|
||||||
"appliesToAllText": "(относится ко всем контроллерам данного типа)",
|
"appliesToAllText": "(настроить ко всем геймпадам данного типа)",
|
||||||
"autoRecalibrateDescriptionText": "(включить, если персонаж не двигается на полной скорости)",
|
"autoRecalibrateDescriptionText": "(включить, если персонаж не двигается на полной скорости)",
|
||||||
"autoRecalibrateText": "Авто-перекалибровка аналоговых стиков",
|
"autoRecalibrateText": "Авто-перекалибровка аналоговых стиков",
|
||||||
"axisText": "ось",
|
"axisText": "ось",
|
||||||
"clearText": "очистить",
|
"clearText": "очистить",
|
||||||
"dpadText": "D-Pad",
|
"dpadText": "D-Pad",
|
||||||
"extraStartButtonText": "Дополнительная кнопка \"Старт",
|
"extraStartButtonText": "Настроить дополнительную кнопку \"Start\"",
|
||||||
"ifNothingHappensTryAnalogText": "Если ничего не происходит, попробуйте вместо этого присвоить аналоговому стику.",
|
"ifNothingHappensTryAnalogText": "Если ничего не происходит, попробуйте вместо этого присвоить аналоговому стику.",
|
||||||
"ifNothingHappensTryDpadText": "Если ничего не происходит, попробуйте вместо этого присвоить D-Pad.",
|
"ifNothingHappensTryDpadText": "Если ничего не происходит, попробуйте вместо этого присвоить D-Pad.",
|
||||||
"ignoreCompletelyDescriptionText": "(не дайте этому контроллеру воздействовать на игру, или меню)",
|
"ignoreCompletelyDescriptionText": "(запретить геймпаду воздействовать на игру, или меню)",
|
||||||
"ignoreCompletelyText": "Игнорировать полностью",
|
"ignoreCompletelyText": "Игнорировать полностью",
|
||||||
"ignoredButton1Text": "Игнорируемая кнопка 1",
|
"ignoredButton1Text": "Игнорируемая кнопка 1",
|
||||||
"ignoredButton2Text": "Игнорируемая кнопка 2",
|
"ignoredButton2Text": "Игнорируемая кнопка 2",
|
||||||
|
|
@ -422,13 +423,13 @@
|
||||||
"runTrigger1Text": "Триггер для бега 1",
|
"runTrigger1Text": "Триггер для бега 1",
|
||||||
"runTrigger2Text": "Триггер для бега 2",
|
"runTrigger2Text": "Триггер для бега 2",
|
||||||
"runTriggerDescriptionText": "(аналоговые триггеры позволяют бегать с разной скоростью)",
|
"runTriggerDescriptionText": "(аналоговые триггеры позволяют бегать с разной скоростью)",
|
||||||
"secondHalfText": "Используйте это для настройки второй половины\nустройства 'два контроллера в одном',\nкоторое показывается как один контроллер.",
|
"secondHalfText": "Используйте эту опцию для настройки второй\nполовины устройства \"два геймпада в одном\",\nдля использования в качестве одного геймпада.",
|
||||||
"secondaryEnableText": "Включить",
|
"secondaryEnableText": "Включить",
|
||||||
"secondaryText": "Вторичный контроллер",
|
"secondaryText": "Второй геймпад",
|
||||||
"startButtonActivatesDefaultDescriptionText": "(выключить, если ваша кнопка \"старт\" работает больше в качестве кнопки \"меню\")",
|
"startButtonActivatesDefaultDescriptionText": "(выключить, если ваша кнопка \"старт\" работает больше в качестве кнопки \"меню\")",
|
||||||
"startButtonActivatesDefaultText": "Кнопка Старт активирует стандартный виджет",
|
"startButtonActivatesDefaultText": "Кнопка Старт активирует стандартный виджет",
|
||||||
"titleText": "Настройка контроллера",
|
"titleText": "Настройка геймпада",
|
||||||
"twoInOneSetupText": "Настройка контроллера 2-в-1",
|
"twoInOneSetupText": "Настройка геймпада 2-в-1",
|
||||||
"uiOnlyDescriptionText": "(Запретить этому контроллеру присоединяться к игре)",
|
"uiOnlyDescriptionText": "(Запретить этому контроллеру присоединяться к игре)",
|
||||||
"uiOnlyText": "Ограничить только для меню",
|
"uiOnlyText": "Ограничить только для меню",
|
||||||
"unassignedButtonsRunText": "Все неприсвоенные кнопки для бега",
|
"unassignedButtonsRunText": "Все неприсвоенные кнопки для бега",
|
||||||
|
|
@ -481,8 +482,8 @@
|
||||||
"challengesText": "Испытания",
|
"challengesText": "Испытания",
|
||||||
"currentBestText": "Последний рекорд",
|
"currentBestText": "Последний рекорд",
|
||||||
"customText": "Другое",
|
"customText": "Другое",
|
||||||
"entryFeeText": "Участие",
|
"entryFeeText": "Участвовать",
|
||||||
"forfeitConfirmText": "Так просто сдаться?",
|
"forfeitConfirmText": "Сдаться?",
|
||||||
"forfeitNotAllowedYetText": "Вы не можете покинуть это состязание.",
|
"forfeitNotAllowedYetText": "Вы не можете покинуть это состязание.",
|
||||||
"forfeitText": "Сдаться",
|
"forfeitText": "Сдаться",
|
||||||
"multipliersText": "Множители",
|
"multipliersText": "Множители",
|
||||||
|
|
@ -651,14 +652,16 @@
|
||||||
"epicDescriptionFilterText": "${DESCRIPTION} в эпическом замедленном действии.",
|
"epicDescriptionFilterText": "${DESCRIPTION} в эпическом замедленном действии.",
|
||||||
"epicNameFilterText": "${NAME} в эпическом режиме",
|
"epicNameFilterText": "${NAME} в эпическом режиме",
|
||||||
"errorAccessDeniedText": "доступ запрещен",
|
"errorAccessDeniedText": "доступ запрещен",
|
||||||
|
"errorDeviceTimeIncorrectText": "Время на устройстве отстает на ${HOURS} часов.\nЭто вызывает проблемы.\nПожалуйста, проверьте настройки времени и часового пояса.",
|
||||||
"errorOutOfDiskSpaceText": "нет места на диске",
|
"errorOutOfDiskSpaceText": "нет места на диске",
|
||||||
|
"errorSecureConnectionFailText": "Ошибка установки безопасного облачного соединения; сетевые функции могут дать сбой.",
|
||||||
"errorText": "Ошибка",
|
"errorText": "Ошибка",
|
||||||
"errorUnknownText": "неизвестная ошибка",
|
"errorUnknownText": "неизвестная ошибка",
|
||||||
"exitGameText": "Выйти из ${APP_NAME}?",
|
"exitGameText": "Выйти из ${APP_NAME}?",
|
||||||
"exportSuccessText": "'${NAME}' экспортирован.",
|
"exportSuccessText": "'${NAME}' экспортирован.",
|
||||||
"externalStorageText": "Внешняя память",
|
"externalStorageText": "Внешняя память",
|
||||||
"failText": "Провал",
|
"failText": "Провал",
|
||||||
"fatalErrorText": "Ой, что-то потерялось или сломалось.\nПопытайтесь переустановить приложение или\nобратитесь к ${EMAIL} за помощью.",
|
"fatalErrorText": "Файлы игры повреждены или отсутствуют.\nПопробуйте переустановить приложение или\nобратитесь к ${EMAIL} за помощью.",
|
||||||
"fileSelectorWindow": {
|
"fileSelectorWindow": {
|
||||||
"titleFileFolderText": "Выберите файл или папку",
|
"titleFileFolderText": "Выберите файл или папку",
|
||||||
"titleFileText": "Выберите файл",
|
"titleFileText": "Выберите файл",
|
||||||
|
|
@ -670,7 +673,7 @@
|
||||||
"finalScoresText": "Финальные очки",
|
"finalScoresText": "Финальные очки",
|
||||||
"finalTimeText": "Финальное время",
|
"finalTimeText": "Финальное время",
|
||||||
"finishingInstallText": "Завершается установка, минутку...",
|
"finishingInstallText": "Завершается установка, минутку...",
|
||||||
"fireTVRemoteWarningText": "* Для лучшего результата используйте\nигровые контроллеры или установите\nприложение '${REMOTE_APP_NAME}'\nна ваших телефонах и планшетах.",
|
"fireTVRemoteWarningText": "* Для лучшего результата используйте\nгеймпады или установите\nприложение '${REMOTE_APP_NAME}'\nна ваших телефонах и планшетах.",
|
||||||
"firstToFinalText": "Финал до ${COUNT} очков",
|
"firstToFinalText": "Финал до ${COUNT} очков",
|
||||||
"firstToSeriesText": "Серия до ${COUNT} очков",
|
"firstToSeriesText": "Серия до ${COUNT} очков",
|
||||||
"fiveKillText": "ПЯТЕРЫХ ЗА РАЗ!!!",
|
"fiveKillText": "ПЯТЕРЫХ ЗА РАЗ!!!",
|
||||||
|
|
@ -708,7 +711,7 @@
|
||||||
"addressFetchErrorText": "<ошибка запроса адресов>",
|
"addressFetchErrorText": "<ошибка запроса адресов>",
|
||||||
"appInviteInfoText": "Пригласите друзей поиграть в BombSquad и они\nполучат ${COUNT} бесплатных билетов. Ты получишь\n${YOU_COUNT} за каждого друга.",
|
"appInviteInfoText": "Пригласите друзей поиграть в BombSquad и они\nполучат ${COUNT} бесплатных билетов. Ты получишь\n${YOU_COUNT} за каждого друга.",
|
||||||
"appInviteMessageText": "${NAME} отправил вам ${COUNT} билетов в ${APP_NAME}",
|
"appInviteMessageText": "${NAME} отправил вам ${COUNT} билетов в ${APP_NAME}",
|
||||||
"appInviteSendACodeText": "Отправьте им код",
|
"appInviteSendACodeText": "Отправить им код",
|
||||||
"appInviteTitleText": "Приглашение в ${APP_NAME}",
|
"appInviteTitleText": "Приглашение в ${APP_NAME}",
|
||||||
"bluetoothAndroidSupportText": "(работает с любым устройством, поддерживающим Bluetooth)",
|
"bluetoothAndroidSupportText": "(работает с любым устройством, поддерживающим Bluetooth)",
|
||||||
"bluetoothDescriptionText": "Создать/войти в лобби через Bluetooth:",
|
"bluetoothDescriptionText": "Создать/войти в лобби через Bluetooth:",
|
||||||
|
|
@ -829,7 +832,7 @@
|
||||||
"ticketPack4Text": "Огромная пачка билетов",
|
"ticketPack4Text": "Огромная пачка билетов",
|
||||||
"ticketPack5Text": "Слоновая пачка билетов",
|
"ticketPack5Text": "Слоновая пачка билетов",
|
||||||
"ticketPack6Text": "Максимальная пачка билетов",
|
"ticketPack6Text": "Максимальная пачка билетов",
|
||||||
"ticketsFromASponsorText": "Получить ${COUNT} билетов\nот спонсора",
|
"ticketsFromASponsorText": "Посмотреть рекламу,\nчтобы получить ${COUNT} билетов",
|
||||||
"ticketsText": "Билетов: ${COUNT}",
|
"ticketsText": "Билетов: ${COUNT}",
|
||||||
"titleText": "Получить билеты",
|
"titleText": "Получить билеты",
|
||||||
"unavailableLinkAccountText": "Извините, но на этой платформе покупки недоступны.\nВ качестве решения, вы можете привязать этот аккаунт \nк аккаунту на другой платформе, и совершать покупки там.",
|
"unavailableLinkAccountText": "Извините, но на этой платформе покупки недоступны.\nВ качестве решения, вы можете привязать этот аккаунт \nк аккаунту на другой платформе, и совершать покупки там.",
|
||||||
|
|
@ -840,6 +843,7 @@
|
||||||
"youHaveText": "У вас ${COUNT} билетов"
|
"youHaveText": "У вас ${COUNT} билетов"
|
||||||
},
|
},
|
||||||
"googleMultiplayerDiscontinuedText": "Простите, сервис многопользовательской игры Google больше не поддерживается.\nЯ работаю над заменой так быстро, насколько это возможно.\nДо тех пор, пожалуйста выберете другой способ подключения.\n-Эрик",
|
"googleMultiplayerDiscontinuedText": "Простите, сервис многопользовательской игры Google больше не поддерживается.\nЯ работаю над заменой так быстро, насколько это возможно.\nДо тех пор, пожалуйста выберете другой способ подключения.\n-Эрик",
|
||||||
|
"googlePlayPurchasesNotAvailableText": "Покупки в Google Play недоступны.\nВозможно, вам необходимо обновить приложение магазина.",
|
||||||
"googlePlayText": "Google Play",
|
"googlePlayText": "Google Play",
|
||||||
"graphicsSettingsWindow": {
|
"graphicsSettingsWindow": {
|
||||||
"alwaysText": "Всегда",
|
"alwaysText": "Всегда",
|
||||||
|
|
@ -1166,7 +1170,10 @@
|
||||||
"playlistsText": "Плей-листы",
|
"playlistsText": "Плей-листы",
|
||||||
"pleaseRateText": "Если вам нравится игра ${APP_NAME}, пожалуйста, подумайте о том,\nчтобы оценить ее или написать рецензию. Это обеспечивает полезную\nобратную связь и помогает поддержать дальнейшую разработку.\n\nСпасибо!\n- Эрик",
|
"pleaseRateText": "Если вам нравится игра ${APP_NAME}, пожалуйста, подумайте о том,\nчтобы оценить ее или написать рецензию. Это обеспечивает полезную\nобратную связь и помогает поддержать дальнейшую разработку.\n\nСпасибо!\n- Эрик",
|
||||||
"pleaseWaitText": "Пожалуйста, подождите...",
|
"pleaseWaitText": "Пожалуйста, подождите...",
|
||||||
|
"pluginClassLoadErrorText": "Ошибка при попытке загрузить класс плагина '${PLUGIN}': ${ERROR}",
|
||||||
|
"pluginInitErrorText": "Ошибка при инициализации плагина '${PLUGIN}': ${ERROR}",
|
||||||
"pluginsDetectedText": "Обнаружены новые плагины! Перезапустите игру, чтобы активировать их, или настройте их в настройках.",
|
"pluginsDetectedText": "Обнаружены новые плагины! Перезапустите игру, чтобы активировать их, или настройте их в настройках.",
|
||||||
|
"pluginsRemovedText": "${NUM} плагин(ов) больше не найдены.",
|
||||||
"pluginsText": "Плагины",
|
"pluginsText": "Плагины",
|
||||||
"practiceText": "Тренировка",
|
"practiceText": "Тренировка",
|
||||||
"pressAnyButtonPlayAgainText": "Нажмите любую кнопку чтобы играть снова...",
|
"pressAnyButtonPlayAgainText": "Нажмите любую кнопку чтобы играть снова...",
|
||||||
|
|
@ -1188,10 +1195,10 @@
|
||||||
},
|
},
|
||||||
"promoSubmitErrorText": "Ошибка отправки кода, проверьте своё интернете соединение",
|
"promoSubmitErrorText": "Ошибка отправки кода, проверьте своё интернете соединение",
|
||||||
"ps3ControllersWindow": {
|
"ps3ControllersWindow": {
|
||||||
"macInstructionsText": "Выключите питание на задней панели PS3, убедитесь, что Bluetooth\nвключен на вашем компьютере, а затем подключите контроллер к Маку\nс помощью кабеля USB для синхронизации. Теперь можно использовать\nкнопку контроллера 'PS' чтобы подключить его к Маку\nв проводном (USB) или беспроводном (Bluetooth) режиме.\n\nНа некоторых Маках при синхронизации может потребоваться код доступа.\nВ этом случае обратитесь к следующей инструкции или к гуглу.\n\n\n\n\nКонтроллеры PS3, связанные по беспроводной сети, должны появиться\nв списке устройств в Настройках системы -> Bluetooth. Возможно, вам придется\nудалить их из этого списка, если вы хотите снова использовать их с PS3.\n\nТакже всегда отключайте их от Bluetooth, когда он не используется,\nиначе будут садиться батарейки.\n\nBluetooth должен обрабатывать до 7 подключенных устройств,\nхотя у вас может получиться по-другому.",
|
"macInstructionsText": "Выключите питание на задней панели PS3, убедитесь, что Bluetooth\nвключен на вашем компьютере, а затем подключите геймпад к Mac\nс помощью кабеля USB для синхронизации. Теперь можно использовать\nкнопку геймпад 'PS' чтобы подключить его к Mac\nв проводном (USB) или беспроводном (Bluetooth) режиме.\n\nНа некоторых системах Mac при синхронизации может потребоватьсякод доступа.\nВ этом случае обратитесь к следующей инструкции или к гуглу.\n\n\n\n\nГеймпады PS3, связанные по беспроводной сети, должны появиться\nв списке устройств в Настройках системы -> Bluetooth. Возможно, вам придется\nудалить их из этого списка, если вы хотите снова использовать их с PS3.\n\nТакже всегда отключайте их от Bluetooth, когда он не используется,\nиначе будут садиться батарейки.\n\nBluetooth должен обрабатывать до 7 подключенных устройств,\nхотя у вас может получиться по-другому.",
|
||||||
"ouyaInstructionsText": "Чтобы использовать контроллер PS3 с OUYA, просто подключите его один раз\nс помощью кабеля USB для синхронизации. Это может отключить другие\nконтроллеры, тогда нужно перезагрузить OUYA и отсоединить кабель USB.\n\nПосле этого можно использовать кнопку 'PS' контроллера для беспроводного\nподключения. После игры нажмите и удерживайте кнопку 'PS' в течение\n10 секунд чтобы выключить контроллер, в противном случае он может\nостаться включенным и разрядит батарейки.",
|
"ouyaInstructionsText": "Чтобы использовать геймпад PS3 с OUYA, просто подключите его один раз\nс помощью кабеля USB для синхронизации. Это может отключить другие\nгеймпады, тогда нужно перезагрузить OUYA и отсоединить кабель USB.\n\nПосле этого можно использовать кнопку 'PS' геймпада для беспроводного\nподключения. После игры нажмите и удерживайте кнопку 'PS' в течение\n10 секунд чтобы выключить геймпад, в противном случае он может\nостаться включенным и разрядит батарейки.",
|
||||||
"pairingTutorialText": "видео-тьюториал по синхронизации",
|
"pairingTutorialText": "видео-тьюториал по синхронизации",
|
||||||
"titleText": "Использование контроллеров PS3 с ${APP_NAME}:"
|
"titleText": "Использование геймпада PS3 с ${APP_NAME}:"
|
||||||
},
|
},
|
||||||
"publicBetaText": "ОТКРЫТАЯ БЕТА-ВЕРСИЯ",
|
"publicBetaText": "ОТКРЫТАЯ БЕТА-ВЕРСИЯ",
|
||||||
"punchBoldText": "УДАР",
|
"punchBoldText": "УДАР",
|
||||||
|
|
@ -1201,7 +1208,7 @@
|
||||||
"purchasingText": "Покупка...",
|
"purchasingText": "Покупка...",
|
||||||
"quitGameText": "Выйти из ${APP_NAME}?",
|
"quitGameText": "Выйти из ${APP_NAME}?",
|
||||||
"quittingIn5SecondsText": "Выход через 5 секунд...",
|
"quittingIn5SecondsText": "Выход через 5 секунд...",
|
||||||
"randomPlayerNamesText": "Дима, Кузя, Вован, Маха, Русский, Какуля, Бибер, Борька, Няшка, Толян, Ержан, Дибисяра, Вася, Морген, Серёга, Ваня, Кеша, Жорик, Стёпа, Эдгар, Циган",
|
"randomPlayerNamesText": "Дима, Кузя, Вован, Маха, Русский, Какуля, Бибер, Борька, Няшка, Толян, Ержан, Дибисяра, Вася, Морген, Серёга, Ваня, Кеша, Жорик, Стёпа, Эдгар, Цыган, Олег, Егор, Ёршик",
|
||||||
"randomText": "Случайный",
|
"randomText": "Случайный",
|
||||||
"rankText": "Ранг",
|
"rankText": "Ранг",
|
||||||
"ratingText": "Рейтинг",
|
"ratingText": "Рейтинг",
|
||||||
|
|
@ -1508,9 +1515,9 @@
|
||||||
"Get the flag to the enemy end zone.": "Отнесите флаг в зону защиты противника.",
|
"Get the flag to the enemy end zone.": "Отнесите флаг в зону защиты противника.",
|
||||||
"How fast can you defeat the ninjas?": "Как быстро вы сможете победить ниндзя?",
|
"How fast can you defeat the ninjas?": "Как быстро вы сможете победить ниндзя?",
|
||||||
"Kill a set number of enemies to win.": "Убейте заданное число врагов, чтобы выиграть.",
|
"Kill a set number of enemies to win.": "Убейте заданное число врагов, чтобы выиграть.",
|
||||||
"Last one standing wins.": "Побеждает последний стоящий на ногах.",
|
"Last one standing wins.": "Побеждает последний живой игрок.",
|
||||||
"Last remaining alive wins.": "Побеждает последний в живых.",
|
"Last remaining alive wins.": "Побеждает последний живой игрок.",
|
||||||
"Last team standing wins.": "Побеждает последняя стоящая на ногах команда.",
|
"Last team standing wins.": "Побеждает последняя живая команда.",
|
||||||
"Prevent enemies from reaching the exit.": "Не дайте врагам дойти до выхода.",
|
"Prevent enemies from reaching the exit.": "Не дайте врагам дойти до выхода.",
|
||||||
"Reach the enemy flag to score.": "Доберитесь до вражеского флага чтобы набрать очки.",
|
"Reach the enemy flag to score.": "Доберитесь до вражеского флага чтобы набрать очки.",
|
||||||
"Return the enemy flag to score.": "Принесите вражеский флаг на базу, чтобы набрать очки.",
|
"Return the enemy flag to score.": "Принесите вражеский флаг на базу, чтобы набрать очки.",
|
||||||
|
|
@ -1536,8 +1543,8 @@
|
||||||
"Touch the enemy flag.": "Коснитесь вражеского флага.",
|
"Touch the enemy flag.": "Коснитесь вражеского флага.",
|
||||||
"carry the flag for ${ARG1} seconds": "пронесите флаг в течение ${ARG1} секунд",
|
"carry the flag for ${ARG1} seconds": "пронесите флаг в течение ${ARG1} секунд",
|
||||||
"kill ${ARG1} enemies": "убейте ${ARG1} врагов",
|
"kill ${ARG1} enemies": "убейте ${ARG1} врагов",
|
||||||
"last one standing wins": "побеждает последний стоящий на ногах",
|
"last one standing wins": "побеждает последний живой игрок",
|
||||||
"last team standing wins": "побеждает последняя стоящая на ногах команда",
|
"last team standing wins": "побеждает последняя живая команда",
|
||||||
"return ${ARG1} flags": "принесите ${ARG1} флагов на базу",
|
"return ${ARG1} flags": "принесите ${ARG1} флагов на базу",
|
||||||
"return 1 flag": "принесите 1 флаг на базу",
|
"return 1 flag": "принесите 1 флаг на базу",
|
||||||
"run ${ARG1} laps": "пробегите ${ARG1} кругов",
|
"run ${ARG1} laps": "пробегите ${ARG1} кругов",
|
||||||
|
|
@ -1874,7 +1881,7 @@
|
||||||
},
|
},
|
||||||
"twoKillText": "ДВОИХ ЗА РАЗ!",
|
"twoKillText": "ДВОИХ ЗА РАЗ!",
|
||||||
"unavailableText": "недоступно",
|
"unavailableText": "недоступно",
|
||||||
"unconfiguredControllerDetectedText": "Обнаружен ненастроенный контроллер:",
|
"unconfiguredControllerDetectedText": "Обнаружен ненастроенный геймпад:",
|
||||||
"unlockThisInTheStoreText": "Это должно быть разблокировано в магазине.",
|
"unlockThisInTheStoreText": "Это должно быть разблокировано в магазине.",
|
||||||
"unlockThisProfilesText": "Чтобы создать более ${NUM} профиль, Вам необходимо:",
|
"unlockThisProfilesText": "Чтобы создать более ${NUM} профиль, Вам необходимо:",
|
||||||
"unlockThisText": "Чтобы разблокировать это, вам нужно:",
|
"unlockThisText": "Чтобы разблокировать это, вам нужно:",
|
||||||
|
|
@ -1940,13 +1947,15 @@
|
||||||
"winsPlayerText": "Победил ${NAME}!",
|
"winsPlayerText": "Победил ${NAME}!",
|
||||||
"winsTeamText": "Победили ${NAME}!",
|
"winsTeamText": "Победили ${NAME}!",
|
||||||
"winsText": "${NAME} выиграл!",
|
"winsText": "${NAME} выиграл!",
|
||||||
|
"workspaceSyncErrorText": "Ошибка при попытке синхронизации ${WORKSPACE}. Посмотрите лог для информации.",
|
||||||
|
"workspaceSyncReuseText": "Не может синронизировать ${WORKSPACE}. Будет использоватся прошлая синхронизация.",
|
||||||
"worldScoresUnavailableText": "Мировые результаты недоступны.",
|
"worldScoresUnavailableText": "Мировые результаты недоступны.",
|
||||||
"worldsBestScoresText": "Лучшие в мире очки",
|
"worldsBestScoresText": "Лучшие в мире очки",
|
||||||
"worldsBestTimesText": "Лучшее в мире время",
|
"worldsBestTimesText": "Лучшее в мире время",
|
||||||
"xbox360ControllersWindow": {
|
"xbox360ControllersWindow": {
|
||||||
"getDriverText": "Скачать драйвер",
|
"getDriverText": "Скачать драйвер",
|
||||||
"macInstructions2Text": "Для использования контроллеров по беспроводной связи, вам также\nпотребуется ресивер, который поставляется с \"беспроводным контроллером\nXbox 360 для Windows\". Один ресивер позволяет подключить до 4 контроллеров.\n\nВнимание: ресиверы сторонних производителей не будут работать с этим драйвером,\nубедитесь, что на вашем ресивере написано \"Microsoft\", а не \"XBOX 360\".\nMicrosoft больше не продает их отдельно, так что вам нужно будет найти\nресивер в комплекте с контроллером, либо искать на ebay.\n\nЕсли вы считаете это полезным, можете отправить денег разработчику\nдрайвера на его сайте.",
|
"macInstructions2Text": "Для использования контроллеров по беспроводной связи, вам также\nпотребуется ресивер, который поставляется с \"беспроводным геймпадом\nXbox 360 для Windows\". Один ресивер позволяет подключить до 4 контроллеров.\n\nВнимание: ресиверы сторонних производителей не будут работать с этим драйвером,\nубедитесь, что на вашем ресивере написано \"Microsoft\", а не \"XBOX 360\".\nMicrosoft больше не продает их отдельно, так что вам нужно будет найти\nресивер в комплекте с геймпадом, либо искать на ebay.\n\nЕсли вы считаете это полезным, можете отправить денег разработчику\nдрайвера на его сайте.",
|
||||||
"macInstructionsText": "Для использования контроллеров Xbox 360 необходимо\nустановить драйвер Mac, доступный по ссылке ниже.\nОн работает и с проводными и беспроводными контроллерами.",
|
"macInstructionsText": "Для использования геймпада Xbox 360 необходимо\nустановить драйвер Mac, доступный по ссылке ниже.\nОн работает и с проводными и беспроводными геймпадами.",
|
||||||
"macInstructionsTextScale": 0.8,
|
"macInstructionsTextScale": 0.8,
|
||||||
"ouyaInstructionsText": "Для использования проводных контроллеров Xbox 360 в BombSquad,\nпросто подключите их к USB-порту вашего устройства. Для нескольких\nконтроллеров можно использовать концентратор USB.\n\nДля использования беспроводных контроллеров вам понадобится беспроводной\nресивер который поставляется в наборе \"беспроводного геймпада Xbox 360\nдля Windows\" или продается отдельно. Каждый ресивер подключается\nк порту USB и позволяет подключать до 4 беспроводных контроллеров.",
|
"ouyaInstructionsText": "Для использования проводных контроллеров Xbox 360 в BombSquad,\nпросто подключите их к USB-порту вашего устройства. Для нескольких\nконтроллеров можно использовать концентратор USB.\n\nДля использования беспроводных контроллеров вам понадобится беспроводной\nресивер который поставляется в наборе \"беспроводного геймпада Xbox 360\nдля Windows\" или продается отдельно. Каждый ресивер подключается\nк порту USB и позволяет подключать до 4 беспроводных контроллеров.",
|
||||||
"titleText": "Использование контроллеров Xbox 360 в ${APP_NAME}:"
|
"titleText": "Использование контроллеров Xbox 360 в ${APP_NAME}:"
|
||||||
|
|
|
||||||
10
dist/ba_data/data/languages/serbian.json
vendored
10
dist/ba_data/data/languages/serbian.json
vendored
|
|
@ -328,6 +328,7 @@
|
||||||
"achievementsRemainingText": "Неизвршена достигнућа:",
|
"achievementsRemainingText": "Неизвршена достигнућа:",
|
||||||
"achievementsText": "Достигнућа",
|
"achievementsText": "Достигнућа",
|
||||||
"achievementsUnavailableForOldSeasonsText": "Извини, информације нису доступне за старије сезоне.",
|
"achievementsUnavailableForOldSeasonsText": "Извини, информације нису доступне за старије сезоне.",
|
||||||
|
"activatedText": "${THING} Активиран",
|
||||||
"addGameWindow": {
|
"addGameWindow": {
|
||||||
"getMoreGamesText": "Додај више игри...",
|
"getMoreGamesText": "Додај више игри...",
|
||||||
"titleText": "Додај игру"
|
"titleText": "Додај игру"
|
||||||
|
|
@ -627,7 +628,9 @@
|
||||||
"epicDescriptionFilterText": "${DESCRIPTION} у епско успореној игри.",
|
"epicDescriptionFilterText": "${DESCRIPTION} у епско успореној игри.",
|
||||||
"epicNameFilterText": "Епски ${NAME}",
|
"epicNameFilterText": "Епски ${NAME}",
|
||||||
"errorAccessDeniedText": "приступ одбијен",
|
"errorAccessDeniedText": "приступ одбијен",
|
||||||
|
"errorDeviceTimeIncorrectText": "Време на твом уређају је нетачно за ${HOURS} сати.\nОво може изазвати проблеме.\nМолимо вас проверите подешавања времена и временску зону.",
|
||||||
"errorOutOfDiskSpaceText": "нема места на диску",
|
"errorOutOfDiskSpaceText": "нема места на диску",
|
||||||
|
"errorSecureConnectionFailText": "Немогуће успоставити везу са клаудом; функција мреже може престати.",
|
||||||
"errorText": "Грешка",
|
"errorText": "Грешка",
|
||||||
"errorUnknownText": "непозната грешка",
|
"errorUnknownText": "непозната грешка",
|
||||||
"exitGameText": "Изађи из \"${APP_NAME}\"?",
|
"exitGameText": "Изађи из \"${APP_NAME}\"?",
|
||||||
|
|
@ -1119,7 +1122,10 @@
|
||||||
"playlistsText": "Листе игара",
|
"playlistsText": "Листе игара",
|
||||||
"pleaseRateText": "Ако уживате у \"${APP_NAME}\" игри, молимо вас да издвојите\nмало времена да оцените апликацију или напишете коментар.\nОво нам даје корисне информације и помаже у будућем развоју.\n\nХвала!\n-Ерик",
|
"pleaseRateText": "Ако уживате у \"${APP_NAME}\" игри, молимо вас да издвојите\nмало времена да оцените апликацију или напишете коментар.\nОво нам даје корисне информације и помаже у будућем развоју.\n\nХвала!\n-Ерик",
|
||||||
"pleaseWaitText": "Молимо вас сачекајте...",
|
"pleaseWaitText": "Молимо вас сачекајте...",
|
||||||
"pluginsDetectedText": "Нови додатак/ци пронађен/и. Укључи/подеси их у подешавањима.",
|
"pluginClassLoadErrorText": "Грешка учитавања плугина класе '${PLUGIN}': ${ERROR}",
|
||||||
|
"pluginInitErrorText": "Грешка иницијације плугина '${PLUGIN}': ${ERROR}",
|
||||||
|
"pluginsDetectedText": "Нови додатак/ци пронађени. Рестартуј да их активираш,или конфигуришеш у подешавањима.",
|
||||||
|
"pluginsRemovedText": "${NUM} додатак/ више не постоје.",
|
||||||
"pluginsText": "Додаци",
|
"pluginsText": "Додаци",
|
||||||
"practiceText": "Вежбање",
|
"practiceText": "Вежбање",
|
||||||
"pressAnyButtonPlayAgainText": "Притисни било које дугме да одиграш опет...",
|
"pressAnyButtonPlayAgainText": "Притисни било које дугме да одиграш опет...",
|
||||||
|
|
@ -1855,6 +1861,8 @@
|
||||||
"winsPlayerText": "${NAME} је победио!",
|
"winsPlayerText": "${NAME} је победио!",
|
||||||
"winsTeamText": "${NAME} је победио!",
|
"winsTeamText": "${NAME} је победио!",
|
||||||
"winsText": "${NAME} је победио!",
|
"winsText": "${NAME} је победио!",
|
||||||
|
"workspaceSyncErrorText": "Грешка синхронизовања ${WORKSPACE}. Погледајте лог за више детаља.",
|
||||||
|
"workspaceSyncReuseText": "Синхронизовање ${WORKSPACE} неуспешно. Коришћење претходно синхронизоване верзије.",
|
||||||
"worldScoresUnavailableText": "Светски резултати недоступни.",
|
"worldScoresUnavailableText": "Светски резултати недоступни.",
|
||||||
"worldsBestScoresText": "Најбољи резултати на свету",
|
"worldsBestScoresText": "Најбољи резултати на свету",
|
||||||
"worldsBestTimesText": "Најбоља времена на свету",
|
"worldsBestTimesText": "Најбоља времена на свету",
|
||||||
|
|
|
||||||
15
dist/ba_data/data/languages/spanish.json
vendored
15
dist/ba_data/data/languages/spanish.json
vendored
|
|
@ -32,7 +32,7 @@
|
||||||
"signInWithTestAccountInfoText": "(Cuenta de prueba, usa la cuenta del dispositivo para avanzar)",
|
"signInWithTestAccountInfoText": "(Cuenta de prueba, usa la cuenta del dispositivo para avanzar)",
|
||||||
"signInWithTestAccountText": "Registrarse con una Cuenta de Prueba",
|
"signInWithTestAccountText": "Registrarse con una Cuenta de Prueba",
|
||||||
"signInWithV2InfoText": "(una cuenta que funciona en todas las plataformas)",
|
"signInWithV2InfoText": "(una cuenta que funciona en todas las plataformas)",
|
||||||
"signInWithV2Text": "Inicie cesión con una cuenta de bosquad",
|
"signInWithV2Text": "Inicie sesión con tú cuenta de BombSquad",
|
||||||
"signOutText": "Cerrar Sesión",
|
"signOutText": "Cerrar Sesión",
|
||||||
"signingInText": "Iniciando sesión...",
|
"signingInText": "Iniciando sesión...",
|
||||||
"signingOutText": "Cerrando sesión...",
|
"signingOutText": "Cerrando sesión...",
|
||||||
|
|
@ -332,6 +332,7 @@
|
||||||
"achievementsRemainingText": "Logros pendientes:",
|
"achievementsRemainingText": "Logros pendientes:",
|
||||||
"achievementsText": "Logros",
|
"achievementsText": "Logros",
|
||||||
"achievementsUnavailableForOldSeasonsText": "Lo sentimos, los logros específicos no están disponibles para temporadas anteriores.",
|
"achievementsUnavailableForOldSeasonsText": "Lo sentimos, los logros específicos no están disponibles para temporadas anteriores.",
|
||||||
|
"activatedText": "${THING} activado.",
|
||||||
"addGameWindow": {
|
"addGameWindow": {
|
||||||
"getMoreGamesText": "Más Juegos...",
|
"getMoreGamesText": "Más Juegos...",
|
||||||
"titleText": "Agregar Juego"
|
"titleText": "Agregar Juego"
|
||||||
|
|
@ -651,7 +652,9 @@
|
||||||
"epicDescriptionFilterText": "${DESCRIPTION} En cámara lenta épica.",
|
"epicDescriptionFilterText": "${DESCRIPTION} En cámara lenta épica.",
|
||||||
"epicNameFilterText": "${NAME} - Modo épico",
|
"epicNameFilterText": "${NAME} - Modo épico",
|
||||||
"errorAccessDeniedText": "acceso negado",
|
"errorAccessDeniedText": "acceso negado",
|
||||||
|
"errorDeviceTimeIncorrectText": "La hora actual de tu dispositivo es ${HOURS} horas.\nEsto podría causar problemas.\nPorfavor verifica la hora y zona horaria en ajustes.",
|
||||||
"errorOutOfDiskSpaceText": "insuficiente espacio en disco",
|
"errorOutOfDiskSpaceText": "insuficiente espacio en disco",
|
||||||
|
"errorSecureConnectionFailText": "No se puede establecer una conexión segura en la nube; La red podría estar fallando",
|
||||||
"errorText": "Error",
|
"errorText": "Error",
|
||||||
"errorUnknownText": "error desconocido",
|
"errorUnknownText": "error desconocido",
|
||||||
"exitGameText": "¿Salir de ${APP_NAME}?",
|
"exitGameText": "¿Salir de ${APP_NAME}?",
|
||||||
|
|
@ -838,6 +841,7 @@
|
||||||
"youHaveText": "tienes ${COUNT} boletos"
|
"youHaveText": "tienes ${COUNT} boletos"
|
||||||
},
|
},
|
||||||
"googleMultiplayerDiscontinuedText": "Lo siento, Google's multijugador servicio ya no esta mas disponible.\nEstoy trabajando en un reemplazo lo mas rapido posible.\nHasta entonces, por favor intente con otro metodo de conexión.\n-Eric",
|
"googleMultiplayerDiscontinuedText": "Lo siento, Google's multijugador servicio ya no esta mas disponible.\nEstoy trabajando en un reemplazo lo mas rapido posible.\nHasta entonces, por favor intente con otro metodo de conexión.\n-Eric",
|
||||||
|
"googlePlayPurchasesNotAvailableText": "Las compras de Google Play no están disponibles.\nEs posible que deba actualizar la aplicación de su tienda.",
|
||||||
"googlePlayText": "Google Play",
|
"googlePlayText": "Google Play",
|
||||||
"graphicsSettingsWindow": {
|
"graphicsSettingsWindow": {
|
||||||
"alwaysText": "Siempre",
|
"alwaysText": "Siempre",
|
||||||
|
|
@ -1079,8 +1083,8 @@
|
||||||
"modeArcadeText": "Modo Arcade",
|
"modeArcadeText": "Modo Arcade",
|
||||||
"modeClassicText": "Modo Clásico",
|
"modeClassicText": "Modo Clásico",
|
||||||
"modeDemoText": "Modo De Demostración",
|
"modeDemoText": "Modo De Demostración",
|
||||||
"mostValuablePlayerText": "Jugador más valorado",
|
"mostValuablePlayerText": "Jugador más Valorado",
|
||||||
"mostViolatedPlayerText": "Jugador más agredido",
|
"mostViolatedPlayerText": "Jugador más Violado",
|
||||||
"mostViolentPlayerText": "Jugador más Violento",
|
"mostViolentPlayerText": "Jugador más Violento",
|
||||||
"moveText": "Mover",
|
"moveText": "Mover",
|
||||||
"multiKillText": "¡¡¡${COUNT}-COMBO!!!",
|
"multiKillText": "¡¡¡${COUNT}-COMBO!!!",
|
||||||
|
|
@ -1178,7 +1182,10 @@
|
||||||
"playlistsText": "Listas de Juego",
|
"playlistsText": "Listas de Juego",
|
||||||
"pleaseRateText": "Si te gusta ${APP_NAME}, por favor tomate un momento\npara calificar o escribir una reseña. Esto proporcionará\ninformación útil y ayuda al soporte del futuro desarrollo del juego.\n\n¡gracias!\n-eric",
|
"pleaseRateText": "Si te gusta ${APP_NAME}, por favor tomate un momento\npara calificar o escribir una reseña. Esto proporcionará\ninformación útil y ayuda al soporte del futuro desarrollo del juego.\n\n¡gracias!\n-eric",
|
||||||
"pleaseWaitText": "Por favor, espera...",
|
"pleaseWaitText": "Por favor, espera...",
|
||||||
|
"pluginClassLoadErrorText": "Error al cargar la clase del plugin '${PLUGIN}': ${ERROR}",
|
||||||
|
"pluginInitErrorText": "Error al iniciar el plugin '${PLUGIN}': ${ERROR}",
|
||||||
"pluginsDetectedText": "Nuevos complemento(s) detectados. Reinicie para activarlos, o configúrelos en la configuración",
|
"pluginsDetectedText": "Nuevos complemento(s) detectados. Reinicie para activarlos, o configúrelos en la configuración",
|
||||||
|
"pluginsRemovedText": "${NUM} plugin(s) ya no se encuentran.",
|
||||||
"pluginsText": "Plugins",
|
"pluginsText": "Plugins",
|
||||||
"practiceText": "Práctica",
|
"practiceText": "Práctica",
|
||||||
"pressAnyButtonPlayAgainText": "Oprime cualquier botón jugar de nuevo...",
|
"pressAnyButtonPlayAgainText": "Oprime cualquier botón jugar de nuevo...",
|
||||||
|
|
@ -1960,6 +1967,8 @@
|
||||||
"winsPlayerText": "¡${NAME} Gana!",
|
"winsPlayerText": "¡${NAME} Gana!",
|
||||||
"winsTeamText": "¡${NAME} Gana!!",
|
"winsTeamText": "¡${NAME} Gana!!",
|
||||||
"winsText": "¡${NAME} Gana!",
|
"winsText": "¡${NAME} Gana!",
|
||||||
|
"workspaceSyncErrorText": "Error al sincronizar ${WORKSPACE}. Mira el registro para mas detalles.",
|
||||||
|
"workspaceSyncReuseText": "No se puede sincronizar ${WORKSPACE}. Reusando la versión sincronizada anterior.",
|
||||||
"worldScoresUnavailableText": "Puntuaciones globales no disponibles.",
|
"worldScoresUnavailableText": "Puntuaciones globales no disponibles.",
|
||||||
"worldsBestScoresText": "Mejores puntuaciones Mundiales",
|
"worldsBestScoresText": "Mejores puntuaciones Mundiales",
|
||||||
"worldsBestTimesText": "Mejores tiempos Mundiales",
|
"worldsBestTimesText": "Mejores tiempos Mundiales",
|
||||||
|
|
|
||||||
11
dist/ba_data/data/languages/tamil.json
vendored
11
dist/ba_data/data/languages/tamil.json
vendored
|
|
@ -324,6 +324,7 @@
|
||||||
"achievementsRemainingText": "மீதமுள்ள சாதனைகள்:",
|
"achievementsRemainingText": "மீதமுள்ள சாதனைகள்:",
|
||||||
"achievementsText": "சாதனைகள்",
|
"achievementsText": "சாதனைகள்",
|
||||||
"achievementsUnavailableForOldSeasonsText": "மன்னிக்கவும், சாதனை விவரங்கள் பழைய பருவங்களுக்கு கிடைக்கவில்லை.",
|
"achievementsUnavailableForOldSeasonsText": "மன்னிக்கவும், சாதனை விவரங்கள் பழைய பருவங்களுக்கு கிடைக்கவில்லை.",
|
||||||
|
"activatedText": "${THING} செயல்படுத்தப்பட்டது.",
|
||||||
"addGameWindow": {
|
"addGameWindow": {
|
||||||
"getMoreGamesText": "மேலும் விளையாட்டுகளைப் பெறுங்கள்...",
|
"getMoreGamesText": "மேலும் விளையாட்டுகளைப் பெறுங்கள்...",
|
||||||
"titleText": "விளையாட்டைச் சேர்"
|
"titleText": "விளையாட்டைச் சேர்"
|
||||||
|
|
@ -623,7 +624,9 @@
|
||||||
"epicDescriptionFilterText": "${DESCRIPTION} காவிய மெதுவான இயக்கத்தில்.",
|
"epicDescriptionFilterText": "${DESCRIPTION} காவிய மெதுவான இயக்கத்தில்.",
|
||||||
"epicNameFilterText": "காவியம் ${NAME}",
|
"epicNameFilterText": "காவியம் ${NAME}",
|
||||||
"errorAccessDeniedText": "அணுகல் மறுக்கப்பட்டது",
|
"errorAccessDeniedText": "அணுகல் மறுக்கப்பட்டது",
|
||||||
|
"errorDeviceTimeIncorrectText": "உங்கள் சாதனத்தின் நேரம் ${HOURS} மணிநேரம் உள்ளது.\nஇதனால் பிரச்னைகள் ஏற்பட வாய்ப்புள்ளது.\nஉங்கள் நேரம் மற்றும் நேர மண்டல அமைப்புகளைச் சரிபார்க்கவும்.",
|
||||||
"errorOutOfDiskSpaceText": "வட்டு இடத்திற்கு வெளியே",
|
"errorOutOfDiskSpaceText": "வட்டு இடத்திற்கு வெளியே",
|
||||||
|
"errorSecureConnectionFailText": "பாதுகாப்பான கிளவுட் இணைப்பை நிறுவ முடியவில்லை; பிணைய செயல்பாடு தோல்வியடையலாம்.",
|
||||||
"errorText": "பிழை",
|
"errorText": "பிழை",
|
||||||
"errorUnknownText": "அறியப்படாத பிழை",
|
"errorUnknownText": "அறியப்படாத பிழை",
|
||||||
"exitGameText": "${APP_NAME} இலிருந்து வெளியேறவா?",
|
"exitGameText": "${APP_NAME} இலிருந்து வெளியேறவா?",
|
||||||
|
|
@ -786,7 +789,7 @@
|
||||||
"ticketPack4Text": "ஜம்போ டிக்கெட் பேக்",
|
"ticketPack4Text": "ஜம்போ டிக்கெட் பேக்",
|
||||||
"ticketPack5Text": "மம்மத் டிக்கெட் பேக்",
|
"ticketPack5Text": "மம்மத் டிக்கெட் பேக்",
|
||||||
"ticketPack6Text": "அல்டிமேட் டிக்கெட் பேக்",
|
"ticketPack6Text": "அல்டிமேட் டிக்கெட் பேக்",
|
||||||
"ticketsFromASponsorText": "${COUNT} டிக்கெட்டுகளைப் பெறுங்கள்\nஒரு ஸ்பான்சரிடமிருந்து",
|
"ticketsFromASponsorText": "ஒரு விளம்பரத்தைப் பார்த்து\n${COUNT} டிக்கெட்டுகளை பெறுங்கள்",
|
||||||
"ticketsText": "${COUNT} டிக்கெட்டுகள்",
|
"ticketsText": "${COUNT} டிக்கெட்டுகள்",
|
||||||
"titleText": "டிக்கெட்டுகளைப் பெறுங்கள்",
|
"titleText": "டிக்கெட்டுகளைப் பெறுங்கள்",
|
||||||
"unavailableLinkAccountText": "மன்னிக்கவும், இந்த தளத்தில் கொள்முதல் கிடைக்கவில்லை.\nஒரு தீர்வாக, இந்தக் கணக்கை ஒரு கணக்குடன் இணைக்கலாம்\nமற்றொரு தளம் மற்றும் அங்கு கொள்முதல் செய்யுங்கள்.",
|
"unavailableLinkAccountText": "மன்னிக்கவும், இந்த தளத்தில் கொள்முதல் கிடைக்கவில்லை.\nஒரு தீர்வாக, இந்தக் கணக்கை ஒரு கணக்குடன் இணைக்கலாம்\nமற்றொரு தளம் மற்றும் அங்கு கொள்முதல் செய்யுங்கள்.",
|
||||||
|
|
@ -797,6 +800,7 @@
|
||||||
"youHaveText": "உங்களிடம் ${COUNT} டிக்கெட்டுகள் உள்ளன"
|
"youHaveText": "உங்களிடம் ${COUNT} டிக்கெட்டுகள் உள்ளன"
|
||||||
},
|
},
|
||||||
"googleMultiplayerDiscontinuedText": "மன்னிக்கவும், கூகுளின் மல்டிபிளேயர் சேவை இனி கிடைக்காது.\nநான் முடிந்தவரை விரைவாக மாற்றுவதற்கு வேலை செய்கிறேன்.\nஅதுவரை, வேறு இணைப்பு முறையை முயற்சிக்கவும்.\n-எரிக்",
|
"googleMultiplayerDiscontinuedText": "மன்னிக்கவும், கூகுளின் மல்டிபிளேயர் சேவை இனி கிடைக்காது.\nநான் முடிந்தவரை விரைவாக மாற்றுவதற்கு வேலை செய்கிறேன்.\nஅதுவரை, வேறு இணைப்பு முறையை முயற்சிக்கவும்.\n-எரிக்",
|
||||||
|
"googlePlayPurchasesNotAvailableText": "Google Play வாங்குதல்கள் கிடைக்கவில்லை.\nஉங்கள் ஸ்டோர் பயன்பாட்டைப் புதுப்பிக்க வேண்டியிருக்கலாம்.",
|
||||||
"googlePlayText": "கூகுள் பிளே",
|
"googlePlayText": "கூகுள் பிளே",
|
||||||
"graphicsSettingsWindow": {
|
"graphicsSettingsWindow": {
|
||||||
"alwaysText": "எப்போதும்",
|
"alwaysText": "எப்போதும்",
|
||||||
|
|
@ -1108,7 +1112,10 @@
|
||||||
"playlistsText": "பிளேலிஸ்ட்கள்",
|
"playlistsText": "பிளேலிஸ்ட்கள்",
|
||||||
"pleaseRateText": "நீங்கள் ${APP_NAME} ஐ அனுபவிக்கிறீர்கள் என்றால், தயவுசெய்து எடுப்பதைக் கவனியுங்கள்\nதருணம் மற்றும் மதிப்பிடுதல் அல்லது விமர்சனம் எழுதுதல். இது வழங்குகிறது\nபயனுள்ள கருத்து மற்றும் எதிர்கால வளர்ச்சிக்கு உதவுகிறது.\n\nநன்றி!\n-எரிக்",
|
"pleaseRateText": "நீங்கள் ${APP_NAME} ஐ அனுபவிக்கிறீர்கள் என்றால், தயவுசெய்து எடுப்பதைக் கவனியுங்கள்\nதருணம் மற்றும் மதிப்பிடுதல் அல்லது விமர்சனம் எழுதுதல். இது வழங்குகிறது\nபயனுள்ள கருத்து மற்றும் எதிர்கால வளர்ச்சிக்கு உதவுகிறது.\n\nநன்றி!\n-எரிக்",
|
||||||
"pleaseWaitText": "தயவுசெய்து காத்திருங்கள்...",
|
"pleaseWaitText": "தயவுசெய்து காத்திருங்கள்...",
|
||||||
|
"pluginClassLoadErrorText": "செருகுநிரல் வகுப்பை ஏற்றுவதில் பிழை '${PLUGIN}': ${ERROR}",
|
||||||
|
"pluginInitErrorText": "'${PLUGIN}' செருகுநிரலைத் தொடங்குவதில் பிழை: ${ERROR}",
|
||||||
"pluginsDetectedText": "புதிய செருகுநிரல்(கள்) கண்டறியப்பட்டது. அவற்றைச் செயல்படுத்த மீண்டும் தொடங்கவும் அல்லது அமைப்புகளில் உள்ளமைக்கவும்.",
|
"pluginsDetectedText": "புதிய செருகுநிரல்(கள்) கண்டறியப்பட்டது. அவற்றைச் செயல்படுத்த மீண்டும் தொடங்கவும் அல்லது அமைப்புகளில் உள்ளமைக்கவும்.",
|
||||||
|
"pluginsRemovedText": "${NUM} செருகுநிரல்(கள்) இனி காணப்படவில்லை.",
|
||||||
"pluginsText": "செருகுநிரல்கள்",
|
"pluginsText": "செருகுநிரல்கள்",
|
||||||
"practiceText": "பயிற்சி",
|
"practiceText": "பயிற்சி",
|
||||||
"pressAnyButtonPlayAgainText": "மீண்டும் விளையாட எந்த பட்டனையும் அழுத்தவும்...",
|
"pressAnyButtonPlayAgainText": "மீண்டும் விளையாட எந்த பட்டனையும் அழுத்தவும்...",
|
||||||
|
|
@ -1844,6 +1851,8 @@
|
||||||
"winsPlayerText": "${NAME} வெற்றி!",
|
"winsPlayerText": "${NAME} வெற்றி!",
|
||||||
"winsTeamText": "${NAME} வெற்றி!",
|
"winsTeamText": "${NAME} வெற்றி!",
|
||||||
"winsText": "${NAME} வெற்றி!",
|
"winsText": "${NAME} வெற்றி!",
|
||||||
|
"workspaceSyncErrorText": "${WORKSPACE} ஐ ஒத்திசைப்பதில் பிழை. விவரங்களுக்கு பதிவைப் பார்க்கவும்.",
|
||||||
|
"workspaceSyncReuseText": "${WORKSPACE} ஐ ஒத்திசைக்க முடியவில்லை. முந்தைய ஒத்திசைக்கப்பட்ட பதிப்பை மீண்டும் பயன்படுத்துகிறது.",
|
||||||
"worldScoresUnavailableText": "உலக ஸ்கோர் கிடைக்கவில்லை.",
|
"worldScoresUnavailableText": "உலக ஸ்கோர் கிடைக்கவில்லை.",
|
||||||
"worldsBestScoresText": "உலகின் சிறந்த மதிப்பெண்கள்",
|
"worldsBestScoresText": "உலகின் சிறந்த மதிப்பெண்கள்",
|
||||||
"worldsBestTimesText": "உலகின் சிறந்த நேரங்கள்",
|
"worldsBestTimesText": "உலகின் சிறந்த நேரங்கள்",
|
||||||
|
|
|
||||||
11
dist/ba_data/data/languages/turkish.json
vendored
11
dist/ba_data/data/languages/turkish.json
vendored
|
|
@ -326,6 +326,7 @@
|
||||||
"achievementsRemainingText": "Kalan Başarılar;",
|
"achievementsRemainingText": "Kalan Başarılar;",
|
||||||
"achievementsText": "Başarı",
|
"achievementsText": "Başarı",
|
||||||
"achievementsUnavailableForOldSeasonsText": "Üzgünüz, başarı detayları eski sezonlar için kullanılamaz.",
|
"achievementsUnavailableForOldSeasonsText": "Üzgünüz, başarı detayları eski sezonlar için kullanılamaz.",
|
||||||
|
"activatedText": "${THING} aktifleştirildi.",
|
||||||
"addGameWindow": {
|
"addGameWindow": {
|
||||||
"getMoreGamesText": "Daha Çok Oyun...",
|
"getMoreGamesText": "Daha Çok Oyun...",
|
||||||
"titleText": "Oyun Ekle"
|
"titleText": "Oyun Ekle"
|
||||||
|
|
@ -624,7 +625,9 @@
|
||||||
"epicDescriptionFilterText": "${DESCRIPTION} epik ağırçekim.",
|
"epicDescriptionFilterText": "${DESCRIPTION} epik ağırçekim.",
|
||||||
"epicNameFilterText": "Epik ${NAME}",
|
"epicNameFilterText": "Epik ${NAME}",
|
||||||
"errorAccessDeniedText": "erişim reddedildi",
|
"errorAccessDeniedText": "erişim reddedildi",
|
||||||
|
"errorDeviceTimeIncorrectText": "Eyvah! Cihazın ile sunucu arasındaki zaman farkı ${HOURS} saat.\nBu bazı sorunlara yol açabilir.\nLütfen saat ve saat dilimi ayarlarını kontrol et.",
|
||||||
"errorOutOfDiskSpaceText": "disk alanı doldu",
|
"errorOutOfDiskSpaceText": "disk alanı doldu",
|
||||||
|
"errorSecureConnectionFailText": "Güvenli bulut bağlantısı kurulamadı; ağ işlevi başarısız olabilir.",
|
||||||
"errorText": "Hata",
|
"errorText": "Hata",
|
||||||
"errorUnknownText": "bilinmeyen hata",
|
"errorUnknownText": "bilinmeyen hata",
|
||||||
"exitGameText": "Çık ${APP_NAME}?",
|
"exitGameText": "Çık ${APP_NAME}?",
|
||||||
|
|
@ -787,7 +790,7 @@
|
||||||
"ticketPack4Text": "Dev Bilet Paketi",
|
"ticketPack4Text": "Dev Bilet Paketi",
|
||||||
"ticketPack5Text": "Muazzam Bilet Paketi",
|
"ticketPack5Text": "Muazzam Bilet Paketi",
|
||||||
"ticketPack6Text": "En Üst Düzey Bilet Paketi",
|
"ticketPack6Text": "En Üst Düzey Bilet Paketi",
|
||||||
"ticketsFromASponsorText": "Bir sponsordan\n${COUNT} Bilet Al",
|
"ticketsFromASponsorText": "${COUNT} Bilet için\nbir reklam izle",
|
||||||
"ticketsText": "${COUNT} Bilet",
|
"ticketsText": "${COUNT} Bilet",
|
||||||
"titleText": "Bilet Al",
|
"titleText": "Bilet Al",
|
||||||
"unavailableLinkAccountText": "Üzgünüz, Satın almalar bu patformda kullanılamaz.\nBu geçici oldugu gibi, bu hesabını diğer platformlardaki\nhesablara bağlayabilir oradan satın alma işlemi yapbilirsin.",
|
"unavailableLinkAccountText": "Üzgünüz, Satın almalar bu patformda kullanılamaz.\nBu geçici oldugu gibi, bu hesabını diğer platformlardaki\nhesablara bağlayabilir oradan satın alma işlemi yapbilirsin.",
|
||||||
|
|
@ -798,6 +801,7 @@
|
||||||
"youHaveText": "${COUNT} biletin var"
|
"youHaveText": "${COUNT} biletin var"
|
||||||
},
|
},
|
||||||
"googleMultiplayerDiscontinuedText": "Üzgünüz, Google'ın çok oyunculu servisi şu anda çalışmıyor.\nBir yer değişimi için olabildiğince hızlı çalışıyorum.\nO zamana kadar, lütfen başka bir bağlantı yöntemi deneyin.\n-Eric",
|
"googleMultiplayerDiscontinuedText": "Üzgünüz, Google'ın çok oyunculu servisi şu anda çalışmıyor.\nBir yer değişimi için olabildiğince hızlı çalışıyorum.\nO zamana kadar, lütfen başka bir bağlantı yöntemi deneyin.\n-Eric",
|
||||||
|
"googlePlayPurchasesNotAvailableText": "Google Play satın alma işlemleri mevcut değildir.\nMağaza uygulamanızı güncellemeniz gerekebilir.",
|
||||||
"googlePlayText": "Google Play",
|
"googlePlayText": "Google Play",
|
||||||
"graphicsSettingsWindow": {
|
"graphicsSettingsWindow": {
|
||||||
"alwaysText": "Her Zaman",
|
"alwaysText": "Her Zaman",
|
||||||
|
|
@ -1108,7 +1112,10 @@
|
||||||
"playlistsText": "ÇalmaListesi",
|
"playlistsText": "ÇalmaListesi",
|
||||||
"pleaseRateText": "Eğer ${APP_NAME}'dan zevk aldıysan, lütfen oyunu değerlerdir\nve yorumunu yaz. Bu oyunun daha fazla geliştirilmesine\nyardımcı olur.\n\nteşekkürler!\n-eric",
|
"pleaseRateText": "Eğer ${APP_NAME}'dan zevk aldıysan, lütfen oyunu değerlerdir\nve yorumunu yaz. Bu oyunun daha fazla geliştirilmesine\nyardımcı olur.\n\nteşekkürler!\n-eric",
|
||||||
"pleaseWaitText": "Lütfen bekle...",
|
"pleaseWaitText": "Lütfen bekle...",
|
||||||
|
"pluginClassLoadErrorText": "'${PLUGIN}' eklenti sınıfı yüklenirken hata oluştu: ${ERROR}",
|
||||||
|
"pluginInitErrorText": "'${PLUGIN}' eklentisi başlatılırken hata oluştu: ${ERROR}",
|
||||||
"pluginsDetectedText": "Yeni eklentiler tespit edildi. Onları etkinleştirmek veya ayarlarda yapılandırmak için oyunu yeniden başlatın.",
|
"pluginsDetectedText": "Yeni eklentiler tespit edildi. Onları etkinleştirmek veya ayarlarda yapılandırmak için oyunu yeniden başlatın.",
|
||||||
|
"pluginsRemovedText": "${NUM} eklenti(ler) artık bulunmuyor.",
|
||||||
"pluginsText": "Eklentiler",
|
"pluginsText": "Eklentiler",
|
||||||
"practiceText": "Alıştırma",
|
"practiceText": "Alıştırma",
|
||||||
"pressAnyButtonPlayAgainText": "Tekrar oynamak için bir tuşa basın...",
|
"pressAnyButtonPlayAgainText": "Tekrar oynamak için bir tuşa basın...",
|
||||||
|
|
@ -1844,6 +1851,8 @@
|
||||||
"winsPlayerText": "${NAME} Kazandı!",
|
"winsPlayerText": "${NAME} Kazandı!",
|
||||||
"winsTeamText": "${NAME} Kazandı!",
|
"winsTeamText": "${NAME} Kazandı!",
|
||||||
"winsText": "${NAME} Kazandı!",
|
"winsText": "${NAME} Kazandı!",
|
||||||
|
"workspaceSyncErrorText": "${WORKSPACE} eşitlemesinde hata oluştu. Detaylar için günlüğü inceleyin.",
|
||||||
|
"workspaceSyncReuseText": "${WORKSPACE} eşitlenemiyor. Önceden eşitlenmiş sürüm kullanılıyor.",
|
||||||
"worldScoresUnavailableText": "Global Skorlar Mevcut Değil.",
|
"worldScoresUnavailableText": "Global Skorlar Mevcut Değil.",
|
||||||
"worldsBestScoresText": "Global En-İyi Skorlar",
|
"worldsBestScoresText": "Global En-İyi Skorlar",
|
||||||
"worldsBestTimesText": "Global En-İyi Süreler",
|
"worldsBestTimesText": "Global En-İyi Süreler",
|
||||||
|
|
|
||||||
172
dist/ba_data/data/languages/venetian.json
vendored
172
dist/ba_data/data/languages/venetian.json
vendored
|
|
@ -5,27 +5,27 @@
|
||||||
"achievementProgressText": "Obietivi: ${COUNT} de ${TOTAL}",
|
"achievementProgressText": "Obietivi: ${COUNT} de ${TOTAL}",
|
||||||
"campaignProgressText": "Progreso canpagna [Defìsiłe]: ${PROGRESS}",
|
"campaignProgressText": "Progreso canpagna [Defìsiłe]: ${PROGRESS}",
|
||||||
"changeOncePerSeason": "A te połi canbiar ’sto dato soło na volta par stajon.",
|
"changeOncePerSeason": "A te połi canbiar ’sto dato soło na volta par stajon.",
|
||||||
"changeOncePerSeasonError": "Par modifegar (${NUM} days) A te ghè da spetar ła stajon pròsema.",
|
"changeOncePerSeasonError": "Par canbiarlo te ghè da spetar ła pròsema stajon (${NUM} days).",
|
||||||
"customName": "Nome parsonałizà",
|
"customName": "Nome parsonałizà",
|
||||||
"linkAccountsEnterCodeText": "Insarisi còdaze",
|
"linkAccountsEnterCodeText": "Insarisi còdaze",
|
||||||
"linkAccountsGenerateCodeText": "Jènara còdaze",
|
"linkAccountsGenerateCodeText": "Jènara còdaze",
|
||||||
"linkAccountsInfoText": "(sparpagna progresi infrà dispozitivi defarenti)",
|
"linkAccountsInfoText": "(sparpagna progresi infrà dispozidivi defarenti)",
|
||||||
"linkAccountsInstructionsNewText": "Par cołegar do account, jènara un còdaze inte'l primo\ndispozitivo e insarìseło inte’l segondo. I dati de’l\nsegondo account i vegnarà sparpagnài so tuti do i account\n(i dati de’l primo account i ndarà perdesti).\n\nA te połi cołegar fin a ${COUNT} account.\n\nINPORTANTE: cołega soło i account de to propiedà.\nSe A te cołeghi account de calche to amigo, A no sarè\npì boni de zugar online inte’l mèdemo momento.",
|
"linkAccountsInstructionsNewText": "Par cołegar do account, jènara un còdaze inte'l primo\ndispozidivo e insarìseło inte’l segondo. I dati de’l\nsegondo account i vegnarà sparpagnài so tuti do i account\n(i dati de’l primo account i ndarà perdesti).\n\nTe połi cołegar fin a ${COUNT} account.\n\nINPORTANTE: cołega soło i account de to propiedà.\nSe te cołeghi account de calche to amigo, no sarè\npì boni de zugar online inte’l mèdemo momento.",
|
||||||
"linkAccountsText": "Cołega account",
|
"linkAccountsText": "Cołega account",
|
||||||
"linkedAccountsText": "Account cołegài:",
|
"linkedAccountsText": "Account cołegài:",
|
||||||
"nameChangeConfirm": "Vutu canbiar el nome de’l to account co ${NAME}?",
|
"nameChangeConfirm": "Vutu canbiar el nome de’l to account co ${NAME}?",
|
||||||
"resetProgressConfirmNoAchievementsText": "A te si drio ełimenar i to progresi so ła modałidà\ncooparadiva e i to punteji łogałi (ma miga i to biłieti).\n’Sta asion no ła połe mìa èsar anułada. Vutu ndar vanti?",
|
"resetProgressConfirmNoAchievementsText": "Te si drio ełimenar i to progresi so ła modałidà\ncooparadiva e i to punteji łogałi (ma miga i to biłieti).\n’Sta asion no ła połe pì èsar anułada. Vutu ndar vanti?",
|
||||||
"resetProgressConfirmText": "A te si drio ełimenar i to progresi so ła\nmodałidà cooparadiva, i to obietivi e i to punteji\nłogałi (ma miga i to biłieti). ’Sta asion\nno ła połe mìa èsar anułada. Vutu ndar vanti?",
|
"resetProgressConfirmText": "Te si drio ełimenar i to progresi so ła\nmodałidà cooparadiva, i to obietivi e i to punteji\nłogałi (ma miga i to biłieti). ’Sta asion\nno ła połe pì èsar anułada. Vutu ndar vanti?",
|
||||||
"resetProgressText": "Ełìmena progresi",
|
"resetProgressText": "Ełìmena progresi",
|
||||||
"setAccountName": "Inposta un nome utente",
|
"setAccountName": "Inposta un nome utente",
|
||||||
"setAccountNameDesc": "Sełesiona el nome da vizuałizar so’l to account.\nA te połi doparar el nome da uno de i to account\ncołegài o crear un nome parsonałizà ma ùnivogo.",
|
"setAccountNameDesc": "Sełesiona el nome da vizuałizar so’l to account.\nA te połi doparar el nome da uno de i to account\ncołegài o crear un nome parsonałizà ma ùnivogo.",
|
||||||
"signInInfoText": "Conétate par tirar sù biłieti, batajar online e\nsparpagnar i to progresi infrà dispozitivi defarenti.",
|
"signInInfoText": "Conétate par tirar sù biłieti, batajar online e\nsparpagnar i to progresi infrà dispozidivi defarenti.",
|
||||||
"signInText": "Conétate",
|
"signInText": "Conétate",
|
||||||
"signInWithDeviceInfoText": "(par 'sto dispozitivo A ze disponìbiłe un soło account automàtego)",
|
"signInWithDeviceInfoText": "(par 'sto dispozidivo ze disponìbiłe un soło account automàtego)",
|
||||||
"signInWithDeviceText": "Conétate co l'account de’l dispozitivo",
|
"signInWithDeviceText": "Conétate co l'account de’l dispozidivo",
|
||||||
"signInWithGameCircleText": "Conétate co Game Circle",
|
"signInWithGameCircleText": "Conétate co Game Circle",
|
||||||
"signInWithGooglePlayText": "Conétate co Google Play",
|
"signInWithGooglePlayText": "Conétate co Google Play",
|
||||||
"signInWithTestAccountInfoText": "(account de proa vecio: in fuduro dòpara i account de’l dispozitivo)",
|
"signInWithTestAccountInfoText": "(account de proa vecio: in fuduro dòpara i account de’l dispozidivo)",
|
||||||
"signInWithTestAccountText": "Conétate co un account de proa",
|
"signInWithTestAccountText": "Conétate co un account de proa",
|
||||||
"signInWithV2InfoText": "(un account che fusiona so tute łe piataforme)",
|
"signInWithV2InfoText": "(un account che fusiona so tute łe piataforme)",
|
||||||
"signInWithV2Text": "Acedi co un account BombSquad",
|
"signInWithV2Text": "Acedi co un account BombSquad",
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
"unlinkAccountsText": "Descołega account",
|
"unlinkAccountsText": "Descołega account",
|
||||||
"v2LinkInstructionsText": "Acedi o dòpara 'sto link par crear un account.",
|
"v2LinkInstructionsText": "Acedi o dòpara 'sto link par crear un account.",
|
||||||
"viaAccount": "(doparando ${NAME})",
|
"viaAccount": "(doparando ${NAME})",
|
||||||
"youAreSignedInAsText": "A te zugarè cofà:"
|
"youAreSignedInAsText": "Te zugarè cofà:"
|
||||||
},
|
},
|
||||||
"achievementChallengesText": "Obietivi sfide",
|
"achievementChallengesText": "Obietivi sfide",
|
||||||
"achievementText": "Obietivo",
|
"achievementText": "Obietivo",
|
||||||
|
|
@ -323,14 +323,15 @@
|
||||||
},
|
},
|
||||||
"achievementsRemainingText": "Obietivi restanti:",
|
"achievementsRemainingText": "Obietivi restanti:",
|
||||||
"achievementsText": "Obietivi",
|
"achievementsText": "Obietivi",
|
||||||
"achievementsUnavailableForOldSeasonsText": "Ne despiaze, i obietivi de łe stajon pasàe no i ze mìa disponìbiłe.",
|
"achievementsUnavailableForOldSeasonsText": "Ne despiaze, i obietivi de łe stajon pasàe no i ze pì disponìbiłi.",
|
||||||
|
"activatedText": "${THING} ativà.",
|
||||||
"addGameWindow": {
|
"addGameWindow": {
|
||||||
"getMoreGamesText": "Otien pì łevełi...",
|
"getMoreGamesText": "Otien pì łevełi...",
|
||||||
"titleText": "Zonta zugo"
|
"titleText": "Zonta zugo"
|
||||||
},
|
},
|
||||||
"allowText": "Parmeti",
|
"allowText": "Parmeti",
|
||||||
"alreadySignedInText": "El to account el ze in dòparo inte n’antro\ndispozitivo: canbia account o sara sù el zugo\ninte cheł’altro to dispozitivo e proa danovo.",
|
"alreadySignedInText": "El to account el ze in dòparo inte n’antro\ndispozidivo: canbia account o sara sù el zugo\ninte cheł’altro to dispozidivo e proa danovo.",
|
||||||
"apiVersionErrorText": "A no ze mìa posìbiłe cargar el mòduło ${NAME}, el se refarise a ła varsion ${VERSION_USED}. A serve invese ła ${VERSION_REQUIRED}.",
|
"apiVersionErrorText": "Inposìbiłe cargar el mòduło ${NAME}, el se refarise a ła varsion ${VERSION_USED}. Serve invese ła ${VERSION_REQUIRED}.",
|
||||||
"audioSettingsWindow": {
|
"audioSettingsWindow": {
|
||||||
"headRelativeVRAudioInfoText": "(Ativa \"Auto\" soło co A te tachi sù łe fonarołe par ła realtà virtuałe)",
|
"headRelativeVRAudioInfoText": "(Ativa \"Auto\" soło co A te tachi sù łe fonarołe par ła realtà virtuałe)",
|
||||||
"headRelativeVRAudioText": "Àudio par fonarołe VR",
|
"headRelativeVRAudioText": "Àudio par fonarołe VR",
|
||||||
|
|
@ -354,19 +355,19 @@
|
||||||
"buttonText": "boton",
|
"buttonText": "boton",
|
||||||
"canWeDebugText": "Ghetu caro che BombSquad el reporte in automàtego bai,\nblochi e informasion baze só'l so dòparo a'l dezviłupador?\n\n'Sti dati no i contien miga informasion parsonałi ma i ło\njuta a far ndar ben el zugo sensa blochi o bai.",
|
"canWeDebugText": "Ghetu caro che BombSquad el reporte in automàtego bai,\nblochi e informasion baze só'l so dòparo a'l dezviłupador?\n\n'Sti dati no i contien miga informasion parsonałi ma i ło\njuta a far ndar ben el zugo sensa blochi o bai.",
|
||||||
"cancelText": "Anuła",
|
"cancelText": "Anuła",
|
||||||
"cantConfigureDeviceText": "Ne despiaze, ${DEVICE} no'l ze mìa configuràbiłe.",
|
"cantConfigureDeviceText": "Ne despiaze, ${DEVICE} no'l ze miga configuràbiłe.",
|
||||||
"challengeEndedText": "'Sta sfida ła ze fenìa.",
|
"challengeEndedText": "'Sta sfida ła ze fenìa.",
|
||||||
"chatMuteText": "Siłensia ciacołada",
|
"chatMuteText": "Siłensia ciacołada",
|
||||||
"chatMutedText": "Ciacołada siłensiada",
|
"chatMutedText": "Ciacołada siłensiada",
|
||||||
"chatUnMuteText": "Reativa son",
|
"chatUnMuteText": "Reativa son",
|
||||||
"choosingPlayerText": "<sernisi zugador>",
|
"choosingPlayerText": "<sernisi zugador>",
|
||||||
"completeThisLevelToProceedText": "A te ghè da conpletar 'sto\nłeveło par ndar vanti!",
|
"completeThisLevelToProceedText": "Par ndar vanti te ghè\nda conpletar 'sto łeveło!",
|
||||||
"completionBonusText": "Premio de concruzion",
|
"completionBonusText": "Premio de concruzion",
|
||||||
"configControllersWindow": {
|
"configControllersWindow": {
|
||||||
"configureControllersText": "Configura controładori",
|
"configureControllersText": "Configura controładori",
|
||||||
"configureKeyboard2Text": "Configura botonera P2",
|
"configureKeyboard2Text": "Configura botonera P2",
|
||||||
"configureKeyboardText": "Configura botonera",
|
"configureKeyboardText": "Configura botonera",
|
||||||
"configureMobileText": "Dòpara dispozitivi cofà controładori",
|
"configureMobileText": "Dòpara dispozidivi cofà controładori",
|
||||||
"configureTouchText": "Configura schermo tàtiłe",
|
"configureTouchText": "Configura schermo tàtiłe",
|
||||||
"ps3Text": "Controładori PS3",
|
"ps3Text": "Controładori PS3",
|
||||||
"titleText": "Controładori",
|
"titleText": "Controładori",
|
||||||
|
|
@ -374,7 +375,7 @@
|
||||||
"xbox360Text": "Controładori Xbox 360"
|
"xbox360Text": "Controładori Xbox 360"
|
||||||
},
|
},
|
||||||
"configGamepadSelectWindow": {
|
"configGamepadSelectWindow": {
|
||||||
"androidNoteText": "Nota: ła conpatibiłidà par i controładori ła muda drio dispozitivo e varsion de Android.",
|
"androidNoteText": "Nota: ła conpatibiłidà par i controładori ła muda drio dispozidivo e varsion de Android.",
|
||||||
"pressAnyButtonText": "Struca un boton calsìase de'l controłador\nche A te vołi configurar...",
|
"pressAnyButtonText": "Struca un boton calsìase de'l controłador\nche A te vołi configurar...",
|
||||||
"titleText": "Configura controładori"
|
"titleText": "Configura controładori"
|
||||||
},
|
},
|
||||||
|
|
@ -418,13 +419,13 @@
|
||||||
"twoInOneSetupText": "Configurasion controłador 2 so 1",
|
"twoInOneSetupText": "Configurasion controłador 2 so 1",
|
||||||
"uiOnlyDescriptionText": "(par evitar che 'sto controłador el posa zontarse inte na partìa)",
|
"uiOnlyDescriptionText": "(par evitar che 'sto controłador el posa zontarse inte na partìa)",
|
||||||
"uiOnlyText": "Łìmida el dòparo de'l menù",
|
"uiOnlyText": "Łìmida el dòparo de'l menù",
|
||||||
"unassignedButtonsRunText": "Tuti i botoni mìa defenìi i fà córar",
|
"unassignedButtonsRunText": "Tuti i botoni miga defenìi i fà córar",
|
||||||
"unsetText": "<mìa defenìo>",
|
"unsetText": "<miga defenìo>",
|
||||||
"vrReorientButtonText": "Boton de repozision VR"
|
"vrReorientButtonText": "Boton de repozision VR"
|
||||||
},
|
},
|
||||||
"configKeyboardWindow": {
|
"configKeyboardWindow": {
|
||||||
"configuringText": "Configurasion ${DEVICE}",
|
"configuringText": "Configurasion ${DEVICE}",
|
||||||
"keyboard2NoteText": "Nota: ła parte pì granda de łe botonere łe połe rejistrar\nsoło un fià de comandi a'l colpo. Donca, par zugar in du,\nA se ndarìa mejo doparar do botonere defarenti. Tien daconto\nche A te gavarè da defenir in tuti i cazi botoni unìvoghi\npar i tuti do i zugadori."
|
"keyboard2NoteText": "Nota: ła parte pì granda de łe botonere łe połe rejistrar\nsoło un fià de comandi a'l colpo. Donca, par zugar in du,\nse ndarìa mejo doparar do botonere defarenti. Tien daconto\nche te gavarè da defenir in tuti i cazi botoni unìvoghi\npar i tuti do i zugadori."
|
||||||
},
|
},
|
||||||
"configTouchscreenWindow": {
|
"configTouchscreenWindow": {
|
||||||
"actionControlScaleText": "Grandesa controło",
|
"actionControlScaleText": "Grandesa controło",
|
||||||
|
|
@ -445,13 +446,13 @@
|
||||||
"connectMobileDevicesWindow": {
|
"connectMobileDevicesWindow": {
|
||||||
"amazonText": "Amazon Store",
|
"amazonText": "Amazon Store",
|
||||||
"appStoreText": "App Store",
|
"appStoreText": "App Store",
|
||||||
"bestResultsText": "Par zugar co rezultài pì boni A te serve na rede wifi ràpida.\nA te połi redùzar el retardo (lag) de ła rede zugando visin a’l\ntrazmetidor de’l segnałe, desconetendo altri dispozitivi sensa\nfiło o conetendo l’ospitador de’l zugo co un cavo ethernet.",
|
"bestResultsText": "Par zugar co rezultài pì boni te serve na rede wifi ràpida.\nTe połi redùzar el retardo (lag) de ła rede zugando visin a’l\ntrazmetidor de’l segnałe, desconetendo altri dispozidivi sensa\nfiło o conetendo l’ospitador de’l zugo co un cavo ethernet.",
|
||||||
"explanationText": "Par doparar un tełèfono o un tołeto cofà un controłador sensa fiło,\ninstàłaghe rento l’apl \"${REMOTE_APP_NAME}\". Par zugar a ${APP_NAME}\nA te połi conétar co’l wifi tuti i dispozitivi che A te vołi! A ze gratis!",
|
"explanationText": "Par doparar un tełèfono o un tołeto cofà un controłador sensa fiło,\ninstàłaghe rento l’apl \"${REMOTE_APP_NAME}\". Par zugar a ${APP_NAME}\nte połi conétar co’l wifi tuti i dispozidivi che te vołi! Ze agratis!",
|
||||||
"forAndroidText": "par Android:",
|
"forAndroidText": "par Android:",
|
||||||
"forIOSText": "par iOS:",
|
"forIOSText": "par iOS:",
|
||||||
"getItForText": "Descarga ${REMOTE_APP_NAME} par iOS so l'AppStore de\nApple o par Android so'l Store de Google Play o l'Amazon Store",
|
"getItForText": "Descarga ${REMOTE_APP_NAME} par iOS so l'AppStore de\nApple o par Android so'l Store de Google Play o l'Amazon Store",
|
||||||
"googlePlayText": "Google Play",
|
"googlePlayText": "Google Play",
|
||||||
"titleText": "Doparar dispozitivi mòbiłi cofà controładori:"
|
"titleText": "Doparar dispozidivi mòbiłi cofà controładori:"
|
||||||
},
|
},
|
||||||
"continuePurchaseText": "Vutu ndar vanti par ${PRICE}?",
|
"continuePurchaseText": "Vutu ndar vanti par ${PRICE}?",
|
||||||
"continueText": "Sì!",
|
"continueText": "Sì!",
|
||||||
|
|
@ -466,7 +467,7 @@
|
||||||
"currentBestText": "El mejo par deso",
|
"currentBestText": "El mejo par deso",
|
||||||
"customText": "E in pì...",
|
"customText": "E in pì...",
|
||||||
"entryFeeText": "Costo",
|
"entryFeeText": "Costo",
|
||||||
"forfeitConfirmText": "Vutu dalvero dàrgheła vinta?",
|
"forfeitConfirmText": "Vutu dabon dàrgheła vinta?",
|
||||||
"forfeitNotAllowedYetText": "Deso A no te połi miga dàrgheła vinta suito.",
|
"forfeitNotAllowedYetText": "Deso A no te połi miga dàrgheła vinta suito.",
|
||||||
"forfeitText": "Dàgheła vinta",
|
"forfeitText": "Dàgheła vinta",
|
||||||
"multipliersText": "Moltiplegadori",
|
"multipliersText": "Moltiplegadori",
|
||||||
|
|
@ -533,7 +534,7 @@
|
||||||
"stressTestRoundDurationText": "Durada turno",
|
"stressTestRoundDurationText": "Durada turno",
|
||||||
"stressTestTitleText": "Proa soto sforso",
|
"stressTestTitleText": "Proa soto sforso",
|
||||||
"titleText": "Prestasion e Proe soto sforso",
|
"titleText": "Prestasion e Proe soto sforso",
|
||||||
"totalReloadTimeText": "Tenpo totałe recargamento: ${TIME} (par i detaji varda el rejistro)"
|
"totalReloadTimeText": "Tenpo totałe recargamento: ${TIME} (par i detaji varda el rejistro eventi)"
|
||||||
},
|
},
|
||||||
"defaultGameListNameText": "Łista de zugo \"${PLAYMODE}\" predefenìa",
|
"defaultGameListNameText": "Łista de zugo \"${PLAYMODE}\" predefenìa",
|
||||||
"defaultNewGameListNameText": "Ła me łista de zugo ${PLAYMODE}",
|
"defaultNewGameListNameText": "Ła me łista de zugo ${PLAYMODE}",
|
||||||
|
|
@ -623,7 +624,7 @@
|
||||||
"errorAccessDeniedText": "aceso refudà",
|
"errorAccessDeniedText": "aceso refudà",
|
||||||
"errorOutOfDiskSpaceText": "spasio so'l disco fenìo",
|
"errorOutOfDiskSpaceText": "spasio so'l disco fenìo",
|
||||||
"errorText": "Eror",
|
"errorText": "Eror",
|
||||||
"errorUnknownText": "eror mìa conosesto",
|
"errorUnknownText": "eror miga conosesto",
|
||||||
"exitGameText": "Vutu ndar fora da ${APP_NAME}?",
|
"exitGameText": "Vutu ndar fora da ${APP_NAME}?",
|
||||||
"exportSuccessText": "'${NAME}' esportà.",
|
"exportSuccessText": "'${NAME}' esportà.",
|
||||||
"externalStorageText": "Memoria esterna",
|
"externalStorageText": "Memoria esterna",
|
||||||
|
|
@ -646,7 +647,7 @@
|
||||||
"fiveKillText": "BEN 5 SASINÀI!!!!",
|
"fiveKillText": "BEN 5 SASINÀI!!!!",
|
||||||
"flawlessWaveText": "Ondada parfeta!",
|
"flawlessWaveText": "Ondada parfeta!",
|
||||||
"fourKillText": "EŁIMENÀI: 4!!!",
|
"fourKillText": "EŁIMENÀI: 4!!!",
|
||||||
"friendScoresUnavailableText": "Punteji de i amighi mìa disponìbiłi.",
|
"friendScoresUnavailableText": "Punteji de i amighi miga disponìbiłi.",
|
||||||
"gameCenterText": "GameCenter",
|
"gameCenterText": "GameCenter",
|
||||||
"gameCircleText": "GameCircle",
|
"gameCircleText": "GameCircle",
|
||||||
"gameLeadersText": "Clasìfega de'l łeveło ${COUNT}",
|
"gameLeadersText": "Clasìfega de'l łeveło ${COUNT}",
|
||||||
|
|
@ -668,14 +669,14 @@
|
||||||
},
|
},
|
||||||
"gamesToText": "${WINCOUNT} a ${LOSECOUNT}",
|
"gamesToText": "${WINCOUNT} a ${LOSECOUNT}",
|
||||||
"gatherWindow": {
|
"gatherWindow": {
|
||||||
"aboutDescriptionLocalMultiplayerExtraText": "Recòrdate: se A te ghè bastansa controładori, caun\ndispozitivo de un grupo el połe ospitar pì zugadori.",
|
"aboutDescriptionLocalMultiplayerExtraText": "Recòrdate: se te ghè bastansa controładori, tuti i\ndispozidivi de un grupo i połe ospitar pì zugadori.",
|
||||||
"aboutDescriptionText": "Dòpara ’ste sesion par far sù un grupo.\n\nI grupi i te parmete de zugar partìe e tornèi\nco i to amighi infrà i vari dispozitivi.\n\nDòpara el boton ${PARTY} insima a drita par\nciacołar e interajir co’l to grupo.\n(so un controłador, struca ${BUTTON} co A te si inte un menù)",
|
"aboutDescriptionText": "Dòpara 'ste sesion par far sù un grupo.\n\nI grupi i te parmete de zugar partìe e tornèi\nco i to amighi infrà i vari dispozidivi.\n\nDòpara el boton ${PARTY} insima a drita par\nciacołar e interajir co’l to grupo.\n(so un controłador, struca ${BUTTON} co te si inte un menù)",
|
||||||
"aboutText": "Info",
|
"aboutText": "Info",
|
||||||
"addressFetchErrorText": "<eror rancurando sù i ndarisi>",
|
"addressFetchErrorText": "<eror rancurando sù i ndarisi>",
|
||||||
"appInviteMessageText": "L'utente ${NAME} el te ga mandà ${COUNT} biłieti so ${APP_NAME}",
|
"appInviteMessageText": "L'utente ${NAME} el te ga mandà ${COUNT} biłieti so ${APP_NAME}",
|
||||||
"appInviteSendACodeText": "Màndaghe un còdaze",
|
"appInviteSendACodeText": "Màndaghe un còdaze",
|
||||||
"appInviteTitleText": "Invido a proar ${APP_NAME}",
|
"appInviteTitleText": "Invido a proar ${APP_NAME}",
|
||||||
"bluetoothAndroidSupportText": "(el funsiona so tuti i dispozitivi Android co el bluetooth)",
|
"bluetoothAndroidSupportText": "(el funsiona so tuti i dispozidivi Android co el bluetooth)",
|
||||||
"bluetoothDescriptionText": "Òspita/zóntate so un grupo co'l bluetooth:",
|
"bluetoothDescriptionText": "Òspita/zóntate so un grupo co'l bluetooth:",
|
||||||
"bluetoothHostText": "Òspita",
|
"bluetoothHostText": "Òspita",
|
||||||
"bluetoothJoinText": "Zóntate",
|
"bluetoothJoinText": "Zóntate",
|
||||||
|
|
@ -708,8 +709,8 @@
|
||||||
"googlePlayText": "Google Play",
|
"googlePlayText": "Google Play",
|
||||||
"googlePlayVersionOnlyText": "(soło inte ła varsion Android / Google Play)",
|
"googlePlayVersionOnlyText": "(soło inte ła varsion Android / Google Play)",
|
||||||
"hostPublicPartyDescriptionText": "Òspita un grupo pùblego",
|
"hostPublicPartyDescriptionText": "Òspita un grupo pùblego",
|
||||||
"hostingUnavailableText": "Ospitamento mìa disponìbiłe",
|
"hostingUnavailableText": "Ospitamento miga disponìbiłe",
|
||||||
"inDevelopmentWarningText": "Nota:\n\nEl zugo in rede ła ze na funsion nova e in dezviłupo.\nPar deso, A ze dalvero racomandà che tuti i\nzugadori i sie tuti so ła mèdema rede wifi.",
|
"inDevelopmentWarningText": "Nota:\n\nEl zugo in rede ła ze na funsion nova e in dezviłupo.\nPar deso, ze dabon racomandà che tuti i\nzugadori i sipie tuti so ła mèdema rede wifi.",
|
||||||
"internetText": "Internet",
|
"internetText": "Internet",
|
||||||
"inviteAFriendText": "I to amighi zełi sensa zugo? Invìdełi a\nproarlo e i resevarà ${COUNT} biłieti gratùidi.",
|
"inviteAFriendText": "I to amighi zełi sensa zugo? Invìdełi a\nproarlo e i resevarà ${COUNT} biłieti gratùidi.",
|
||||||
"inviteFriendsText": "Invida amighi",
|
"inviteFriendsText": "Invida amighi",
|
||||||
|
|
@ -734,7 +735,7 @@
|
||||||
"otherVersionsText": "(par altre varsion)",
|
"otherVersionsText": "(par altre varsion)",
|
||||||
"partyCodeText": "Còdaze de'l grupo",
|
"partyCodeText": "Còdaze de'l grupo",
|
||||||
"partyInviteAcceptText": "Và ben",
|
"partyInviteAcceptText": "Và ben",
|
||||||
"partyInviteDeclineText": "Mìa deso",
|
"partyInviteDeclineText": "Miga deso",
|
||||||
"partyInviteGooglePlayExtraText": "(varda el paneło 'Google Play' inte ła fenestra 'Crea grupo')",
|
"partyInviteGooglePlayExtraText": "(varda el paneło 'Google Play' inte ła fenestra 'Crea grupo')",
|
||||||
"partyInviteIgnoreText": "Ignora",
|
"partyInviteIgnoreText": "Ignora",
|
||||||
"partyInviteText": "A te ze rivà un invido de ${NAME}\npar zontarte inte'l só grupo!",
|
"partyInviteText": "A te ze rivà un invido de ${NAME}\npar zontarte inte'l só grupo!",
|
||||||
|
|
@ -744,7 +745,7 @@
|
||||||
"partyStatusCheckingText": "Varìfega condision...",
|
"partyStatusCheckingText": "Varìfega condision...",
|
||||||
"partyStatusJoinableText": "deso el to grupo el połe èsar catà da internet",
|
"partyStatusJoinableText": "deso el to grupo el połe èsar catà da internet",
|
||||||
"partyStatusNoConnectionText": "A no ze miga posìbiłe conétarse a'l server",
|
"partyStatusNoConnectionText": "A no ze miga posìbiłe conétarse a'l server",
|
||||||
"partyStatusNotJoinableText": "el to grupo no'l połe mìa èsar catà da internet",
|
"partyStatusNotJoinableText": "el to grupo no'l połe miga èsar catà da internet",
|
||||||
"partyStatusNotPublicText": "el to grupo no'l ze miga pùblego",
|
"partyStatusNotPublicText": "el to grupo no'l ze miga pùblego",
|
||||||
"pingText": "łatensa",
|
"pingText": "łatensa",
|
||||||
"portText": "Porta",
|
"portText": "Porta",
|
||||||
|
|
@ -763,12 +764,12 @@
|
||||||
"startStopHostingMinutesText": "Te połi tacar o fermar de ospitar grupi łìbaramente par n'antri ${MINUTES} menuti.",
|
"startStopHostingMinutesText": "Te połi tacar o fermar de ospitar grupi łìbaramente par n'antri ${MINUTES} menuti.",
|
||||||
"stopHostingText": "Ferma ospitamento",
|
"stopHostingText": "Ferma ospitamento",
|
||||||
"titleText": "Crea grupo",
|
"titleText": "Crea grupo",
|
||||||
"wifiDirectDescriptionBottomText": "Se tuti i dispozitivi i gà ła sesion 'Wifi direto', i sarà boni de dopararlo par\ncatarse e conétarse infrà de łori. Na volta che tuti i dispozitivi i sarà conetesti,\nA te podarè crear grupi inte ła sesion 'Rede łogałe', cofà ła fuse na rede wifi normałe.\n\nPar rezultài pì boni, mejo che l’ospitador de’l wifi direto el sipie l’òspite anca de’l grupo so ${APP_NAME}.",
|
"wifiDirectDescriptionBottomText": "Se tuti i dispozidivi i gà ła sesion 'Wifi direto', i sarà boni de dopararlo par\ncatarse e conétarse infrà de łori. Na volta che tuti i dispozidivi i sarà conetesti,\nte podarè crear grupi inte ła sesion 'Rede łogałe', cofà ła fuse na rede wifi normałe.\n\nPar rezultài pì boni, mejo che l’ospitador de’l wifi direto el sipie l’òspite anca de’l grupo so ${APP_NAME}.",
|
||||||
"wifiDirectDescriptionTopText": "El Wifi direto el połe èsar doparà par conétar diretamente dispozitivi Android\nsensa pasar par ła rede wifi. El funsiona mejo so varsion Android 4.2 o pì resenti.\n\nPar dopararlo, verzi łe inpostasion wifi e controła ła funsion 'Wifi direto'.",
|
"wifiDirectDescriptionTopText": "El Wifi direto el połe èsar doparà par conétar diretamente dispozidivi Android\nsensa pasar par ła rede wifi. El funsiona mejo so varsion Android 4.2 o pì resenti.\n\nPar dopararlo, verzi łe inpostasion wifi e controła ła funsion 'Wifi direto'.",
|
||||||
"wifiDirectOpenWiFiSettingsText": "Verzi inpostasion wifi",
|
"wifiDirectOpenWiFiSettingsText": "Verzi inpostasion wifi",
|
||||||
"wifiDirectText": "Wifi direto",
|
"wifiDirectText": "Wifi direto",
|
||||||
"worksBetweenAllPlatformsText": "(el funsiona intrà tute łe piataforme)",
|
"worksBetweenAllPlatformsText": "(el funsiona intrà tute łe piataforme)",
|
||||||
"worksWithGooglePlayDevicesText": "(el funsiona co tuti i dispozitivi co ła varsion de’l zugo de Google Play par Android)",
|
"worksWithGooglePlayDevicesText": "(el funsiona co tuti i dispozidivi co ła varsion de’l zugo de Google Play par Android)",
|
||||||
"youHaveBeenSentAPromoCodeText": "A te ze stà mandà un còdaze promosionałe de ${APP_NAME}:"
|
"youHaveBeenSentAPromoCodeText": "A te ze stà mandà un còdaze promosionałe de ${APP_NAME}:"
|
||||||
},
|
},
|
||||||
"getTicketsWindow": {
|
"getTicketsWindow": {
|
||||||
|
|
@ -788,8 +789,8 @@
|
||||||
"ticketsText": "${COUNT} biłieti",
|
"ticketsText": "${COUNT} biłieti",
|
||||||
"titleText": "Otien biłieti",
|
"titleText": "Otien biłieti",
|
||||||
"unavailableLinkAccountText": "Ne despiaze, A no se połe miga cronpar so 'sta piataforma.\nVołendo, cofà sołusion, A te połi cołegar 'sto account co\nuno inte n'antra piataforma e cronpar calcosa da łà.",
|
"unavailableLinkAccountText": "Ne despiaze, A no se połe miga cronpar so 'sta piataforma.\nVołendo, cofà sołusion, A te połi cołegar 'sto account co\nuno inte n'antra piataforma e cronpar calcosa da łà.",
|
||||||
"unavailableTemporarilyText": "'Sta funsion no ła ze mìa disponìbiłe par deso: proa danovo pì tardi.",
|
"unavailableTemporarilyText": "'Sta funsion no ła ze miga disponìbiłe par deso: proa danovo pì tardi.",
|
||||||
"unavailableText": "Ne despiaze, 'sta funsion no ła ze mìa disponìbiłe.",
|
"unavailableText": "Ne despiaze, 'sta funsion no ła ze miga disponìbiłe.",
|
||||||
"versionTooOldText": "Ne despiaze, 'sta varsion ła ze masa vecia: ajorna el zugo co cheła nova.",
|
"versionTooOldText": "Ne despiaze, 'sta varsion ła ze masa vecia: ajorna el zugo co cheła nova.",
|
||||||
"youHaveShortText": "A te ghè ${COUNT}",
|
"youHaveShortText": "A te ghè ${COUNT}",
|
||||||
"youHaveText": "A te ghè ${COUNT} biłieti"
|
"youHaveText": "A te ghè ${COUNT} biłieti"
|
||||||
|
|
@ -817,13 +818,13 @@
|
||||||
"helpWindow": {
|
"helpWindow": {
|
||||||
"bombInfoText": "- Bonbe -\nPì forti de i crogni, ma łe połe\nfarte małe anca a ti. Dopàrełe\nben tràndoghełe doso a i nemighi\nprima che łe salte par aria.",
|
"bombInfoText": "- Bonbe -\nPì forti de i crogni, ma łe połe\nfarte małe anca a ti. Dopàrełe\nben tràndoghełe doso a i nemighi\nprima che łe salte par aria.",
|
||||||
"canHelpText": "${APP_NAME} el połe jutarte!",
|
"canHelpText": "${APP_NAME} el połe jutarte!",
|
||||||
"controllersInfoText": "A te połi zugar a ${APP_NAME} co i amighi co na rede o, se gavì\ncontroładori che basta, połì zugar tuti insenbre so el mèdemo\ndispozitivo: ${APP_NAME} el ghin suporta racuanti. Połì senpre doparar\ni tełèfoni cofà controładori co l’apl gratùida '${REMOTE_APP_NAME}'.\nPar info in pì varda so Inpostasion > Controładori.",
|
"controllersInfoText": "Te połi zugar a ${APP_NAME} co i amighi co na rede o, se gavì\ncontroładori che basta, połì zugar tuti insenbre so el mèdemo\ndispozidivo: ${APP_NAME} el ghin suporta racuanti. Połì senpre doparar\ni tełèfoni cofà controładori co l’apl gratùida '${REMOTE_APP_NAME}'.\nPar info in pì varda so Inpostasion > Controładori.",
|
||||||
"controllersInfoTextRemoteOnly": "Te połi zugar a ${APP_NAME} co i to amighi doparando na rede,\no zugar tuti so'l mèdemo dispozitivo doparando i tełèfoni cofà\ncontroładori co l'apl gratùida '${REMOTE_APP_NAME}'.",
|
"controllersInfoTextRemoteOnly": "Te połi zugar a ${APP_NAME} co i to amighi doparando na rede,\no zugar tuti so'l mèdemo dispozidivo doparando i tełèfoni cofà\ncontroładori co l'apl gratùida '${REMOTE_APP_NAME}'.",
|
||||||
"controllersText": "Controładori",
|
"controllersText": "Controładori",
|
||||||
"controlsSubtitleText": "El to amighévołe parsonajo de ${APP_NAME} el gà un fià de funsion de baze:",
|
"controlsSubtitleText": "El to amighévołe parsonajo de ${APP_NAME} el gà un fià de funsion de baze:",
|
||||||
"controlsText": "Controłi",
|
"controlsText": "Controłi",
|
||||||
"devicesInfoText": "Ła varsion VR de ${APP_NAME} ła połe èsar zugada so na rede anca\nco ła varsion normałe de l'app, donca tira fora tełèfoni, tołeti\ne computers e taca a zugar! Podarìa èsar ùtiłe conétar na varsion\nnormałe de'l zugo a cheła VR anca soło par parmétarghe a łe parsone\nde poder ndarghe drio a'l zugo da fora.",
|
"devicesInfoText": "Ła varsion VR de ${APP_NAME} ła połe èsar zugada so na rede anca\nco ła varsion normałe de l'app, donca tira fora tełèfoni, tołeti\ne computers e taca a zugar! Podarìa èsar ùtiłe conétar na varsion\nnormałe de'l zugo a cheła VR anca soło par parmétarghe a łe parsone\nde poder ndarghe drio a'l zugo da fora.",
|
||||||
"devicesText": "Dispozitivi",
|
"devicesText": "Dispozidivi",
|
||||||
"friendsGoodText": "A ze senpre bona roba vèrghene. Se se ła gode de pì co pì zugadori\ne ${APP_NAME} el ghin suporta fin a 8, e 'sta roba ła ne mena a:",
|
"friendsGoodText": "A ze senpre bona roba vèrghene. Se se ła gode de pì co pì zugadori\ne ${APP_NAME} el ghin suporta fin a 8, e 'sta roba ła ne mena a:",
|
||||||
"friendsText": "Amighi",
|
"friendsText": "Amighi",
|
||||||
"jumpInfoText": "- Salto -\nSalta par traversar buzi cełi,\npar trar robe pì alte, o par\nfar védar tuta ła to ałegresa.",
|
"jumpInfoText": "- Salto -\nSalta par traversar buzi cełi,\npar trar robe pì alte, o par\nfar védar tuta ła to ałegresa.",
|
||||||
|
|
@ -858,18 +859,18 @@
|
||||||
},
|
},
|
||||||
"holdAnyButtonText": "<tien strucà un boton calsìase>",
|
"holdAnyButtonText": "<tien strucà un boton calsìase>",
|
||||||
"holdAnyKeyText": "<tien strucà un boton calsìase>",
|
"holdAnyKeyText": "<tien strucà un boton calsìase>",
|
||||||
"hostIsNavigatingMenusText": "- ${HOST} l'è drio navegar intrà i menù a zbregabałon! -",
|
"hostIsNavigatingMenusText": "- ${HOST} ze drio navegar intrà i menù a zbregabałon! -",
|
||||||
"importPlaylistCodeInstructionsText": "Dòpara 'sto còdaze par inportar 'sta łista de zugo ndove che te vołi:",
|
"importPlaylistCodeInstructionsText": "Dòpara 'sto còdaze par inportar 'sta łista de zugo ndove che te vołi:",
|
||||||
"importPlaylistSuccessText": "Łista de zugo '${NAME}' a ${TYPE} inportada",
|
"importPlaylistSuccessText": "Łista de zugo '${NAME}' a ${TYPE} inportada",
|
||||||
"importText": "Inporta",
|
"importText": "Inporta",
|
||||||
"importingText": "Inportasion...",
|
"importingText": "Inportasion...",
|
||||||
"inGameClippedNameText": "rento el zugo:\n\"${NAME}\"",
|
"inGameClippedNameText": "rento el zugo:\n\"${NAME}\"",
|
||||||
"installDiskSpaceErrorText": "EROR: A no ze mìa posìbiłe fenir l’instałasion.\nEl to dispozitivo el podarìa èsar sensa spasio.\nŁìbara un fià de memoria e proa danovo.",
|
"installDiskSpaceErrorText": "EROR: inposìbiłe fenir l’instałasion.\nEl to dispozidivo el podarìa èsar sensa spasio.\nŁìbara un fià de memoria e proa danovo.",
|
||||||
"internal": {
|
"internal": {
|
||||||
"arrowsToExitListText": "struca ${LEFT} o ${RIGHT} par ndar fora da ła serie",
|
"arrowsToExitListText": "struca ${LEFT} o ${RIGHT} par ndar fora da ła serie",
|
||||||
"buttonText": "boton",
|
"buttonText": "boton",
|
||||||
"cantKickHostError": "A no te połi miga parar vìa l'ospitador.",
|
"cantKickHostError": "A no te połi miga parar vìa l'ospitador.",
|
||||||
"chatBlockedText": "${NAME} l'è stà tajà fora da ła chat par ${TIME} segondi.",
|
"chatBlockedText": "${NAME} ze stà tajà fora da ła chat par ${TIME} segondi.",
|
||||||
"connectedToGameText": "A te te si zontà so '${NAME}'",
|
"connectedToGameText": "A te te si zontà so '${NAME}'",
|
||||||
"connectedToPartyText": "A te te si zontà so'l grupo de ${NAME}!",
|
"connectedToPartyText": "A te te si zontà so'l grupo de ${NAME}!",
|
||||||
"connectingToPartyText": "Conesion...",
|
"connectingToPartyText": "Conesion...",
|
||||||
|
|
@ -890,10 +891,10 @@
|
||||||
"corruptFileText": "A ze stà catài fora file coronpesti. Proa reinstałar el zugo o manda na mail a: ${EMAIL}",
|
"corruptFileText": "A ze stà catài fora file coronpesti. Proa reinstałar el zugo o manda na mail a: ${EMAIL}",
|
||||||
"errorPlayingMusicText": "Eror de reprodusion muzegałe: ${MUSIC}",
|
"errorPlayingMusicText": "Eror de reprodusion muzegałe: ${MUSIC}",
|
||||||
"errorResettingAchievementsText": "A no ze miga posìbiłe reinpostar i obietivi in łinea. Proa danovo pì tardi.",
|
"errorResettingAchievementsText": "A no ze miga posìbiłe reinpostar i obietivi in łinea. Proa danovo pì tardi.",
|
||||||
"hasMenuControlText": "${NAME} l'à el controło de'l menù",
|
"hasMenuControlText": "${NAME} gà el controło de'l menù",
|
||||||
"incompatibleNewerVersionHostText": "L'ospitador el gà na varsion de'l zugo pì resente.\nAjórneło anca ti a ła varsion ùltema e proa danovo.",
|
"incompatibleNewerVersionHostText": "L'ospitador el gà na varsion de'l zugo pì resente.\nAjórneło anca ti a ła varsion ùltema e proa danovo.",
|
||||||
"incompatibleVersionHostText": "L'ospitador el gà na varsion de'l zugo defarente.\nSegùreve de ver tuti do l'apl ajornada e provè danovo.",
|
"incompatibleVersionHostText": "L'ospitador el gà na varsion de'l zugo defarente.\nSegùreve de ver tuti do l'apl ajornada e provè danovo.",
|
||||||
"incompatibleVersionPlayerText": "${NAME} l'à na varsion de'l zugo defarente.\nSegùreve de ver tuti do l'apl ajornada e provè danovo.",
|
"incompatibleVersionPlayerText": "${NAME} gà na varsion de'l zugo defarente.\nSegùreve de ver tuti do l'apl ajornada e provè danovo.",
|
||||||
"invalidAddressErrorText": "Eror: ndariso miga vàłido.",
|
"invalidAddressErrorText": "Eror: ndariso miga vàłido.",
|
||||||
"invalidNameErrorText": "Eror: nome miga vàłido.",
|
"invalidNameErrorText": "Eror: nome miga vàłido.",
|
||||||
"invalidPortErrorText": "Eror: porta miga vàłida.",
|
"invalidPortErrorText": "Eror: porta miga vàłida.",
|
||||||
|
|
@ -901,20 +902,20 @@
|
||||||
"invitationsSentText": "Mandài ${COUNT} invidi.",
|
"invitationsSentText": "Mandài ${COUNT} invidi.",
|
||||||
"joinedPartyInstructionsText": "Calchedun el se gà zontà inte'l to grupo.\nVà so \"Zuga\" par tacar na partìa.",
|
"joinedPartyInstructionsText": "Calchedun el se gà zontà inte'l to grupo.\nVà so \"Zuga\" par tacar na partìa.",
|
||||||
"keyboardText": "Botonera",
|
"keyboardText": "Botonera",
|
||||||
"kickIdlePlayersKickedText": "A ze stà parà vìa ${NAME} par masa sonera.",
|
"kickIdlePlayersKickedText": "Ze stà parà fora ${NAME} par masa sonera.",
|
||||||
"kickIdlePlayersWarning1Text": "Se ła só sonera ła sèvita, ${NAME} l'vegnarà parà vìa tenpo ${COUNT} segondi.",
|
"kickIdlePlayersWarning1Text": "Se ła só sonera ła sèvita, ${NAME} vegnarà parà fora tenpo ${COUNT} segondi.",
|
||||||
"kickIdlePlayersWarning2Text": "(A te połi dezativarlo so Inpostasion > Avansàe)",
|
"kickIdlePlayersWarning2Text": "(A te połi dezativarlo so Inpostasion > Avansàe)",
|
||||||
"leftGameText": "A te si ndà fora da '${NAME}'.",
|
"leftGameText": "A te si ndà fora da '${NAME}'.",
|
||||||
"leftPartyText": "A te si ndà fora da'l grupo de ${NAME}.",
|
"leftPartyText": "A te si ndà fora da'l grupo de ${NAME}.",
|
||||||
"noMusicFilesInFolderText": "Ła carteła no ła gà rento gnaun file muzegałe.",
|
"noMusicFilesInFolderText": "Ła carteła no ła gà rento gnaun file muzegałe.",
|
||||||
"playerJoinedPartyText": "${NAME} l'se gà zontà inte'l grupo!",
|
"playerJoinedPartyText": "${NAME} l'se gà zontà inte'l grupo!",
|
||||||
"playerLeftPartyText": "${NAME} l'è ndà fora da'l grupo!",
|
"playerLeftPartyText": "${NAME} gà mołà el grupo!",
|
||||||
"rejectingInviteAlreadyInPartyText": "Invido refudà (dezà inte un grupo).",
|
"rejectingInviteAlreadyInPartyText": "Invido refudà (dezà inte un grupo).",
|
||||||
"serverRestartingText": "El server el ze drio retacarse. Reconétate infrà na scianta...",
|
"serverRestartingText": "El server el ze drio retacarse. Reconétate infrà na scianta...",
|
||||||
"serverShuttingDownText": "El server el ze drio stuarse...",
|
"serverShuttingDownText": "El server el ze drio stuarse...",
|
||||||
"signInErrorText": "Eror in entrada.",
|
"signInErrorText": "Eror in entrada.",
|
||||||
"signInNoConnectionText": "A no ze mìa posìbiłe ndar rento. (gnauna conesion a internet?)",
|
"signInNoConnectionText": "Inposìbiłe acédar. (sensa conesion internet?)",
|
||||||
"telnetAccessDeniedText": "EROR: l'utente no'l gà mìa parmeso l'aceso co telnet.",
|
"telnetAccessDeniedText": "EROR: l'utente no'l gà miga parmeso l'aceso co telnet.",
|
||||||
"timeOutText": "(tocarà a ti tenpo ${TIME} segondi)",
|
"timeOutText": "(tocarà a ti tenpo ${TIME} segondi)",
|
||||||
"touchScreenJoinWarningText": "A te te si zontà co'l touchscreen.\nSe ła ze stà na capeła, struca 'Menù > Moła łeveło'.",
|
"touchScreenJoinWarningText": "A te te si zontà co'l touchscreen.\nSe ła ze stà na capeła, struca 'Menù > Moła łeveło'.",
|
||||||
"touchScreenText": "TouchScreen",
|
"touchScreenText": "TouchScreen",
|
||||||
|
|
@ -931,9 +932,9 @@
|
||||||
"keyboardChangeInstructionsText": "Struca spasio do 'olte par mudar botonera.",
|
"keyboardChangeInstructionsText": "Struca spasio do 'olte par mudar botonera.",
|
||||||
"keyboardNoOthersAvailableText": "A no ghe ze miga altre botonere disponìbiłi.",
|
"keyboardNoOthersAvailableText": "A no ghe ze miga altre botonere disponìbiłi.",
|
||||||
"keyboardSwitchText": "Pasajo a ła botonera \"${NAME}\".",
|
"keyboardSwitchText": "Pasajo a ła botonera \"${NAME}\".",
|
||||||
"kickOccurredText": "${NAME} l'è stà parà vìa.",
|
"kickOccurredText": "${NAME} ze stà parà fora.",
|
||||||
"kickQuestionText": "Vutu parar vìa ${NAME}?",
|
"kickQuestionText": "Vutu parar vìa ${NAME}?",
|
||||||
"kickText": "Para vìa",
|
"kickText": "Para fora",
|
||||||
"kickVoteCantKickAdminsText": "I aministradori no i połe mìa èsar parài vìa.",
|
"kickVoteCantKickAdminsText": "I aministradori no i połe mìa èsar parài vìa.",
|
||||||
"kickVoteCantKickSelfText": "A no te połi mìa pararte vìa da soło.",
|
"kickVoteCantKickSelfText": "A no te połi mìa pararte vìa da soło.",
|
||||||
"kickVoteFailedNotEnoughVotersText": "A ghe ze masa pochi zugadori par na votasion.",
|
"kickVoteFailedNotEnoughVotersText": "A ghe ze masa pochi zugadori par na votasion.",
|
||||||
|
|
@ -996,8 +997,8 @@
|
||||||
"howToPlayText": "Come zugar",
|
"howToPlayText": "Come zugar",
|
||||||
"justPlayerText": "(Soło par ${NAME})",
|
"justPlayerText": "(Soło par ${NAME})",
|
||||||
"leaveGameText": "Moła łeveło",
|
"leaveGameText": "Moła łeveło",
|
||||||
"leavePartyConfirmText": "Vutu dalvero ndar fora da'l grupo?",
|
"leavePartyConfirmText": "Vutu dabon ndar fora da'l grupo?",
|
||||||
"leavePartyText": "Va fora da'l grupo",
|
"leavePartyText": "Moła grupo",
|
||||||
"quitText": "Sortisi",
|
"quitText": "Sortisi",
|
||||||
"resumeText": "Continua",
|
"resumeText": "Continua",
|
||||||
"settingsText": "Inpostasion"
|
"settingsText": "Inpostasion"
|
||||||
|
|
@ -1020,9 +1021,9 @@
|
||||||
"multiKillText": "CAENA DE ${COUNT} FATI FORA!!!!!",
|
"multiKillText": "CAENA DE ${COUNT} FATI FORA!!!!!",
|
||||||
"multiPlayerCountText": "${COUNT} zugadori",
|
"multiPlayerCountText": "${COUNT} zugadori",
|
||||||
"mustInviteFriendsText": "Nota: A te ghè da invidar i amighi\nso'l paneło \"${GATHER}\" o picar pì\ncontroładori par zugar in multizugador.",
|
"mustInviteFriendsText": "Nota: A te ghè da invidar i amighi\nso'l paneło \"${GATHER}\" o picar pì\ncontroładori par zugar in multizugador.",
|
||||||
"nameBetrayedText": "${NAME} l'à tradìo ${VICTIM}.",
|
"nameBetrayedText": "${NAME} gà tradìo ${VICTIM}.",
|
||||||
"nameDiedText": "${NAME} l'è crepà.",
|
"nameDiedText": "${NAME} ze crepà.",
|
||||||
"nameKilledText": "${NAME} l'à copà ${VICTIM}.",
|
"nameKilledText": "${NAME} gà copà ${VICTIM}.",
|
||||||
"nameNotEmptyText": "El nome no'l połe miga star vodo!",
|
"nameNotEmptyText": "El nome no'l połe miga star vodo!",
|
||||||
"nameScoresText": "Un ponto par ${NAME}!",
|
"nameScoresText": "Un ponto par ${NAME}!",
|
||||||
"nameSuicideKidFriendlyText": "${NAME} par zbałio L ze crepà.",
|
"nameSuicideKidFriendlyText": "${NAME} par zbałio L ze crepà.",
|
||||||
|
|
@ -1037,8 +1038,8 @@
|
||||||
"nextLevelText": "Łeveło seguente",
|
"nextLevelText": "Łeveło seguente",
|
||||||
"noAchievementsRemainingText": "- gnaun",
|
"noAchievementsRemainingText": "- gnaun",
|
||||||
"noContinuesText": "(sensa continui)",
|
"noContinuesText": "(sensa continui)",
|
||||||
"noExternalStorageErrorText": "Inte ’sto dispozitivo A no ze stà catada gnauna memoria esterna",
|
"noExternalStorageErrorText": "So ’sto dispozidivo no ze stà catada gnauna memoria esterna",
|
||||||
"noGameCircleText": "Eror: A no te si miga conetesto co GameCircle",
|
"noGameCircleText": "Eror: no te si miga conetesto co GameCircle",
|
||||||
"noScoresYetText": "Gnancora gnaun puntejo.",
|
"noScoresYetText": "Gnancora gnaun puntejo.",
|
||||||
"noThanksText": "Nò, grasie",
|
"noThanksText": "Nò, grasie",
|
||||||
"noTournamentsInTestBuildText": "AVERTENSA: i punteji de'l tornèo de 'sta varsion de proa i vegnarà ignorài.",
|
"noTournamentsInTestBuildText": "AVERTENSA: i punteji de'l tornèo de 'sta varsion de proa i vegnarà ignorài.",
|
||||||
|
|
@ -1087,7 +1088,7 @@
|
||||||
"playerCountAbbreviatedText": "${COUNT}z",
|
"playerCountAbbreviatedText": "${COUNT}z",
|
||||||
"playerDelayedJoinText": "Co tacarà el turno che'l vien A se zontarà anca ${PLAYER}.",
|
"playerDelayedJoinText": "Co tacarà el turno che'l vien A se zontarà anca ${PLAYER}.",
|
||||||
"playerInfoText": "Informasion zugador",
|
"playerInfoText": "Informasion zugador",
|
||||||
"playerLeftText": "${PLAYER} l'à mołà el łeveło.",
|
"playerLeftText": "${PLAYER} gà mołà el łeveło.",
|
||||||
"playerLimitReachedText": "Nùmaro màsemo de ${COUNT} zugadori: A no połe zontarse pì nesun.",
|
"playerLimitReachedText": "Nùmaro màsemo de ${COUNT} zugadori: A no połe zontarse pì nesun.",
|
||||||
"playerProfilesWindow": {
|
"playerProfilesWindow": {
|
||||||
"cantDeleteAccountProfileText": "A no te połi miga ełimenar el profiło prinsipałe de'l to account.",
|
"cantDeleteAccountProfileText": "A no te połi miga ełimenar el profiło prinsipałe de'l to account.",
|
||||||
|
|
@ -1105,7 +1106,10 @@
|
||||||
"playlistsText": "Łiste de zugo",
|
"playlistsText": "Łiste de zugo",
|
||||||
"pleaseRateText": "Se ${APP_NAME} el ze drio piazerte, tote un àtemo par\nłasarghe zó na vałudasion o scrìvarghe zó un comento. 'Ste\nopinion łe tornarà còmode par dezviłupi fuduri de'l zugo.\n\ngrasie!\n-eric",
|
"pleaseRateText": "Se ${APP_NAME} el ze drio piazerte, tote un àtemo par\nłasarghe zó na vałudasion o scrìvarghe zó un comento. 'Ste\nopinion łe tornarà còmode par dezviłupi fuduri de'l zugo.\n\ngrasie!\n-eric",
|
||||||
"pleaseWaitText": "Speta n'àtemo...",
|
"pleaseWaitText": "Speta n'àtemo...",
|
||||||
|
"pluginClassLoadErrorText": "Eror de cargamento de ła clase de estension '${PLUGIN}': ${ERROR}",
|
||||||
|
"pluginInitErrorText": "Eror de inisiałizasion de l'estension '${PLUGIN}': ${ERROR}",
|
||||||
"pluginsDetectedText": "Estension nove rełevàe. Retaca el zugo par ativarle, o configùrełe so łe inpostasion.",
|
"pluginsDetectedText": "Estension nove rełevàe. Retaca el zugo par ativarle, o configùrełe so łe inpostasion.",
|
||||||
|
"pluginsRemovedText": "Estension miga catàe: ${NUM}",
|
||||||
"pluginsText": "Estension",
|
"pluginsText": "Estension",
|
||||||
"practiceText": "Pràtega",
|
"practiceText": "Pràtega",
|
||||||
"pressAnyButtonPlayAgainText": "Struca un boton calsìase par zugar danovo...",
|
"pressAnyButtonPlayAgainText": "Struca un boton calsìase par zugar danovo...",
|
||||||
|
|
@ -1125,7 +1129,7 @@
|
||||||
},
|
},
|
||||||
"promoSubmitErrorText": "Eror de trazmision de'l còdaze: controła ła to conesion internet",
|
"promoSubmitErrorText": "Eror de trazmision de'l còdaze: controła ła to conesion internet",
|
||||||
"ps3ControllersWindow": {
|
"ps3ControllersWindow": {
|
||||||
"macInstructionsText": "Stua ła corente so'l dadrìo de ła to PS3, segùrate che'l\nbluetooth de'l to Mac el sipie ativà, daspò coneti el to controłador\na'l to Mac co un cavo USB par cubiarli. Da deso in vanti A te\npołi doparar el boton \"cao\" de'l controłador par conétarlo co'l to\nMac in modałidà USB (co'l fiło) o bluetooth (sensa fiło).\n\nPar el cubiamento calche Mac el podarìa dimandarte un còdaze.\nSe càpida, varda ła demostrasion seguente o serca juto so Google.\n\n\n\n\nI controładori PS3 conetesti sensa fiło i gavarìa da védarse inte ła łista\nde'l dispozitivo so Prefarense de sistema > Bluetooth. Co te vorè\ndopararli danovo so ła to PS3, te podarisi ver da cavarli vìa da 'sta łista.\n\nSegùrate anca de desconétarli da'l bluetooth co A no te łi\ndòpari o łe só batarìe łe sevitarà a sconsumarse.\n\nEl bluetooth el gavarìa da suportar fin a 7 dispozitivi conetesti,\nanca se ła capasidà ła podarìa variar.",
|
"macInstructionsText": "Stua ła corente so'l dadrìo de ła to PS3, segùrate che'l\nbluetooth de'l to Mac el sipie ativà, daspò coneti el to controłador\na'l to Mac co un cavo USB par cubiarli. Da deso in vanti te\npołi doparar el boton \"cao\" de'l controłador par conétarlo co'l to\nMac in modałidà USB (co'l fiło) o bluetooth (sensa fiło).\n\nPar el cubiamento calche Mac el podarìa dimandarte un còdaze.\nSe càpida, varda ła demostrasion seguente o serca juto so Google.\n\n\n\n\nI controładori PS3 conetesti sensa fiło i gavarìa da védarse inte ła łista\nde'l dispozidivo so Prefarense de sistema > Bluetooth. Co te vorè\ndopararli danovo so ła to PS3, te podarisi ver da cavarli vìa da 'sta łista.\n\nSegùrate anca de desconétarli da'l bluetooth co no te łi\ndòpari o łe só batarìe łe sevitarà a sconsumarse.\n\nEl bluetooth el gavarìa da suportar fin a 7 dispozidivi conetesti,\nanca se ła capasidà ła podarìa variar.",
|
||||||
"ouyaInstructionsText": "Par doparar un controłador PS3 co ła to OUYA, conéteło co un cavo USB par\ncubiarlo. 'Sta asion ła podarìa desconétar cheł'altri to controładori, donca\nA podarìa servirte retacar ła to OUYA e destacar el cavo USB.\n\nDa deso in vanti A te dovarisi èsar bon de doparar el boton \"cao\" de'l\ncontrołador par conétarlo sensa fiło. Co A te ghè fenìo de zugar, tien\nstrucà el boton \"cao\" par 10 segondi par stuar el controłador, el\npodarìa restar inpisà e stracar ła batarìa.",
|
"ouyaInstructionsText": "Par doparar un controłador PS3 co ła to OUYA, conéteło co un cavo USB par\ncubiarlo. 'Sta asion ła podarìa desconétar cheł'altri to controładori, donca\nA podarìa servirte retacar ła to OUYA e destacar el cavo USB.\n\nDa deso in vanti A te dovarisi èsar bon de doparar el boton \"cao\" de'l\ncontrołador par conétarlo sensa fiło. Co A te ghè fenìo de zugar, tien\nstrucà el boton \"cao\" par 10 segondi par stuar el controłador, el\npodarìa restar inpisà e stracar ła batarìa.",
|
||||||
"pairingTutorialText": "demostrasion video pa'l cubiamento",
|
"pairingTutorialText": "demostrasion video pa'l cubiamento",
|
||||||
"titleText": "Doparar un controłador PS3 co ${APP_NAME}:"
|
"titleText": "Doparar un controłador PS3 co ${APP_NAME}:"
|
||||||
|
|
@ -1153,7 +1157,7 @@
|
||||||
"cant_resolve_host": "A no ze mìa posìbiłe catar fora l'ospitador.",
|
"cant_resolve_host": "A no ze mìa posìbiłe catar fora l'ospitador.",
|
||||||
"capturing": "Drio spetar i zugadori…",
|
"capturing": "Drio spetar i zugadori…",
|
||||||
"connected": "Conetesto.",
|
"connected": "Conetesto.",
|
||||||
"description": "Dòpara el to tełèfono o tołeto cofà controłador par BombSquad.\nA połe conétarse so un schermo ùgnoło fin a 8 dispozitivi insenbre, par un feston bueło multizugador!",
|
"description": "Dòpara el to tełèfono o tołeto cofà controłador par BombSquad.\nPołe conétarse so un schermo ùgnoło fin a 8 dispozidivi insenbre, par un feston bueło multizugador!",
|
||||||
"disconnected": "Desconetesto da'l server.",
|
"disconnected": "Desconetesto da'l server.",
|
||||||
"dpad_fixed": "fiso",
|
"dpad_fixed": "fiso",
|
||||||
"dpad_floating": "mòbiłe",
|
"dpad_floating": "mòbiłe",
|
||||||
|
|
@ -1206,9 +1210,9 @@
|
||||||
},
|
},
|
||||||
"scoreWasText": "(prima ${COUNT})",
|
"scoreWasText": "(prima ${COUNT})",
|
||||||
"selectText": "Sełesiona",
|
"selectText": "Sełesiona",
|
||||||
"seriesWinLine1PlayerText": "L'À VINTO ŁA",
|
"seriesWinLine1PlayerText": "GÀ VINTO ŁA",
|
||||||
"seriesWinLine1TeamText": "L'À VINTO ŁA",
|
"seriesWinLine1TeamText": "GÀ VINTO ŁA",
|
||||||
"seriesWinLine1Text": "L'À VINTO ŁA",
|
"seriesWinLine1Text": "GÀ VINTO ŁA",
|
||||||
"seriesWinLine2Text": "DESFIDA!",
|
"seriesWinLine2Text": "DESFIDA!",
|
||||||
"settingsWindow": {
|
"settingsWindow": {
|
||||||
"accountText": "Account",
|
"accountText": "Account",
|
||||||
|
|
@ -1231,7 +1235,7 @@
|
||||||
"enterPromoCodeText": "Insarisi còdaze",
|
"enterPromoCodeText": "Insarisi còdaze",
|
||||||
"forTestingText": "Nota: vałori vàłidi soło par proe. Sortendo da l'apl łi vegnarà perdesti.",
|
"forTestingText": "Nota: vałori vàłidi soło par proe. Sortendo da l'apl łi vegnarà perdesti.",
|
||||||
"helpTranslateText": "Łe tradusion de ${APP_NAME} łe ze curàe da vołontari.\nSe A te vol darghe na ociada a cheła veneta, struca so'l boton\ncuà soto. Curada da Còdaze Veneto: codazeveneto@gmail.com",
|
"helpTranslateText": "Łe tradusion de ${APP_NAME} łe ze curàe da vołontari.\nSe A te vol darghe na ociada a cheła veneta, struca so'l boton\ncuà soto. Curada da Còdaze Veneto: codazeveneto@gmail.com",
|
||||||
"kickIdlePlayersText": "Para vìa zugadori in sonera",
|
"kickIdlePlayersText": "Para fora zugadori in sonera",
|
||||||
"kidFriendlyModeText": "Modałidà bocia (viołensa reduzesta, evc)",
|
"kidFriendlyModeText": "Modałidà bocia (viołensa reduzesta, evc)",
|
||||||
"languageText": "Łengua",
|
"languageText": "Łengua",
|
||||||
"moddingGuideText": "Guida par modifegasion",
|
"moddingGuideText": "Guida par modifegasion",
|
||||||
|
|
@ -1317,7 +1321,7 @@
|
||||||
"winterSpecialText": "Spesiałe inverno",
|
"winterSpecialText": "Spesiałe inverno",
|
||||||
"youOwnThisText": "- dezà tuo -"
|
"youOwnThisText": "- dezà tuo -"
|
||||||
},
|
},
|
||||||
"storeDescriptionText": "Feston bueło a 8 zugadori!\n\nFà saltar par aria i to amighi (o el computer) inte un tornèo de minizughi cofà 'Brinca ła bandiera', 'Scravaso de stełe' o 'Scontri mortałi' in movensa camoma!\n\nFin a 8 parsone łe sarà bone de batajar insenbre, grasie a comandi senpi e a ła conpatibiłidà co tanti controładori. Co l'apl gratùida 'BombSquad Remote' A te połi parfin doparar i to dispozitivi mòbiłi cofà controładori!\n\nE deso... tira fora łe bonbe!\n\nPar informasion in pì daghe na ociada so www.froemling.net/bombsquad.",
|
"storeDescriptionText": "Feston bueło a 8 zugadori!\n\nFà saltar par aria i to amighi (o el computer) inte un tornèo de minizughi cofà 'Brinca ła bandiera', 'Scravaso de stełe' o 'Scontri mortałi' in movensa camoma!\n\nFin a 8 parsone łe sarà bone de batajar insenbre, grasie a comandi senpi e a ła conpatibiłidà co tanti controładori. Co l'apl gratùida 'BombSquad Remote' te połi parfin doparar i to dispozidivi mòbiłi cofà controładori!\n\nE deso... tira fora łe bonbe!\n\nPar informasion in pì daghe na ociada so www.froemling.net/bombsquad.",
|
||||||
"storeDescriptions": {
|
"storeDescriptions": {
|
||||||
"blowUpYourFriendsText": "Fà sciopar par aria i to amighi.",
|
"blowUpYourFriendsText": "Fà sciopar par aria i to amighi.",
|
||||||
"competeInMiniGamesText": "Zuga co tanti minizughi: da corse a zvołi.",
|
"competeInMiniGamesText": "Zuga co tanti minizughi: da corse a zvołi.",
|
||||||
|
|
@ -1572,7 +1576,7 @@
|
||||||
"An error has occurred; please contact support. (${ERROR})": "A se gà verifegà un eror: contata l'asistensa. (${ERROR})",
|
"An error has occurred; please contact support. (${ERROR})": "A se gà verifegà un eror: contata l'asistensa. (${ERROR})",
|
||||||
"An error has occurred; please contact support@froemling.net.": "A se gà verifegà un eror: contata support@froemling.net.",
|
"An error has occurred; please contact support@froemling.net.": "A se gà verifegà un eror: contata support@froemling.net.",
|
||||||
"An error has occurred; please try again later.": "A se gà verifegà un eror: proa danovo pì tardi.",
|
"An error has occurred; please try again later.": "A se gà verifegà un eror: proa danovo pì tardi.",
|
||||||
"Are you sure you want to link these accounts?\n\n${ACCOUNT1}\n${ACCOUNT2}\n\nThis cannot be undone!": "Vutu dalvero cołegar 'sti profiłi?\n\n${ACCOUNT1}\n${ACCOUNT2}\n\n'Sta asion no ła połe mìa èsar anułada!",
|
"Are you sure you want to link these accounts?\n\n${ACCOUNT1}\n${ACCOUNT2}\n\nThis cannot be undone!": "Vutu dabon cołegar 'sti profiłi?\n\n${ACCOUNT1}\n${ACCOUNT2}\n\n'Sta asion no ła połe pì èsar anułada!",
|
||||||
"BombSquad Pro unlocked!": "BombSquad Pro dezblocà!",
|
"BombSquad Pro unlocked!": "BombSquad Pro dezblocà!",
|
||||||
"Can't link 2 accounts of this type.": "A no se połe mìa cołegar 2 profiłi de 'sto tipo.",
|
"Can't link 2 accounts of this type.": "A no se połe mìa cołegar 2 profiłi de 'sto tipo.",
|
||||||
"Can't link 2 diamond league accounts.": "A no se połe mìa cołegar 2 profiłi de ła łega de damante.",
|
"Can't link 2 diamond league accounts.": "A no se połe mìa cołegar 2 profiłi de ła łega de damante.",
|
||||||
|
|
@ -1588,7 +1592,7 @@
|
||||||
"Invalid tournament entry; score will be ignored.": "Entrada inte'l tornèo mìa vàłida: el puntejo el vegnarà ignorà.",
|
"Invalid tournament entry; score will be ignored.": "Entrada inte'l tornèo mìa vàłida: el puntejo el vegnarà ignorà.",
|
||||||
"Item unlocked!": "Ojeto dezblocà!",
|
"Item unlocked!": "Ojeto dezblocà!",
|
||||||
"LINKING DENIED. ${ACCOUNT} contains\nsignificant data that would ALL BE LOST.\nYou can link in the opposite order if you'd like\n(and lose THIS account's data instead)": "COŁEGAMENTO REFUDÀ. ${ACCOUNT} el contien dati\ninportanti che i ndarà PERDESTI.\nSe te vołi A te połi cołegarli in òrdane raverso\n(e pèrdar a'l só posto i dati de 'STO account cuà).",
|
"LINKING DENIED. ${ACCOUNT} contains\nsignificant data that would ALL BE LOST.\nYou can link in the opposite order if you'd like\n(and lose THIS account's data instead)": "COŁEGAMENTO REFUDÀ. ${ACCOUNT} el contien dati\ninportanti che i ndarà PERDESTI.\nSe te vołi A te połi cołegarli in òrdane raverso\n(e pèrdar a'l só posto i dati de 'STO account cuà).",
|
||||||
"Link account ${ACCOUNT} to this account?\nAll existing data on ${ACCOUNT} will be lost.\nThis can not be undone. Are you sure?": "Vutu dalvero cołegar l'account ${ACCOUNT} a 'sto account?\nTuti i dati so ${ACCOUNT} i ndarà perdesti.\n'Sta asion no ła połe mìa èsar anułada: situ seguro?",
|
"Link account ${ACCOUNT} to this account?\nAll existing data on ${ACCOUNT} will be lost.\nThis can not be undone. Are you sure?": "Vutu dabon cołegar l'account ${ACCOUNT} a 'sto account?\nTuti i dati so ${ACCOUNT} i ndarà perdesti.\n'Sta asion no ła połe pì èsar anułada: vutu ndar vanti?",
|
||||||
"Max number of playlists reached.": "Nùmaro màsemo de łiste de scolto pasà.",
|
"Max number of playlists reached.": "Nùmaro màsemo de łiste de scolto pasà.",
|
||||||
"Max number of profiles reached.": "Nùmaro màsemo de profiłi pasà.",
|
"Max number of profiles reached.": "Nùmaro màsemo de profiłi pasà.",
|
||||||
"Maximum friend code rewards reached.": "Brincà el nùmaro màsemo de premi da'l còdaze amigo.",
|
"Maximum friend code rewards reached.": "Brincà el nùmaro màsemo de premi da'l còdaze amigo.",
|
||||||
|
|
@ -1610,11 +1614,11 @@
|
||||||
"This code cannot be used on the account that created it.": "'Sto còdaze no'l połe mìa èsar doparà inte l'account che'l ło gà creà.",
|
"This code cannot be used on the account that created it.": "'Sto còdaze no'l połe mìa èsar doparà inte l'account che'l ło gà creà.",
|
||||||
"This is currently unavailable; please try again later.": "Par deso, funsion miga disponìbiłe. Proa danovo pì tardi.",
|
"This is currently unavailable; please try again later.": "Par deso, funsion miga disponìbiłe. Proa danovo pì tardi.",
|
||||||
"This requires version ${VERSION} or newer.": "A ghe serve ła varsion ${VERSION} o una pì nova.",
|
"This requires version ${VERSION} or newer.": "A ghe serve ła varsion ${VERSION} o una pì nova.",
|
||||||
"Tournaments disabled due to rooted device.": "Tornèi dezativài parvìa de'l dispozitivo co'l root.",
|
"Tournaments disabled due to rooted device.": "Tornèi dezativài parvìa de'l dispozidivo co'l root.",
|
||||||
"Tournaments require ${VERSION} or newer": "Par i tornèi A serve ła varsion ${VERSION} o una pì resente",
|
"Tournaments require ${VERSION} or newer": "Par i tornèi A serve ła varsion ${VERSION} o una pì resente",
|
||||||
"Unlink ${ACCOUNT} from this account?\nAll data on ${ACCOUNT} will be reset.\n(except for achievements in some cases)": "Vutu descołegar l'account ${ACCOUNT} da 'sto account?\nTuti i dati de ${ACCOUNT} i vegnarà ełimenài.\n(obietivi a parte in calche cazo)",
|
"Unlink ${ACCOUNT} from this account?\nAll data on ${ACCOUNT} will be reset.\n(except for achievements in some cases)": "Vutu descołegar l'account ${ACCOUNT} da 'sto account?\nTuti i dati de ${ACCOUNT} i vegnarà ełimenài.\n(obietivi a parte in calche cazo)",
|
||||||
"WARNING: complaints of hacking have been issued against your account.\nAccounts found to be hacking will be banned. Please play fair.": "AVERTENSA: el to account el ze stà segnałà par el dòparo de truchi.\nI zugaduri catài a doparar truchi i vegnarà blocài. Zuga da gałantomo.",
|
"WARNING: complaints of hacking have been issued against your account.\nAccounts found to be hacking will be banned. Please play fair.": "AVERTENSA: el to account el ze stà segnałà par el dòparo de truchi.\nI zugaduri catài a doparar truchi i vegnarà blocài. Zuga da gałantomo.",
|
||||||
"Would you like to link your device account to this one?\n\nYour device account is ${ACCOUNT1}\nThis account is ${ACCOUNT2}\n\nThis will allow you to keep your existing progress.\nWarning: this cannot be undone!\n": "Ghetu caro cołegar l'account de'l to dispozitivo co 'sto cuà?\n\nL'account de'l to dispozitivo el ze ${ACCOUNT1}\n'Sto account el ze ${ACCOUNT2}\n\n'Sta oparasion ła te parmetarà de mantegner i to progresi ezistenti.\nAvertensa: 'sta asion no ła połe mìa èsar anułada!",
|
"Would you like to link your device account to this one?\n\nYour device account is ${ACCOUNT1}\nThis account is ${ACCOUNT2}\n\nThis will allow you to keep your existing progress.\nWarning: this cannot be undone!\n": "Ghetu caro cołegar l'account de'l to dispozidivo co 'sto cuà?\n\nL'account de'l to dispozidivo el ze ${ACCOUNT1}\n'Sto account el ze ${ACCOUNT2}\n\n'Sta oparasion ła te parmetarà de mantegner i to progresi ezistenti.\nAvertensa: 'sta asion no ła połe pì èsar anułada!",
|
||||||
"You already own this!": "Dezà cronpà!",
|
"You already own this!": "Dezà cronpà!",
|
||||||
"You can join in ${COUNT} seconds.": "A te połi zontarte tenpo ${COUNT} segondi.",
|
"You can join in ${COUNT} seconds.": "A te połi zontarte tenpo ${COUNT} segondi.",
|
||||||
"You don't have enough tickets for this!": "A no te ghè miga biłieti che basta par cronparlo!",
|
"You don't have enough tickets for this!": "A no te ghè miga biłieti che basta par cronparlo!",
|
||||||
|
|
@ -1672,7 +1676,7 @@
|
||||||
"Time Limit": "Łìmide de tenpo"
|
"Time Limit": "Łìmide de tenpo"
|
||||||
},
|
},
|
||||||
"statements": {
|
"statements": {
|
||||||
"${TEAM} is disqualified because ${PLAYER} left": "Ła scuadra ${TEAM} ła ze scuałifegada parché ${PLAYER} l'à mołà.",
|
"${TEAM} is disqualified because ${PLAYER} left": "Ła scuadra ${TEAM} ła ze scuałifegada parché ${PLAYER} gà mołà.",
|
||||||
"Killing ${NAME} for skipping part of the track!": "Copà ${NAME} par ver saltà un toco de'l parcorso!",
|
"Killing ${NAME} for skipping part of the track!": "Copà ${NAME} par ver saltà un toco de'l parcorso!",
|
||||||
"Warning to ${NAME}: turbo / button-spamming knocks you out.": "Avertensa par ${NAME}: el turbo / spam co i botoni el te gà fato trar fora."
|
"Warning to ${NAME}: turbo / button-spamming knocks you out.": "Avertensa par ${NAME}: el turbo / spam co i botoni el te gà fato trar fora."
|
||||||
},
|
},
|
||||||
|
|
@ -1689,19 +1693,19 @@
|
||||||
"Curse boxes turn you into a ticking time bomb.\nThe only cure is to quickly grab a health-pack.": "Łe case małedision łe te transforma inte na bonba a tenpo.\nA te połi curarte soło tołendo in presa un pacheto sałude.",
|
"Curse boxes turn you into a ticking time bomb.\nThe only cure is to quickly grab a health-pack.": "Łe case małedision łe te transforma inte na bonba a tenpo.\nA te połi curarte soło tołendo in presa un pacheto sałude.",
|
||||||
"Despite their looks, all characters' abilities are identical,\nso just pick whichever one you most closely resemble.": "Anca se drio ła siera A no par, łe abiłidà de tuti i parsonaji\nłe ze conpagne, donca tote sù cheło che'l te połe somejar de pì.",
|
"Despite their looks, all characters' abilities are identical,\nso just pick whichever one you most closely resemble.": "Anca se drio ła siera A no par, łe abiłidà de tuti i parsonaji\nłe ze conpagne, donca tote sù cheło che'l te połe somejar de pì.",
|
||||||
"Don't get too cocky with that energy shield; you can still get yourself thrown off a cliff.": "Mai far masa i gałeti co'l scudo nerjètego: A te połi uncora farte trar baso da na croda.",
|
"Don't get too cocky with that energy shield; you can still get yourself thrown off a cliff.": "Mai far masa i gałeti co'l scudo nerjètego: A te połi uncora farte trar baso da na croda.",
|
||||||
"Don't run all the time. Really. You will fall off cliffs.": "No stà córar tuto el tenpo. Dalvero. A te fenirè zó par na croda.",
|
"Don't run all the time. Really. You will fall off cliffs.": "No stà córar tuto el tenpo. Dabon. Te fenirè zó par na croda.",
|
||||||
"Don't spin for too long; you'll become dizzy and fall.": "No stà ndar torno par masa tenpo: te vegnarà na storniroła e te cascarè.",
|
"Don't spin for too long; you'll become dizzy and fall.": "No stà ndar torno par masa tenpo: te vegnarà na storniroła e te cascarè.",
|
||||||
"Hold any button to run. (Trigger buttons work well if you have them)": "Tien strucà un boton calsìase par córar. (I griłeti nałòzeghi i ze i pì adati, se A te łi ghè)",
|
"Hold any button to run. (Trigger buttons work well if you have them)": "Tien strucà un boton calsìase par córar. (I griłeti nałòzeghi i ze i pì adati, se A te łi ghè)",
|
||||||
"Hold down any button to run. You'll get places faster\nbut won't turn very well, so watch out for cliffs.": "Tien strucà un boton calsìase par córar. A te te movarè pì in\npresa ma no te voltarè miga masa ben, donca ocio a łe crode.",
|
"Hold down any button to run. You'll get places faster\nbut won't turn very well, so watch out for cliffs.": "Tien strucà un boton calsìase par córar. A te te movarè pì in\npresa ma no te voltarè miga masa ben, donca ocio a łe crode.",
|
||||||
"Ice bombs are not very powerful, but they freeze\nwhoever they hit, leaving them vulnerable to shattering.": "Łe bonbe jaso no łe ze miga tanto potenti, ma łe injasa tuto cheło\nche łe brinca, e cheło che'l ze injasà el ze anca fàsiłe da fracasar.",
|
"Ice bombs are not very powerful, but they freeze\nwhoever they hit, leaving them vulnerable to shattering.": "Łe bonbe jaso no łe ze miga tanto potenti, ma łe injasa tuto cheło\nche łe brinca, e cheło che'l ze injasà el ze anca fàsiłe da fracasar.",
|
||||||
"If someone picks you up, punch them and they'll let go.\nThis works in real life too.": "Se calchedun el te łeva sù, daghe un crogno che'l te\nmołe zó. 'Sta roba ła funsiona anca inte ła vida vera.",
|
"If someone picks you up, punch them and they'll let go.\nThis works in real life too.": "Se calchedun el te łeva sù, daghe un crogno che'l te\nmołe zó. 'Sta roba ła funsiona anca inte ła vida vera.",
|
||||||
"If you are short on controllers, install the '${REMOTE_APP_NAME}' app\non your mobile devices to use them as controllers.": "Se A te si a curto de controładori, instała l'apl '${REMOTE_APP_NAME}'\nso i to dispozitivi mòbiłi e dopàrełi cofà controładori.",
|
"If you are short on controllers, install the '${REMOTE_APP_NAME}' app\non your mobile devices to use them as controllers.": "Se te si a curto de controładori, instała l'apl '${REMOTE_APP_NAME}'\nso i to dispozidivi mòbiłi e dopàrełi cofà controładori.",
|
||||||
"If you get a sticky-bomb stuck to you, jump around and spin in circles. You might\nshake the bomb off, or if nothing else your last moments will be entertaining.": "Se na bonba petaisa ła te se taca doso, salta in volta e và torno: ła gavarìa da cavarse.\nE se no funsionase, i to momenti ùltemi de vida i gavarà almanco dà spetàgoło!",
|
"If you get a sticky-bomb stuck to you, jump around and spin in circles. You might\nshake the bomb off, or if nothing else your last moments will be entertaining.": "Se na bonba petaisa ła te se taca doso, salta in volta e và torno: ła gavarìa da cavarse.\nE se no funsionase, i to momenti ùltemi de vida i gavarà almanco dà spetàgoło!",
|
||||||
"If you kill an enemy in one hit you get double points for it.": "Se A te copi un nemigo co un colpo soło A te ciapi el dupio de i punti.",
|
"If you kill an enemy in one hit you get double points for it.": "Se A te copi un nemigo co un colpo soło A te ciapi el dupio de i punti.",
|
||||||
"If you pick up a curse, your only hope for survival is to\nfind a health powerup in the next few seconds.": "Se A te ciapi na małedision, A te ghè soło na sparansa de salvesa:\ncatar fora un pacheto sałude inte i puchi segondi che A te resta.",
|
"If you pick up a curse, your only hope for survival is to\nfind a health powerup in the next few seconds.": "Se A te ciapi na małedision, A te ghè soło na sparansa de salvesa:\ncatar fora un pacheto sałude inte i puchi segondi che A te resta.",
|
||||||
"If you stay in one place, you're toast. Run and dodge to survive..": "Se A se stà fermi inte un posto, A se ze friti. Cori e schiva par soravìvar...",
|
"If you stay in one place, you're toast. Run and dodge to survive..": "Se A se stà fermi inte un posto, A se ze friti. Cori e schiva par soravìvar...",
|
||||||
"If you've got lots of players coming and going, turn on 'auto-kick-idle-players'\nunder settings in case anyone forgets to leave the game.": "Se A te te cati tanti zugadori che i và e vien, e inte'l cazo che calchedun el se dezménteghe de\nmołar el zugo, ativa ła funsion automàtega 'Para vìa zugadori in sonera' inte łe inpostasion.",
|
"If you've got lots of players coming and going, turn on 'auto-kick-idle-players'\nunder settings in case anyone forgets to leave the game.": "Se te te cati tanti zugadori che và e vien, e inte'l cazo che calchedun el se dezménteghe de\nmołar el zugo, ativa ła funsion automàtega 'Para fora zugadori in sonera' inte łe inpostasion.",
|
||||||
"If your device gets too warm or you'd like to conserve battery power,\nturn down \"Visuals\" or \"Resolution\" in Settings->Graphics": "Se'l to dispozitivo el taca scotar o se A te ghè caro sparagnar batarìa,\ncała ła \"Prospetiva\" o ła \"Resołusion\" so Inpostasion > Gràfega",
|
"If your device gets too warm or you'd like to conserve battery power,\nturn down \"Visuals\" or \"Resolution\" in Settings->Graphics": "Se'l to dispozidivo el taca scotar o se te ghè caro sparagnar batarìa,\ncała ła \"Prospetiva\" o ła \"Resołusion\" so Inpostasion > Gràfega",
|
||||||
"If your framerate is choppy, try turning down resolution\nor visuals in the game's graphics settings.": "Se el zugo el và a scati, proa całar ła resołusion\no ła prospetiva inte l'inpostasion gràfega.",
|
"If your framerate is choppy, try turning down resolution\nor visuals in the game's graphics settings.": "Se el zugo el và a scati, proa całar ła resołusion\no ła prospetiva inte l'inpostasion gràfega.",
|
||||||
"In Capture-the-Flag, your own flag must be at your base to score, If the other\nteam is about to score, stealing their flag can be a good way to stop them.": "Par far ponto so 'Brinca ła bandiera', A te ghè da portar ła bandiera fin so ła to\nbaze. Se cheł'altra scuadra ła ze drio far ponto, A te połi fermarla anca robàndogheła.",
|
"In Capture-the-Flag, your own flag must be at your base to score, If the other\nteam is about to score, stealing their flag can be a good way to stop them.": "Par far ponto so 'Brinca ła bandiera', A te ghè da portar ła bandiera fin so ła to\nbaze. Se cheł'altra scuadra ła ze drio far ponto, A te połi fermarla anca robàndogheła.",
|
||||||
"In hockey, you'll maintain more speed if you turn gradually.": "Inte l'hockey, voltando gradualmente A te mantien alta ła vełosidà.",
|
"In hockey, you'll maintain more speed if you turn gradually.": "Inte l'hockey, voltando gradualmente A te mantien alta ła vełosidà.",
|
||||||
|
|
@ -1769,7 +1773,7 @@
|
||||||
"randomName3Text": "Teo",
|
"randomName3Text": "Teo",
|
||||||
"randomName4Text": "Cesco",
|
"randomName4Text": "Cesco",
|
||||||
"randomName5Text": "Stè",
|
"randomName5Text": "Stè",
|
||||||
"skipConfirmText": "Vutu dalvero saltar ła demostrasion? Toca o struca par confermar.",
|
"skipConfirmText": "Vutu dabon saltar ła demostrasion? Toca o struca par confermar.",
|
||||||
"skipVoteCountText": "Voti par saltar ła demostrasion: ${COUNT}/${TOTAL}",
|
"skipVoteCountText": "Voti par saltar ła demostrasion: ${COUNT}/${TOTAL}",
|
||||||
"skippingText": "demostrasion saltada...",
|
"skippingText": "demostrasion saltada...",
|
||||||
"toSkipPressAnythingText": "(toca o struca un boton par saltar ła demostrasion)"
|
"toSkipPressAnythingText": "(toca o struca un boton par saltar ła demostrasion)"
|
||||||
|
|
@ -1787,7 +1791,7 @@
|
||||||
"upgradeText": "Mejora",
|
"upgradeText": "Mejora",
|
||||||
"upgradeToPlayText": "Par zugarghe, dezbloca \"${PRO}\" inte ła botega.",
|
"upgradeToPlayText": "Par zugarghe, dezbloca \"${PRO}\" inte ła botega.",
|
||||||
"useDefaultText": "Reinposta",
|
"useDefaultText": "Reinposta",
|
||||||
"usesExternalControllerText": "'Sto zugo el dòpara un controłador esterno cofà dispozitivo de entrada.",
|
"usesExternalControllerText": "'Sto zugo el dòpara un controłador esterno cofà dispozidivo de entrada.",
|
||||||
"usingItunesText": "Doparar l'apl de mùzega par el son de fondo...",
|
"usingItunesText": "Doparar l'apl de mùzega par el son de fondo...",
|
||||||
"validatingTestBuildText": "Confermasion varsion de proa...",
|
"validatingTestBuildText": "Confermasion varsion de proa...",
|
||||||
"victoryText": "Vitoria!",
|
"victoryText": "Vitoria!",
|
||||||
|
|
@ -1832,21 +1836,23 @@
|
||||||
"wiimoteSetupWindow": {
|
"wiimoteSetupWindow": {
|
||||||
"copyrightText": "Deriti d'autor DarwiinRemote",
|
"copyrightText": "Deriti d'autor DarwiinRemote",
|
||||||
"listenText": "Scolta",
|
"listenText": "Scolta",
|
||||||
"macInstructionsText": "Segùrate che ła to Wii ła sipie stuada e el bluetooth de'l\nto Mac ativà, donca stuca so 'Scolta'. Ła conpatibiłidà co'l\nWiimote ła podarìa èsar un fià inserta, donca te podarisi\ncatarte a proar pì 'olte prima de otegner na conesion.\n\nEl bluetooth el gavarìa da suportar fin a 7 dispozitivi conetesti,\nanca se ła capasidà ła podarìa variar.\n\nBombSquad el suporta el controłador Clàsego e i controładori\norijinałi Wiimotes, Nunchuks.\nAnca el novo Wii Remote Plus el funsiona\nma soło sensa acesori.",
|
"macInstructionsText": "Segùrate che ła to Wii ła sipie stuada e el bluetooth de'l\nto Mac ativà, donca stuca so 'Scolta'. Ła conpatibiłidà co'l\nWiimote ła podarìa èsar un fià inserta, donca te podarisi\ncatarte a proar pì 'olte prima de otegner na conesion.\n\nEl bluetooth el gavarìa da suportar fin a 7 dispozidivi conetesti,\nanca se ła capasidà ła podarìa variar.\n\nBombSquad el suporta el controłador Clàsego e i controładori\norijinałi Wiimotes, Nunchuks.\nAnca el novo Wii Remote Plus el funsiona\nma soło sensa acesori.",
|
||||||
"thanksText": "Grasie a ła scuadra DarwiinRemote\npar verlo rendesto posìbiłe.",
|
"thanksText": "Grasie a ła scuadra DarwiinRemote\npar verlo rendesto posìbiłe.",
|
||||||
"titleText": "Configurasion Wiimote"
|
"titleText": "Configurasion Wiimote"
|
||||||
},
|
},
|
||||||
"winsPlayerText": "Vitoria de ${NAME}!",
|
"winsPlayerText": "Vitoria de ${NAME}!",
|
||||||
"winsTeamText": "Vitoria de i ${NAME}!",
|
"winsTeamText": "Vitoria de i ${NAME}!",
|
||||||
"winsText": "Vitoria de ${NAME}!",
|
"winsText": "Vitoria de ${NAME}!",
|
||||||
|
"workspaceSyncErrorText": "Eror de sincronizasion de ${WORKSPACE}. Varda el rejistro eventi par i detaji.",
|
||||||
|
"workspaceSyncReuseText": "Inposìbiłe sinconizar ${WORKSPACE}. Dòparo de ła varsion sincronizada presedente.",
|
||||||
"worldScoresUnavailableText": "Punteji mondiałi miga disponìbiłi.",
|
"worldScoresUnavailableText": "Punteji mondiałi miga disponìbiłi.",
|
||||||
"worldsBestScoresText": "I punteji mejo de'l mondo",
|
"worldsBestScoresText": "I punteji mejo de'l mondo",
|
||||||
"worldsBestTimesText": "I tenpi mejo de'l mondo",
|
"worldsBestTimesText": "I tenpi mejo de'l mondo",
|
||||||
"xbox360ControllersWindow": {
|
"xbox360ControllersWindow": {
|
||||||
"getDriverText": "Descarga el driver",
|
"getDriverText": "Descarga el driver",
|
||||||
"macInstructions2Text": "Par doparar sensa fiło i controładori, A te serve anca el resevidor\nche'l riva co l''Xbox 360 Wireless Controller par Windows'.\nUn resevidor el te parmete de conétar fin a 4 controładori.\n\nInportante: i resevidori de terse parti no i funsionarà mìa co 'sto driver;\nsegùrate che'l to resevidor el sipia 'Microsoft' e miga 'XBOX 360'.\nŁa Microsoft no łi vende pì destacài, donca A te servirà par forsa cheło\nvendesto insebre co'l controłador, o senò, proa sercar so Ebay.\n\nSe A te cati ùtiłe el driver, ciapa in considerasion de farghe na\ndonasion a'l só dezviłupador so 'sto sito.",
|
"macInstructions2Text": "Par doparar sensa fiło i controładori, A te serve anca el resevidor\nche'l riva co l''Xbox 360 Wireless Controller par Windows'.\nUn resevidor el te parmete de conétar fin a 4 controładori.\n\nInportante: i resevidori de terse parti no i funsionarà miga co 'sto driver;\nsegùrate che'l to resevidor el sipia 'Microsoft' e miga 'XBOX 360'.\nŁa Microsoft no łi vende pì destacài, donca te servirà par forsa cheło\nvendesto insebre co'l controłador, o senò, proa sercar so Ebay.\n\nSe te cati ùtiłe el driver, ciapa in considerasion de farghe na\ndonasion a'l só dezviłupador so 'sto sito.",
|
||||||
"macInstructionsText": "Per doparar i controładori co'l fiło de ła Xbox 360, A te ghè\nda instałar el driver Mac disponìbiłe so'l link cuà soto.\nEl funsiona co anbo i controładori, co'l fiło o sensa.",
|
"macInstructionsText": "Per doparar i controładori co'l fiło de ła Xbox 360, A te ghè\nda instałar el driver Mac disponìbiłe so'l link cuà soto.\nEl funsiona co anbo i controładori, co'l fiło o sensa.",
|
||||||
"ouyaInstructionsText": "Par doparar so Bombsquad un controłador de l'Xbox 360 co'l fiło,\ntàcheło sù inte ła porta USB de’l to dispozitivo. A te połi anca\ntacar sù pì controładori insenbre doparando un hub USB.\n\nPar doparar i controładori sensa fiło invese, A te serve un resevidor\nde segnałe. A te połi catarlo, o rento ła scàtoła \"Controładori sensa fiło\nXbox 360 par Windows\", o vendesto a parte. Caun resevidor el và tacà so\nna porta USB e el te parmete de conétar fin a 4 controładori.",
|
"ouyaInstructionsText": "Par doparar so Bombsquad un controłador de l'Xbox 360 co'l fiło,\ntàcheło sù inte ła porta USB de’l to dispozidivo. Te połi anca\ntacar sù pì controładori insenbre doparando un hub USB.\n\nPar doparar i controładori sensa fiło invese, te serve un resevidor\nde segnałe. Te połi catarlo, o rento ła scàtoła \"Controładori sensa fiło\nXbox 360 par Windows\", o vendesto a parte. Caun resevidor el và tacà so\nna porta USB e el te parmete de conétar fin a 4 controładori.",
|
||||||
"titleText": "Doparar un controłador Xbox 360 co ${APP_NAME}:"
|
"titleText": "Doparar un controłador Xbox 360 co ${APP_NAME}:"
|
||||||
},
|
},
|
||||||
"yesAllowText": "Sì, parmeti!",
|
"yesAllowText": "Sì, parmeti!",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from .core import contents, where
|
from .core import contents, where
|
||||||
|
|
||||||
__all__ = ["contents", "where"]
|
__all__ = ["contents", "where"]
|
||||||
__version__ = "2022.05.18.1"
|
__version__ = "2022.06.15"
|
||||||
|
|
|
||||||
221
dist/ba_data/python-site-packages/certifi/cacert.pem
vendored
221
dist/ba_data/python-site-packages/certifi/cacert.pem
vendored
|
|
@ -1362,39 +1362,6 @@ Agu+TGbrIP65y7WZf+a2E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xl
|
||||||
nJ2lYJU6Un/10asIbvPuW/mIPX64b24D5EI=
|
nJ2lYJU6Un/10asIbvPuW/mIPX64b24D5EI=
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
# Issuer: CN=Hellenic Academic and Research Institutions RootCA 2011 O=Hellenic Academic and Research Institutions Cert. Authority
|
|
||||||
# Subject: CN=Hellenic Academic and Research Institutions RootCA 2011 O=Hellenic Academic and Research Institutions Cert. Authority
|
|
||||||
# Label: "Hellenic Academic and Research Institutions RootCA 2011"
|
|
||||||
# Serial: 0
|
|
||||||
# MD5 Fingerprint: 73:9f:4c:4b:73:5b:79:e9:fa:ba:1c:ef:6e:cb:d5:c9
|
|
||||||
# SHA1 Fingerprint: fe:45:65:9b:79:03:5b:98:a1:61:b5:51:2e:ac:da:58:09:48:22:4d
|
|
||||||
# SHA256 Fingerprint: bc:10:4f:15:a4:8b:e7:09:dc:a5:42:a7:e1:d4:b9:df:6f:05:45:27:e8:02:ea:a9:2d:59:54:44:25:8a:fe:71
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1Ix
|
|
||||||
RDBCBgNVBAoTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1
|
|
||||||
dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1p
|
|
||||||
YyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIFJvb3RDQSAyMDExMB4XDTExMTIw
|
|
||||||
NjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYTAkdSMUQwQgYDVQQK
|
|
||||||
EztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENl
|
|
||||||
cnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl
|
|
||||||
c2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEB
|
|
||||||
BQADggEPADCCAQoCggEBAKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPz
|
|
||||||
dYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJ
|
|
||||||
fel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa71HFK9+WXesyHgLacEns
|
|
||||||
bgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u8yBRQlqD
|
|
||||||
75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSP
|
|
||||||
FEDH3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNV
|
|
||||||
HRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp
|
|
||||||
5dgTBCPuQSUwRwYDVR0eBEAwPqA8MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQu
|
|
||||||
b3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQub3JnMA0GCSqGSIb3DQEBBQUA
|
|
||||||
A4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVtXdMiKahsog2p
|
|
||||||
6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
|
|
||||||
TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7
|
|
||||||
dIsXRSZMFpGD/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8Acys
|
|
||||||
Nnq/onN694/BtZqhFLKPM58N7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXI
|
|
||||||
l7WdmplNsDz4SgCbZN2fOUvRJ9e4
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
|
|
||||||
# Issuer: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967
|
# Issuer: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967
|
||||||
# Subject: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967
|
# Subject: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967
|
||||||
# Label: "Actalis Authentication Root CA"
|
# Label: "Actalis Authentication Root CA"
|
||||||
|
|
@ -4528,3 +4495,191 @@ PQQDAwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CA
|
||||||
y/m0sRtW9XLS/BnRAjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJb
|
y/m0sRtW9XLS/BnRAjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJb
|
||||||
gfM0agPnIjhQW+0ZT0MW
|
gfM0agPnIjhQW+0ZT0MW
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
# Issuer: CN=DigiCert TLS ECC P384 Root G5 O=DigiCert, Inc.
|
||||||
|
# Subject: CN=DigiCert TLS ECC P384 Root G5 O=DigiCert, Inc.
|
||||||
|
# Label: "DigiCert TLS ECC P384 Root G5"
|
||||||
|
# Serial: 13129116028163249804115411775095713523
|
||||||
|
# MD5 Fingerprint: d3:71:04:6a:43:1c:db:a6:59:e1:a8:a3:aa:c5:71:ed
|
||||||
|
# SHA1 Fingerprint: 17:f3:de:5e:9f:0f:19:e9:8e:f6:1f:32:26:6e:20:c4:07:ae:30:ee
|
||||||
|
# SHA256 Fingerprint: 01:8e:13:f0:77:25:32:cf:80:9b:d1:b1:72:81:86:72:83:fc:48:c6:e1:3b:e9:c6:98:12:85:4a:49:0c:1b:05
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQsw
|
||||||
|
CQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURp
|
||||||
|
Z2lDZXJ0IFRMUyBFQ0MgUDM4NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2
|
||||||
|
MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ
|
||||||
|
bmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQgUm9vdCBHNTB2MBAG
|
||||||
|
ByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1TzvdlHJS
|
||||||
|
7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp
|
||||||
|
0zVozptjn4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICIS
|
||||||
|
B4CIfBFqMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49
|
||||||
|
BAMDA2gAMGUCMQCJao1H5+z8blUD2WdsJk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQ
|
||||||
|
LgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIxAJSdYsiJvRmEFOml+wG4
|
||||||
|
DXZDjC5Ty3zfDBeWUA==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
# Issuer: CN=DigiCert TLS RSA4096 Root G5 O=DigiCert, Inc.
|
||||||
|
# Subject: CN=DigiCert TLS RSA4096 Root G5 O=DigiCert, Inc.
|
||||||
|
# Label: "DigiCert TLS RSA4096 Root G5"
|
||||||
|
# Serial: 11930366277458970227240571539258396554
|
||||||
|
# MD5 Fingerprint: ac:fe:f7:34:96:a9:f2:b3:b4:12:4b:e4:27:41:6f:e1
|
||||||
|
# SHA1 Fingerprint: a7:88:49:dc:5d:7c:75:8c:8c:de:39:98:56:b3:aa:d0:b2:a5:71:35
|
||||||
|
# SHA256 Fingerprint: 37:1a:00:dc:05:33:b3:72:1a:7e:eb:40:e8:41:9e:70:79:9d:2b:0a:0f:2c:1d:80:69:31:65:f7:ce:c4:ad:75
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBN
|
||||||
|
MQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMT
|
||||||
|
HERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcN
|
||||||
|
NDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQs
|
||||||
|
IEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwggIi
|
||||||
|
MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS87IE+
|
||||||
|
ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG0
|
||||||
|
2C+JFvuUAT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgp
|
||||||
|
wgscONyfMXdcvyej/Cestyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZM
|
||||||
|
pG2T6T867jp8nVid9E6P/DsjyG244gXazOvswzH016cpVIDPRFtMbzCe88zdH5RD
|
||||||
|
nU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnVDdXifBBiqmvwPXbzP6Po
|
||||||
|
sMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9qTXeXAaDx
|
||||||
|
Zre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cd
|
||||||
|
Lvvyz6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvX
|
||||||
|
KyY//SovcfXWJL5/MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNe
|
||||||
|
XoVPzthwiHvOAbWWl9fNff2C+MIkwcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPL
|
||||||
|
tgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4EFgQUUTMc7TZArxfTJc1paPKv
|
||||||
|
TiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN
|
||||||
|
AQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw
|
||||||
|
GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7H
|
||||||
|
PNtQOa27PShNlnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLF
|
||||||
|
O4uJ+DQtpBflF+aZfTCIITfNMBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQ
|
||||||
|
REtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/u4cnYiWB39yhL/btp/96j1EuMPik
|
||||||
|
AdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9GOUrYU9DzLjtxpdRv
|
||||||
|
/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh47a+
|
||||||
|
p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilw
|
||||||
|
MUc/dNAUFvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WF
|
||||||
|
qUITVuwhd4GTWgzqltlJyqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCK
|
||||||
|
ovfepEWFJqgejF0pW8hL2JpqA15w8oVPbEtoL8pU9ozaMv7Da4M/OMZ+
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
# Issuer: CN=Certainly Root R1 O=Certainly
|
||||||
|
# Subject: CN=Certainly Root R1 O=Certainly
|
||||||
|
# Label: "Certainly Root R1"
|
||||||
|
# Serial: 188833316161142517227353805653483829216
|
||||||
|
# MD5 Fingerprint: 07:70:d4:3e:82:87:a0:fa:33:36:13:f4:fa:33:e7:12
|
||||||
|
# SHA1 Fingerprint: a0:50:ee:0f:28:71:f4:27:b2:12:6d:6f:50:96:25:ba:cc:86:42:af
|
||||||
|
# SHA256 Fingerprint: 77:b8:2c:d8:64:4c:43:05:f7:ac:c5:cb:15:6b:45:67:50:04:03:3d:51:c6:0c:62:02:a8:e0:c3:34:67:d3:a0
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAw
|
||||||
|
PTELMAkGA1UEBhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2Vy
|
||||||
|
dGFpbmx5IFJvb3QgUjEwHhcNMjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9
|
||||||
|
MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0
|
||||||
|
YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANA2
|
||||||
|
1B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O5MQT
|
||||||
|
vqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbed
|
||||||
|
aFySpvXl8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b0
|
||||||
|
1C7jcvk2xusVtyWMOvwlDbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5
|
||||||
|
r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGIXsXwClTNSaa/ApzSRKft43jvRl5tcdF5
|
||||||
|
cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkNKPl6I7ENPT2a/Z2B7yyQ
|
||||||
|
wHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQAjeZjOVJ
|
||||||
|
6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA
|
||||||
|
2CnbrlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyH
|
||||||
|
Wyf5QBGenDPBt+U1VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMR
|
||||||
|
eiFPCyEQtkA6qyI6BJyLm4SGcprSp6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB
|
||||||
|
/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTgqj8ljZ9EXME66C6u
|
||||||
|
d0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAszHQNTVfSVcOQr
|
||||||
|
PbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d
|
||||||
|
8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi
|
||||||
|
1wrykXprOQ4vMMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrd
|
||||||
|
rRT90+7iIgXr0PK3aBLXWopBGsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9di
|
||||||
|
taY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+gjwN/KUD+nsa2UUeYNrEjvn8K8l7
|
||||||
|
lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgHJBu6haEaBQmAupVj
|
||||||
|
yTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7fpYn
|
||||||
|
Kx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLy
|
||||||
|
yCwzk5Iwx06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5n
|
||||||
|
wXARPbv0+Em34yaXOp/SX3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6
|
||||||
|
OV+KmalBWQewLK8=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
# Issuer: CN=Certainly Root E1 O=Certainly
|
||||||
|
# Subject: CN=Certainly Root E1 O=Certainly
|
||||||
|
# Label: "Certainly Root E1"
|
||||||
|
# Serial: 8168531406727139161245376702891150584
|
||||||
|
# MD5 Fingerprint: 0a:9e:ca:cd:3e:52:50:c6:36:f3:4b:a3:ed:a7:53:e9
|
||||||
|
# SHA1 Fingerprint: f9:e1:6d:dc:01:89:cf:d5:82:45:63:3e:c5:37:7d:c2:eb:93:6f:2b
|
||||||
|
# SHA256 Fingerprint: b4:58:5f:22:e4:ac:75:6a:4e:86:12:a1:36:1c:5d:9d:03:1a:93:fd:84:fe:bb:77:8f:a3:06:8b:0f:c4:2d:c2
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQsw
|
||||||
|
CQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlu
|
||||||
|
bHkgUm9vdCBFMTAeFw0yMTA0MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJ
|
||||||
|
BgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlubHkxGjAYBgNVBAMTEUNlcnRhaW5s
|
||||||
|
eSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4fxzf7flHh4axpMCK
|
||||||
|
+IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9YBk2
|
||||||
|
QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8E
|
||||||
|
BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4
|
||||||
|
hevIIgcwCgYIKoZIzj0EAwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozm
|
||||||
|
ut6Dacpps6kFtZaSF4fC0urQe87YQVt8rgIwRt7qy12a7DLCZRawTDBcMPPaTnOG
|
||||||
|
BtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
# Issuer: CN=E-Tugra Global Root CA RSA v3 O=E-Tugra EBG A.S. OU=E-Tugra Trust Center
|
||||||
|
# Subject: CN=E-Tugra Global Root CA RSA v3 O=E-Tugra EBG A.S. OU=E-Tugra Trust Center
|
||||||
|
# Label: "E-Tugra Global Root CA RSA v3"
|
||||||
|
# Serial: 75951268308633135324246244059508261641472512052
|
||||||
|
# MD5 Fingerprint: 22:be:10:f6:c2:f8:03:88:73:5f:33:29:47:28:47:a4
|
||||||
|
# SHA1 Fingerprint: e9:a8:5d:22:14:52:1c:5b:aa:0a:b4:be:24:6a:23:8a:c9:ba:e2:a9
|
||||||
|
# SHA256 Fingerprint: ef:66:b0:b1:0a:3c:db:9f:2e:36:48:c7:6b:d2:af:18:ea:d2:bf:e6:f1:17:65:5e:28:c4:06:0d:a1:a3:f4:c2
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIF8zCCA9ugAwIBAgIUDU3FzRYilZYIfrgLfxUGNPt5EDQwDQYJKoZIhvcNAQEL
|
||||||
|
BQAwgYAxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUt
|
||||||
|
VHVncmEgRUJHIEEuUy4xHTAbBgNVBAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYw
|
||||||
|
JAYDVQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290IENBIFJTQSB2MzAeFw0yMDAzMTgw
|
||||||
|
OTA3MTdaFw00NTAzMTIwOTA3MTdaMIGAMQswCQYDVQQGEwJUUjEPMA0GA1UEBxMG
|
||||||
|
QW5rYXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRFLVR1
|
||||||
|
Z3JhIFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBD
|
||||||
|
QSBSU0EgdjMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCiZvCJt3J7
|
||||||
|
7gnJY9LTQ91ew6aEOErxjYG7FL1H6EAX8z3DeEVypi6Q3po61CBxyryfHUuXCscx
|
||||||
|
uj7X/iWpKo429NEvx7epXTPcMHD4QGxLsqYxYdE0PD0xesevxKenhOGXpOhL9hd8
|
||||||
|
7jwH7eKKV9y2+/hDJVDqJ4GohryPUkqWOmAalrv9c/SF/YP9f4RtNGx/ardLAQO/
|
||||||
|
rWm31zLZ9Vdq6YaCPqVmMbMWPcLzJmAy01IesGykNz709a/r4d+ABs8qQedmCeFL
|
||||||
|
l+d3vSFtKbZnwy1+7dZ5ZdHPOrbRsV5WYVB6Ws5OUDGAA5hH5+QYfERaxqSzO8bG
|
||||||
|
wzrwbMOLyKSRBfP12baqBqG3q+Sx6iEUXIOk/P+2UNOMEiaZdnDpwA+mdPy70Bt4
|
||||||
|
znKS4iicvObpCdg604nmvi533wEKb5b25Y08TVJ2Glbhc34XrD2tbKNSEhhw5oBO
|
||||||
|
M/J+JjKsBY04pOZ2PJ8QaQ5tndLBeSBrW88zjdGUdjXnXVXHt6woq0bM5zshtQoK
|
||||||
|
5EpZ3IE1S0SVEgpnpaH/WwAH0sDM+T/8nzPyAPiMbIedBi3x7+PmBvrFZhNb/FAH
|
||||||
|
nnGGstpvdDDPk1Po3CLW3iAfYY2jLqN4MpBs3KwytQXk9TwzDdbgh3cXTJ2w2Amo
|
||||||
|
DVf3RIXwyAS+XF1a4xeOVGNpf0l0ZAWMowIDAQABo2MwYTAPBgNVHRMBAf8EBTAD
|
||||||
|
AQH/MB8GA1UdIwQYMBaAFLK0ruYt9ybVqnUtdkvAG1Mh0EjvMB0GA1UdDgQWBBSy
|
||||||
|
tK7mLfcm1ap1LXZLwBtTIdBI7zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEL
|
||||||
|
BQADggIBAImocn+M684uGMQQgC0QDP/7FM0E4BQ8Tpr7nym/Ip5XuYJzEmMmtcyQ
|
||||||
|
6dIqKe6cLcwsmb5FJ+Sxce3kOJUxQfJ9emN438o2Fi+CiJ+8EUdPdk3ILY7r3y18
|
||||||
|
Tjvarvbj2l0Upq7ohUSdBm6O++96SmotKygY/r+QLHUWnw/qln0F7psTpURs+APQ
|
||||||
|
3SPh/QMSEgj0GDSz4DcLdxEBSL9htLX4GdnLTeqjjO/98Aa1bZL0SmFQhO3sSdPk
|
||||||
|
vmjmLuMxC1QLGpLWgti2omU8ZgT5Vdps+9u1FGZNlIM7zR6mK7L+d0CGq+ffCsn9
|
||||||
|
9t2HVhjYsCxVYJb6CH5SkPVLpi6HfMsg2wY+oF0Dd32iPBMbKaITVaA9FCKvb7jQ
|
||||||
|
mhty3QUBjYZgv6Rn7rWlDdF/5horYmbDB7rnoEgcOMPpRfunf/ztAmgayncSd6YA
|
||||||
|
VSgU7NbHEqIbZULpkejLPoeJVF3Zr52XnGnnCv8PWniLYypMfUeUP95L6VPQMPHF
|
||||||
|
9p5J3zugkaOj/s1YzOrfr28oO6Bpm4/srK4rVJ2bBLFHIK+WEj5jlB0E5y67hscM
|
||||||
|
moi/dkfv97ALl2bSRM9gUgfh1SxKOidhd8rXj+eHDjD/DLsE4mHDosiXYY60MGo8
|
||||||
|
bcIHX0pzLz/5FooBZu+6kcpSV3uu1OYP3Qt6f4ueJiDPO++BcYNZ
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
# Issuer: CN=E-Tugra Global Root CA ECC v3 O=E-Tugra EBG A.S. OU=E-Tugra Trust Center
|
||||||
|
# Subject: CN=E-Tugra Global Root CA ECC v3 O=E-Tugra EBG A.S. OU=E-Tugra Trust Center
|
||||||
|
# Label: "E-Tugra Global Root CA ECC v3"
|
||||||
|
# Serial: 218504919822255052842371958738296604628416471745
|
||||||
|
# MD5 Fingerprint: 46:bc:81:bb:f1:b5:1e:f7:4b:96:bc:14:e2:e7:27:64
|
||||||
|
# SHA1 Fingerprint: 8a:2f:af:57:53:b1:b0:e6:a1:04:ec:5b:6a:69:71:6d:f6:1c:e2:84
|
||||||
|
# SHA256 Fingerprint: 87:3f:46:85:fa:7f:56:36:25:25:2e:6d:36:bc:d7:f1:6f:c2:49:51:f2:64:e4:7e:1b:95:4f:49:08:cd:ca:13
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICpTCCAiqgAwIBAgIUJkYZdzHhT28oNt45UYbm1JeIIsEwCgYIKoZIzj0EAwMw
|
||||||
|
gYAxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUtVHVn
|
||||||
|
cmEgRUJHIEEuUy4xHTAbBgNVBAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYwJAYD
|
||||||
|
VQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290IENBIEVDQyB2MzAeFw0yMDAzMTgwOTQ2
|
||||||
|
NThaFw00NTAzMTIwOTQ2NThaMIGAMQswCQYDVQQGEwJUUjEPMA0GA1UEBxMGQW5r
|
||||||
|
YXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRFLVR1Z3Jh
|
||||||
|
IFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBDQSBF
|
||||||
|
Q0MgdjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASOmCm/xxAeJ9urA8woLNheSBkQ
|
||||||
|
KczLWYHMjLiSF4mDKpL2w6QdTGLVn9agRtwcvHbB40fQWxPa56WzZkjnIZpKT4YK
|
||||||
|
fWzqTTKACrJ6CZtpS5iB4i7sAnCWH/31Rs7K3IKjYzBhMA8GA1UdEwEB/wQFMAMB
|
||||||
|
Af8wHwYDVR0jBBgwFoAU/4Ixcj75xGZsrTie0bBRiKWQzPUwHQYDVR0OBBYEFP+C
|
||||||
|
MXI++cRmbK04ntGwUYilkMz1MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNp
|
||||||
|
ADBmAjEA5gVYaWHlLcoNy/EZCL3W/VGSGn5jVASQkZo1kTmZ+gepZpO6yGjUij/6
|
||||||
|
7W4WAie3AjEA3VoXK3YdZUKWpqxdinlW2Iob35reX8dQj7FbcQwm32pAAOwzkSFx
|
||||||
|
vmjkI6TZraE3
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ __all__ = [
|
||||||
'Counter',
|
'Counter',
|
||||||
'Deque',
|
'Deque',
|
||||||
'DefaultDict',
|
'DefaultDict',
|
||||||
|
'NamedTuple',
|
||||||
'OrderedDict',
|
'OrderedDict',
|
||||||
'TypedDict',
|
'TypedDict',
|
||||||
|
|
||||||
|
|
@ -380,6 +381,46 @@ def _is_callable_members_only(cls):
|
||||||
return all(callable(getattr(cls, attr, None)) for attr in _get_protocol_attrs(cls))
|
return all(callable(getattr(cls, attr, None)) for attr in _get_protocol_attrs(cls))
|
||||||
|
|
||||||
|
|
||||||
|
def _maybe_adjust_parameters(cls):
|
||||||
|
"""Helper function used in Protocol.__init_subclass__ and _TypedDictMeta.__new__.
|
||||||
|
|
||||||
|
The contents of this function are very similar
|
||||||
|
to logic found in typing.Generic.__init_subclass__
|
||||||
|
on the CPython main branch.
|
||||||
|
"""
|
||||||
|
tvars = []
|
||||||
|
if '__orig_bases__' in cls.__dict__:
|
||||||
|
tvars = typing._collect_type_vars(cls.__orig_bases__)
|
||||||
|
# Look for Generic[T1, ..., Tn] or Protocol[T1, ..., Tn].
|
||||||
|
# If found, tvars must be a subset of it.
|
||||||
|
# If not found, tvars is it.
|
||||||
|
# Also check for and reject plain Generic,
|
||||||
|
# and reject multiple Generic[...] and/or Protocol[...].
|
||||||
|
gvars = None
|
||||||
|
for base in cls.__orig_bases__:
|
||||||
|
if (isinstance(base, typing._GenericAlias) and
|
||||||
|
base.__origin__ in (typing.Generic, Protocol)):
|
||||||
|
# for error messages
|
||||||
|
the_base = base.__origin__.__name__
|
||||||
|
if gvars is not None:
|
||||||
|
raise TypeError(
|
||||||
|
"Cannot inherit from Generic[...]"
|
||||||
|
" and/or Protocol[...] multiple types.")
|
||||||
|
gvars = base.__parameters__
|
||||||
|
if gvars is None:
|
||||||
|
gvars = tvars
|
||||||
|
else:
|
||||||
|
tvarset = set(tvars)
|
||||||
|
gvarset = set(gvars)
|
||||||
|
if not tvarset <= gvarset:
|
||||||
|
s_vars = ', '.join(str(t) for t in tvars if t not in gvarset)
|
||||||
|
s_args = ', '.join(str(g) for g in gvars)
|
||||||
|
raise TypeError(f"Some type variables ({s_vars}) are"
|
||||||
|
f" not listed in {the_base}[{s_args}]")
|
||||||
|
tvars = gvars
|
||||||
|
cls.__parameters__ = tuple(tvars)
|
||||||
|
|
||||||
|
|
||||||
# 3.8+
|
# 3.8+
|
||||||
if hasattr(typing, 'Protocol'):
|
if hasattr(typing, 'Protocol'):
|
||||||
Protocol = typing.Protocol
|
Protocol = typing.Protocol
|
||||||
|
|
@ -476,43 +517,13 @@ else:
|
||||||
return typing._GenericAlias(cls, params)
|
return typing._GenericAlias(cls, params)
|
||||||
|
|
||||||
def __init_subclass__(cls, *args, **kwargs):
|
def __init_subclass__(cls, *args, **kwargs):
|
||||||
tvars = []
|
|
||||||
if '__orig_bases__' in cls.__dict__:
|
if '__orig_bases__' in cls.__dict__:
|
||||||
error = typing.Generic in cls.__orig_bases__
|
error = typing.Generic in cls.__orig_bases__
|
||||||
else:
|
else:
|
||||||
error = typing.Generic in cls.__bases__
|
error = typing.Generic in cls.__bases__
|
||||||
if error:
|
if error:
|
||||||
raise TypeError("Cannot inherit from plain Generic")
|
raise TypeError("Cannot inherit from plain Generic")
|
||||||
if '__orig_bases__' in cls.__dict__:
|
_maybe_adjust_parameters(cls)
|
||||||
tvars = typing._collect_type_vars(cls.__orig_bases__)
|
|
||||||
# Look for Generic[T1, ..., Tn] or Protocol[T1, ..., Tn].
|
|
||||||
# If found, tvars must be a subset of it.
|
|
||||||
# If not found, tvars is it.
|
|
||||||
# Also check for and reject plain Generic,
|
|
||||||
# and reject multiple Generic[...] and/or Protocol[...].
|
|
||||||
gvars = None
|
|
||||||
for base in cls.__orig_bases__:
|
|
||||||
if (isinstance(base, typing._GenericAlias) and
|
|
||||||
base.__origin__ in (typing.Generic, Protocol)):
|
|
||||||
# for error messages
|
|
||||||
the_base = base.__origin__.__name__
|
|
||||||
if gvars is not None:
|
|
||||||
raise TypeError(
|
|
||||||
"Cannot inherit from Generic[...]"
|
|
||||||
" and/or Protocol[...] multiple types.")
|
|
||||||
gvars = base.__parameters__
|
|
||||||
if gvars is None:
|
|
||||||
gvars = tvars
|
|
||||||
else:
|
|
||||||
tvarset = set(tvars)
|
|
||||||
gvarset = set(gvars)
|
|
||||||
if not tvarset <= gvarset:
|
|
||||||
s_vars = ', '.join(str(t) for t in tvars if t not in gvarset)
|
|
||||||
s_args = ', '.join(str(g) for g in gvars)
|
|
||||||
raise TypeError(f"Some type variables ({s_vars}) are"
|
|
||||||
f" not listed in {the_base}[{s_args}]")
|
|
||||||
tvars = gvars
|
|
||||||
cls.__parameters__ = tuple(tvars)
|
|
||||||
|
|
||||||
# Determine if this is a protocol or a concrete subclass.
|
# Determine if this is a protocol or a concrete subclass.
|
||||||
if not cls.__dict__.get('_is_protocol', None):
|
if not cls.__dict__.get('_is_protocol', None):
|
||||||
|
|
@ -613,6 +624,7 @@ if hasattr(typing, "Required"):
|
||||||
# keyword with old-style TypedDict(). See https://bugs.python.org/issue42059
|
# keyword with old-style TypedDict(). See https://bugs.python.org/issue42059
|
||||||
# The standard library TypedDict below Python 3.11 does not store runtime
|
# The standard library TypedDict below Python 3.11 does not store runtime
|
||||||
# information about optional and required keys when using Required or NotRequired.
|
# information about optional and required keys when using Required or NotRequired.
|
||||||
|
# Generic TypedDicts are also impossible using typing.TypedDict on Python <3.11.
|
||||||
TypedDict = typing.TypedDict
|
TypedDict = typing.TypedDict
|
||||||
_TypedDictMeta = typing._TypedDictMeta
|
_TypedDictMeta = typing._TypedDictMeta
|
||||||
is_typeddict = typing.is_typeddict
|
is_typeddict = typing.is_typeddict
|
||||||
|
|
@ -695,8 +707,16 @@ else:
|
||||||
# Subclasses and instances of TypedDict return actual dictionaries
|
# Subclasses and instances of TypedDict return actual dictionaries
|
||||||
# via _dict_new.
|
# via _dict_new.
|
||||||
ns['__new__'] = _typeddict_new if name == 'TypedDict' else _dict_new
|
ns['__new__'] = _typeddict_new if name == 'TypedDict' else _dict_new
|
||||||
|
# Don't insert typing.Generic into __bases__ here,
|
||||||
|
# or Generic.__init_subclass__ will raise TypeError
|
||||||
|
# in the super().__new__() call.
|
||||||
|
# Instead, monkey-patch __bases__ onto the class after it's been created.
|
||||||
tp_dict = super().__new__(cls, name, (dict,), ns)
|
tp_dict = super().__new__(cls, name, (dict,), ns)
|
||||||
|
|
||||||
|
if any(issubclass(base, typing.Generic) for base in bases):
|
||||||
|
tp_dict.__bases__ = (typing.Generic, dict)
|
||||||
|
_maybe_adjust_parameters(tp_dict)
|
||||||
|
|
||||||
annotations = {}
|
annotations = {}
|
||||||
own_annotations = ns.get('__annotations__', {})
|
own_annotations = ns.get('__annotations__', {})
|
||||||
msg = "TypedDict('Name', {f0: t0, f1: t1, ...}); each t must be a type"
|
msg = "TypedDict('Name', {f0: t0, f1: t1, ...}); each t must be a type"
|
||||||
|
|
@ -1958,3 +1978,92 @@ else:
|
||||||
if not hasattr(typing, "TypeVarTuple"):
|
if not hasattr(typing, "TypeVarTuple"):
|
||||||
typing._collect_type_vars = _collect_type_vars
|
typing._collect_type_vars = _collect_type_vars
|
||||||
typing._check_generic = _check_generic
|
typing._check_generic = _check_generic
|
||||||
|
|
||||||
|
|
||||||
|
# Backport typing.NamedTuple as it exists in Python 3.11.
|
||||||
|
# In 3.11, the ability to define generic `NamedTuple`s was supported.
|
||||||
|
# This was explicitly disallowed in 3.9-3.10, and only half-worked in <=3.8.
|
||||||
|
if sys.version_info >= (3, 11):
|
||||||
|
NamedTuple = typing.NamedTuple
|
||||||
|
else:
|
||||||
|
def _caller():
|
||||||
|
try:
|
||||||
|
return sys._getframe(2).f_globals.get('__name__', '__main__')
|
||||||
|
except (AttributeError, ValueError): # For platforms without _getframe()
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _make_nmtuple(name, types, module, defaults=()):
|
||||||
|
fields = [n for n, t in types]
|
||||||
|
annotations = {n: typing._type_check(t, f"field {n} annotation must be a type")
|
||||||
|
for n, t in types}
|
||||||
|
nm_tpl = collections.namedtuple(name, fields,
|
||||||
|
defaults=defaults, module=module)
|
||||||
|
nm_tpl.__annotations__ = nm_tpl.__new__.__annotations__ = annotations
|
||||||
|
# The `_field_types` attribute was removed in 3.9;
|
||||||
|
# in earlier versions, it is the same as the `__annotations__` attribute
|
||||||
|
if sys.version_info < (3, 9):
|
||||||
|
nm_tpl._field_types = annotations
|
||||||
|
return nm_tpl
|
||||||
|
|
||||||
|
_prohibited_namedtuple_fields = typing._prohibited
|
||||||
|
_special_namedtuple_fields = frozenset({'__module__', '__name__', '__annotations__'})
|
||||||
|
|
||||||
|
class _NamedTupleMeta(type):
|
||||||
|
def __new__(cls, typename, bases, ns):
|
||||||
|
assert _NamedTuple in bases
|
||||||
|
for base in bases:
|
||||||
|
if base is not _NamedTuple and base is not typing.Generic:
|
||||||
|
raise TypeError(
|
||||||
|
'can only inherit from a NamedTuple type and Generic')
|
||||||
|
bases = tuple(tuple if base is _NamedTuple else base for base in bases)
|
||||||
|
types = ns.get('__annotations__', {})
|
||||||
|
default_names = []
|
||||||
|
for field_name in types:
|
||||||
|
if field_name in ns:
|
||||||
|
default_names.append(field_name)
|
||||||
|
elif default_names:
|
||||||
|
raise TypeError(f"Non-default namedtuple field {field_name} "
|
||||||
|
f"cannot follow default field"
|
||||||
|
f"{'s' if len(default_names) > 1 else ''} "
|
||||||
|
f"{', '.join(default_names)}")
|
||||||
|
nm_tpl = _make_nmtuple(
|
||||||
|
typename, types.items(),
|
||||||
|
defaults=[ns[n] for n in default_names],
|
||||||
|
module=ns['__module__']
|
||||||
|
)
|
||||||
|
nm_tpl.__bases__ = bases
|
||||||
|
if typing.Generic in bases:
|
||||||
|
class_getitem = typing.Generic.__class_getitem__.__func__
|
||||||
|
nm_tpl.__class_getitem__ = classmethod(class_getitem)
|
||||||
|
# update from user namespace without overriding special namedtuple attributes
|
||||||
|
for key in ns:
|
||||||
|
if key in _prohibited_namedtuple_fields:
|
||||||
|
raise AttributeError("Cannot overwrite NamedTuple attribute " + key)
|
||||||
|
elif key not in _special_namedtuple_fields and key not in nm_tpl._fields:
|
||||||
|
setattr(nm_tpl, key, ns[key])
|
||||||
|
if typing.Generic in bases:
|
||||||
|
nm_tpl.__init_subclass__()
|
||||||
|
return nm_tpl
|
||||||
|
|
||||||
|
def NamedTuple(__typename, __fields=None, **kwargs):
|
||||||
|
if __fields is None:
|
||||||
|
__fields = kwargs.items()
|
||||||
|
elif kwargs:
|
||||||
|
raise TypeError("Either list of fields or keywords"
|
||||||
|
" can be provided to NamedTuple, not both")
|
||||||
|
return _make_nmtuple(__typename, __fields, module=_caller())
|
||||||
|
|
||||||
|
NamedTuple.__doc__ = typing.NamedTuple.__doc__
|
||||||
|
_NamedTuple = type.__new__(_NamedTupleMeta, 'NamedTuple', (), {})
|
||||||
|
|
||||||
|
# On 3.8+, alter the signature so that it matches typing.NamedTuple.
|
||||||
|
# The signature of typing.NamedTuple on >=3.8 is invalid syntax in Python 3.7,
|
||||||
|
# so just leave the signature as it is on 3.7.
|
||||||
|
if sys.version_info >= (3, 8):
|
||||||
|
NamedTuple.__text_signature__ = '(typename, fields=None, /, **kwargs)'
|
||||||
|
|
||||||
|
def _namedtuple_mro_entries(bases):
|
||||||
|
assert NamedTuple in bases
|
||||||
|
return (_NamedTuple,)
|
||||||
|
|
||||||
|
NamedTuple.__mro_entries__ = _namedtuple_mro_entries
|
||||||
|
|
|
||||||
30
dist/ba_data/python/ba/_app.py
vendored
30
dist/ba_data/python/ba/_app.py
vendored
|
|
@ -29,6 +29,7 @@ if TYPE_CHECKING:
|
||||||
from ba._cloud import CloudSubsystem
|
from ba._cloud import CloudSubsystem
|
||||||
from bastd.actor import spazappearance
|
from bastd.actor import spazappearance
|
||||||
from ba._accountv2 import AccountV2Subsystem
|
from ba._accountv2 import AccountV2Subsystem
|
||||||
|
from ba._level import Level
|
||||||
|
|
||||||
|
|
||||||
class App:
|
class App:
|
||||||
|
|
@ -274,6 +275,7 @@ class App:
|
||||||
|
|
||||||
# Co-op Campaigns.
|
# Co-op Campaigns.
|
||||||
self.campaigns: dict[str, ba.Campaign] = {}
|
self.campaigns: dict[str, ba.Campaign] = {}
|
||||||
|
self.custom_coop_practice_games: list[str] = []
|
||||||
|
|
||||||
# Server Mode.
|
# Server Mode.
|
||||||
self.server: ba.ServerController | None = None
|
self.server: ba.ServerController | None = None
|
||||||
|
|
@ -342,6 +344,7 @@ class App:
|
||||||
from bastd.actor import spazappearance
|
from bastd.actor import spazappearance
|
||||||
from ba._generated.enums import TimeType
|
from ba._generated.enums import TimeType
|
||||||
|
|
||||||
|
|
||||||
self._aioloop = _asyncio.setup_asyncio()
|
self._aioloop = _asyncio.setup_asyncio()
|
||||||
|
|
||||||
cfg = self.config
|
cfg = self.config
|
||||||
|
|
@ -432,8 +435,6 @@ class App:
|
||||||
|
|
||||||
# from ba._dependency import test_depset
|
# from ba._dependency import test_depset
|
||||||
# test_depset()
|
# test_depset()
|
||||||
if bool(False):
|
|
||||||
self._test_https()
|
|
||||||
|
|
||||||
def _update_state(self) -> None:
|
def _update_state(self) -> None:
|
||||||
if self._app_paused:
|
if self._app_paused:
|
||||||
|
|
@ -527,6 +528,15 @@ class App:
|
||||||
# FIXME: This should not be an actor attr.
|
# FIXME: This should not be an actor attr.
|
||||||
activity.paused_text = None
|
activity.paused_text = None
|
||||||
|
|
||||||
|
def add_coop_practice_level(self, level: Level) -> None:
|
||||||
|
"""Adds an individual level to the 'practice' section in Co-op."""
|
||||||
|
|
||||||
|
# Assign this level to our catch-all campaign.
|
||||||
|
self.campaigns['Challenges'].addlevel(level)
|
||||||
|
|
||||||
|
# Make note to add it to our challenges UI.
|
||||||
|
self.custom_coop_practice_games.append(f'Challenges:{level.name}')
|
||||||
|
|
||||||
def return_to_main_menu_session_gracefully(self,
|
def return_to_main_menu_session_gracefully(self,
|
||||||
reset_ui: bool = True) -> None:
|
reset_ui: bool = True) -> None:
|
||||||
"""Attempt to cleanly get back to the main menu."""
|
"""Attempt to cleanly get back to the main menu."""
|
||||||
|
|
@ -643,19 +653,3 @@ class App:
|
||||||
"""
|
"""
|
||||||
self._initial_login_completed = True
|
self._initial_login_completed = True
|
||||||
self._update_state()
|
self._update_state()
|
||||||
|
|
||||||
def _test_https(self) -> None:
|
|
||||||
"""Testing https support.
|
|
||||||
|
|
||||||
(would be nice to get this working on our custom Python builds; need
|
|
||||||
to wrangle certificates somehow).
|
|
||||||
"""
|
|
||||||
import urllib.request
|
|
||||||
try:
|
|
||||||
with urllib.request.urlopen('https://example.com') as url:
|
|
||||||
val = url.read()
|
|
||||||
_ba.screenmessage('HTTPS SUCCESS!')
|
|
||||||
print('HTTPS TEST SUCCESS', len(val))
|
|
||||||
except Exception as exc:
|
|
||||||
_ba.screenmessage('HTTPS FAIL.')
|
|
||||||
print('HTTPS TEST FAIL:', exc)
|
|
||||||
|
|
|
||||||
6
dist/ba_data/python/ba/_assetmanager.py
vendored
6
dist/ba_data/python/ba/_assetmanager.py
vendored
|
|
@ -17,6 +17,7 @@ import sys
|
||||||
|
|
||||||
from efro.dataclassio import (ioprepped, IOAttrs, dataclass_from_json,
|
from efro.dataclassio import (ioprepped, IOAttrs, dataclass_from_json,
|
||||||
dataclass_to_json)
|
dataclass_to_json)
|
||||||
|
import _ba
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from bacommon.assets import AssetPackageFlavor
|
from bacommon.assets import AssetPackageFlavor
|
||||||
|
|
@ -165,7 +166,6 @@ def fetch_url(url: str, filename: Path, asset_gather: AssetGather) -> None:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# pylint: disable=consider-using-with
|
# pylint: disable=consider-using-with
|
||||||
|
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
# We don't want to keep the provided AssetGather alive, but we want
|
# We don't want to keep the provided AssetGather alive, but we want
|
||||||
|
|
@ -175,7 +175,9 @@ def fetch_url(url: str, filename: Path, asset_gather: AssetGather) -> None:
|
||||||
|
|
||||||
# Pass a very short timeout to urllib so we have opportunities
|
# Pass a very short timeout to urllib so we have opportunities
|
||||||
# to cancel even with network blockage.
|
# to cancel even with network blockage.
|
||||||
req = urllib.request.urlopen(url, timeout=1)
|
req = urllib.request.urlopen(url,
|
||||||
|
context=_ba.app.net.sslcontext,
|
||||||
|
timeout=1)
|
||||||
file_size = int(req.headers['Content-Length'])
|
file_size = int(req.headers['Content-Length'])
|
||||||
print(f'\nDownloading: {filename} Bytes: {file_size:,}')
|
print(f'\nDownloading: {filename} Bytes: {file_size:,}')
|
||||||
|
|
||||||
|
|
|
||||||
16
dist/ba_data/python/ba/_asyncio.py
vendored
16
dist/ba_data/python/ba/_asyncio.py
vendored
|
|
@ -11,6 +11,9 @@ from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import logging
|
||||||
|
import time
|
||||||
|
import os
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
import ba
|
import ba
|
||||||
|
|
@ -19,6 +22,8 @@ if TYPE_CHECKING:
|
||||||
_asyncio_timer: ba.Timer | None = None
|
_asyncio_timer: ba.Timer | None = None
|
||||||
_asyncio_event_loop: asyncio.AbstractEventLoop | None = None
|
_asyncio_event_loop: asyncio.AbstractEventLoop | None = None
|
||||||
|
|
||||||
|
DEBUG_TIMING = os.environ.get('BA_DEBUG_TIMING') == '1'
|
||||||
|
|
||||||
|
|
||||||
def setup_asyncio() -> asyncio.AbstractEventLoop:
|
def setup_asyncio() -> asyncio.AbstractEventLoop:
|
||||||
"""Setup asyncio functionality for the logic thread."""
|
"""Setup asyncio functionality for the logic thread."""
|
||||||
|
|
@ -53,7 +58,18 @@ def setup_asyncio() -> asyncio.AbstractEventLoop:
|
||||||
def run_cycle() -> None:
|
def run_cycle() -> None:
|
||||||
assert _asyncio_event_loop is not None
|
assert _asyncio_event_loop is not None
|
||||||
_asyncio_event_loop.call_soon(_asyncio_event_loop.stop)
|
_asyncio_event_loop.call_soon(_asyncio_event_loop.stop)
|
||||||
|
starttime = time.monotonic() if DEBUG_TIMING else 0
|
||||||
_asyncio_event_loop.run_forever()
|
_asyncio_event_loop.run_forever()
|
||||||
|
endtime = time.monotonic() if DEBUG_TIMING else 0
|
||||||
|
|
||||||
|
# Let's aim to have nothing take longer than 1/120 of a second.
|
||||||
|
if DEBUG_TIMING:
|
||||||
|
warn_time = 1.0 / 120
|
||||||
|
duration = endtime - starttime
|
||||||
|
if duration > warn_time:
|
||||||
|
logging.warning(
|
||||||
|
'Asyncio loop step took %.4fs; ideal max is %.4f',
|
||||||
|
duration, warn_time)
|
||||||
|
|
||||||
global _asyncio_timer # pylint: disable=invalid-name
|
global _asyncio_timer # pylint: disable=invalid-name
|
||||||
_asyncio_timer = _ba.Timer(1.0 / 30.0,
|
_asyncio_timer = _ba.Timer(1.0 / 30.0,
|
||||||
|
|
|
||||||
468
dist/ba_data/python/ba/_campaign.py
vendored
468
dist/ba_data/python/ba/_campaign.py
vendored
|
|
@ -28,10 +28,16 @@ class Campaign:
|
||||||
Category: **App Classes**
|
Category: **App Classes**
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name: str, sequential: bool = True):
|
def __init__(self,
|
||||||
|
name: str,
|
||||||
|
sequential: bool = True,
|
||||||
|
levels: list[ba.Level] | None = None):
|
||||||
self._name = name
|
self._name = name
|
||||||
self._levels: list[ba.Level] = []
|
|
||||||
self._sequential = sequential
|
self._sequential = sequential
|
||||||
|
self._levels: list[ba.Level] = []
|
||||||
|
if levels is not None:
|
||||||
|
for level in levels:
|
||||||
|
self.addlevel(level)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
|
|
@ -43,12 +49,15 @@ class Campaign:
|
||||||
"""Whether this Campaign's levels must be played in sequence."""
|
"""Whether this Campaign's levels must be played in sequence."""
|
||||||
return self._sequential
|
return self._sequential
|
||||||
|
|
||||||
def addlevel(self, level: ba.Level) -> None:
|
def addlevel(self, level: ba.Level, index: int | None = None) -> None:
|
||||||
"""Adds a ba.Level to the Campaign."""
|
"""Adds a ba.Level to the Campaign."""
|
||||||
if level.campaign is not None:
|
if level.campaign is not None:
|
||||||
raise RuntimeError('Level already belongs to a campaign.')
|
raise RuntimeError('Level already belongs to a campaign.')
|
||||||
level.set_campaign(self, len(self._levels))
|
level.set_campaign(self, len(self._levels))
|
||||||
self._levels.append(level)
|
if index is None:
|
||||||
|
self._levels.append(level)
|
||||||
|
else:
|
||||||
|
self._levels.insert(index, level)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def levels(self) -> list[ba.Level]:
|
def levels(self) -> list[ba.Level]:
|
||||||
|
|
@ -91,9 +100,8 @@ class Campaign:
|
||||||
|
|
||||||
def init_campaigns() -> None:
|
def init_campaigns() -> None:
|
||||||
"""Fill out initial default Campaigns."""
|
"""Fill out initial default Campaigns."""
|
||||||
# pylint: disable=too-many-statements
|
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from ba import _level
|
from ba._level import Level
|
||||||
from bastd.game.onslaught import OnslaughtGame
|
from bastd.game.onslaught import OnslaughtGame
|
||||||
from bastd.game.football import FootballCoopGame
|
from bastd.game.football import FootballCoopGame
|
||||||
from bastd.game.runaround import RunaroundGame
|
from bastd.game.runaround import RunaroundGame
|
||||||
|
|
@ -109,244 +117,218 @@ def init_campaigns() -> None:
|
||||||
|
|
||||||
# FIXME: Once translations catch up, we can convert these to use the
|
# FIXME: Once translations catch up, we can convert these to use the
|
||||||
# generic display-name '${GAME} Training' type stuff.
|
# generic display-name '${GAME} Training' type stuff.
|
||||||
campaign = Campaign('Easy')
|
register_campaign(
|
||||||
campaign.addlevel(
|
Campaign(
|
||||||
_level.Level('Onslaught Training',
|
'Easy',
|
||||||
gametype=OnslaughtGame,
|
levels=[
|
||||||
settings={'preset': 'training_easy'},
|
Level('Onslaught Training',
|
||||||
preview_texture_name='doomShroomPreview'))
|
gametype=OnslaughtGame,
|
||||||
campaign.addlevel(
|
settings={'preset': 'training_easy'},
|
||||||
_level.Level('Rookie Onslaught',
|
preview_texture_name='doomShroomPreview'),
|
||||||
gametype=OnslaughtGame,
|
Level('Rookie Onslaught',
|
||||||
settings={'preset': 'rookie_easy'},
|
gametype=OnslaughtGame,
|
||||||
preview_texture_name='courtyardPreview'))
|
settings={'preset': 'rookie_easy'},
|
||||||
campaign.addlevel(
|
preview_texture_name='courtyardPreview'),
|
||||||
_level.Level('Rookie Football',
|
Level('Rookie Football',
|
||||||
gametype=FootballCoopGame,
|
gametype=FootballCoopGame,
|
||||||
settings={'preset': 'rookie_easy'},
|
settings={'preset': 'rookie_easy'},
|
||||||
preview_texture_name='footballStadiumPreview'))
|
preview_texture_name='footballStadiumPreview'),
|
||||||
campaign.addlevel(
|
Level('Pro Onslaught',
|
||||||
_level.Level('Pro Onslaught',
|
gametype=OnslaughtGame,
|
||||||
gametype=OnslaughtGame,
|
settings={'preset': 'pro_easy'},
|
||||||
settings={'preset': 'pro_easy'},
|
preview_texture_name='doomShroomPreview'),
|
||||||
preview_texture_name='doomShroomPreview'))
|
Level('Pro Football',
|
||||||
campaign.addlevel(
|
gametype=FootballCoopGame,
|
||||||
_level.Level('Pro Football',
|
settings={'preset': 'pro_easy'},
|
||||||
gametype=FootballCoopGame,
|
preview_texture_name='footballStadiumPreview'),
|
||||||
settings={'preset': 'pro_easy'},
|
Level('Pro Runaround',
|
||||||
preview_texture_name='footballStadiumPreview'))
|
gametype=RunaroundGame,
|
||||||
campaign.addlevel(
|
settings={'preset': 'pro_easy'},
|
||||||
_level.Level('Pro Runaround',
|
preview_texture_name='towerDPreview'),
|
||||||
gametype=RunaroundGame,
|
Level('Uber Onslaught',
|
||||||
settings={'preset': 'pro_easy'},
|
gametype=OnslaughtGame,
|
||||||
preview_texture_name='towerDPreview'))
|
settings={'preset': 'uber_easy'},
|
||||||
campaign.addlevel(
|
preview_texture_name='courtyardPreview'),
|
||||||
_level.Level('Uber Onslaught',
|
Level('Uber Football',
|
||||||
gametype=OnslaughtGame,
|
gametype=FootballCoopGame,
|
||||||
settings={'preset': 'uber_easy'},
|
settings={'preset': 'uber_easy'},
|
||||||
preview_texture_name='courtyardPreview'))
|
preview_texture_name='footballStadiumPreview'),
|
||||||
campaign.addlevel(
|
Level('Uber Runaround',
|
||||||
_level.Level('Uber Football',
|
gametype=RunaroundGame,
|
||||||
gametype=FootballCoopGame,
|
settings={'preset': 'uber_easy'},
|
||||||
settings={'preset': 'uber_easy'},
|
preview_texture_name='towerDPreview')
|
||||||
preview_texture_name='footballStadiumPreview'))
|
],
|
||||||
campaign.addlevel(
|
))
|
||||||
_level.Level('Uber Runaround',
|
|
||||||
gametype=RunaroundGame,
|
|
||||||
settings={'preset': 'uber_easy'},
|
|
||||||
preview_texture_name='towerDPreview'))
|
|
||||||
register_campaign(campaign)
|
|
||||||
|
|
||||||
# "hard" mode
|
# "hard" mode
|
||||||
campaign = Campaign('Default')
|
register_campaign(
|
||||||
campaign.addlevel(
|
Campaign(
|
||||||
_level.Level('Onslaught Training',
|
'Default',
|
||||||
gametype=OnslaughtGame,
|
levels=[
|
||||||
settings={'preset': 'training'},
|
Level('Onslaught Training',
|
||||||
preview_texture_name='doomShroomPreview'))
|
gametype=OnslaughtGame,
|
||||||
campaign.addlevel(
|
settings={'preset': 'training'},
|
||||||
_level.Level('Rookie Onslaught',
|
preview_texture_name='doomShroomPreview'),
|
||||||
gametype=OnslaughtGame,
|
Level('Rookie Onslaught',
|
||||||
settings={'preset': 'rookie'},
|
gametype=OnslaughtGame,
|
||||||
preview_texture_name='courtyardPreview'))
|
settings={'preset': 'rookie'},
|
||||||
campaign.addlevel(
|
preview_texture_name='courtyardPreview'),
|
||||||
_level.Level('Rookie Football',
|
Level('Rookie Football',
|
||||||
gametype=FootballCoopGame,
|
gametype=FootballCoopGame,
|
||||||
settings={'preset': 'rookie'},
|
settings={'preset': 'rookie'},
|
||||||
preview_texture_name='footballStadiumPreview'))
|
preview_texture_name='footballStadiumPreview'),
|
||||||
campaign.addlevel(
|
Level('Pro Onslaught',
|
||||||
_level.Level('Pro Onslaught',
|
gametype=OnslaughtGame,
|
||||||
gametype=OnslaughtGame,
|
settings={'preset': 'pro'},
|
||||||
settings={'preset': 'pro'},
|
preview_texture_name='doomShroomPreview'),
|
||||||
preview_texture_name='doomShroomPreview'))
|
Level('Pro Football',
|
||||||
campaign.addlevel(
|
gametype=FootballCoopGame,
|
||||||
_level.Level('Pro Football',
|
settings={'preset': 'pro'},
|
||||||
gametype=FootballCoopGame,
|
preview_texture_name='footballStadiumPreview'),
|
||||||
settings={'preset': 'pro'},
|
Level('Pro Runaround',
|
||||||
preview_texture_name='footballStadiumPreview'))
|
gametype=RunaroundGame,
|
||||||
campaign.addlevel(
|
settings={'preset': 'pro'},
|
||||||
_level.Level('Pro Runaround',
|
preview_texture_name='towerDPreview'),
|
||||||
gametype=RunaroundGame,
|
Level('Uber Onslaught',
|
||||||
settings={'preset': 'pro'},
|
gametype=OnslaughtGame,
|
||||||
preview_texture_name='towerDPreview'))
|
settings={'preset': 'uber'},
|
||||||
campaign.addlevel(
|
preview_texture_name='courtyardPreview'),
|
||||||
_level.Level('Uber Onslaught',
|
Level('Uber Football',
|
||||||
gametype=OnslaughtGame,
|
gametype=FootballCoopGame,
|
||||||
settings={'preset': 'uber'},
|
settings={'preset': 'uber'},
|
||||||
preview_texture_name='courtyardPreview'))
|
preview_texture_name='footballStadiumPreview'),
|
||||||
campaign.addlevel(
|
Level('Uber Runaround',
|
||||||
_level.Level('Uber Football',
|
gametype=RunaroundGame,
|
||||||
gametype=FootballCoopGame,
|
settings={'preset': 'uber'},
|
||||||
settings={'preset': 'uber'},
|
preview_texture_name='towerDPreview'),
|
||||||
preview_texture_name='footballStadiumPreview'))
|
Level('The Last Stand',
|
||||||
campaign.addlevel(
|
gametype=TheLastStandGame,
|
||||||
_level.Level('Uber Runaround',
|
settings={},
|
||||||
gametype=RunaroundGame,
|
preview_texture_name='rampagePreview')
|
||||||
settings={'preset': 'uber'},
|
],
|
||||||
preview_texture_name='towerDPreview'))
|
))
|
||||||
campaign.addlevel(
|
|
||||||
_level.Level('The Last Stand',
|
|
||||||
gametype=TheLastStandGame,
|
|
||||||
settings={},
|
|
||||||
preview_texture_name='rampagePreview'))
|
|
||||||
register_campaign(campaign)
|
|
||||||
|
|
||||||
# challenges: our 'official' random extra co-op levels
|
# challenges: our 'official' random extra co-op levels
|
||||||
campaign = Campaign('Challenges', sequential=False)
|
register_campaign(
|
||||||
campaign.addlevel(
|
Campaign(
|
||||||
_level.Level('Infinite Onslaught',
|
'Challenges',
|
||||||
gametype=OnslaughtGame,
|
sequential=False,
|
||||||
settings={'preset': 'endless'},
|
levels=[
|
||||||
preview_texture_name='doomShroomPreview'))
|
Level('Infinite Onslaught',
|
||||||
campaign.addlevel(
|
gametype=OnslaughtGame,
|
||||||
_level.Level('Infinite Runaround',
|
settings={'preset': 'endless'},
|
||||||
gametype=RunaroundGame,
|
preview_texture_name='doomShroomPreview'),
|
||||||
settings={'preset': 'endless'},
|
Level('Infinite Runaround',
|
||||||
preview_texture_name='towerDPreview'))
|
gametype=RunaroundGame,
|
||||||
campaign.addlevel(
|
settings={'preset': 'endless'},
|
||||||
_level.Level('Race',
|
preview_texture_name='towerDPreview'),
|
||||||
displayname='${GAME}',
|
Level('Race',
|
||||||
gametype=RaceGame,
|
displayname='${GAME}',
|
||||||
settings={
|
gametype=RaceGame,
|
||||||
'map': 'Big G',
|
settings={
|
||||||
'Laps': 3,
|
'map': 'Big G',
|
||||||
'Bomb Spawning': 0
|
'Laps': 3,
|
||||||
},
|
'Bomb Spawning': 0
|
||||||
preview_texture_name='bigGPreview'))
|
},
|
||||||
campaign.addlevel(
|
preview_texture_name='bigGPreview'),
|
||||||
_level.Level('Pro Race',
|
Level('Pro Race',
|
||||||
displayname='Pro ${GAME}',
|
displayname='Pro ${GAME}',
|
||||||
gametype=RaceGame,
|
gametype=RaceGame,
|
||||||
settings={
|
settings={
|
||||||
'map': 'Big G',
|
'map': 'Big G',
|
||||||
'Laps': 3,
|
'Laps': 3,
|
||||||
'Bomb Spawning': 1000
|
'Bomb Spawning': 1000
|
||||||
},
|
},
|
||||||
preview_texture_name='bigGPreview'))
|
preview_texture_name='bigGPreview'),
|
||||||
campaign.addlevel(
|
Level('Lake Frigid Race',
|
||||||
_level.Level('Lake Frigid Race',
|
displayname='${GAME}',
|
||||||
displayname='${GAME}',
|
gametype=RaceGame,
|
||||||
gametype=RaceGame,
|
settings={
|
||||||
settings={
|
'map': 'Lake Frigid',
|
||||||
'map': 'Lake Frigid',
|
'Laps': 6,
|
||||||
'Laps': 6,
|
'Mine Spawning': 2000,
|
||||||
'Mine Spawning': 2000,
|
'Bomb Spawning': 0
|
||||||
'Bomb Spawning': 0
|
},
|
||||||
},
|
preview_texture_name='lakeFrigidPreview'),
|
||||||
preview_texture_name='lakeFrigidPreview'))
|
Level('Football',
|
||||||
campaign.addlevel(
|
displayname='${GAME}',
|
||||||
_level.Level('Football',
|
gametype=FootballCoopGame,
|
||||||
displayname='${GAME}',
|
settings={'preset': 'tournament'},
|
||||||
gametype=FootballCoopGame,
|
preview_texture_name='footballStadiumPreview'),
|
||||||
settings={'preset': 'tournament'},
|
Level('Pro Football',
|
||||||
preview_texture_name='footballStadiumPreview'))
|
displayname='Pro ${GAME}',
|
||||||
campaign.addlevel(
|
gametype=FootballCoopGame,
|
||||||
_level.Level('Pro Football',
|
settings={'preset': 'tournament_pro'},
|
||||||
displayname='Pro ${GAME}',
|
preview_texture_name='footballStadiumPreview'),
|
||||||
gametype=FootballCoopGame,
|
Level('Runaround',
|
||||||
settings={'preset': 'tournament_pro'},
|
displayname='${GAME}',
|
||||||
preview_texture_name='footballStadiumPreview'))
|
gametype=RunaroundGame,
|
||||||
campaign.addlevel(
|
settings={'preset': 'tournament'},
|
||||||
_level.Level('Runaround',
|
preview_texture_name='towerDPreview'),
|
||||||
displayname='${GAME}',
|
Level('Uber Runaround',
|
||||||
gametype=RunaroundGame,
|
displayname='Uber ${GAME}',
|
||||||
settings={'preset': 'tournament'},
|
gametype=RunaroundGame,
|
||||||
preview_texture_name='towerDPreview'))
|
settings={'preset': 'tournament_uber'},
|
||||||
campaign.addlevel(
|
preview_texture_name='towerDPreview'),
|
||||||
_level.Level('Uber Runaround',
|
Level('The Last Stand',
|
||||||
displayname='Uber ${GAME}',
|
displayname='${GAME}',
|
||||||
gametype=RunaroundGame,
|
gametype=TheLastStandGame,
|
||||||
settings={'preset': 'tournament_uber'},
|
settings={'preset': 'tournament'},
|
||||||
preview_texture_name='towerDPreview'))
|
preview_texture_name='rampagePreview'),
|
||||||
campaign.addlevel(
|
Level('Tournament Infinite Onslaught',
|
||||||
_level.Level('The Last Stand',
|
displayname='Infinite Onslaught',
|
||||||
displayname='${GAME}',
|
gametype=OnslaughtGame,
|
||||||
gametype=TheLastStandGame,
|
settings={'preset': 'endless_tournament'},
|
||||||
settings={'preset': 'tournament'},
|
preview_texture_name='doomShroomPreview'),
|
||||||
preview_texture_name='rampagePreview'))
|
Level('Tournament Infinite Runaround',
|
||||||
campaign.addlevel(
|
displayname='Infinite Runaround',
|
||||||
_level.Level('Tournament Infinite Onslaught',
|
gametype=RunaroundGame,
|
||||||
displayname='Infinite Onslaught',
|
settings={'preset': 'endless_tournament'},
|
||||||
gametype=OnslaughtGame,
|
preview_texture_name='towerDPreview'),
|
||||||
settings={'preset': 'endless_tournament'},
|
Level('Target Practice',
|
||||||
preview_texture_name='doomShroomPreview'))
|
displayname='Pro ${GAME}',
|
||||||
campaign.addlevel(
|
gametype=TargetPracticeGame,
|
||||||
_level.Level('Tournament Infinite Runaround',
|
settings={},
|
||||||
displayname='Infinite Runaround',
|
preview_texture_name='doomShroomPreview'),
|
||||||
gametype=RunaroundGame,
|
Level('Target Practice B',
|
||||||
settings={'preset': 'endless_tournament'},
|
displayname='${GAME}',
|
||||||
preview_texture_name='towerDPreview'))
|
gametype=TargetPracticeGame,
|
||||||
campaign.addlevel(
|
settings={
|
||||||
_level.Level('Target Practice',
|
'Target Count': 2,
|
||||||
displayname='Pro ${GAME}',
|
'Enable Impact Bombs': False,
|
||||||
gametype=TargetPracticeGame,
|
'Enable Triple Bombs': False
|
||||||
settings={},
|
},
|
||||||
preview_texture_name='doomShroomPreview'))
|
preview_texture_name='doomShroomPreview'),
|
||||||
campaign.addlevel(
|
Level('Meteor Shower',
|
||||||
_level.Level('Target Practice B',
|
displayname='${GAME}',
|
||||||
displayname='${GAME}',
|
gametype=MeteorShowerGame,
|
||||||
gametype=TargetPracticeGame,
|
settings={},
|
||||||
settings={
|
preview_texture_name='rampagePreview'),
|
||||||
'Target Count': 2,
|
Level('Epic Meteor Shower',
|
||||||
'Enable Impact Bombs': False,
|
displayname='${GAME}',
|
||||||
'Enable Triple Bombs': False
|
gametype=MeteorShowerGame,
|
||||||
},
|
settings={'Epic Mode': True},
|
||||||
preview_texture_name='doomShroomPreview'))
|
preview_texture_name='rampagePreview'),
|
||||||
campaign.addlevel(
|
Level('Easter Egg Hunt',
|
||||||
_level.Level('Meteor Shower',
|
displayname='${GAME}',
|
||||||
displayname='${GAME}',
|
gametype=EasterEggHuntGame,
|
||||||
gametype=MeteorShowerGame,
|
settings={},
|
||||||
settings={},
|
preview_texture_name='towerDPreview'),
|
||||||
preview_texture_name='rampagePreview'))
|
Level('Pro Easter Egg Hunt',
|
||||||
campaign.addlevel(
|
displayname='Pro ${GAME}',
|
||||||
_level.Level('Epic Meteor Shower',
|
gametype=EasterEggHuntGame,
|
||||||
displayname='${GAME}',
|
settings={'Pro Mode': True},
|
||||||
gametype=MeteorShowerGame,
|
preview_texture_name='towerDPreview'),
|
||||||
settings={'Epic Mode': True},
|
Level(
|
||||||
preview_texture_name='rampagePreview'))
|
name='Ninja Fight', # (unique id not seen by player)
|
||||||
campaign.addlevel(
|
displayname='${GAME}', # (readable name seen by player)
|
||||||
_level.Level('Easter Egg Hunt',
|
gametype=NinjaFightGame,
|
||||||
displayname='${GAME}',
|
settings={'preset': 'regular'},
|
||||||
gametype=EasterEggHuntGame,
|
preview_texture_name='courtyardPreview'),
|
||||||
settings={},
|
Level(name='Pro Ninja Fight',
|
||||||
preview_texture_name='towerDPreview'))
|
displayname='Pro ${GAME}',
|
||||||
campaign.addlevel(
|
gametype=NinjaFightGame,
|
||||||
_level.Level('Pro Easter Egg Hunt',
|
settings={'preset': 'pro'},
|
||||||
displayname='Pro ${GAME}',
|
preview_texture_name='courtyardPreview')
|
||||||
gametype=EasterEggHuntGame,
|
],
|
||||||
settings={'Pro Mode': True},
|
))
|
||||||
preview_texture_name='towerDPreview'))
|
|
||||||
campaign.addlevel(
|
|
||||||
_level.Level(
|
|
||||||
name='Ninja Fight', # (unique id not seen by player)
|
|
||||||
displayname='${GAME}', # (readable name seen by player)
|
|
||||||
gametype=NinjaFightGame,
|
|
||||||
settings={'preset': 'regular'},
|
|
||||||
preview_texture_name='courtyardPreview'))
|
|
||||||
campaign.addlevel(
|
|
||||||
_level.Level(name='Pro Ninja Fight',
|
|
||||||
displayname='Pro ${GAME}',
|
|
||||||
gametype=NinjaFightGame,
|
|
||||||
settings={'preset': 'pro'},
|
|
||||||
preview_texture_name='courtyardPreview'))
|
|
||||||
register_campaign(campaign)
|
|
||||||
|
|
|
||||||
8
dist/ba_data/python/ba/_cloud.py
vendored
8
dist/ba_data/python/ba/_cloud.py
vendored
|
|
@ -56,6 +56,14 @@ class CloudSubsystem:
|
||||||
) -> None:
|
) -> None:
|
||||||
...
|
...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def send_message_cb(
|
||||||
|
self,
|
||||||
|
msg: bacommon.cloud.PingMessage,
|
||||||
|
on_response: Callable[[bacommon.cloud.PingResponse | Exception], None],
|
||||||
|
) -> None:
|
||||||
|
...
|
||||||
|
|
||||||
def send_message_cb(
|
def send_message_cb(
|
||||||
self,
|
self,
|
||||||
msg: Message,
|
msg: Message,
|
||||||
|
|
|
||||||
6
dist/ba_data/python/ba/_hooks.py
vendored
6
dist/ba_data/python/ba/_hooks.py
vendored
|
|
@ -204,6 +204,12 @@ def no_game_circle_message() -> None:
|
||||||
_ba.screenmessage(Lstr(resource='noGameCircleText'), color=(1, 0, 0))
|
_ba.screenmessage(Lstr(resource='noGameCircleText'), color=(1, 0, 0))
|
||||||
|
|
||||||
|
|
||||||
|
def google_play_purchases_not_available_message() -> None:
|
||||||
|
from ba._language import Lstr
|
||||||
|
_ba.screenmessage(Lstr(resource='googlePlayPurchasesNotAvailableText'),
|
||||||
|
color=(1, 0, 0))
|
||||||
|
|
||||||
|
|
||||||
def empty_call() -> None:
|
def empty_call() -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
||||||
20
dist/ba_data/python/ba/_meta.py
vendored
20
dist/ba_data/python/ba/_meta.py
vendored
|
|
@ -44,7 +44,7 @@ class MetadataSubsystem:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.metascan: ScanResults | None = None
|
self.scanresults: ScanResults | None = None
|
||||||
self.extra_scan_dirs: list[str] = []
|
self.extra_scan_dirs: list[str] = []
|
||||||
|
|
||||||
def on_app_running(self) -> None:
|
def on_app_running(self) -> None:
|
||||||
|
|
@ -58,7 +58,7 @@ class MetadataSubsystem:
|
||||||
|
|
||||||
Should be called only once at launch."""
|
Should be called only once at launch."""
|
||||||
app = _ba.app
|
app = _ba.app
|
||||||
if self.metascan is not None:
|
if self.scanresults is not None:
|
||||||
print('WARNING: meta scan run more than once.')
|
print('WARNING: meta scan run more than once.')
|
||||||
pythondirs = ([app.python_directory_app, app.python_directory_user] +
|
pythondirs = ([app.python_directory_app, app.python_directory_user] +
|
||||||
self.extra_scan_dirs)
|
self.extra_scan_dirs)
|
||||||
|
|
@ -133,7 +133,7 @@ class MetadataSubsystem:
|
||||||
|
|
||||||
def get_scan_results(self) -> ScanResults:
|
def get_scan_results(self) -> ScanResults:
|
||||||
"""Return meta scan results; block if the scan is not yet complete."""
|
"""Return meta scan results; block if the scan is not yet complete."""
|
||||||
if self.metascan is None:
|
if self.scanresults is None:
|
||||||
print('WARNING: ba.meta.get_scan_results()'
|
print('WARNING: ba.meta.get_scan_results()'
|
||||||
' called before scan completed.'
|
' called before scan completed.'
|
||||||
' This can cause hitches.')
|
' This can cause hitches.')
|
||||||
|
|
@ -141,12 +141,12 @@ class MetadataSubsystem:
|
||||||
# Now wait a bit for the scan to complete.
|
# Now wait a bit for the scan to complete.
|
||||||
# Eventually error though if it doesn't.
|
# Eventually error though if it doesn't.
|
||||||
starttime = time.time()
|
starttime = time.time()
|
||||||
while self.metascan is None:
|
while self.scanresults is None:
|
||||||
time.sleep(0.05)
|
time.sleep(0.05)
|
||||||
if time.time() - starttime > 10.0:
|
if time.time() - starttime > 10.0:
|
||||||
raise TimeoutError(
|
raise TimeoutError(
|
||||||
'timeout waiting for meta scan to complete.')
|
'timeout waiting for meta scan to complete.')
|
||||||
return self.metascan
|
return self.scanresults
|
||||||
|
|
||||||
def get_game_types(self) -> list[type[ba.GameActivity]]:
|
def get_game_types(self) -> list[type[ba.GameActivity]]:
|
||||||
"""Return available game types."""
|
"""Return available game types."""
|
||||||
|
|
@ -206,7 +206,7 @@ class ScanThread(threading.Thread):
|
||||||
# We also, however, immediately make results available.
|
# We also, however, immediately make results available.
|
||||||
# This is because the game thread may be blocked waiting
|
# This is because the game thread may be blocked waiting
|
||||||
# for them so we can't push a call or we'd get deadlock.
|
# for them so we can't push a call or we'd get deadlock.
|
||||||
_ba.app.meta.metascan = results
|
_ba.app.meta.scanresults = results
|
||||||
|
|
||||||
|
|
||||||
class DirectoryScan:
|
class DirectoryScan:
|
||||||
|
|
@ -288,7 +288,7 @@ class DirectoryScan:
|
||||||
|
|
||||||
# If we find a module requiring a different api version, warn
|
# If we find a module requiring a different api version, warn
|
||||||
# and ignore.
|
# and ignore.
|
||||||
if required_api is not None and required_api < CURRENT_API_VERSION:
|
if required_api is not None and required_api <= CURRENT_API_VERSION:
|
||||||
self.results.warnings += (
|
self.results.warnings += (
|
||||||
f'Warning: {subpath} requires api {required_api} but'
|
f'Warning: {subpath} requires api {required_api} but'
|
||||||
f' we are running {CURRENT_API_VERSION}; ignoring module.\n')
|
f' we are running {CURRENT_API_VERSION}; ignoring module.\n')
|
||||||
|
|
@ -403,13 +403,13 @@ class DirectoryScan:
|
||||||
if len(lines) > 1:
|
if len(lines) > 1:
|
||||||
self.results.warnings += (
|
self.results.warnings += (
|
||||||
'Warning: ' + str(subpath) +
|
'Warning: ' + str(subpath) +
|
||||||
': multiple "# ba_meta api require <NUM>" lines found;'
|
': multiple "# ba_meta require api <NUM>" lines found;'
|
||||||
' ignoring module.\n')
|
' ignoring module.\n')
|
||||||
elif not lines and toplevel and meta_lines:
|
elif not lines and toplevel and meta_lines:
|
||||||
# If we're a top-level module containing meta lines but
|
# If we're a top-level module containing meta lines but
|
||||||
# no valid api require, complain.
|
# no valid "require api" line found, complain.
|
||||||
self.results.warnings += (
|
self.results.warnings += (
|
||||||
'Warning: ' + str(subpath) +
|
'Warning: ' + str(subpath) +
|
||||||
': no valid "# ba_meta api require <NUM>" line found;'
|
': no valid "# ba_meta require api <NUM>" line found;'
|
||||||
' ignoring module.\n')
|
' ignoring module.\n')
|
||||||
return None
|
return None
|
||||||
|
|
|
||||||
2
dist/ba_data/python/ba/_music.py
vendored
2
dist/ba_data/python/ba/_music.py
vendored
|
|
@ -211,7 +211,7 @@ class MusicSubsystem:
|
||||||
return 'Mac' in uas
|
return 'Mac' in uas
|
||||||
if entry_type in ('musicFile', 'musicFolder'):
|
if entry_type in ('musicFile', 'musicFolder'):
|
||||||
return ('android' in uas
|
return ('android' in uas
|
||||||
and _ba.android_get_external_storage_path() is not None)
|
and _ba.android_get_external_files_dir() is not None)
|
||||||
if entry_type == 'default':
|
if entry_type == 'default':
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
|
||||||
62
dist/ba_data/python/ba/_net.py
vendored
62
dist/ba_data/python/ba/_net.py
vendored
|
|
@ -3,6 +3,7 @@
|
||||||
"""Networking related functionality."""
|
"""Networking related functionality."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import ssl
|
||||||
import copy
|
import copy
|
||||||
import threading
|
import threading
|
||||||
import weakref
|
import weakref
|
||||||
|
|
@ -29,14 +30,32 @@ class NetworkSubsystem:
|
||||||
# as it is updated by a background thread.
|
# as it is updated by a background thread.
|
||||||
self.zone_pings_lock = threading.Lock()
|
self.zone_pings_lock = threading.Lock()
|
||||||
|
|
||||||
# Region IDs mapped to average pings. This will remain empty
|
# Zone IDs mapped to average pings. This will remain empty
|
||||||
# until enough pings have been run to be reasonably certain
|
# until enough pings have been run to be reasonably certain
|
||||||
# that a nearby server has been pinged.
|
# that a nearby server has been pinged.
|
||||||
self.zone_pings: dict[str, float] = {}
|
self.zone_pings: dict[str, float] = {}
|
||||||
|
|
||||||
|
self._sslcontext: ssl.SSLContext | None = None
|
||||||
|
|
||||||
# For debugging.
|
# For debugging.
|
||||||
self.v1_test_log: str = ''
|
self.v1_test_log: str = ''
|
||||||
self.v1_ctest_results: dict[int, str] = {}
|
self.v1_ctest_results: dict[int, str] = {}
|
||||||
|
self.server_time_offset_hours: float | None = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sslcontext(self) -> ssl.SSLContext:
|
||||||
|
"""Create/return our shared SSLContext.
|
||||||
|
|
||||||
|
This can be reused for all standard urllib requests/etc.
|
||||||
|
"""
|
||||||
|
# Note: I've run into older Android devices taking upwards of 1 second
|
||||||
|
# to put together a default SSLContext, so recycling one can definitely
|
||||||
|
# be a worthwhile optimization. This was suggested to me in this
|
||||||
|
# thread by one of Python's SSL maintainers:
|
||||||
|
# https://github.com/python/cpython/issues/94637
|
||||||
|
if self._sslcontext is None:
|
||||||
|
self._sslcontext = ssl.create_default_context()
|
||||||
|
return self._sslcontext
|
||||||
|
|
||||||
|
|
||||||
def get_ip_address_type(addr: str) -> socket.AddressFamily:
|
def get_ip_address_type(addr: str) -> socket.AddressFamily:
|
||||||
|
|
@ -108,30 +127,36 @@ class MasterServerCallThread(threading.Thread):
|
||||||
self._callback(arg)
|
self._callback(arg)
|
||||||
|
|
||||||
def run(self) -> None:
|
def run(self) -> None:
|
||||||
# pylint: disable=too-many-branches, consider-using-with
|
# pylint: disable=consider-using-with
|
||||||
import urllib.request
|
import urllib.request
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
import urllib.error
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from efro.error import is_urllib_network_error
|
from efro.error import is_urllib_communication_error
|
||||||
from ba import _general
|
from ba import _general
|
||||||
|
|
||||||
|
response_data: Any = None
|
||||||
|
url: str | None = None
|
||||||
try:
|
try:
|
||||||
self._data = _general.utf8_all(self._data)
|
self._data = _general.utf8_all(self._data)
|
||||||
_ba.set_thread_name('BA_ServerCallThread')
|
_ba.set_thread_name('BA_ServerCallThread')
|
||||||
if self._request_type == 'get':
|
if self._request_type == 'get':
|
||||||
|
url = (_ba.get_master_server_address() + '/' + self._request +
|
||||||
|
'?' + urllib.parse.urlencode(self._data))
|
||||||
response = urllib.request.urlopen(
|
response = urllib.request.urlopen(
|
||||||
urllib.request.Request(
|
urllib.request.Request(
|
||||||
(_ba.get_master_server_address() + '/' +
|
url, None, {'User-Agent': _ba.app.user_agent_string}),
|
||||||
self._request + '?' +
|
context=_ba.app.net.sslcontext,
|
||||||
urllib.parse.urlencode(self._data)), None,
|
|
||||||
{'User-Agent': _ba.app.user_agent_string}),
|
|
||||||
timeout=DEFAULT_REQUEST_TIMEOUT_SECONDS)
|
timeout=DEFAULT_REQUEST_TIMEOUT_SECONDS)
|
||||||
elif self._request_type == 'post':
|
elif self._request_type == 'post':
|
||||||
|
url = _ba.get_master_server_address() + '/' + self._request
|
||||||
response = urllib.request.urlopen(
|
response = urllib.request.urlopen(
|
||||||
urllib.request.Request(
|
urllib.request.Request(
|
||||||
_ba.get_master_server_address() + '/' + self._request,
|
url,
|
||||||
urllib.parse.urlencode(self._data).encode(),
|
urllib.parse.urlencode(self._data).encode(),
|
||||||
{'User-Agent': _ba.app.user_agent_string}),
|
{'User-Agent': _ba.app.user_agent_string}),
|
||||||
|
context=_ba.app.net.sslcontext,
|
||||||
timeout=DEFAULT_REQUEST_TIMEOUT_SECONDS)
|
timeout=DEFAULT_REQUEST_TIMEOUT_SECONDS)
|
||||||
else:
|
else:
|
||||||
raise TypeError('Invalid request_type: ' + self._request_type)
|
raise TypeError('Invalid request_type: ' + self._request_type)
|
||||||
|
|
@ -151,29 +176,18 @@ class MasterServerCallThread(threading.Thread):
|
||||||
raise TypeError(f'invalid responsetype: {self._response_type}')
|
raise TypeError(f'invalid responsetype: {self._response_type}')
|
||||||
|
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
do_print = False
|
|
||||||
response_data = None
|
|
||||||
|
|
||||||
# Ignore common network errors; note unexpected ones.
|
# Ignore common network errors; note unexpected ones.
|
||||||
if is_urllib_network_error(exc):
|
if not is_urllib_communication_error(exc, url=url):
|
||||||
pass
|
|
||||||
elif (self._response_type == MasterServerResponseType.JSON
|
|
||||||
and isinstance(exc, json.decoder.JSONDecodeError)):
|
|
||||||
# FIXME: should handle this better; could mean either the
|
|
||||||
# server sent us bad data or it got corrupted along the way.
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
do_print = True
|
|
||||||
|
|
||||||
if do_print:
|
|
||||||
# Any other error here is unexpected,
|
|
||||||
# so let's make a note of it,
|
|
||||||
print(f'Error in MasterServerCallThread'
|
print(f'Error in MasterServerCallThread'
|
||||||
f' (response-type={self._response_type},'
|
f' (url={url},'
|
||||||
|
f' response-type={self._response_type},'
|
||||||
f' response-data={response_data}):')
|
f' response-data={response_data}):')
|
||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
|
response_data = None
|
||||||
|
|
||||||
if self._callback is not None:
|
if self._callback is not None:
|
||||||
_ba.pushcall(_general.Call(self._run_callback, response_data),
|
_ba.pushcall(_general.Call(self._run_callback, response_data),
|
||||||
from_other_thread=True)
|
from_other_thread=True)
|
||||||
|
|
|
||||||
12
dist/ba_data/python/ba/_plugin.py
vendored
12
dist/ba_data/python/ba/_plugin.py
vendored
|
|
@ -112,13 +112,15 @@ class PluginSubsystem:
|
||||||
# or workspaces.
|
# or workspaces.
|
||||||
if disappeared_plugs:
|
if disappeared_plugs:
|
||||||
_ba.playsound(_ba.getsound('shieldDown'))
|
_ba.playsound(_ba.getsound('shieldDown'))
|
||||||
_ba.screenmessage(Lstr(resource='pluginsRemovedText',
|
_ba.screenmessage(
|
||||||
subs=[('${NUM}',
|
Lstr(resource='pluginsRemovedText',
|
||||||
str(len(disappeared_plugs)))]),
|
subs=[('${NUM}', str(len(disappeared_plugs)))]),
|
||||||
color=(1, 1, 0))
|
color=(1, 1, 0),
|
||||||
|
)
|
||||||
|
plugnames = ', '.join(disappeared_plugs)
|
||||||
_ba.log(
|
_ba.log(
|
||||||
f'{len(disappeared_plugs)} plugin(s) no longer found:'
|
f'{len(disappeared_plugs)} plugin(s) no longer found:'
|
||||||
f' {disappeared_plugs}',
|
f' {plugnames}.',
|
||||||
to_server=False)
|
to_server=False)
|
||||||
for goneplug in disappeared_plugs:
|
for goneplug in disappeared_plugs:
|
||||||
del _ba.app.config['Plugins'][goneplug]
|
del _ba.app.config['Plugins'][goneplug]
|
||||||
|
|
|
||||||
2
dist/ba_data/python/ba/_workspace.py
vendored
2
dist/ba_data/python/ba/_workspace.py
vendored
|
|
@ -115,7 +115,7 @@ class WorkspaceSubsystem:
|
||||||
tpartial(
|
tpartial(
|
||||||
self._errmsg,
|
self._errmsg,
|
||||||
Lstr(resource='workspaceSyncReuseText',
|
Lstr(resource='workspaceSyncReuseText',
|
||||||
subs=[('$WORKSPACE', workspacename)])),
|
subs=[('${WORKSPACE}', workspacename)])),
|
||||||
from_other_thread=True,
|
from_other_thread=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
28
dist/ba_data/python/ba/modutils.py
vendored
28
dist/ba_data/python/ba/modutils.py
vendored
|
|
@ -17,23 +17,29 @@ def get_human_readable_user_scripts_path() -> str:
|
||||||
|
|
||||||
This is NOT a valid filesystem path; may be something like "(SD Card)".
|
This is NOT a valid filesystem path; may be something like "(SD Card)".
|
||||||
"""
|
"""
|
||||||
from ba import _language
|
|
||||||
app = _ba.app
|
app = _ba.app
|
||||||
path: str | None = app.python_directory_user
|
path: str | None = app.python_directory_user
|
||||||
if path is None:
|
if path is None:
|
||||||
return '<Not Available>'
|
return '<Not Available>'
|
||||||
|
|
||||||
# On newer versions of android, the user's external storage dir is probably
|
# These days, on Android, we use getExternalFilesDir() as the base of our
|
||||||
# only visible to the user's processes and thus not really useful printed
|
# app's user-scripts dir, which gives us paths like:
|
||||||
# in its entirety; lets print it as <External Storage>/myfilepath.
|
# /storage/emulated/0/Android/data/net.froemling.bombsquad/files
|
||||||
|
# Userspace apps tend to show that as:
|
||||||
|
# Android/data/net.froemling.bombsquad/files
|
||||||
|
# We'd like to display it that way, but I'm not sure if there's a clean
|
||||||
|
# way to get the root of the external storage area (/storage/emulated/0)
|
||||||
|
# so that we could strip it off. There is
|
||||||
|
# Environment.getExternalStorageDirectory() but that is deprecated.
|
||||||
|
# So for now let's just be conservative and trim off recognized prefixes
|
||||||
|
# and show the whole ugly path as a fallback.
|
||||||
|
# Note that we used to use externalStorageText resource but gonna try
|
||||||
|
# without it for now. (simply 'foo' instead of <External Storage>/foo).
|
||||||
if app.platform == 'android':
|
if app.platform == 'android':
|
||||||
ext_storage_path: str | None = (
|
for pre in ['/storage/emulated/0/']:
|
||||||
_ba.android_get_external_storage_path())
|
if path.startswith(pre):
|
||||||
if (ext_storage_path is not None
|
path = path.removeprefix(pre)
|
||||||
and app.python_directory_user.startswith(ext_storage_path)):
|
break
|
||||||
path = ('<' +
|
|
||||||
_language.Lstr(resource='externalStorageText').evaluate() +
|
|
||||||
'>' + app.python_directory_user[len(ext_storage_path):])
|
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
2
dist/ba_data/python/bacommon/bacloud.py
vendored
2
dist/ba_data/python/bacommon/bacloud.py
vendored
|
|
@ -14,7 +14,7 @@ if TYPE_CHECKING:
|
||||||
|
|
||||||
# Version is sent to the master-server with all commands. Can be incremented
|
# Version is sent to the master-server with all commands. Can be incremented
|
||||||
# if we need to change behavior server-side to go along with client changes.
|
# if we need to change behavior server-side to go along with client changes.
|
||||||
BACLOUD_VERSION = 6
|
BACLOUD_VERSION = 7
|
||||||
|
|
||||||
|
|
||||||
@ioprepped
|
@ioprepped
|
||||||
|
|
|
||||||
16
dist/ba_data/python/bacommon/cloud.py
vendored
16
dist/ba_data/python/bacommon/cloud.py
vendored
|
|
@ -76,6 +76,22 @@ class LoginProxyCompleteMessage(Message):
|
||||||
proxyid: Annotated[str, IOAttrs('p')]
|
proxyid: Annotated[str, IOAttrs('p')]
|
||||||
|
|
||||||
|
|
||||||
|
@ioprepped
|
||||||
|
@dataclass
|
||||||
|
class PingMessage(Message):
|
||||||
|
"""Standard ping."""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_response_types(cls) -> list[type[Response]]:
|
||||||
|
return [PingResponse]
|
||||||
|
|
||||||
|
|
||||||
|
@ioprepped
|
||||||
|
@dataclass
|
||||||
|
class PingResponse(Response):
|
||||||
|
"""pong."""
|
||||||
|
|
||||||
|
|
||||||
@ioprepped
|
@ioprepped
|
||||||
@dataclass
|
@dataclass
|
||||||
class TestMessage(Message):
|
class TestMessage(Message):
|
||||||
|
|
|
||||||
4
dist/ba_data/python/bacommon/net.py
vendored
4
dist/ba_data/python/bacommon/net.py
vendored
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import datetime
|
||||||
from typing import TYPE_CHECKING, Any, Annotated
|
from typing import TYPE_CHECKING, Any, Annotated
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
|
|
@ -27,6 +28,9 @@ class ServerNodeEntry:
|
||||||
class ServerNodeQueryResponse:
|
class ServerNodeQueryResponse:
|
||||||
"""A response to a query about server-nodes."""
|
"""A response to a query about server-nodes."""
|
||||||
|
|
||||||
|
# The current utc time on the master server.
|
||||||
|
time: Annotated[datetime.datetime, IOAttrs('t')]
|
||||||
|
|
||||||
# If present, something went wrong, and this describes it.
|
# If present, something went wrong, and this describes it.
|
||||||
error: Annotated[str | None, IOAttrs('e', store_default=False)] = None
|
error: Annotated[str | None, IOAttrs('e', store_default=False)] = None
|
||||||
|
|
||||||
|
|
|
||||||
23
dist/ba_data/python/bacommon/transfer.py
vendored
23
dist/ba_data/python/bacommon/transfer.py
vendored
|
|
@ -5,13 +5,14 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
from pathlib import Path
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import TYPE_CHECKING, Annotated
|
from typing import TYPE_CHECKING, Annotated
|
||||||
|
|
||||||
from efro.dataclassio import ioprepped, IOAttrs
|
from efro.dataclassio import ioprepped, IOAttrs
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from pathlib import Path
|
pass
|
||||||
|
|
||||||
|
|
||||||
@ioprepped
|
@ioprepped
|
||||||
|
|
@ -40,15 +41,17 @@ class DirectoryManifest:
|
||||||
paths: list[str] = []
|
paths: list[str] = []
|
||||||
|
|
||||||
if path.is_dir():
|
if path.is_dir():
|
||||||
# Build the full list of package-relative paths.
|
# Build the full list of relative paths.
|
||||||
for basename, _dirnames, filenames in os.walk(path):
|
for basename, _dirnames, filenames in os.walk(path):
|
||||||
for filename in filenames:
|
for filename in filenames:
|
||||||
fullname = os.path.join(basename, filename)
|
fullname = os.path.join(basename, filename)
|
||||||
assert fullname.startswith(pathstr)
|
assert fullname.startswith(pathstr)
|
||||||
paths.append(fullname[len(pathstr) + 1:])
|
# Make sure we end up with forward slashes no matter
|
||||||
|
# what the os.* stuff above here was using.
|
||||||
|
paths.append(Path(fullname[len(pathstr) + 1:]).as_posix())
|
||||||
elif path.exists():
|
elif path.exists():
|
||||||
# Just return a single file entry if path is not a dir.
|
# Just return a single file entry if path is not a dir.
|
||||||
paths.append(pathstr)
|
paths.append(path.as_posix())
|
||||||
|
|
||||||
def _get_file_info(filepath: str) -> tuple[str, DirectoryManifestFile]:
|
def _get_file_info(filepath: str) -> tuple[str, DirectoryManifestFile]:
|
||||||
sha = hashlib.sha256()
|
sha = hashlib.sha256()
|
||||||
|
|
@ -70,6 +73,18 @@ class DirectoryManifest:
|
||||||
with ThreadPoolExecutor(max_workers=cpus) as executor:
|
with ThreadPoolExecutor(max_workers=cpus) as executor:
|
||||||
return cls(files=dict(executor.map(_get_file_info, paths)))
|
return cls(files=dict(executor.map(_get_file_info, paths)))
|
||||||
|
|
||||||
|
def validate(self) -> None:
|
||||||
|
"""Log any odd data in the manifest; for debugging."""
|
||||||
|
import logging
|
||||||
|
for fpath, _fentry in self.files.items():
|
||||||
|
# We want to be dealing in only forward slashes; make sure
|
||||||
|
# that's the case (wondering if we'll ever see backslashes
|
||||||
|
# for escape purposes).
|
||||||
|
if '\\' in fpath:
|
||||||
|
logging.exception("Found unusual path in manifest: '%s'.",
|
||||||
|
fpath)
|
||||||
|
break # 1 error is enough for now.
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_empty_hash(cls) -> str:
|
def get_empty_hash(cls) -> str:
|
||||||
"""Return the hash for an empty file."""
|
"""Return the hash for an empty file."""
|
||||||
|
|
|
||||||
2
dist/ba_data/python/bastd/actor/spaz.py
vendored
2
dist/ba_data/python/bastd/actor/spaz.py
vendored
|
|
@ -606,6 +606,7 @@ class Spaz(ba.Actor):
|
||||||
"""
|
"""
|
||||||
assert self.node
|
assert self.node
|
||||||
self.node.boxing_gloves = True
|
self.node.boxing_gloves = True
|
||||||
|
self._has_boxing_gloves = True
|
||||||
if self._demo_mode: # Preserve old behavior.
|
if self._demo_mode: # Preserve old behavior.
|
||||||
self._punch_power_scale = 1.7
|
self._punch_power_scale = 1.7
|
||||||
self._punch_cooldown = 300
|
self._punch_cooldown = 300
|
||||||
|
|
@ -754,7 +755,6 @@ class Spaz(ba.Actor):
|
||||||
ba.WeakCall(self._bomb_wear_off),
|
ba.WeakCall(self._bomb_wear_off),
|
||||||
timeformat=ba.TimeFormat.MILLISECONDS))
|
timeformat=ba.TimeFormat.MILLISECONDS))
|
||||||
elif msg.poweruptype == 'punch':
|
elif msg.poweruptype == 'punch':
|
||||||
self._has_boxing_gloves = True
|
|
||||||
tex = PowerupBoxFactory.get().tex_punch
|
tex = PowerupBoxFactory.get().tex_punch
|
||||||
self._flash_billboard(tex)
|
self._flash_billboard(tex)
|
||||||
self.equip_boxing_gloves()
|
self.equip_boxing_gloves()
|
||||||
|
|
|
||||||
3
dist/ba_data/python/bastd/game/onslaught.py
vendored
3
dist/ba_data/python/bastd/game/onslaught.py
vendored
|
|
@ -5,6 +5,9 @@
|
||||||
# Yes this is a long one..
|
# Yes this is a long one..
|
||||||
# pylint: disable=too-many-lines
|
# pylint: disable=too-many-lines
|
||||||
|
|
||||||
|
# ba_meta require api 7
|
||||||
|
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
|
|
||||||
3
dist/ba_data/python/bastd/game/runaround.py
vendored
3
dist/ba_data/python/bastd/game/runaround.py
vendored
|
|
@ -5,6 +5,9 @@
|
||||||
# We wear the cone of shame.
|
# We wear the cone of shame.
|
||||||
# pylint: disable=too-many-lines
|
# pylint: disable=too-many-lines
|
||||||
|
|
||||||
|
# ba_meta require api 7
|
||||||
|
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import random
|
import random
|
||||||
|
|
|
||||||
799
dist/ba_data/python/bastd/ui/coop/browser.py
vendored
799
dist/ba_data/python/bastd/ui/coop/browser.py
vendored
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import copy
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import _ba
|
import _ba
|
||||||
|
|
@ -18,6 +17,8 @@ from bastd.ui.store.browser import StoreBrowserWindow
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
from bastd.ui.coop.tournamentbutton import TournamentButton
|
||||||
|
|
||||||
|
|
||||||
class CoopBrowserWindow(ba.Window):
|
class CoopBrowserWindow(ba.Window):
|
||||||
"""Window for browsing co-op levels/games/etc."""
|
"""Window for browsing co-op levels/games/etc."""
|
||||||
|
|
@ -175,8 +176,6 @@ class CoopBrowserWindow(ba.Window):
|
||||||
'Selected Coop Campaign Level', None))
|
'Selected Coop Campaign Level', None))
|
||||||
self._selected_custom_level = (cfg.get('Selected Coop Custom Level',
|
self._selected_custom_level = (cfg.get('Selected Coop Custom Level',
|
||||||
None))
|
None))
|
||||||
self._selected_challenge_level = (cfg.get(
|
|
||||||
'Selected Coop Challenge Level', None))
|
|
||||||
|
|
||||||
# Don't want initial construction affecting our last-selected.
|
# Don't want initial construction affecting our last-selected.
|
||||||
self._do_selection_callbacks = False
|
self._do_selection_callbacks = False
|
||||||
|
|
@ -283,6 +282,7 @@ class CoopBrowserWindow(ba.Window):
|
||||||
import bastd.ui.tournamentscores as _unused8
|
import bastd.ui.tournamentscores as _unused8
|
||||||
import bastd.ui.tournamententry as _unused9
|
import bastd.ui.tournamententry as _unused9
|
||||||
import bastd.ui.play as _unused10
|
import bastd.ui.play as _unused10
|
||||||
|
import bastd.ui.coop.tournamentbutton as _unused11
|
||||||
|
|
||||||
def _update(self) -> None:
|
def _update(self) -> None:
|
||||||
# Do nothing if we've somehow outlived our actual UI.
|
# Do nothing if we've somehow outlived our actual UI.
|
||||||
|
|
@ -335,21 +335,21 @@ class CoopBrowserWindow(ba.Window):
|
||||||
# Decrement time on our tournament buttons.
|
# Decrement time on our tournament buttons.
|
||||||
ads_enabled = _ba.have_incentivized_ad()
|
ads_enabled = _ba.have_incentivized_ad()
|
||||||
for tbtn in self._tournament_buttons:
|
for tbtn in self._tournament_buttons:
|
||||||
tbtn['time_remaining'] = max(0, tbtn['time_remaining'] - 1)
|
tbtn.time_remaining = max(0, tbtn.time_remaining - 1)
|
||||||
if tbtn['time_remaining_value_text'] is not None:
|
if tbtn.time_remaining_value_text is not None:
|
||||||
ba.textwidget(
|
ba.textwidget(
|
||||||
edit=tbtn['time_remaining_value_text'],
|
edit=tbtn.time_remaining_value_text,
|
||||||
text=ba.timestring(tbtn['time_remaining'],
|
text=ba.timestring(tbtn.time_remaining,
|
||||||
centi=False,
|
centi=False,
|
||||||
suppress_format_warning=True) if
|
suppress_format_warning=True) if
|
||||||
(tbtn['has_time_remaining']
|
(tbtn.has_time_remaining
|
||||||
and self._tourney_data_up_to_date) else '-')
|
and self._tourney_data_up_to_date) else '-')
|
||||||
|
|
||||||
# Also adjust the ad icon visibility.
|
# Also adjust the ad icon visibility.
|
||||||
if tbtn.get('allow_ads', False) and _ba.has_video_ads():
|
if tbtn.allow_ads and _ba.has_video_ads():
|
||||||
ba.imagewidget(edit=tbtn['entry_fee_ad_image'],
|
ba.imagewidget(edit=tbtn.entry_fee_ad_image,
|
||||||
opacity=1.0 if ads_enabled else 0.25)
|
opacity=1.0 if ads_enabled else 0.25)
|
||||||
ba.textwidget(edit=tbtn['entry_fee_text_remaining'],
|
ba.textwidget(edit=tbtn.entry_fee_text_remaining,
|
||||||
color=(0.6, 0.6, 0.6, 1 if ads_enabled else 0.2))
|
color=(0.6, 0.6, 0.6, 1 if ads_enabled else 0.2))
|
||||||
|
|
||||||
self._update_hard_mode_lock_image()
|
self._update_hard_mode_lock_image()
|
||||||
|
|
@ -363,232 +363,21 @@ class CoopBrowserWindow(ba.Window):
|
||||||
ba.print_exception('Error updating campaign lock.')
|
ba.print_exception('Error updating campaign lock.')
|
||||||
|
|
||||||
def _update_for_data(self, data: list[dict[str, Any]] | None) -> None:
|
def _update_for_data(self, data: list[dict[str, Any]] | None) -> None:
|
||||||
# pylint: disable=too-many-statements
|
|
||||||
# pylint: disable=too-many-locals
|
|
||||||
# pylint: disable=too-many-branches
|
|
||||||
from ba.internal import getcampaign, get_tournament_prize_strings
|
|
||||||
|
|
||||||
# If the number of tournaments or challenges in the data differs from
|
# If the number of tournaments or challenges in the data differs from
|
||||||
# our current arrangement, refresh with the new number.
|
# our current arrangement, refresh with the new number.
|
||||||
if ((data is None and self._tournament_button_count != 0)
|
if ((data is None and self._tournament_button_count != 0)
|
||||||
or (data is not None and
|
or (data is not None and
|
||||||
(len(data) != self._tournament_button_count))):
|
(len(data) != self._tournament_button_count))):
|
||||||
self._tournament_button_count = len(
|
self._tournament_button_count = (len(data)
|
||||||
data) if data is not None else 0
|
if data is not None else 0)
|
||||||
ba.app.config['Tournament Rows'] = self._tournament_button_count
|
ba.app.config['Tournament Rows'] = self._tournament_button_count
|
||||||
self._refresh()
|
self._refresh()
|
||||||
|
|
||||||
# Update all of our tourney buttons based on whats in data.
|
# Update all of our tourney buttons based on whats in data.
|
||||||
for i, tbtn in enumerate(self._tournament_buttons):
|
for i, tbtn in enumerate(self._tournament_buttons):
|
||||||
assert data is not None
|
assert data is not None
|
||||||
entry: dict[str, Any] = data[i]
|
tbtn.update_for_data(data[i])
|
||||||
prize_y_offs = (34 if 'prizeRange3' in entry else
|
|
||||||
20 if 'prizeRange2' in entry else 12)
|
|
||||||
x_offs = 90
|
|
||||||
|
|
||||||
# This seems to be a false alarm.
|
|
||||||
# pylint: disable=unbalanced-tuple-unpacking
|
|
||||||
pr1, pv1, pr2, pv2, pr3, pv3 = (
|
|
||||||
get_tournament_prize_strings(entry))
|
|
||||||
# pylint: enable=unbalanced-tuple-unpacking
|
|
||||||
enabled = 'requiredLeague' not in entry
|
|
||||||
ba.buttonwidget(edit=tbtn['button'],
|
|
||||||
color=(0.5, 0.7, 0.2) if enabled else
|
|
||||||
(0.5, 0.5, 0.5))
|
|
||||||
ba.imagewidget(edit=tbtn['lock_image'],
|
|
||||||
opacity=0.0 if enabled else 1.0)
|
|
||||||
ba.textwidget(edit=tbtn['prize_range_1_text'],
|
|
||||||
text='-' if pr1 == '' else pr1,
|
|
||||||
position=(tbtn['button_x'] + 365 + x_offs,
|
|
||||||
tbtn['button_y'] + tbtn['button_scale_y'] -
|
|
||||||
93 + prize_y_offs))
|
|
||||||
|
|
||||||
# We want to draw values containing tickets a bit smaller
|
|
||||||
# (scratch that; we now draw medals a bit bigger).
|
|
||||||
ticket_char = ba.charstr(ba.SpecialChar.TICKET_BACKING)
|
|
||||||
prize_value_scale_large = 1.0
|
|
||||||
prize_value_scale_small = 1.0
|
|
||||||
|
|
||||||
ba.textwidget(edit=tbtn['prize_value_1_text'],
|
|
||||||
text='-' if pv1 == '' else pv1,
|
|
||||||
scale=prize_value_scale_large if ticket_char
|
|
||||||
not in pv1 else prize_value_scale_small,
|
|
||||||
position=(tbtn['button_x'] + 380 + x_offs,
|
|
||||||
tbtn['button_y'] + tbtn['button_scale_y'] -
|
|
||||||
93 + prize_y_offs))
|
|
||||||
|
|
||||||
ba.textwidget(edit=tbtn['prize_range_2_text'],
|
|
||||||
text=pr2,
|
|
||||||
position=(tbtn['button_x'] + 365 + x_offs,
|
|
||||||
tbtn['button_y'] + tbtn['button_scale_y'] -
|
|
||||||
93 - 45 + prize_y_offs))
|
|
||||||
ba.textwidget(edit=tbtn['prize_value_2_text'],
|
|
||||||
text=pv2,
|
|
||||||
scale=prize_value_scale_large if ticket_char
|
|
||||||
not in pv2 else prize_value_scale_small,
|
|
||||||
position=(tbtn['button_x'] + 380 + x_offs,
|
|
||||||
tbtn['button_y'] + tbtn['button_scale_y'] -
|
|
||||||
93 - 45 + prize_y_offs))
|
|
||||||
|
|
||||||
ba.textwidget(edit=tbtn['prize_range_3_text'],
|
|
||||||
text=pr3,
|
|
||||||
position=(tbtn['button_x'] + 365 + x_offs,
|
|
||||||
tbtn['button_y'] + tbtn['button_scale_y'] -
|
|
||||||
93 - 90 + prize_y_offs))
|
|
||||||
ba.textwidget(edit=tbtn['prize_value_3_text'],
|
|
||||||
text=pv3,
|
|
||||||
scale=prize_value_scale_large if ticket_char
|
|
||||||
not in pv3 else prize_value_scale_small,
|
|
||||||
position=(tbtn['button_x'] + 380 + x_offs,
|
|
||||||
tbtn['button_y'] + tbtn['button_scale_y'] -
|
|
||||||
93 - 90 + prize_y_offs))
|
|
||||||
|
|
||||||
leader_name = '-'
|
|
||||||
leader_score: str | ba.Lstr = '-'
|
|
||||||
if entry['scores']:
|
|
||||||
score = tbtn['leader'] = copy.deepcopy(entry['scores'][0])
|
|
||||||
leader_name = score[1]
|
|
||||||
leader_score = (ba.timestring(
|
|
||||||
score[0] * 10,
|
|
||||||
centi=True,
|
|
||||||
timeformat=ba.TimeFormat.MILLISECONDS,
|
|
||||||
suppress_format_warning=True) if entry['scoreType']
|
|
||||||
== 'time' else str(score[0]))
|
|
||||||
else:
|
|
||||||
tbtn['leader'] = None
|
|
||||||
|
|
||||||
ba.textwidget(edit=tbtn['current_leader_name_text'],
|
|
||||||
text=ba.Lstr(value=leader_name))
|
|
||||||
self._tournament_leader_score_type = (entry['scoreType'])
|
|
||||||
ba.textwidget(edit=tbtn['current_leader_score_text'],
|
|
||||||
text=leader_score)
|
|
||||||
ba.buttonwidget(edit=tbtn['more_scores_button'],
|
|
||||||
label=ba.Lstr(resource=self._r + '.seeMoreText'))
|
|
||||||
out_of_time_text: str | ba.Lstr = (
|
|
||||||
'-' if 'totalTime' not in entry else ba.Lstr(
|
|
||||||
resource=self._r + '.ofTotalTimeText',
|
|
||||||
subs=[('${TOTAL}',
|
|
||||||
ba.timestring(entry['totalTime'],
|
|
||||||
centi=False,
|
|
||||||
suppress_format_warning=True))]))
|
|
||||||
ba.textwidget(edit=tbtn['time_remaining_out_of_text'],
|
|
||||||
text=out_of_time_text)
|
|
||||||
|
|
||||||
tbtn['time_remaining'] = entry['timeRemaining']
|
|
||||||
tbtn['has_time_remaining'] = entry is not None
|
|
||||||
tbtn['tournament_id'] = entry['tournamentID']
|
|
||||||
tbtn['required_league'] = (None if 'requiredLeague' not in entry
|
|
||||||
else entry['requiredLeague'])
|
|
||||||
|
|
||||||
game = ba.app.accounts_v1.tournament_info[
|
|
||||||
tbtn['tournament_id']]['game']
|
|
||||||
|
|
||||||
if game is None:
|
|
||||||
ba.textwidget(edit=tbtn['button_text'], text='-')
|
|
||||||
ba.imagewidget(edit=tbtn['image'],
|
|
||||||
texture=ba.gettexture('black'),
|
|
||||||
opacity=0.2)
|
|
||||||
else:
|
|
||||||
campaignname, levelname = game.split(':')
|
|
||||||
campaign = getcampaign(campaignname)
|
|
||||||
max_players = ba.app.accounts_v1.tournament_info[
|
|
||||||
tbtn['tournament_id']]['maxPlayers']
|
|
||||||
txt = ba.Lstr(
|
|
||||||
value='${A} ${B}',
|
|
||||||
subs=[('${A}', campaign.getlevel(levelname).displayname),
|
|
||||||
('${B}',
|
|
||||||
ba.Lstr(resource='playerCountAbbreviatedText',
|
|
||||||
subs=[('${COUNT}', str(max_players))]))])
|
|
||||||
ba.textwidget(edit=tbtn['button_text'], text=txt)
|
|
||||||
ba.imagewidget(
|
|
||||||
edit=tbtn['image'],
|
|
||||||
texture=campaign.getlevel(levelname).get_preview_texture(),
|
|
||||||
opacity=1.0 if enabled else 0.5)
|
|
||||||
|
|
||||||
fee = entry['fee']
|
|
||||||
|
|
||||||
if fee is None:
|
|
||||||
fee_var = None
|
|
||||||
elif fee == 4:
|
|
||||||
fee_var = 'price.tournament_entry_4'
|
|
||||||
elif fee == 3:
|
|
||||||
fee_var = 'price.tournament_entry_3'
|
|
||||||
elif fee == 2:
|
|
||||||
fee_var = 'price.tournament_entry_2'
|
|
||||||
elif fee == 1:
|
|
||||||
fee_var = 'price.tournament_entry_1'
|
|
||||||
else:
|
|
||||||
if fee != 0:
|
|
||||||
print('Unknown fee value:', fee)
|
|
||||||
fee_var = 'price.tournament_entry_0'
|
|
||||||
|
|
||||||
tbtn['allow_ads'] = allow_ads = entry['allowAds']
|
|
||||||
|
|
||||||
final_fee: int | None = (None if fee_var is None else
|
|
||||||
_ba.get_v1_account_misc_read_val(
|
|
||||||
fee_var, '?'))
|
|
||||||
|
|
||||||
final_fee_str: str | ba.Lstr
|
|
||||||
if fee_var is None:
|
|
||||||
final_fee_str = ''
|
|
||||||
else:
|
|
||||||
if final_fee == 0:
|
|
||||||
final_fee_str = ba.Lstr(
|
|
||||||
resource='getTicketsWindow.freeText')
|
|
||||||
else:
|
|
||||||
final_fee_str = (
|
|
||||||
ba.charstr(ba.SpecialChar.TICKET_BACKING) +
|
|
||||||
str(final_fee))
|
|
||||||
|
|
||||||
ad_tries_remaining = ba.app.accounts_v1.tournament_info[
|
|
||||||
tbtn['tournament_id']]['adTriesRemaining']
|
|
||||||
free_tries_remaining = ba.app.accounts_v1.tournament_info[
|
|
||||||
tbtn['tournament_id']]['freeTriesRemaining']
|
|
||||||
|
|
||||||
# Now, if this fee allows ads and we support video ads, show
|
|
||||||
# the 'or ad' version.
|
|
||||||
if allow_ads and _ba.has_video_ads():
|
|
||||||
ads_enabled = _ba.have_incentivized_ad()
|
|
||||||
ba.imagewidget(edit=tbtn['entry_fee_ad_image'],
|
|
||||||
opacity=1.0 if ads_enabled else 0.25)
|
|
||||||
or_text = ba.Lstr(resource='orText',
|
|
||||||
subs=[('${A}', ''),
|
|
||||||
('${B}', '')]).evaluate().strip()
|
|
||||||
ba.textwidget(edit=tbtn['entry_fee_text_or'], text=or_text)
|
|
||||||
ba.textwidget(
|
|
||||||
edit=tbtn['entry_fee_text_top'],
|
|
||||||
position=(tbtn['button_x'] + 360,
|
|
||||||
tbtn['button_y'] + tbtn['button_scale_y'] - 60),
|
|
||||||
scale=1.3,
|
|
||||||
text=final_fee_str)
|
|
||||||
|
|
||||||
# Possibly show number of ad-plays remaining.
|
|
||||||
ba.textwidget(
|
|
||||||
edit=tbtn['entry_fee_text_remaining'],
|
|
||||||
position=(tbtn['button_x'] + 360,
|
|
||||||
tbtn['button_y'] + tbtn['button_scale_y'] - 146),
|
|
||||||
text='' if ad_tries_remaining in [None, 0] else
|
|
||||||
('' + str(ad_tries_remaining)),
|
|
||||||
color=(0.6, 0.6, 0.6, 1 if ads_enabled else 0.2))
|
|
||||||
else:
|
|
||||||
ba.imagewidget(edit=tbtn['entry_fee_ad_image'], opacity=0.0)
|
|
||||||
ba.textwidget(edit=tbtn['entry_fee_text_or'], text='')
|
|
||||||
ba.textwidget(
|
|
||||||
edit=tbtn['entry_fee_text_top'],
|
|
||||||
position=(tbtn['button_x'] + 360,
|
|
||||||
tbtn['button_y'] + tbtn['button_scale_y'] - 80),
|
|
||||||
scale=1.3,
|
|
||||||
text=final_fee_str)
|
|
||||||
|
|
||||||
# Possibly show number of free-plays remaining.
|
|
||||||
ba.textwidget(
|
|
||||||
edit=tbtn['entry_fee_text_remaining'],
|
|
||||||
position=(tbtn['button_x'] + 360,
|
|
||||||
tbtn['button_y'] + tbtn['button_scale_y'] - 100),
|
|
||||||
text=('' if (free_tries_remaining in [None, 0]
|
|
||||||
or final_fee != 0) else
|
|
||||||
('' + str(free_tries_remaining))),
|
|
||||||
color=(0.6, 0.6, 0.6, 1))
|
|
||||||
|
|
||||||
def _on_tournament_query_response(self,
|
def _on_tournament_query_response(self,
|
||||||
data: dict[str, Any] | None) -> None:
|
data: dict[str, Any] | None) -> None:
|
||||||
|
|
@ -715,10 +504,13 @@ class CoopBrowserWindow(ba.Window):
|
||||||
items = [
|
items = [
|
||||||
campaignname + ':Onslaught Training',
|
campaignname + ':Onslaught Training',
|
||||||
campaignname + ':Rookie Onslaught',
|
campaignname + ':Rookie Onslaught',
|
||||||
campaignname + ':Rookie Football', campaignname + ':Pro Onslaught',
|
campaignname + ':Rookie Football',
|
||||||
campaignname + ':Pro Football', campaignname + ':Pro Runaround',
|
campaignname + ':Pro Onslaught',
|
||||||
campaignname + ':Uber Onslaught', campaignname + ':Uber Football',
|
campaignname + ':Pro Football',
|
||||||
campaignname + ':Uber Runaround'
|
campaignname + ':Pro Runaround',
|
||||||
|
campaignname + ':Uber Onslaught',
|
||||||
|
campaignname + ':Uber Football',
|
||||||
|
campaignname + ':Uber Runaround',
|
||||||
]
|
]
|
||||||
items += [campaignname + ':The Last Stand']
|
items += [campaignname + ':The Last Stand']
|
||||||
if self._selected_campaign_level is None:
|
if self._selected_campaign_level is None:
|
||||||
|
|
@ -772,6 +564,7 @@ class CoopBrowserWindow(ba.Window):
|
||||||
# pylint: disable=too-many-locals
|
# pylint: disable=too-many-locals
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bastd.ui.coop.gamebutton import GameButton
|
from bastd.ui.coop.gamebutton import GameButton
|
||||||
|
from bastd.ui.coop.tournamentbutton import TournamentButton
|
||||||
|
|
||||||
# (Re)create the sub-container if need be.
|
# (Re)create the sub-container if need be.
|
||||||
if self._subcontainer is not None:
|
if self._subcontainer is not None:
|
||||||
|
|
@ -839,7 +632,7 @@ class CoopBrowserWindow(ba.Window):
|
||||||
|
|
||||||
# Tournaments
|
# Tournaments
|
||||||
|
|
||||||
self._tournament_buttons: list[dict[str, Any]] = []
|
self._tournament_buttons: list[TournamentButton] = []
|
||||||
|
|
||||||
v -= 53
|
v -= 53
|
||||||
# FIXME shouldn't use hard-coded strings here.
|
# FIXME shouldn't use hard-coded strings here.
|
||||||
|
|
@ -919,10 +712,15 @@ class CoopBrowserWindow(ba.Window):
|
||||||
v2 = -2
|
v2 = -2
|
||||||
is_last_sel = True
|
is_last_sel = True
|
||||||
self._tournament_buttons.append(
|
self._tournament_buttons.append(
|
||||||
self._tournament_button(sc2, h, v2, is_last_sel))
|
TournamentButton(sc2,
|
||||||
|
h,
|
||||||
|
v2,
|
||||||
|
is_last_sel,
|
||||||
|
on_pressed=ba.WeakCall(
|
||||||
|
self.run_tournament)))
|
||||||
v -= 200
|
v -= 200
|
||||||
|
|
||||||
# Custom Games.
|
# Custom Games. (called 'Practice' in UI these days).
|
||||||
v -= 50
|
v -= 50
|
||||||
ba.textwidget(parent=w_parent,
|
ba.textwidget(parent=w_parent,
|
||||||
position=(h_base + 27, v + 30 + 198),
|
position=(h_base + 27, v + 30 + 198),
|
||||||
|
|
@ -949,14 +747,13 @@ class CoopBrowserWindow(ba.Window):
|
||||||
if _ba.get_v1_account_misc_read_val(
|
if _ba.get_v1_account_misc_read_val(
|
||||||
'easter', False) or _ba.get_purchased('games.easter_egg_hunt'):
|
'easter', False) or _ba.get_purchased('games.easter_egg_hunt'):
|
||||||
items = [
|
items = [
|
||||||
'Challenges:Easter Egg Hunt', 'Challenges:Pro Easter Egg Hunt'
|
'Challenges:Easter Egg Hunt',
|
||||||
|
'Challenges:Pro Easter Egg Hunt',
|
||||||
] + items
|
] + items
|
||||||
|
|
||||||
# add all custom user levels here..
|
# If we've defined custom games, put them at the beginning.
|
||||||
# items += [
|
if ba.app.custom_coop_practice_games:
|
||||||
# 'User:' + l.getname()
|
items = ba.app.custom_coop_practice_games + items
|
||||||
# for l in getcampaign('User').getlevels()
|
|
||||||
# ]
|
|
||||||
|
|
||||||
self._custom_h_scroll = custom_h_scroll = h_scroll = ba.hscrollwidget(
|
self._custom_h_scroll = custom_h_scroll = h_scroll = ba.hscrollwidget(
|
||||||
parent=w_parent,
|
parent=w_parent,
|
||||||
|
|
@ -995,19 +792,19 @@ class CoopBrowserWindow(ba.Window):
|
||||||
|
|
||||||
for i, tbutton in enumerate(self._tournament_buttons):
|
for i, tbutton in enumerate(self._tournament_buttons):
|
||||||
ba.widget(
|
ba.widget(
|
||||||
edit=tbutton['button'],
|
edit=tbutton.button,
|
||||||
up_widget=self._tournament_info_button
|
up_widget=self._tournament_info_button
|
||||||
if i == 0 else self._tournament_buttons[i - 1]['button'],
|
if i == 0 else self._tournament_buttons[i - 1].button,
|
||||||
down_widget=self._tournament_buttons[(i + 1)]['button']
|
down_widget=self._tournament_buttons[(i + 1)].button
|
||||||
if i + 1 < len(self._tournament_buttons) else custom_h_scroll)
|
if i + 1 < len(self._tournament_buttons) else custom_h_scroll)
|
||||||
ba.widget(
|
ba.widget(
|
||||||
edit=tbutton['more_scores_button'],
|
edit=tbutton.more_scores_button,
|
||||||
down_widget=self._tournament_buttons[(
|
down_widget=self._tournament_buttons[(
|
||||||
i + 1)]['current_leader_name_text']
|
i + 1)].current_leader_name_text
|
||||||
if i + 1 < len(self._tournament_buttons) else custom_h_scroll)
|
if i + 1 < len(self._tournament_buttons) else custom_h_scroll)
|
||||||
ba.widget(edit=tbutton['current_leader_name_text'],
|
ba.widget(edit=tbutton.current_leader_name_text,
|
||||||
up_widget=self._tournament_info_button if i == 0 else
|
up_widget=self._tournament_info_button if i == 0 else
|
||||||
self._tournament_buttons[i - 1]['more_scores_button'])
|
self._tournament_buttons[i - 1].more_scores_button)
|
||||||
|
|
||||||
for btn in self._custom_buttons:
|
for btn in self._custom_buttons:
|
||||||
try:
|
try:
|
||||||
|
|
@ -1037,314 +834,6 @@ class CoopBrowserWindow(ba.Window):
|
||||||
def _enable_selectable_callback(self) -> None:
|
def _enable_selectable_callback(self) -> None:
|
||||||
self._do_selection_callbacks = True
|
self._do_selection_callbacks = True
|
||||||
|
|
||||||
def _tournament_button(self, parent: ba.Widget, x: float, y: float,
|
|
||||||
select: bool) -> dict[str, Any]:
|
|
||||||
sclx = 300
|
|
||||||
scly = 195.0
|
|
||||||
data: dict[str, Any] = {
|
|
||||||
'tournament_id': None,
|
|
||||||
'time_remaining': 0,
|
|
||||||
'has_time_remaining': False,
|
|
||||||
'leader': None
|
|
||||||
}
|
|
||||||
data['button'] = btn = ba.buttonwidget(
|
|
||||||
parent=parent,
|
|
||||||
position=(x + 23, y + 4),
|
|
||||||
size=(sclx, scly),
|
|
||||||
label='',
|
|
||||||
button_type='square',
|
|
||||||
autoselect=True,
|
|
||||||
on_activate_call=lambda: self.run(None, tournament_button=data))
|
|
||||||
ba.widget(edit=btn,
|
|
||||||
show_buffer_bottom=50,
|
|
||||||
show_buffer_top=50,
|
|
||||||
show_buffer_left=400,
|
|
||||||
show_buffer_right=200)
|
|
||||||
if select:
|
|
||||||
ba.containerwidget(edit=parent,
|
|
||||||
selected_child=btn,
|
|
||||||
visible_child=btn)
|
|
||||||
image_width = sclx * 0.85 * 0.75
|
|
||||||
|
|
||||||
data['image'] = ba.imagewidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 21 + sclx * 0.5 - image_width * 0.5, y + scly - 150),
|
|
||||||
size=(image_width, image_width * 0.5),
|
|
||||||
model_transparent=self.lsbt,
|
|
||||||
model_opaque=self.lsbo,
|
|
||||||
texture=ba.gettexture('black'),
|
|
||||||
opacity=0.2,
|
|
||||||
mask_texture=ba.gettexture('mapPreviewMask'))
|
|
||||||
|
|
||||||
data['lock_image'] = ba.imagewidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 21 + sclx * 0.5 - image_width * 0.25,
|
|
||||||
y + scly - 150),
|
|
||||||
size=(image_width * 0.5, image_width * 0.5),
|
|
||||||
texture=ba.gettexture('lock'),
|
|
||||||
opacity=0.0)
|
|
||||||
|
|
||||||
data['button_text'] = ba.textwidget(parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 20 + sclx * 0.5,
|
|
||||||
y + scly - 35),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='center',
|
|
||||||
text='-',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=sclx * 0.76,
|
|
||||||
scale=0.85,
|
|
||||||
color=(0.8, 1.0, 0.8, 1.0))
|
|
||||||
|
|
||||||
header_color = (0.43, 0.4, 0.5, 1)
|
|
||||||
value_color = (0.6, 0.6, 0.6, 1)
|
|
||||||
|
|
||||||
x_offs = 0
|
|
||||||
ba.textwidget(parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 360, y + scly - 20),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='center',
|
|
||||||
text=ba.Lstr(resource=self._r + '.entryFeeText'),
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=100,
|
|
||||||
scale=0.9,
|
|
||||||
color=header_color,
|
|
||||||
flatness=1.0)
|
|
||||||
|
|
||||||
data['entry_fee_text_top'] = ba.textwidget(parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 360,
|
|
||||||
y + scly - 60),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='center',
|
|
||||||
text='-',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=60,
|
|
||||||
scale=1.3,
|
|
||||||
color=value_color,
|
|
||||||
flatness=1.0)
|
|
||||||
data['entry_fee_text_or'] = ba.textwidget(parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 360,
|
|
||||||
y + scly - 90),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='center',
|
|
||||||
text='',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=60,
|
|
||||||
scale=0.5,
|
|
||||||
color=value_color,
|
|
||||||
flatness=1.0)
|
|
||||||
data['entry_fee_text_remaining'] = ba.textwidget(parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 360, y +
|
|
||||||
scly - 90),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='center',
|
|
||||||
text='',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=60,
|
|
||||||
scale=0.5,
|
|
||||||
color=value_color,
|
|
||||||
flatness=1.0)
|
|
||||||
|
|
||||||
data['entry_fee_ad_image'] = ba.imagewidget(
|
|
||||||
parent=parent,
|
|
||||||
size=(40, 40),
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 360 - 20, y + scly - 140),
|
|
||||||
opacity=0.0,
|
|
||||||
texture=ba.gettexture('tv'))
|
|
||||||
|
|
||||||
x_offs += 50
|
|
||||||
|
|
||||||
ba.textwidget(parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 447 + x_offs, y + scly - 20),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='center',
|
|
||||||
text=ba.Lstr(resource=self._r + '.prizesText'),
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=130,
|
|
||||||
scale=0.9,
|
|
||||||
color=header_color,
|
|
||||||
flatness=1.0)
|
|
||||||
|
|
||||||
data['button_x'] = x
|
|
||||||
data['button_y'] = y
|
|
||||||
data['button_scale_y'] = scly
|
|
||||||
|
|
||||||
xo2 = 0
|
|
||||||
prize_value_scale = 1.5
|
|
||||||
|
|
||||||
data['prize_range_1_text'] = ba.textwidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 355 + xo2 + x_offs, y + scly - 93),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='right',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=50,
|
|
||||||
text='-',
|
|
||||||
scale=0.8,
|
|
||||||
color=header_color,
|
|
||||||
flatness=1.0)
|
|
||||||
data['prize_value_1_text'] = ba.textwidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 380 + xo2 + x_offs, y + scly - 93),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='left',
|
|
||||||
text='-',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=100,
|
|
||||||
scale=prize_value_scale,
|
|
||||||
color=value_color,
|
|
||||||
flatness=1.0)
|
|
||||||
|
|
||||||
data['prize_range_2_text'] = ba.textwidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 355 + xo2 + x_offs, y + scly - 93),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='right',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=50,
|
|
||||||
scale=0.8,
|
|
||||||
color=header_color,
|
|
||||||
flatness=1.0)
|
|
||||||
data['prize_value_2_text'] = ba.textwidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 380 + xo2 + x_offs, y + scly - 93),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='left',
|
|
||||||
text='',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=100,
|
|
||||||
scale=prize_value_scale,
|
|
||||||
color=value_color,
|
|
||||||
flatness=1.0)
|
|
||||||
|
|
||||||
data['prize_range_3_text'] = ba.textwidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 355 + xo2 + x_offs, y + scly - 93),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='right',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=50,
|
|
||||||
scale=0.8,
|
|
||||||
color=header_color,
|
|
||||||
flatness=1.0)
|
|
||||||
data['prize_value_3_text'] = ba.textwidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 380 + xo2 + x_offs, y + scly - 93),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='left',
|
|
||||||
text='',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=100,
|
|
||||||
scale=prize_value_scale,
|
|
||||||
color=value_color,
|
|
||||||
flatness=1.0)
|
|
||||||
|
|
||||||
ba.textwidget(parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 620 + x_offs, y + scly - 20),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='center',
|
|
||||||
text=ba.Lstr(resource=self._r + '.currentBestText'),
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=180,
|
|
||||||
scale=0.9,
|
|
||||||
color=header_color,
|
|
||||||
flatness=1.0)
|
|
||||||
data['current_leader_name_text'] = ba.textwidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 620 + x_offs - (170 / 1.4) * 0.5,
|
|
||||||
y + scly - 60 - 40 * 0.5),
|
|
||||||
selectable=True,
|
|
||||||
click_activate=True,
|
|
||||||
autoselect=True,
|
|
||||||
on_activate_call=lambda: self._show_leader(tournament_button=data),
|
|
||||||
size=(170 / 1.4, 40),
|
|
||||||
h_align='center',
|
|
||||||
text='-',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=170,
|
|
||||||
scale=1.4,
|
|
||||||
color=value_color,
|
|
||||||
flatness=1.0)
|
|
||||||
data['current_leader_score_text'] = ba.textwidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 620 + x_offs, y + scly - 113 + 10),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='center',
|
|
||||||
text='-',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=170,
|
|
||||||
scale=1.8,
|
|
||||||
color=value_color,
|
|
||||||
flatness=1.0)
|
|
||||||
|
|
||||||
data['more_scores_button'] = ba.buttonwidget(
|
|
||||||
parent=parent,
|
|
||||||
position=(x + 620 + x_offs - 60, y + scly - 50 - 125),
|
|
||||||
color=(0.5, 0.5, 0.6),
|
|
||||||
textcolor=(0.7, 0.7, 0.8),
|
|
||||||
label='-',
|
|
||||||
size=(120, 40),
|
|
||||||
autoselect=True,
|
|
||||||
up_widget=data['current_leader_name_text'],
|
|
||||||
text_scale=0.6,
|
|
||||||
on_activate_call=lambda: self._show_scores(tournament_button=data))
|
|
||||||
ba.widget(edit=data['current_leader_name_text'],
|
|
||||||
down_widget=data['more_scores_button'])
|
|
||||||
|
|
||||||
ba.textwidget(parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 820 + x_offs, y + scly - 20),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='center',
|
|
||||||
text=ba.Lstr(resource=self._r + '.timeRemainingText'),
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=180,
|
|
||||||
scale=0.9,
|
|
||||||
color=header_color,
|
|
||||||
flatness=1.0)
|
|
||||||
data['time_remaining_value_text'] = ba.textwidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 820 + x_offs, y + scly - 68),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='center',
|
|
||||||
text='-',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=180,
|
|
||||||
scale=2.0,
|
|
||||||
color=value_color,
|
|
||||||
flatness=1.0)
|
|
||||||
data['time_remaining_out_of_text'] = ba.textwidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 820 + x_offs, y + scly - 110),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='center',
|
|
||||||
text='-',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=120,
|
|
||||||
scale=0.72,
|
|
||||||
color=(0.4, 0.4, 0.5),
|
|
||||||
flatness=1.0)
|
|
||||||
return data
|
|
||||||
|
|
||||||
def _switch_to_league_rankings(self) -> None:
|
def _switch_to_league_rankings(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bastd.ui.account import show_sign_in_prompt
|
from bastd.ui.account import show_sign_in_prompt
|
||||||
|
|
@ -1378,100 +867,20 @@ class CoopBrowserWindow(ba.Window):
|
||||||
show_tab=show_tab,
|
show_tab=show_tab,
|
||||||
back_location='CoopBrowserWindow').get_root_widget())
|
back_location='CoopBrowserWindow').get_root_widget())
|
||||||
|
|
||||||
def _show_leader(self, tournament_button: dict[str, Any]) -> None:
|
|
||||||
# pylint: disable=cyclic-import
|
|
||||||
from bastd.ui.account.viewer import AccountViewerWindow
|
|
||||||
tournament_id = tournament_button['tournament_id']
|
|
||||||
|
|
||||||
# FIXME: This assumes a single player entry in leader; should expand
|
|
||||||
# this to work with multiple.
|
|
||||||
if tournament_id is None or tournament_button['leader'] is None or len(
|
|
||||||
tournament_button['leader'][2]) != 1:
|
|
||||||
ba.playsound(ba.getsound('error'))
|
|
||||||
return
|
|
||||||
ba.playsound(ba.getsound('swish'))
|
|
||||||
AccountViewerWindow(
|
|
||||||
account_id=tournament_button['leader'][2][0].get('a', None),
|
|
||||||
profile_id=tournament_button['leader'][2][0].get('p', None),
|
|
||||||
position=tournament_button['current_leader_name_text'].
|
|
||||||
get_screen_space_center())
|
|
||||||
|
|
||||||
def _show_scores(self, tournament_button: dict[str, Any]) -> None:
|
|
||||||
# pylint: disable=cyclic-import
|
|
||||||
from bastd.ui.tournamentscores import TournamentScoresWindow
|
|
||||||
tournament_id = tournament_button['tournament_id']
|
|
||||||
if tournament_id is None:
|
|
||||||
ba.playsound(ba.getsound('error'))
|
|
||||||
return
|
|
||||||
|
|
||||||
TournamentScoresWindow(
|
|
||||||
tournament_id=tournament_id,
|
|
||||||
position=tournament_button['more_scores_button'].
|
|
||||||
get_screen_space_center())
|
|
||||||
|
|
||||||
def is_tourney_data_up_to_date(self) -> bool:
|
def is_tourney_data_up_to_date(self) -> bool:
|
||||||
"""Return whether our tourney data is up to date."""
|
"""Return whether our tourney data is up to date."""
|
||||||
return self._tourney_data_up_to_date
|
return self._tourney_data_up_to_date
|
||||||
|
|
||||||
def run(self,
|
def run_game(self, game: str) -> None:
|
||||||
game: str | None,
|
|
||||||
tournament_button: dict[str, Any] | None = None) -> None:
|
|
||||||
"""Run the provided game."""
|
"""Run the provided game."""
|
||||||
# pylint: disable=too-many-branches
|
# pylint: disable=too-many-branches
|
||||||
# pylint: disable=too-many-statements
|
|
||||||
# pylint: disable=too-many-return-statements
|
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bastd.ui.confirm import ConfirmWindow
|
from bastd.ui.confirm import ConfirmWindow
|
||||||
from bastd.ui.tournamententry import TournamentEntryWindow
|
|
||||||
from bastd.ui.purchase import PurchaseWindow
|
from bastd.ui.purchase import PurchaseWindow
|
||||||
from bastd.ui.account import show_sign_in_prompt
|
from bastd.ui.account import show_sign_in_prompt
|
||||||
args: dict[str, Any] = {}
|
args: dict[str, Any] = {}
|
||||||
|
|
||||||
# Do a bit of pre-flight for tournament options.
|
if game == 'Easy:The Last Stand':
|
||||||
if tournament_button is not None:
|
|
||||||
|
|
||||||
if _ba.get_v1_account_state() != 'signed_in':
|
|
||||||
show_sign_in_prompt()
|
|
||||||
return
|
|
||||||
|
|
||||||
if not self._tourney_data_up_to_date:
|
|
||||||
ba.screenmessage(
|
|
||||||
ba.Lstr(resource='tournamentCheckingStateText'),
|
|
||||||
color=(1, 1, 0))
|
|
||||||
ba.playsound(ba.getsound('error'))
|
|
||||||
return
|
|
||||||
|
|
||||||
if tournament_button['tournament_id'] is None:
|
|
||||||
ba.screenmessage(
|
|
||||||
ba.Lstr(resource='internal.unavailableNoConnectionText'),
|
|
||||||
color=(1, 0, 0))
|
|
||||||
ba.playsound(ba.getsound('error'))
|
|
||||||
return
|
|
||||||
|
|
||||||
if tournament_button['required_league'] is not None:
|
|
||||||
ba.screenmessage(ba.Lstr(
|
|
||||||
resource='league.tournamentLeagueText',
|
|
||||||
subs=[
|
|
||||||
('${NAME}',
|
|
||||||
ba.Lstr(
|
|
||||||
translate=('leagueNames',
|
|
||||||
tournament_button['required_league'])))
|
|
||||||
]),
|
|
||||||
color=(1, 0, 0))
|
|
||||||
ba.playsound(ba.getsound('error'))
|
|
||||||
return
|
|
||||||
|
|
||||||
if tournament_button['time_remaining'] <= 0:
|
|
||||||
ba.screenmessage(ba.Lstr(resource='tournamentEndedText'),
|
|
||||||
color=(1, 0, 0))
|
|
||||||
ba.playsound(ba.getsound('error'))
|
|
||||||
return
|
|
||||||
|
|
||||||
# Game is whatever the tournament tells us it is.
|
|
||||||
game = ba.app.accounts_v1.tournament_info[
|
|
||||||
tournament_button['tournament_id']]['game']
|
|
||||||
|
|
||||||
if tournament_button is None and game == 'Easy:The Last Stand':
|
|
||||||
ConfirmWindow(ba.Lstr(resource='difficultyHardUnlockOnlyText',
|
ConfirmWindow(ba.Lstr(resource='difficultyHardUnlockOnlyText',
|
||||||
fallback_resource='difficultyHardOnlyText'),
|
fallback_resource='difficultyHardOnlyText'),
|
||||||
cancel_button=False,
|
cancel_button=False,
|
||||||
|
|
@ -1479,12 +888,11 @@ class CoopBrowserWindow(ba.Window):
|
||||||
height=130)
|
height=130)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Infinite onslaught/runaround require pro; bring up a store link if
|
# Infinite onslaught/runaround require pro; bring up a store link
|
||||||
# need be.
|
# if need be.
|
||||||
if tournament_button is None and game in (
|
if game in ('Challenges:Infinite Runaround',
|
||||||
'Challenges:Infinite Runaround',
|
'Challenges:Infinite Onslaught'
|
||||||
'Challenges:Infinite Onslaught'
|
) and not ba.app.accounts_v1.have_pro():
|
||||||
) and not ba.app.accounts_v1.have_pro():
|
|
||||||
if _ba.get_v1_account_state() != 'signed_in':
|
if _ba.get_v1_account_state() != 'signed_in':
|
||||||
show_sign_in_prompt()
|
show_sign_in_prompt()
|
||||||
else:
|
else:
|
||||||
|
|
@ -1495,7 +903,8 @@ class CoopBrowserWindow(ba.Window):
|
||||||
if game in ['Challenges:Meteor Shower']:
|
if game in ['Challenges:Meteor Shower']:
|
||||||
required_purchase = 'games.meteor_shower'
|
required_purchase = 'games.meteor_shower'
|
||||||
elif game in [
|
elif game in [
|
||||||
'Challenges:Target Practice', 'Challenges:Target Practice B'
|
'Challenges:Target Practice',
|
||||||
|
'Challenges:Target Practice B',
|
||||||
]:
|
]:
|
||||||
required_purchase = 'games.target_practice'
|
required_purchase = 'games.target_practice'
|
||||||
elif game in ['Challenges:Ninja Fight']:
|
elif game in ['Challenges:Ninja Fight']:
|
||||||
|
|
@ -1503,13 +912,14 @@ class CoopBrowserWindow(ba.Window):
|
||||||
elif game in ['Challenges:Pro Ninja Fight']:
|
elif game in ['Challenges:Pro Ninja Fight']:
|
||||||
required_purchase = 'games.ninja_fight'
|
required_purchase = 'games.ninja_fight'
|
||||||
elif game in [
|
elif game in [
|
||||||
'Challenges:Easter Egg Hunt', 'Challenges:Pro Easter Egg Hunt'
|
'Challenges:Easter Egg Hunt',
|
||||||
|
'Challenges:Pro Easter Egg Hunt',
|
||||||
]:
|
]:
|
||||||
required_purchase = 'games.easter_egg_hunt'
|
required_purchase = 'games.easter_egg_hunt'
|
||||||
else:
|
else:
|
||||||
required_purchase = None
|
required_purchase = None
|
||||||
|
|
||||||
if (tournament_button is None and required_purchase is not None
|
if (required_purchase is not None
|
||||||
and not _ba.get_purchased(required_purchase)):
|
and not _ba.get_purchased(required_purchase)):
|
||||||
if _ba.get_v1_account_state() != 'signed_in':
|
if _ba.get_v1_account_state() != 'signed_in':
|
||||||
show_sign_in_prompt()
|
show_sign_in_prompt()
|
||||||
|
|
@ -1519,17 +929,57 @@ class CoopBrowserWindow(ba.Window):
|
||||||
|
|
||||||
self._save_state()
|
self._save_state()
|
||||||
|
|
||||||
# For tournaments, we pop up the entry window.
|
if ba.app.launch_coop_game(game, args=args):
|
||||||
if tournament_button is not None:
|
ba.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
TournamentEntryWindow(
|
|
||||||
tournament_id=tournament_button['tournament_id'],
|
def run_tournament(self, tournament_button: TournamentButton) -> None:
|
||||||
position=tournament_button['button'].get_screen_space_center())
|
"""Run the provided tournament game."""
|
||||||
else:
|
from bastd.ui.account import show_sign_in_prompt
|
||||||
# Otherwise just dive right in.
|
from bastd.ui.tournamententry import TournamentEntryWindow
|
||||||
assert game is not None
|
|
||||||
if ba.app.launch_coop_game(game, args=args):
|
if _ba.get_v1_account_state() != 'signed_in':
|
||||||
ba.containerwidget(edit=self._root_widget,
|
show_sign_in_prompt()
|
||||||
transition='out_left')
|
return
|
||||||
|
|
||||||
|
if not self._tourney_data_up_to_date:
|
||||||
|
ba.screenmessage(ba.Lstr(resource='tournamentCheckingStateText'),
|
||||||
|
color=(1, 1, 0))
|
||||||
|
ba.playsound(ba.getsound('error'))
|
||||||
|
return
|
||||||
|
|
||||||
|
if tournament_button.tournament_id is None:
|
||||||
|
ba.screenmessage(
|
||||||
|
ba.Lstr(resource='internal.unavailableNoConnectionText'),
|
||||||
|
color=(1, 0, 0))
|
||||||
|
ba.playsound(ba.getsound('error'))
|
||||||
|
return
|
||||||
|
|
||||||
|
if tournament_button.required_league is not None:
|
||||||
|
ba.screenmessage(
|
||||||
|
ba.Lstr(
|
||||||
|
resource='league.tournamentLeagueText',
|
||||||
|
subs=[('${NAME}',
|
||||||
|
ba.Lstr(
|
||||||
|
translate=('leagueNames',
|
||||||
|
tournament_button.required_league)))
|
||||||
|
]),
|
||||||
|
color=(1, 0, 0),
|
||||||
|
)
|
||||||
|
ba.playsound(ba.getsound('error'))
|
||||||
|
return
|
||||||
|
|
||||||
|
if tournament_button.time_remaining <= 0:
|
||||||
|
ba.screenmessage(ba.Lstr(resource='tournamentEndedText'),
|
||||||
|
color=(1, 0, 0))
|
||||||
|
ba.playsound(ba.getsound('error'))
|
||||||
|
return
|
||||||
|
|
||||||
|
self._save_state()
|
||||||
|
|
||||||
|
assert tournament_button.tournament_id is not None
|
||||||
|
TournamentEntryWindow(
|
||||||
|
tournament_id=tournament_button.tournament_id,
|
||||||
|
position=tournament_button.button.get_screen_space_center())
|
||||||
|
|
||||||
def _back(self) -> None:
|
def _back(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
|
|
@ -1542,24 +992,6 @@ class CoopBrowserWindow(ba.Window):
|
||||||
ba.app.ui.set_main_menu_window(
|
ba.app.ui.set_main_menu_window(
|
||||||
PlayWindow(transition='in_left').get_root_widget())
|
PlayWindow(transition='in_left').get_root_widget())
|
||||||
|
|
||||||
def _restore_state(self) -> None:
|
|
||||||
try:
|
|
||||||
sel_name = ba.app.ui.window_states.get(type(self),
|
|
||||||
{}).get('sel_name')
|
|
||||||
if sel_name == 'Back':
|
|
||||||
sel = self._back_button
|
|
||||||
elif sel_name == 'Scroll':
|
|
||||||
sel = self._scrollwidget
|
|
||||||
elif sel_name == 'PowerRanking':
|
|
||||||
sel = self._league_rank_button_widget
|
|
||||||
elif sel_name == 'Store':
|
|
||||||
sel = self._store_button_widget
|
|
||||||
else:
|
|
||||||
sel = self._scrollwidget
|
|
||||||
ba.containerwidget(edit=self._root_widget, selected_child=sel)
|
|
||||||
except Exception:
|
|
||||||
ba.print_exception(f'Error restoring state for {self}.')
|
|
||||||
|
|
||||||
def _save_state(self) -> None:
|
def _save_state(self) -> None:
|
||||||
cfg = ba.app.config
|
cfg = ba.app.config
|
||||||
try:
|
try:
|
||||||
|
|
@ -1580,16 +1012,31 @@ class CoopBrowserWindow(ba.Window):
|
||||||
|
|
||||||
cfg['Selected Coop Row'] = self._selected_row
|
cfg['Selected Coop Row'] = self._selected_row
|
||||||
cfg['Selected Coop Custom Level'] = self._selected_custom_level
|
cfg['Selected Coop Custom Level'] = self._selected_custom_level
|
||||||
cfg['Selected Coop Challenge Level'] = self._selected_challenge_level
|
|
||||||
cfg['Selected Coop Campaign Level'] = self._selected_campaign_level
|
cfg['Selected Coop Campaign Level'] = self._selected_campaign_level
|
||||||
cfg.commit()
|
cfg.commit()
|
||||||
|
|
||||||
|
def _restore_state(self) -> None:
|
||||||
|
try:
|
||||||
|
sel_name = ba.app.ui.window_states.get(type(self),
|
||||||
|
{}).get('sel_name')
|
||||||
|
if sel_name == 'Back':
|
||||||
|
sel = self._back_button
|
||||||
|
elif sel_name == 'Scroll':
|
||||||
|
sel = self._scrollwidget
|
||||||
|
elif sel_name == 'PowerRanking':
|
||||||
|
sel = self._league_rank_button_widget
|
||||||
|
elif sel_name == 'Store':
|
||||||
|
sel = self._store_button_widget
|
||||||
|
else:
|
||||||
|
sel = self._scrollwidget
|
||||||
|
ba.containerwidget(edit=self._root_widget, selected_child=sel)
|
||||||
|
except Exception:
|
||||||
|
ba.print_exception(f'Error restoring state for {self}.')
|
||||||
|
|
||||||
def sel_change(self, row: str, game: str) -> None:
|
def sel_change(self, row: str, game: str) -> None:
|
||||||
"""(internal)"""
|
"""(internal)"""
|
||||||
if self._do_selection_callbacks:
|
if self._do_selection_callbacks:
|
||||||
if row == 'custom':
|
if row == 'custom':
|
||||||
self._selected_custom_level = game
|
self._selected_custom_level = game
|
||||||
if row == 'challenges':
|
|
||||||
self._selected_challenge_level = game
|
|
||||||
elif row == 'campaign':
|
elif row == 'campaign':
|
||||||
self._selected_campaign_level = game
|
self._selected_campaign_level = game
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ class GameButton:
|
||||||
position=(x + 23, y + 4),
|
position=(x + 23, y + 4),
|
||||||
size=(sclx, scly),
|
size=(sclx, scly),
|
||||||
label='',
|
label='',
|
||||||
on_activate_call=ba.Call(window.run, game),
|
on_activate_call=ba.Call(window.run_game, game),
|
||||||
button_type='square',
|
button_type='square',
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
on_select_call=ba.Call(window.sel_change, row, game))
|
on_select_call=ba.Call(window.sel_change, row, game))
|
||||||
|
|
|
||||||
561
dist/ba_data/python/bastd/ui/coop/tournamentbutton.py
vendored
Normal file
561
dist/ba_data/python/bastd/ui/coop/tournamentbutton.py
vendored
Normal file
|
|
@ -0,0 +1,561 @@
|
||||||
|
# Released under the MIT License. See LICENSE for details.
|
||||||
|
#
|
||||||
|
"""Defines button for co-op games."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
import copy
|
||||||
|
|
||||||
|
import ba
|
||||||
|
import _ba
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from typing import Any, Callable
|
||||||
|
|
||||||
|
|
||||||
|
class TournamentButton:
|
||||||
|
"""Button showing a tournament in coop window."""
|
||||||
|
|
||||||
|
def __init__(self, parent: ba.Widget, x: float, y: float, select: bool,
|
||||||
|
on_pressed: Callable[[TournamentButton], None]) -> None:
|
||||||
|
self._r = 'coopSelectWindow'
|
||||||
|
sclx = 300
|
||||||
|
scly = 195.0
|
||||||
|
self.on_pressed = on_pressed
|
||||||
|
self.lsbt = ba.getmodel('level_select_button_transparent')
|
||||||
|
self.lsbo = ba.getmodel('level_select_button_opaque')
|
||||||
|
self.allow_ads = False
|
||||||
|
self.tournament_id: str | None = None
|
||||||
|
self.time_remaining: int = 0
|
||||||
|
self.has_time_remaining: bool = False
|
||||||
|
self.leader: Any = None
|
||||||
|
self.required_league: str | None = None
|
||||||
|
self.button = btn = ba.buttonwidget(
|
||||||
|
parent=parent,
|
||||||
|
position=(x + 23, y + 4),
|
||||||
|
size=(sclx, scly),
|
||||||
|
label='',
|
||||||
|
button_type='square',
|
||||||
|
autoselect=True,
|
||||||
|
# on_activate_call=lambda: self.run(None, tournament_button=data)
|
||||||
|
on_activate_call=ba.WeakCall(self._pressed))
|
||||||
|
ba.widget(edit=btn,
|
||||||
|
show_buffer_bottom=50,
|
||||||
|
show_buffer_top=50,
|
||||||
|
show_buffer_left=400,
|
||||||
|
show_buffer_right=200)
|
||||||
|
if select:
|
||||||
|
ba.containerwidget(edit=parent,
|
||||||
|
selected_child=btn,
|
||||||
|
visible_child=btn)
|
||||||
|
image_width = sclx * 0.85 * 0.75
|
||||||
|
|
||||||
|
self.image = ba.imagewidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 21 + sclx * 0.5 - image_width * 0.5, y + scly - 150),
|
||||||
|
size=(image_width, image_width * 0.5),
|
||||||
|
model_transparent=self.lsbt,
|
||||||
|
model_opaque=self.lsbo,
|
||||||
|
texture=ba.gettexture('black'),
|
||||||
|
opacity=0.2,
|
||||||
|
mask_texture=ba.gettexture('mapPreviewMask'))
|
||||||
|
|
||||||
|
self.lock_image = ba.imagewidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 21 + sclx * 0.5 - image_width * 0.25,
|
||||||
|
y + scly - 150),
|
||||||
|
size=(image_width * 0.5, image_width * 0.5),
|
||||||
|
texture=ba.gettexture('lock'),
|
||||||
|
opacity=0.0)
|
||||||
|
|
||||||
|
self.button_text = ba.textwidget(parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 20 + sclx * 0.5,
|
||||||
|
y + scly - 35),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
text='-',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=sclx * 0.76,
|
||||||
|
scale=0.85,
|
||||||
|
color=(0.8, 1.0, 0.8, 1.0))
|
||||||
|
|
||||||
|
header_color = (0.43, 0.4, 0.5, 1)
|
||||||
|
value_color = (0.6, 0.6, 0.6, 1)
|
||||||
|
|
||||||
|
x_offs = 0
|
||||||
|
ba.textwidget(parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 360, y + scly - 20),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
text=ba.Lstr(resource=self._r + '.entryFeeText'),
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=100,
|
||||||
|
scale=0.9,
|
||||||
|
color=header_color,
|
||||||
|
flatness=1.0)
|
||||||
|
|
||||||
|
self.entry_fee_text_top = ba.textwidget(parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 360,
|
||||||
|
y + scly - 60),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
text='-',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=60,
|
||||||
|
scale=1.3,
|
||||||
|
color=value_color,
|
||||||
|
flatness=1.0)
|
||||||
|
self.entry_fee_text_or = ba.textwidget(parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 360,
|
||||||
|
y + scly - 90),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
text='',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=60,
|
||||||
|
scale=0.5,
|
||||||
|
color=value_color,
|
||||||
|
flatness=1.0)
|
||||||
|
self.entry_fee_text_remaining = ba.textwidget(parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 360,
|
||||||
|
y + scly - 90),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
text='',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=60,
|
||||||
|
scale=0.5,
|
||||||
|
color=value_color,
|
||||||
|
flatness=1.0)
|
||||||
|
|
||||||
|
self.entry_fee_ad_image = ba.imagewidget(parent=parent,
|
||||||
|
size=(40, 40),
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 360 - 20,
|
||||||
|
y + scly - 140),
|
||||||
|
opacity=0.0,
|
||||||
|
texture=ba.gettexture('tv'))
|
||||||
|
|
||||||
|
x_offs += 50
|
||||||
|
|
||||||
|
ba.textwidget(parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 447 + x_offs, y + scly - 20),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
text=ba.Lstr(resource=self._r + '.prizesText'),
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=130,
|
||||||
|
scale=0.9,
|
||||||
|
color=header_color,
|
||||||
|
flatness=1.0)
|
||||||
|
|
||||||
|
self.button_x = x
|
||||||
|
self.button_y = y
|
||||||
|
self.button_scale_y = scly
|
||||||
|
|
||||||
|
xo2 = 0
|
||||||
|
prize_value_scale = 1.5
|
||||||
|
|
||||||
|
self.prize_range_1_text = ba.textwidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 355 + xo2 + x_offs, y + scly - 93),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='right',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=50,
|
||||||
|
text='-',
|
||||||
|
scale=0.8,
|
||||||
|
color=header_color,
|
||||||
|
flatness=1.0)
|
||||||
|
self.prize_value_1_text = ba.textwidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 380 + xo2 + x_offs, y + scly - 93),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='left',
|
||||||
|
text='-',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=100,
|
||||||
|
scale=prize_value_scale,
|
||||||
|
color=value_color,
|
||||||
|
flatness=1.0)
|
||||||
|
|
||||||
|
self.prize_range_2_text = ba.textwidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 355 + xo2 + x_offs, y + scly - 93),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='right',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=50,
|
||||||
|
scale=0.8,
|
||||||
|
color=header_color,
|
||||||
|
flatness=1.0)
|
||||||
|
self.prize_value_2_text = ba.textwidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 380 + xo2 + x_offs, y + scly - 93),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='left',
|
||||||
|
text='',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=100,
|
||||||
|
scale=prize_value_scale,
|
||||||
|
color=value_color,
|
||||||
|
flatness=1.0)
|
||||||
|
|
||||||
|
self.prize_range_3_text = ba.textwidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 355 + xo2 + x_offs, y + scly - 93),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='right',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=50,
|
||||||
|
scale=0.8,
|
||||||
|
color=header_color,
|
||||||
|
flatness=1.0)
|
||||||
|
self.prize_value_3_text = ba.textwidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 380 + xo2 + x_offs, y + scly - 93),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='left',
|
||||||
|
text='',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=100,
|
||||||
|
scale=prize_value_scale,
|
||||||
|
color=value_color,
|
||||||
|
flatness=1.0)
|
||||||
|
|
||||||
|
ba.textwidget(parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 620 + x_offs, y + scly - 20),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
text=ba.Lstr(resource=self._r + '.currentBestText'),
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=180,
|
||||||
|
scale=0.9,
|
||||||
|
color=header_color,
|
||||||
|
flatness=1.0)
|
||||||
|
self.current_leader_name_text = ba.textwidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 620 + x_offs - (170 / 1.4) * 0.5,
|
||||||
|
y + scly - 60 - 40 * 0.5),
|
||||||
|
selectable=True,
|
||||||
|
click_activate=True,
|
||||||
|
autoselect=True,
|
||||||
|
on_activate_call=ba.WeakCall(self._show_leader),
|
||||||
|
size=(170 / 1.4, 40),
|
||||||
|
h_align='center',
|
||||||
|
text='-',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=170,
|
||||||
|
scale=1.4,
|
||||||
|
color=value_color,
|
||||||
|
flatness=1.0)
|
||||||
|
self.current_leader_score_text = ba.textwidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 620 + x_offs, y + scly - 113 + 10),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
text='-',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=170,
|
||||||
|
scale=1.8,
|
||||||
|
color=value_color,
|
||||||
|
flatness=1.0)
|
||||||
|
|
||||||
|
self.more_scores_button = ba.buttonwidget(
|
||||||
|
parent=parent,
|
||||||
|
position=(x + 620 + x_offs - 60, y + scly - 50 - 125),
|
||||||
|
color=(0.5, 0.5, 0.6),
|
||||||
|
textcolor=(0.7, 0.7, 0.8),
|
||||||
|
label='-',
|
||||||
|
size=(120, 40),
|
||||||
|
autoselect=True,
|
||||||
|
up_widget=self.current_leader_name_text,
|
||||||
|
text_scale=0.6,
|
||||||
|
on_activate_call=ba.WeakCall(self._show_scores))
|
||||||
|
ba.widget(edit=self.current_leader_name_text,
|
||||||
|
down_widget=self.more_scores_button)
|
||||||
|
|
||||||
|
ba.textwidget(parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 820 + x_offs, y + scly - 20),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
text=ba.Lstr(resource=self._r + '.timeRemainingText'),
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=180,
|
||||||
|
scale=0.9,
|
||||||
|
color=header_color,
|
||||||
|
flatness=1.0)
|
||||||
|
self.time_remaining_value_text = ba.textwidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 820 + x_offs, y + scly - 68),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
text='-',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=180,
|
||||||
|
scale=2.0,
|
||||||
|
color=value_color,
|
||||||
|
flatness=1.0)
|
||||||
|
self.time_remaining_out_of_text = ba.textwidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 820 + x_offs, y + scly - 110),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
text='-',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=120,
|
||||||
|
scale=0.72,
|
||||||
|
color=(0.4, 0.4, 0.5),
|
||||||
|
flatness=1.0)
|
||||||
|
|
||||||
|
def _pressed(self) -> None:
|
||||||
|
self.on_pressed(self)
|
||||||
|
|
||||||
|
def _show_leader(self) -> None:
|
||||||
|
# pylint: disable=cyclic-import
|
||||||
|
from bastd.ui.account.viewer import AccountViewerWindow
|
||||||
|
tournament_id = self.tournament_id
|
||||||
|
|
||||||
|
# FIXME: This assumes a single player entry in leader; should expand
|
||||||
|
# this to work with multiple.
|
||||||
|
if tournament_id is None or self.leader is None or len(
|
||||||
|
self.leader[2]) != 1:
|
||||||
|
ba.playsound(ba.getsound('error'))
|
||||||
|
return
|
||||||
|
ba.playsound(ba.getsound('swish'))
|
||||||
|
AccountViewerWindow(
|
||||||
|
account_id=self.leader[2][0].get('a', None),
|
||||||
|
profile_id=self.leader[2][0].get('p', None),
|
||||||
|
position=self.current_leader_name_text.get_screen_space_center())
|
||||||
|
|
||||||
|
def _show_scores(self) -> None:
|
||||||
|
# pylint: disable=cyclic-import
|
||||||
|
from bastd.ui.tournamentscores import TournamentScoresWindow
|
||||||
|
tournament_id = self.tournament_id
|
||||||
|
if tournament_id is None:
|
||||||
|
ba.playsound(ba.getsound('error'))
|
||||||
|
return
|
||||||
|
|
||||||
|
TournamentScoresWindow(
|
||||||
|
tournament_id=tournament_id,
|
||||||
|
position=self.more_scores_button.get_screen_space_center())
|
||||||
|
|
||||||
|
def update_for_data(self, entry: dict[str, Any]) -> None:
|
||||||
|
"""Update for new incoming data."""
|
||||||
|
# pylint: disable=too-many-statements
|
||||||
|
# pylint: disable=too-many-locals
|
||||||
|
# pylint: disable=too-many-branches
|
||||||
|
from ba.internal import getcampaign, get_tournament_prize_strings
|
||||||
|
prize_y_offs = (34 if 'prizeRange3' in entry else
|
||||||
|
20 if 'prizeRange2' in entry else 12)
|
||||||
|
x_offs = 90
|
||||||
|
|
||||||
|
# This seems to be a false alarm.
|
||||||
|
# pylint: disable=unbalanced-tuple-unpacking
|
||||||
|
pr1, pv1, pr2, pv2, pr3, pv3 = (get_tournament_prize_strings(entry))
|
||||||
|
# pylint: enable=unbalanced-tuple-unpacking
|
||||||
|
enabled = 'requiredLeague' not in entry
|
||||||
|
ba.buttonwidget(edit=self.button,
|
||||||
|
color=(0.5, 0.7, 0.2) if enabled else (0.5, 0.5, 0.5))
|
||||||
|
ba.imagewidget(edit=self.lock_image, opacity=0.0 if enabled else 1.0)
|
||||||
|
ba.textwidget(edit=self.prize_range_1_text,
|
||||||
|
text='-' if pr1 == '' else pr1,
|
||||||
|
position=(self.button_x + 365 + x_offs, self.button_y +
|
||||||
|
self.button_scale_y - 93 + prize_y_offs))
|
||||||
|
|
||||||
|
# We want to draw values containing tickets a bit smaller
|
||||||
|
# (scratch that; we now draw medals a bit bigger).
|
||||||
|
ticket_char = ba.charstr(ba.SpecialChar.TICKET_BACKING)
|
||||||
|
prize_value_scale_large = 1.0
|
||||||
|
prize_value_scale_small = 1.0
|
||||||
|
|
||||||
|
ba.textwidget(edit=self.prize_value_1_text,
|
||||||
|
text='-' if pv1 == '' else pv1,
|
||||||
|
scale=prize_value_scale_large
|
||||||
|
if ticket_char not in pv1 else prize_value_scale_small,
|
||||||
|
position=(self.button_x + 380 + x_offs, self.button_y +
|
||||||
|
self.button_scale_y - 93 + prize_y_offs))
|
||||||
|
|
||||||
|
ba.textwidget(edit=self.prize_range_2_text,
|
||||||
|
text=pr2,
|
||||||
|
position=(self.button_x + 365 + x_offs, self.button_y +
|
||||||
|
self.button_scale_y - 93 - 45 + prize_y_offs))
|
||||||
|
ba.textwidget(edit=self.prize_value_2_text,
|
||||||
|
text=pv2,
|
||||||
|
scale=prize_value_scale_large
|
||||||
|
if ticket_char not in pv2 else prize_value_scale_small,
|
||||||
|
position=(self.button_x + 380 + x_offs, self.button_y +
|
||||||
|
self.button_scale_y - 93 - 45 + prize_y_offs))
|
||||||
|
|
||||||
|
ba.textwidget(edit=self.prize_range_3_text,
|
||||||
|
text=pr3,
|
||||||
|
position=(self.button_x + 365 + x_offs, self.button_y +
|
||||||
|
self.button_scale_y - 93 - 90 + prize_y_offs))
|
||||||
|
ba.textwidget(edit=self.prize_value_3_text,
|
||||||
|
text=pv3,
|
||||||
|
scale=prize_value_scale_large
|
||||||
|
if ticket_char not in pv3 else prize_value_scale_small,
|
||||||
|
position=(self.button_x + 380 + x_offs, self.button_y +
|
||||||
|
self.button_scale_y - 93 - 90 + prize_y_offs))
|
||||||
|
|
||||||
|
leader_name = '-'
|
||||||
|
leader_score: str | ba.Lstr = '-'
|
||||||
|
if entry['scores']:
|
||||||
|
score = self.leader = copy.deepcopy(entry['scores'][0])
|
||||||
|
leader_name = score[1]
|
||||||
|
leader_score = (ba.timestring(
|
||||||
|
score[0] * 10,
|
||||||
|
centi=True,
|
||||||
|
timeformat=ba.TimeFormat.MILLISECONDS,
|
||||||
|
suppress_format_warning=True)
|
||||||
|
if entry['scoreType'] == 'time' else str(score[0]))
|
||||||
|
else:
|
||||||
|
self.leader = None
|
||||||
|
|
||||||
|
ba.textwidget(edit=self.current_leader_name_text,
|
||||||
|
text=ba.Lstr(value=leader_name))
|
||||||
|
ba.textwidget(edit=self.current_leader_score_text, text=leader_score)
|
||||||
|
ba.buttonwidget(edit=self.more_scores_button,
|
||||||
|
label=ba.Lstr(resource=self._r + '.seeMoreText'))
|
||||||
|
out_of_time_text: str | ba.Lstr = (
|
||||||
|
'-' if 'totalTime' not in entry else ba.Lstr(
|
||||||
|
resource=self._r + '.ofTotalTimeText',
|
||||||
|
subs=[('${TOTAL}',
|
||||||
|
ba.timestring(entry['totalTime'],
|
||||||
|
centi=False,
|
||||||
|
suppress_format_warning=True))]))
|
||||||
|
ba.textwidget(edit=self.time_remaining_out_of_text,
|
||||||
|
text=out_of_time_text)
|
||||||
|
|
||||||
|
self.time_remaining = entry['timeRemaining']
|
||||||
|
self.has_time_remaining = entry is not None
|
||||||
|
self.tournament_id = entry['tournamentID']
|
||||||
|
self.required_league = (None if 'requiredLeague' not in entry else
|
||||||
|
entry['requiredLeague'])
|
||||||
|
|
||||||
|
game = ba.app.accounts_v1.tournament_info[self.tournament_id]['game']
|
||||||
|
|
||||||
|
if game is None:
|
||||||
|
ba.textwidget(edit=self.button_text, text='-')
|
||||||
|
ba.imagewidget(edit=self.image,
|
||||||
|
texture=ba.gettexture('black'),
|
||||||
|
opacity=0.2)
|
||||||
|
else:
|
||||||
|
campaignname, levelname = game.split(':')
|
||||||
|
campaign = getcampaign(campaignname)
|
||||||
|
max_players = ba.app.accounts_v1.tournament_info[
|
||||||
|
self.tournament_id]['maxPlayers']
|
||||||
|
txt = ba.Lstr(value='${A} ${B}',
|
||||||
|
subs=[('${A}',
|
||||||
|
campaign.getlevel(levelname).displayname),
|
||||||
|
('${B}',
|
||||||
|
ba.Lstr(resource='playerCountAbbreviatedText',
|
||||||
|
subs=[('${COUNT}', str(max_players))
|
||||||
|
]))])
|
||||||
|
ba.textwidget(edit=self.button_text, text=txt)
|
||||||
|
ba.imagewidget(
|
||||||
|
edit=self.image,
|
||||||
|
texture=campaign.getlevel(levelname).get_preview_texture(),
|
||||||
|
opacity=1.0 if enabled else 0.5)
|
||||||
|
|
||||||
|
fee = entry['fee']
|
||||||
|
|
||||||
|
if fee is None:
|
||||||
|
fee_var = None
|
||||||
|
elif fee == 4:
|
||||||
|
fee_var = 'price.tournament_entry_4'
|
||||||
|
elif fee == 3:
|
||||||
|
fee_var = 'price.tournament_entry_3'
|
||||||
|
elif fee == 2:
|
||||||
|
fee_var = 'price.tournament_entry_2'
|
||||||
|
elif fee == 1:
|
||||||
|
fee_var = 'price.tournament_entry_1'
|
||||||
|
else:
|
||||||
|
if fee != 0:
|
||||||
|
print('Unknown fee value:', fee)
|
||||||
|
fee_var = 'price.tournament_entry_0'
|
||||||
|
|
||||||
|
self.allow_ads = allow_ads = entry['allowAds']
|
||||||
|
|
||||||
|
final_fee: int | None = (None if fee_var is None else
|
||||||
|
_ba.get_v1_account_misc_read_val(
|
||||||
|
fee_var, '?'))
|
||||||
|
|
||||||
|
final_fee_str: str | ba.Lstr
|
||||||
|
if fee_var is None:
|
||||||
|
final_fee_str = ''
|
||||||
|
else:
|
||||||
|
if final_fee == 0:
|
||||||
|
final_fee_str = ba.Lstr(resource='getTicketsWindow.freeText')
|
||||||
|
else:
|
||||||
|
final_fee_str = (ba.charstr(ba.SpecialChar.TICKET_BACKING) +
|
||||||
|
str(final_fee))
|
||||||
|
|
||||||
|
ad_tries_remaining = ba.app.accounts_v1.tournament_info[
|
||||||
|
self.tournament_id]['adTriesRemaining']
|
||||||
|
free_tries_remaining = ba.app.accounts_v1.tournament_info[
|
||||||
|
self.tournament_id]['freeTriesRemaining']
|
||||||
|
|
||||||
|
# Now, if this fee allows ads and we support video ads, show
|
||||||
|
# the 'or ad' version.
|
||||||
|
if allow_ads and _ba.has_video_ads():
|
||||||
|
ads_enabled = _ba.have_incentivized_ad()
|
||||||
|
ba.imagewidget(edit=self.entry_fee_ad_image,
|
||||||
|
opacity=1.0 if ads_enabled else 0.25)
|
||||||
|
or_text = ba.Lstr(resource='orText',
|
||||||
|
subs=[('${A}', ''),
|
||||||
|
('${B}', '')]).evaluate().strip()
|
||||||
|
ba.textwidget(edit=self.entry_fee_text_or, text=or_text)
|
||||||
|
ba.textwidget(edit=self.entry_fee_text_top,
|
||||||
|
position=(self.button_x + 360,
|
||||||
|
self.button_y + self.button_scale_y - 60),
|
||||||
|
scale=1.3,
|
||||||
|
text=final_fee_str)
|
||||||
|
|
||||||
|
# Possibly show number of ad-plays remaining.
|
||||||
|
ba.textwidget(edit=self.entry_fee_text_remaining,
|
||||||
|
position=(self.button_x + 360,
|
||||||
|
self.button_y + self.button_scale_y - 146),
|
||||||
|
text='' if ad_tries_remaining in [None, 0] else
|
||||||
|
('' + str(ad_tries_remaining)),
|
||||||
|
color=(0.6, 0.6, 0.6, 1 if ads_enabled else 0.2))
|
||||||
|
else:
|
||||||
|
ba.imagewidget(edit=self.entry_fee_ad_image, opacity=0.0)
|
||||||
|
ba.textwidget(edit=self.entry_fee_text_or, text='')
|
||||||
|
ba.textwidget(edit=self.entry_fee_text_top,
|
||||||
|
position=(self.button_x + 360,
|
||||||
|
self.button_y + self.button_scale_y - 80),
|
||||||
|
scale=1.3,
|
||||||
|
text=final_fee_str)
|
||||||
|
|
||||||
|
# Possibly show number of free-plays remaining.
|
||||||
|
ba.textwidget(
|
||||||
|
edit=self.entry_fee_text_remaining,
|
||||||
|
position=(self.button_x + 360,
|
||||||
|
self.button_y + self.button_scale_y - 100),
|
||||||
|
text=('' if (free_tries_remaining in [None, 0]
|
||||||
|
or final_fee != 0) else
|
||||||
|
('' + str(free_tries_remaining))),
|
||||||
|
color=(0.6, 0.6, 0.6, 1),
|
||||||
|
)
|
||||||
7
dist/ba_data/python/bastd/ui/creditslist.py
vendored
7
dist/ba_data/python/bastd/ui/creditslist.py
vendored
|
|
@ -207,10 +207,15 @@ class CreditsListWindow(ba.Window):
|
||||||
'\n' + '\n'.join(translation_names.splitlines()[:146]) +
|
'\n' + '\n'.join(translation_names.splitlines()[:146]) +
|
||||||
'\n'.join(translation_names.splitlines()[146:]) + '\n'
|
'\n'.join(translation_names.splitlines()[146:]) + '\n'
|
||||||
'\n'
|
'\n'
|
||||||
' Shout Out to Awesome Mods / Modders:\n\n'
|
' Shout Out to Awesome Mods / Modders / Contributors:\n\n'
|
||||||
' BombDash ModPack\n'
|
' BombDash ModPack\n'
|
||||||
' TheMikirog & SoK - BombSquad Joyride Modpack\n'
|
' TheMikirog & SoK - BombSquad Joyride Modpack\n'
|
||||||
' Mrmaxmeier - BombSquad-Community-Mod-Manager\n'
|
' Mrmaxmeier - BombSquad-Community-Mod-Manager\n'
|
||||||
|
' Ritiek Malhotra \n'
|
||||||
|
' Dliwk\n'
|
||||||
|
' vishal332008\n'
|
||||||
|
' itsre3\n'
|
||||||
|
' Drooopyyy\n'
|
||||||
'\n'
|
'\n'
|
||||||
' Holiday theme vector art designed by Freepik\n'
|
' Holiday theme vector art designed by Freepik\n'
|
||||||
'\n'
|
'\n'
|
||||||
|
|
|
||||||
|
|
@ -705,8 +705,8 @@ class ManualGatherTab(GatherTab):
|
||||||
from_other_thread=True,
|
from_other_thread=True,
|
||||||
)
|
)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
from efro.error import is_udp_network_error
|
from efro.error import is_udp_communication_error
|
||||||
if is_udp_network_error(exc):
|
if is_udp_communication_error(exc):
|
||||||
ba.pushcall(ba.Call(
|
ba.pushcall(ba.Call(
|
||||||
_safe_set_text, self._checking_state_text,
|
_safe_set_text, self._checking_state_text,
|
||||||
ba.Lstr(resource='gatherWindow.'
|
ba.Lstr(resource='gatherWindow.'
|
||||||
|
|
|
||||||
|
|
@ -219,9 +219,9 @@ class AddrFetchThread(threading.Thread):
|
||||||
sock.close()
|
sock.close()
|
||||||
ba.pushcall(ba.Call(self._call, val), from_other_thread=True)
|
ba.pushcall(ba.Call(self._call, val), from_other_thread=True)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
from efro.error import is_udp_network_error
|
from efro.error import is_udp_communication_error
|
||||||
# Ignore expected network errors; log others.
|
# Ignore expected network errors; log others.
|
||||||
if is_udp_network_error(exc):
|
if is_udp_communication_error(exc):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
ba.print_exception()
|
ba.print_exception()
|
||||||
|
|
@ -271,8 +271,8 @@ class PingThread(threading.Thread):
|
||||||
ping if accessible else None),
|
ping if accessible else None),
|
||||||
from_other_thread=True)
|
from_other_thread=True)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
from efro.error import is_udp_network_error
|
from efro.error import is_udp_communication_error
|
||||||
if is_udp_network_error(exc):
|
if is_udp_communication_error(exc):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
ba.print_exception('Error on gather ping', once=True)
|
ba.print_exception('Error on gather ping', once=True)
|
||||||
|
|
|
||||||
14
dist/ba_data/python/bastd/ui/onscreenkeyboard.py
vendored
14
dist/ba_data/python/bastd/ui/onscreenkeyboard.py
vendored
|
|
@ -213,8 +213,8 @@ class OnScreenKeyboardWindow(ba.Window):
|
||||||
|
|
||||||
# Show change instructions only if we have more than one
|
# Show change instructions only if we have more than one
|
||||||
# keyboard option.
|
# keyboard option.
|
||||||
if (ba.app.meta.metascan is not None
|
if (ba.app.meta.scanresults is not None
|
||||||
and len(ba.app.meta.metascan.keyboards) > 1):
|
and len(ba.app.meta.scanresults.keyboards) > 1):
|
||||||
ba.textwidget(
|
ba.textwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
h_align='center',
|
h_align='center',
|
||||||
|
|
@ -238,8 +238,8 @@ class OnScreenKeyboardWindow(ba.Window):
|
||||||
self._refresh()
|
self._refresh()
|
||||||
|
|
||||||
def _get_keyboard(self) -> ba.Keyboard:
|
def _get_keyboard(self) -> ba.Keyboard:
|
||||||
assert ba.app.meta.metascan is not None
|
assert ba.app.meta.scanresults is not None
|
||||||
classname = ba.app.meta.metascan.keyboards[self._keyboard_index]
|
classname = ba.app.meta.scanresults.keyboards[self._keyboard_index]
|
||||||
kbclass = ba.getclass(classname, ba.Keyboard)
|
kbclass = ba.getclass(classname, ba.Keyboard)
|
||||||
return kbclass()
|
return kbclass()
|
||||||
|
|
||||||
|
|
@ -317,11 +317,11 @@ class OnScreenKeyboardWindow(ba.Window):
|
||||||
self._refresh()
|
self._refresh()
|
||||||
|
|
||||||
def _next_keyboard(self) -> None:
|
def _next_keyboard(self) -> None:
|
||||||
assert ba.app.meta.metascan is not None
|
assert ba.app.meta.scanresults is not None
|
||||||
self._keyboard_index = (self._keyboard_index + 1) % len(
|
self._keyboard_index = (self._keyboard_index + 1) % len(
|
||||||
ba.app.meta.metascan.keyboards)
|
ba.app.meta.scanresults.keyboards)
|
||||||
self._load_keyboard()
|
self._load_keyboard()
|
||||||
if len(ba.app.meta.metascan.keyboards) < 2:
|
if len(ba.app.meta.scanresults.keyboards) < 2:
|
||||||
ba.playsound(ba.getsound('error'))
|
ba.playsound(ba.getsound('error'))
|
||||||
ba.screenmessage(ba.Lstr(resource='keyboardNoOthersAvailableText'),
|
ba.screenmessage(ba.Lstr(resource='keyboardNoOthersAvailableText'),
|
||||||
color=(1, 0, 0))
|
color=(1, 0, 0))
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ class AdvancedSettingsWindow(ba.Window):
|
||||||
scale=(2.06 if uiscale is ba.UIScale.SMALL else
|
scale=(2.06 if uiscale is ba.UIScale.SMALL else
|
||||||
1.4 if uiscale is ba.UIScale.MEDIUM else 1.0),
|
1.4 if uiscale is ba.UIScale.MEDIUM else 1.0),
|
||||||
stack_offset=(0, -25) if uiscale is ba.UIScale.SMALL else (0, 0)))
|
stack_offset=(0, -25) if uiscale is ba.UIScale.SMALL else (0, 0)))
|
||||||
|
|
||||||
self._prev_lang = ''
|
self._prev_lang = ''
|
||||||
self._prev_lang_list: list[str] = []
|
self._prev_lang_list: list[str] = []
|
||||||
self._complete_langs_list: list | None = None
|
self._complete_langs_list: list | None = None
|
||||||
|
|
@ -423,29 +424,6 @@ class AdvancedSettingsWindow(ba.Window):
|
||||||
v -= self._spacing * 2.1
|
v -= self._spacing * 2.1
|
||||||
|
|
||||||
this_button_width = 410
|
this_button_width = 410
|
||||||
self._show_user_mods_button = ba.buttonwidget(
|
|
||||||
parent=self._subcontainer,
|
|
||||||
position=(self._sub_width / 2 - this_button_width / 2, v - 10),
|
|
||||||
size=(this_button_width, 60),
|
|
||||||
autoselect=True,
|
|
||||||
label=ba.Lstr(resource=self._r + '.showUserModsText'),
|
|
||||||
text_scale=1.0,
|
|
||||||
on_activate_call=show_user_scripts)
|
|
||||||
if self._show_always_use_internal_keyboard:
|
|
||||||
assert self._always_use_internal_keyboard_check_box is not None
|
|
||||||
ba.widget(edit=self._always_use_internal_keyboard_check_box.widget,
|
|
||||||
down_widget=self._show_user_mods_button)
|
|
||||||
ba.widget(
|
|
||||||
edit=self._show_user_mods_button,
|
|
||||||
up_widget=self._always_use_internal_keyboard_check_box.widget)
|
|
||||||
else:
|
|
||||||
ba.widget(edit=self._show_user_mods_button,
|
|
||||||
up_widget=self._kick_idle_players_check_box.widget)
|
|
||||||
ba.widget(edit=self._kick_idle_players_check_box.widget,
|
|
||||||
down_widget=self._show_user_mods_button)
|
|
||||||
|
|
||||||
v -= self._spacing * 2.0
|
|
||||||
|
|
||||||
self._modding_guide_button = ba.buttonwidget(
|
self._modding_guide_button = ba.buttonwidget(
|
||||||
parent=self._subcontainer,
|
parent=self._subcontainer,
|
||||||
position=(self._sub_width / 2 - this_button_width / 2, v - 10),
|
position=(self._sub_width / 2 - this_button_width / 2, v - 10),
|
||||||
|
|
@ -454,8 +432,30 @@ class AdvancedSettingsWindow(ba.Window):
|
||||||
label=ba.Lstr(resource=self._r + '.moddingGuideText'),
|
label=ba.Lstr(resource=self._r + '.moddingGuideText'),
|
||||||
text_scale=1.0,
|
text_scale=1.0,
|
||||||
on_activate_call=ba.Call(
|
on_activate_call=ba.Call(
|
||||||
ba.open_url,
|
ba.open_url, 'http://ballistica.net/wiki/modding-guide'))
|
||||||
'http://www.froemling.net/docs/bombsquad-modding-guide'))
|
if self._show_always_use_internal_keyboard:
|
||||||
|
assert self._always_use_internal_keyboard_check_box is not None
|
||||||
|
ba.widget(edit=self._always_use_internal_keyboard_check_box.widget,
|
||||||
|
down_widget=self._modding_guide_button)
|
||||||
|
ba.widget(
|
||||||
|
edit=self._modding_guide_button,
|
||||||
|
up_widget=self._always_use_internal_keyboard_check_box.widget)
|
||||||
|
else:
|
||||||
|
ba.widget(edit=self._modding_guide_button,
|
||||||
|
up_widget=self._kick_idle_players_check_box.widget)
|
||||||
|
ba.widget(edit=self._kick_idle_players_check_box.widget,
|
||||||
|
down_widget=self._modding_guide_button)
|
||||||
|
|
||||||
|
v -= self._spacing * 2.0
|
||||||
|
|
||||||
|
self._show_user_mods_button = ba.buttonwidget(
|
||||||
|
parent=self._subcontainer,
|
||||||
|
position=(self._sub_width / 2 - this_button_width / 2, v - 10),
|
||||||
|
size=(this_button_width, 60),
|
||||||
|
autoselect=True,
|
||||||
|
label=ba.Lstr(resource=self._r + '.showUserModsText'),
|
||||||
|
text_scale=1.0,
|
||||||
|
on_activate_call=show_user_scripts)
|
||||||
|
|
||||||
v -= self._spacing * 2.0
|
v -= self._spacing * 2.0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import weakref
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from efro.error import CleanError
|
||||||
import _ba
|
import _ba
|
||||||
import ba
|
import ba
|
||||||
from bastd.ui.settings.testing import TestingWindow
|
from bastd.ui.settings.testing import TestingWindow
|
||||||
|
|
@ -148,10 +149,12 @@ def _run_diagnostics(weakwin: weakref.ref[NetTestingWindow]) -> None:
|
||||||
call()
|
call()
|
||||||
duration = time.monotonic() - starttime
|
duration = time.monotonic() - starttime
|
||||||
_print(f'Succeeded in {duration:.2f}s.', color=(0, 1, 0))
|
_print(f'Succeeded in {duration:.2f}s.', color=(0, 1, 0))
|
||||||
except Exception:
|
except Exception as exc:
|
||||||
import traceback
|
import traceback
|
||||||
duration = time.monotonic() - starttime
|
duration = time.monotonic() - starttime
|
||||||
_print(traceback.format_exc(), color=(1.0, 1.0, 0.3))
|
msg = (str(exc)
|
||||||
|
if isinstance(exc, CleanError) else traceback.format_exc())
|
||||||
|
_print(msg, color=(1.0, 1.0, 0.3))
|
||||||
_print(f'Failed in {duration:.2f}s.', color=(1, 0, 0))
|
_print(f'Failed in {duration:.2f}s.', color=(1, 0, 0))
|
||||||
have_error[0] = True
|
have_error[0] = True
|
||||||
|
|
||||||
|
|
@ -193,6 +196,9 @@ def _run_diagnostics(weakwin: weakref.ref[NetTestingWindow]) -> None:
|
||||||
_print(f'\nContacting V2 master-server ({baseaddr})...')
|
_print(f'\nContacting V2 master-server ({baseaddr})...')
|
||||||
_print_test_results(lambda: _test_fetch(baseaddr))
|
_print_test_results(lambda: _test_fetch(baseaddr))
|
||||||
|
|
||||||
|
_print('\nComparing local time to V2 server...')
|
||||||
|
_print_test_results(_test_v2_time)
|
||||||
|
|
||||||
# Get V2 nearby zone
|
# Get V2 nearby zone
|
||||||
with ba.app.net.zone_pings_lock:
|
with ba.app.net.zone_pings_lock:
|
||||||
zone_pings = copy.deepcopy(ba.app.net.zone_pings)
|
zone_pings = copy.deepcopy(ba.app.net.zone_pings)
|
||||||
|
|
@ -206,6 +212,9 @@ def _run_diagnostics(weakwin: weakref.ref[NetTestingWindow]) -> None:
|
||||||
_print(f'\nChecking nearest V2 zone ping ({nearstr})...')
|
_print(f'\nChecking nearest V2 zone ping ({nearstr})...')
|
||||||
_print_test_results(lambda: _test_nearby_zone_ping(nearest_zone))
|
_print_test_results(lambda: _test_nearby_zone_ping(nearest_zone))
|
||||||
|
|
||||||
|
_print('\nSending V2 cloud message...')
|
||||||
|
_print_test_results(_test_v2_cloud_message)
|
||||||
|
|
||||||
if have_error[0]:
|
if have_error[0]:
|
||||||
_print('\nDiagnostics complete. Some diagnostics failed.',
|
_print('\nDiagnostics complete. Some diagnostics failed.',
|
||||||
color=(10, 0, 0))
|
color=(10, 0, 0))
|
||||||
|
|
@ -271,12 +280,67 @@ def _test_v1_transaction() -> None:
|
||||||
raise RuntimeError(results[0])
|
raise RuntimeError(results[0])
|
||||||
|
|
||||||
|
|
||||||
|
def _test_v2_cloud_message() -> None:
|
||||||
|
from dataclasses import dataclass
|
||||||
|
import bacommon.cloud
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class _Results:
|
||||||
|
errstr: str | None = None
|
||||||
|
send_time: float | None = None
|
||||||
|
response_time: float | None = None
|
||||||
|
|
||||||
|
results = _Results()
|
||||||
|
|
||||||
|
def _cb(response: bacommon.cloud.PingResponse | Exception) -> None:
|
||||||
|
# Note: this runs in another thread so need to avoid exceptions.
|
||||||
|
results.response_time = time.monotonic()
|
||||||
|
if isinstance(response, Exception):
|
||||||
|
results.errstr = str(response)
|
||||||
|
if not isinstance(response, bacommon.cloud.PingResponse):
|
||||||
|
results.errstr = f'invalid response type: {type(response)}.'
|
||||||
|
|
||||||
|
def _send() -> None:
|
||||||
|
# Note: this runs in another thread so need to avoid exceptions.
|
||||||
|
results.send_time = time.monotonic()
|
||||||
|
ba.app.cloud.send_message_cb(bacommon.cloud.PingMessage(), _cb)
|
||||||
|
|
||||||
|
# This stuff expects to be run from the logic thread.
|
||||||
|
ba.pushcall(_send, from_other_thread=True)
|
||||||
|
|
||||||
|
wait_start_time = time.monotonic()
|
||||||
|
while True:
|
||||||
|
if results.response_time is not None:
|
||||||
|
break
|
||||||
|
time.sleep(0.01)
|
||||||
|
if time.monotonic() - wait_start_time > 10.0:
|
||||||
|
raise RuntimeError('Timeout waiting for cloud message response')
|
||||||
|
if results.errstr is not None:
|
||||||
|
raise RuntimeError(results.errstr)
|
||||||
|
|
||||||
|
|
||||||
|
def _test_v2_time() -> None:
|
||||||
|
offset = ba.app.net.server_time_offset_hours
|
||||||
|
if offset is None:
|
||||||
|
raise RuntimeError('no time offset found;'
|
||||||
|
' perhaps unable to communicate with v2 server?')
|
||||||
|
if abs(offset) >= 2.0:
|
||||||
|
raise CleanError(
|
||||||
|
f'Your device time is off from world time by {offset:.1f} hours.\n'
|
||||||
|
'This may cause network operations to fail due to your device\n'
|
||||||
|
' incorrectly treating SSL certificates as not-yet-valid, etc.\n'
|
||||||
|
'Check your device time and time-zone settings to fix this.\n')
|
||||||
|
|
||||||
|
|
||||||
def _test_fetch(baseaddr: str) -> None:
|
def _test_fetch(baseaddr: str) -> None:
|
||||||
# pylint: disable=consider-using-with
|
# pylint: disable=consider-using-with
|
||||||
import urllib.request
|
import urllib.request
|
||||||
response = urllib.request.urlopen(urllib.request.Request(
|
response = urllib.request.urlopen(
|
||||||
f'{baseaddr}/ping', None, {'User-Agent': _ba.app.user_agent_string}),
|
urllib.request.Request(f'{baseaddr}/ping', None,
|
||||||
timeout=10.0)
|
{'User-Agent': _ba.app.user_agent_string}),
|
||||||
|
context=ba.app.net.sslcontext,
|
||||||
|
timeout=10.0,
|
||||||
|
)
|
||||||
if response.getcode() != 200:
|
if response.getcode() != 200:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f'Got unexpected response code {response.getcode()}.')
|
f'Got unexpected response code {response.getcode()}.')
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ class PluginSettingsWindow(ba.Window):
|
||||||
self._subcontainer = ba.columnwidget(parent=self._scrollwidget,
|
self._subcontainer = ba.columnwidget(parent=self._scrollwidget,
|
||||||
selection_loops_to_parent=True)
|
selection_loops_to_parent=True)
|
||||||
|
|
||||||
if ba.app.meta.metascan is None:
|
if ba.app.meta.scanresults is None:
|
||||||
ba.screenmessage('Still scanning plugins; please try again.',
|
ba.screenmessage('Still scanning plugins; please try again.',
|
||||||
color=(1, 0, 0))
|
color=(1, 0, 0))
|
||||||
ba.playsound(ba.getsound('error'))
|
ba.playsound(ba.getsound('error'))
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,7 @@ class SoundtrackEntryTypeSelectWindow(ba.Window):
|
||||||
from ba.osmusic import OSMusicPlayer
|
from ba.osmusic import OSMusicPlayer
|
||||||
from bastd.ui.fileselector import FileSelectorWindow
|
from bastd.ui.fileselector import FileSelectorWindow
|
||||||
ba.containerwidget(edit=self._root_widget, transition='out_left')
|
ba.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
base_path = _ba.android_get_external_storage_path()
|
base_path = _ba.android_get_external_files_dir()
|
||||||
ba.app.ui.set_main_menu_window(
|
ba.app.ui.set_main_menu_window(
|
||||||
FileSelectorWindow(
|
FileSelectorWindow(
|
||||||
base_path,
|
base_path,
|
||||||
|
|
@ -173,7 +173,7 @@ class SoundtrackEntryTypeSelectWindow(ba.Window):
|
||||||
def _on_music_folder_press(self) -> None:
|
def _on_music_folder_press(self) -> None:
|
||||||
from bastd.ui.fileselector import FileSelectorWindow
|
from bastd.ui.fileselector import FileSelectorWindow
|
||||||
ba.containerwidget(edit=self._root_widget, transition='out_left')
|
ba.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
base_path = _ba.android_get_external_storage_path()
|
base_path = _ba.android_get_external_files_dir()
|
||||||
ba.app.ui.set_main_menu_window(
|
ba.app.ui.set_main_menu_window(
|
||||||
FileSelectorWindow(base_path,
|
FileSelectorWindow(base_path,
|
||||||
callback=self._music_folder_selector_cb,
|
callback=self._music_folder_selector_cb,
|
||||||
|
|
|
||||||
|
|
@ -182,8 +182,9 @@ class TournamentEntryWindow(popup.PopupWindow):
|
||||||
h_align='center',
|
h_align='center',
|
||||||
v_align='center',
|
v_align='center',
|
||||||
scale=0.6,
|
scale=0.6,
|
||||||
text=ba.Lstr(resource='watchAVideoText',
|
# Note: AdMob now requires rewarded ad usage
|
||||||
fallback_resource='watchAnAdText'),
|
# specifically says 'Ad' in it.
|
||||||
|
text=ba.Lstr(resource='watchAnAdText'),
|
||||||
maxwidth=95,
|
maxwidth=95,
|
||||||
color=(0, 1, 0))
|
color=(0, 1, 0))
|
||||||
ad_plays_remaining_text = (
|
ad_plays_remaining_text = (
|
||||||
|
|
|
||||||
10
dist/ba_data/python/bastd/ui/trophies.py
vendored
10
dist/ba_data/python/bastd/ui/trophies.py
vendored
|
|
@ -112,7 +112,7 @@ class TrophiesWindow(popup.PopupWindow):
|
||||||
sub_width: int,
|
sub_width: int,
|
||||||
trophy_types: list[list[str]]) -> int:
|
trophy_types: list[list[str]]) -> int:
|
||||||
from ba.internal import get_trophy_string
|
from ba.internal import get_trophy_string
|
||||||
pts = 0
|
total_pts = 0
|
||||||
for i, trophy_type in enumerate(trophy_types):
|
for i, trophy_type in enumerate(trophy_types):
|
||||||
t_count = self._data['t' + trophy_type[0]]
|
t_count = self._data['t' + trophy_type[0]]
|
||||||
t_mult = self._data['t' + trophy_type[0] + 'm']
|
t_mult = self._data['t' + trophy_type[0] + 'm']
|
||||||
|
|
@ -157,7 +157,7 @@ class TrophiesWindow(popup.PopupWindow):
|
||||||
h_align='center',
|
h_align='center',
|
||||||
v_align='center')
|
v_align='center')
|
||||||
|
|
||||||
pts = t_count * t_mult
|
this_pts = t_count * t_mult
|
||||||
ba.textwidget(parent=self._subcontainer,
|
ba.textwidget(parent=self._subcontainer,
|
||||||
position=(sub_width * 0.88,
|
position=(sub_width * 0.88,
|
||||||
sub_height - 20 - incr * i),
|
sub_height - 20 - incr * i),
|
||||||
|
|
@ -167,12 +167,12 @@ class TrophiesWindow(popup.PopupWindow):
|
||||||
flatness=1.0,
|
flatness=1.0,
|
||||||
shadow=0.0,
|
shadow=0.0,
|
||||||
scale=0.5,
|
scale=0.5,
|
||||||
text=eq_text.replace('${NUMBER}', str(pts)),
|
text=eq_text.replace('${NUMBER}', str(this_pts)),
|
||||||
size=(0, 0),
|
size=(0, 0),
|
||||||
h_align='center',
|
h_align='center',
|
||||||
v_align='center')
|
v_align='center')
|
||||||
pts += pts
|
total_pts += this_pts
|
||||||
return pts
|
return total_pts
|
||||||
|
|
||||||
def _on_cancel_press(self) -> None:
|
def _on_cancel_press(self) -> None:
|
||||||
self._transition_out()
|
self._transition_out()
|
||||||
|
|
|
||||||
64
dist/ba_data/python/efro/error.py
vendored
64
dist/ba_data/python/efro/error.py
vendored
|
|
@ -4,6 +4,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
import errno
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
pass
|
pass
|
||||||
|
|
@ -39,12 +40,13 @@ class CommunicationError(Exception):
|
||||||
"""A communication related error has occurred.
|
"""A communication related error has occurred.
|
||||||
|
|
||||||
This covers anything network-related going wrong in the sending
|
This covers anything network-related going wrong in the sending
|
||||||
of data or receiving of a response. This error does not imply
|
of data or receiving of a response. Basically anything that is out
|
||||||
|
of our control should get lumped in here. This error does not imply
|
||||||
that data was not received on the other end; only that a full
|
that data was not received on the other end; only that a full
|
||||||
acknowledgement round trip was not completed.
|
acknowledgement round trip was not completed.
|
||||||
|
|
||||||
These errors should be gracefully handled whenever possible, as
|
These errors should be gracefully handled whenever possible, as
|
||||||
occasional network outages are generally unavoidable.
|
occasional network issues are unavoidable.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -55,9 +57,9 @@ class RemoteError(Exception):
|
||||||
occurs remotely. The error string can consist of a remote stack
|
occurs remotely. The error string can consist of a remote stack
|
||||||
trace or a simple message depending on the context.
|
trace or a simple message depending on the context.
|
||||||
|
|
||||||
Communication systems should raise more specific error types when
|
Communication systems should raise more specific error types locally
|
||||||
more introspection/control is needed; this is intended somewhat as
|
when more introspection/control is needed; this is intended somewhat
|
||||||
a catch-all.
|
as a catch-all.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
|
|
@ -69,31 +71,43 @@ class IntegrityError(ValueError):
|
||||||
"""Data has been tampered with or corrupted in some form."""
|
"""Data has been tampered with or corrupted in some form."""
|
||||||
|
|
||||||
|
|
||||||
def is_urllib_network_error(exc: BaseException) -> bool:
|
def is_urllib_communication_error(exc: BaseException, url: str | None) -> bool:
|
||||||
"""Is the provided exception from urllib a network-related error?
|
"""Is the provided exception from urllib a communication-related error?
|
||||||
|
|
||||||
|
Url, if provided can provide extra context for when to treat an error
|
||||||
|
as such an error.
|
||||||
|
|
||||||
This should be passed an exception which resulted from opening or
|
This should be passed an exception which resulted from opening or
|
||||||
reading a urllib Request. It returns True for any errors that could
|
reading a urllib Request. It returns True for any errors that could
|
||||||
conceivably arise due to unavailable/poor network connections,
|
conceivably arise due to unavailable/poor network connections,
|
||||||
firewall/connectivity issues, etc. These issues can often be safely
|
firewall/connectivity issues, or other issues out of our control.
|
||||||
ignored or presented to the user as general 'network-unavailable'
|
These errors can often be safely ignored or presented to the user
|
||||||
states.
|
as general 'network-unavailable' states.
|
||||||
"""
|
"""
|
||||||
import urllib.error
|
import urllib.error
|
||||||
import http.client
|
import http.client
|
||||||
import errno
|
|
||||||
import socket
|
import socket
|
||||||
if isinstance(
|
if isinstance(exc, (urllib.error.URLError, ConnectionError,
|
||||||
exc,
|
http.client.IncompleteRead, http.client.BadStatusLine,
|
||||||
(urllib.error.URLError, ConnectionError, http.client.IncompleteRead,
|
http.client.RemoteDisconnected, socket.timeout)):
|
||||||
http.client.BadStatusLine, socket.timeout)):
|
|
||||||
# Special case: although an HTTPError is a subclass of URLError,
|
# Special case: although an HTTPError is a subclass of URLError,
|
||||||
# we don't return True for it. It means we have successfully
|
# we don't consider it a communication error. It generally means we
|
||||||
# communicated with the server but what we are asking for is
|
# have successfully communicated with the server but what we are asking
|
||||||
# not there/etc.
|
# for is not there/etc.
|
||||||
if isinstance(exc, urllib.error.HTTPError):
|
if isinstance(exc, urllib.error.HTTPError):
|
||||||
|
|
||||||
|
# Special sub-case: appspot.com hosting seems to give 403 errors
|
||||||
|
# (forbidden) to some countries. I'm assuming for legal reasons?..
|
||||||
|
# Let's consider that a communication error since its out of our
|
||||||
|
# control so we don't fill up logs with it.
|
||||||
|
if exc.code == 403 and url is not None and '.appspot.com' in url:
|
||||||
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if isinstance(exc, OSError):
|
if isinstance(exc, OSError):
|
||||||
if exc.errno == 10051: # Windows unreachable network error.
|
if exc.errno == 10051: # Windows unreachable network error.
|
||||||
return True
|
return True
|
||||||
|
|
@ -106,18 +120,17 @@ def is_urllib_network_error(exc: BaseException) -> bool:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def is_udp_network_error(exc: BaseException) -> bool:
|
def is_udp_communication_error(exc: BaseException) -> bool:
|
||||||
"""Is the provided exception a network-related error?
|
"""Should this udp-related exception be considered a communication error?
|
||||||
|
|
||||||
This should be passed an exception which resulted from creating and
|
This should be passed an exception which resulted from creating and
|
||||||
using a socket.SOCK_DGRAM type socket. It should return True for any
|
using a socket.SOCK_DGRAM type socket. It should return True for any
|
||||||
errors that could conceivably arise due to unavailable/poor network
|
errors that could conceivably arise due to unavailable/poor network
|
||||||
connections, firewall/connectivity issues, etc. These issues can often
|
conditions, firewall/connectivity issues, etc. These issues can often
|
||||||
be safely ignored or presented to the user as general
|
be safely ignored or presented to the user as general
|
||||||
'network-unavailable' states.
|
'network-unavailable' states.
|
||||||
"""
|
"""
|
||||||
import errno
|
if isinstance(exc, ConnectionRefusedError | TimeoutError):
|
||||||
if isinstance(exc, ConnectionRefusedError):
|
|
||||||
return True
|
return True
|
||||||
if isinstance(exc, OSError):
|
if isinstance(exc, OSError):
|
||||||
if exc.errno == 10051: # Windows unreachable network error.
|
if exc.errno == 10051: # Windows unreachable network error.
|
||||||
|
|
@ -140,8 +153,8 @@ def is_udp_network_error(exc: BaseException) -> bool:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def is_asyncio_streams_network_error(exc: BaseException) -> bool:
|
def is_asyncio_streams_communication_error(exc: BaseException) -> bool:
|
||||||
"""Is the provided exception a network-related error?
|
"""Should this streams error be considered a communication error?
|
||||||
|
|
||||||
This should be passed an exception which resulted from creating and
|
This should be passed an exception which resulted from creating and
|
||||||
using asyncio streams. It should return True for any errors that could
|
using asyncio streams. It should return True for any errors that could
|
||||||
|
|
@ -149,7 +162,6 @@ def is_asyncio_streams_network_error(exc: BaseException) -> bool:
|
||||||
firewall/connectivity issues, etc. These issues can often be safely
|
firewall/connectivity issues, etc. These issues can often be safely
|
||||||
ignored or presented to the user as general 'connection-lost' events.
|
ignored or presented to the user as general 'connection-lost' events.
|
||||||
"""
|
"""
|
||||||
import errno
|
|
||||||
import ssl
|
import ssl
|
||||||
|
|
||||||
if isinstance(exc, (
|
if isinstance(exc, (
|
||||||
|
|
|
||||||
1
dist/ba_data/python/efro/message/_message.py
vendored
1
dist/ba_data/python/efro/message/_message.py
vendored
|
|
@ -56,6 +56,7 @@ class ErrorResponse(Response):
|
||||||
OTHER = 0
|
OTHER = 0
|
||||||
CLEAN = 1
|
CLEAN = 1
|
||||||
LOCAL = 2
|
LOCAL = 2
|
||||||
|
COMMUNICATION = 3
|
||||||
|
|
||||||
error_message: Annotated[str, IOAttrs('m')]
|
error_message: Annotated[str, IOAttrs('m')]
|
||||||
error_type: Annotated[ErrorType, IOAttrs('e')] = ErrorType.OTHER
|
error_type: Annotated[ErrorType, IOAttrs('e')] = ErrorType.OTHER
|
||||||
|
|
|
||||||
49
dist/ba_data/python/efro/message/_protocol.py
vendored
49
dist/ba_data/python/efro/message/_protocol.py
vendored
|
|
@ -25,28 +25,40 @@ class MessageProtocol:
|
||||||
"""Wrangles a set of message types, formats, and response types.
|
"""Wrangles a set of message types, formats, and response types.
|
||||||
Both endpoints must be using a compatible Protocol for communication
|
Both endpoints must be using a compatible Protocol for communication
|
||||||
to succeed. To maintain Protocol compatibility between revisions,
|
to succeed. To maintain Protocol compatibility between revisions,
|
||||||
all message types must retain the same id, message attr storage names must
|
all message types must retain the same id, message attr storage
|
||||||
not change, newly added attrs must have default values, etc.
|
names must not change, newly added attrs must have default values,
|
||||||
|
etc.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
message_types: dict[int, type[Message]],
|
message_types: dict[int, type[Message]],
|
||||||
response_types: dict[int, type[Response]],
|
response_types: dict[int, type[Response]],
|
||||||
preserve_clean_errors: bool = True,
|
preserve_clean_errors: bool = True,
|
||||||
log_remote_exceptions: bool = True,
|
receiver_logs_exceptions: bool = True,
|
||||||
trusted_sender: bool = False) -> None:
|
receiver_returns_stack_traces: bool = False) -> None:
|
||||||
"""Create a protocol with a given configuration.
|
"""Create a protocol with a given configuration.
|
||||||
|
|
||||||
Note that common response types are automatically registered
|
Note that common response types are automatically registered
|
||||||
with (unchanging negative ids) so they don't need to be passed
|
with (unchanging negative ids) so they don't need to be passed
|
||||||
explicitly (but can be if a different id is desired).
|
explicitly (but can be if a different id is desired).
|
||||||
|
|
||||||
If 'preserve_clean_errors' is True, efro.error.CleanError errors
|
If 'preserve_clean_errors' is True, efro.error.CleanError
|
||||||
on the remote end will result in the same error raised locally.
|
exceptions raised on the receiver end will result in a matching
|
||||||
All other Exception types come across as efro.error.RemoteError.
|
CleanError raised back on the sender. All other Exception types
|
||||||
|
come across as efro.error.RemoteError.
|
||||||
|
|
||||||
If 'trusted_sender' is True, stringified remote stack traces will
|
When 'receiver_logs_exceptions' is True, any uncaught Exceptions
|
||||||
be included in the responses if errors occur.
|
on the receiver end will be logged there via logging.exception()
|
||||||
|
(in addition to the usual behavior of returning an ErrorResponse
|
||||||
|
to the sender). This is good to leave enabled if your
|
||||||
|
intention is to never return ErrorResponses. Looser setups
|
||||||
|
making routine use of CleanErrors or whatnot may want to
|
||||||
|
disable this, however.
|
||||||
|
|
||||||
|
If 'receiver_returns_stack_traces' is True, stringified stack
|
||||||
|
traces will be returned to the sender for exceptions occurring
|
||||||
|
on the receiver end. This can make debugging easier but should
|
||||||
|
only be used when the client is trusted to see such info.
|
||||||
"""
|
"""
|
||||||
self.message_types_by_id: dict[int, type[Message]] = {}
|
self.message_types_by_id: dict[int, type[Message]] = {}
|
||||||
self.message_ids_by_type: dict[type[Message], int] = {}
|
self.message_ids_by_type: dict[type[Message], int] = {}
|
||||||
|
|
@ -102,9 +114,9 @@ class MessageProtocol:
|
||||||
assert is_ioprepped_dataclass(cls)
|
assert is_ioprepped_dataclass(cls)
|
||||||
assert issubclass(cls, Response)
|
assert issubclass(cls, Response)
|
||||||
if cls not in self.response_ids_by_type:
|
if cls not in self.response_ids_by_type:
|
||||||
raise ValueError(f'Possible response type {cls}'
|
raise ValueError(
|
||||||
f' needs to be included in response_types'
|
f'Possible response type {cls} needs to be included'
|
||||||
f' for this protocol.')
|
f' in response_types for this protocol.')
|
||||||
|
|
||||||
# Make sure all registered types have unique base names.
|
# Make sure all registered types have unique base names.
|
||||||
# We can take advantage of this to generate cleaner looking
|
# We can take advantage of this to generate cleaner looking
|
||||||
|
|
@ -116,8 +128,8 @@ class MessageProtocol:
|
||||||
' all types are required to have unique names.')
|
' all types are required to have unique names.')
|
||||||
|
|
||||||
self.preserve_clean_errors = preserve_clean_errors
|
self.preserve_clean_errors = preserve_clean_errors
|
||||||
self.log_remote_exceptions = log_remote_exceptions
|
self.receiver_logs_exceptions = receiver_logs_exceptions
|
||||||
self.trusted_sender = trusted_sender
|
self.receiver_returns_stack_traces = receiver_returns_stack_traces
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def encode_dict(obj: dict) -> str:
|
def encode_dict(obj: dict) -> str:
|
||||||
|
|
@ -134,7 +146,9 @@ class MessageProtocol:
|
||||||
|
|
||||||
def error_to_response(self, exc: Exception) -> Response:
|
def error_to_response(self, exc: Exception) -> Response:
|
||||||
"""Translate an error to a response."""
|
"""Translate an error to a response."""
|
||||||
if self.log_remote_exceptions:
|
|
||||||
|
# Log any errors we got during handling if so desired.
|
||||||
|
if self.receiver_logs_exceptions:
|
||||||
logging.exception('Error handling message.')
|
logging.exception('Error handling message.')
|
||||||
|
|
||||||
# If anything goes wrong, return a ErrorResponse instead.
|
# If anything goes wrong, return a ErrorResponse instead.
|
||||||
|
|
@ -142,8 +156,9 @@ class MessageProtocol:
|
||||||
return ErrorResponse(error_message=str(exc),
|
return ErrorResponse(error_message=str(exc),
|
||||||
error_type=ErrorResponse.ErrorType.CLEAN)
|
error_type=ErrorResponse.ErrorType.CLEAN)
|
||||||
return ErrorResponse(
|
return ErrorResponse(
|
||||||
error_message=(traceback.format_exc() if self.trusted_sender else
|
error_message=(traceback.format_exc()
|
||||||
'An unknown error has occurred.'),
|
if self.receiver_returns_stack_traces else
|
||||||
|
'An internal error has occurred.'),
|
||||||
error_type=ErrorResponse.ErrorType.OTHER)
|
error_type=ErrorResponse.ErrorType.OTHER)
|
||||||
|
|
||||||
def _to_dict(self, message: Any, ids_by_type: dict[type, int],
|
def _to_dict(self, message: Any, ids_by_type: dict[type, int],
|
||||||
|
|
|
||||||
52
dist/ba_data/python/efro/message/_sender.py
vendored
52
dist/ba_data/python/efro/message/_sender.py
vendored
|
|
@ -9,7 +9,7 @@ from __future__ import annotations
|
||||||
import logging
|
import logging
|
||||||
from typing import TYPE_CHECKING, TypeVar
|
from typing import TYPE_CHECKING, TypeVar
|
||||||
|
|
||||||
from efro.error import CleanError, RemoteError
|
from efro.error import CleanError, RemoteError, CommunicationError
|
||||||
from efro.message._message import EmptyResponse, ErrorResponse
|
from efro.message._message import EmptyResponse, ErrorResponse
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
|
@ -35,7 +35,7 @@ class MessageSender:
|
||||||
def send_raw_message(self, message: str) -> str:
|
def send_raw_message(self, message: str) -> str:
|
||||||
# Actually send the message here.
|
# Actually send the message here.
|
||||||
|
|
||||||
# MyMessageSender class should provide overloads for send(), send_bg(),
|
# MyMessageSender class should provide overloads for send(), send_async(),
|
||||||
# etc. to ensure all sending happens with valid types.
|
# etc. to ensure all sending happens with valid types.
|
||||||
obj = MyClass()
|
obj = MyClass()
|
||||||
obj.msg.send(SomeMessageType())
|
obj.msg.send(SomeMessageType())
|
||||||
|
|
@ -54,7 +54,12 @@ class MessageSender:
|
||||||
def send_method(
|
def send_method(
|
||||||
self, call: Callable[[Any, str],
|
self, call: Callable[[Any, str],
|
||||||
str]) -> Callable[[Any, str], str]:
|
str]) -> Callable[[Any, str], str]:
|
||||||
"""Function decorator for setting raw send method."""
|
"""Function decorator for setting raw send method.
|
||||||
|
|
||||||
|
Send methods take strings and should return strings.
|
||||||
|
Any Exception raised during the send_method manifests as
|
||||||
|
a CommunicationError for the message sender.
|
||||||
|
"""
|
||||||
assert self._send_raw_message_call is None
|
assert self._send_raw_message_call is None
|
||||||
self._send_raw_message_call = call
|
self._send_raw_message_call = call
|
||||||
return call
|
return call
|
||||||
|
|
@ -62,7 +67,12 @@ class MessageSender:
|
||||||
def send_async_method(
|
def send_async_method(
|
||||||
self, call: Callable[[Any, str], Awaitable[str]]
|
self, call: Callable[[Any, str], Awaitable[str]]
|
||||||
) -> Callable[[Any, str], Awaitable[str]]:
|
) -> Callable[[Any, str], Awaitable[str]]:
|
||||||
"""Function decorator for setting raw send-async method."""
|
"""Function decorator for setting raw send-async method.
|
||||||
|
|
||||||
|
Send methods take strings and should return strings.
|
||||||
|
Any Exception raised during the send_method manifests as
|
||||||
|
a CommunicationError for the message sender.
|
||||||
|
"""
|
||||||
assert self._send_async_raw_message_call is None
|
assert self._send_async_raw_message_call is None
|
||||||
self._send_async_raw_message_call = call
|
self._send_async_raw_message_call = call
|
||||||
return call
|
return call
|
||||||
|
|
@ -123,7 +133,17 @@ class MessageSender:
|
||||||
raise RuntimeError('send() is unimplemented for this type.')
|
raise RuntimeError('send() is unimplemented for this type.')
|
||||||
|
|
||||||
msg_encoded = self._encode_message(bound_obj, message)
|
msg_encoded = self._encode_message(bound_obj, message)
|
||||||
response_encoded = self._send_raw_message_call(bound_obj, msg_encoded)
|
try:
|
||||||
|
response_encoded = self._send_raw_message_call(
|
||||||
|
bound_obj, msg_encoded)
|
||||||
|
except Exception as exc:
|
||||||
|
# Any error in the raw send call gets recorded as either
|
||||||
|
# a local or communication error.
|
||||||
|
return ErrorResponse(
|
||||||
|
error_message=f'Error in send async method: {exc}',
|
||||||
|
error_type=(ErrorResponse.ErrorType.COMMUNICATION
|
||||||
|
if isinstance(exc, CommunicationError) else
|
||||||
|
ErrorResponse.ErrorType.LOCAL))
|
||||||
return self._decode_raw_response(bound_obj, message, response_encoded)
|
return self._decode_raw_response(bound_obj, message, response_encoded)
|
||||||
|
|
||||||
async def send_split_part_1_async(self, bound_obj: Any,
|
async def send_split_part_1_async(self, bound_obj: Any,
|
||||||
|
|
@ -139,9 +159,17 @@ class MessageSender:
|
||||||
raise RuntimeError('send_async() is unimplemented for this type.')
|
raise RuntimeError('send_async() is unimplemented for this type.')
|
||||||
|
|
||||||
msg_encoded = self._encode_message(bound_obj, message)
|
msg_encoded = self._encode_message(bound_obj, message)
|
||||||
response_encoded = await self._send_async_raw_message_call(
|
try:
|
||||||
bound_obj, msg_encoded)
|
response_encoded = await self._send_async_raw_message_call(
|
||||||
|
bound_obj, msg_encoded)
|
||||||
|
except Exception as exc:
|
||||||
|
# Any error in the raw send call gets recorded as either
|
||||||
|
# a local or communication error.
|
||||||
|
return ErrorResponse(
|
||||||
|
error_message=f'Error in send async method: {exc}',
|
||||||
|
error_type=(ErrorResponse.ErrorType.COMMUNICATION
|
||||||
|
if isinstance(exc, CommunicationError) else
|
||||||
|
ErrorResponse.ErrorType.LOCAL))
|
||||||
return self._decode_raw_response(bound_obj, message, response_encoded)
|
return self._decode_raw_response(bound_obj, message, response_encoded)
|
||||||
|
|
||||||
def send_split_part_2(self, message: Message,
|
def send_split_part_2(self, message: Message,
|
||||||
|
|
@ -183,8 +211,8 @@ class MessageSender:
|
||||||
# If we got to this point, we successfully communicated
|
# If we got to this point, we successfully communicated
|
||||||
# with the other end so errors represent protocol mismatches
|
# with the other end so errors represent protocol mismatches
|
||||||
# or other invalid data. For now let's just log it but perhaps
|
# or other invalid data. For now let's just log it but perhaps
|
||||||
# we'd want to somehow embed it in the ErrorResponse to be raised
|
# we'd want to somehow embed it in the ErrorResponse to be
|
||||||
# directly to the user later.
|
# available directly to the user later.
|
||||||
logging.exception('Error decoding raw response')
|
logging.exception('Error decoding raw response')
|
||||||
response = ErrorResponse(
|
response = ErrorResponse(
|
||||||
error_message=
|
error_message=
|
||||||
|
|
@ -208,6 +236,10 @@ class MessageSender:
|
||||||
# Some error occurred. Raise a local Exception for it.
|
# Some error occurred. Raise a local Exception for it.
|
||||||
if isinstance(raw_response, ErrorResponse):
|
if isinstance(raw_response, ErrorResponse):
|
||||||
|
|
||||||
|
if (raw_response.error_type is
|
||||||
|
ErrorResponse.ErrorType.COMMUNICATION):
|
||||||
|
raise CommunicationError(raw_response.error_message)
|
||||||
|
|
||||||
# If something went wrong on our end of the connection,
|
# If something went wrong on our end of the connection,
|
||||||
# don't say it was a remote error.
|
# don't say it was a remote error.
|
||||||
if raw_response.error_type is ErrorResponse.ErrorType.LOCAL:
|
if raw_response.error_type is ErrorResponse.ErrorType.LOCAL:
|
||||||
|
|
|
||||||
5
dist/ba_data/python/efro/rpc.py
vendored
5
dist/ba_data/python/efro/rpc.py
vendored
|
|
@ -13,8 +13,9 @@ from dataclasses import dataclass
|
||||||
from threading import current_thread
|
from threading import current_thread
|
||||||
from typing import TYPE_CHECKING, Annotated
|
from typing import TYPE_CHECKING, Annotated
|
||||||
|
|
||||||
from efro.error import CommunicationError, is_asyncio_streams_network_error
|
|
||||||
from efro.util import assert_never
|
from efro.util import assert_never
|
||||||
|
from efro.error import (CommunicationError,
|
||||||
|
is_asyncio_streams_communication_error)
|
||||||
from efro.dataclassio import (dataclass_to_json, dataclass_from_json,
|
from efro.dataclassio import (dataclass_to_json, dataclass_from_json,
|
||||||
ioprepped, IOAttrs)
|
ioprepped, IOAttrs)
|
||||||
|
|
||||||
|
|
@ -596,7 +597,7 @@ class RPCEndpoint:
|
||||||
if isinstance(exc, _KeepaliveTimeoutError):
|
if isinstance(exc, _KeepaliveTimeoutError):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return is_asyncio_streams_network_error(exc)
|
return is_asyncio_streams_communication_error(exc)
|
||||||
|
|
||||||
def _check_env(self) -> None:
|
def _check_env(self) -> None:
|
||||||
# I was seeing that asyncio stuff wasn't working as expected if
|
# I was seeing that asyncio stuff wasn't working as expected if
|
||||||
|
|
|
||||||
4
dist/ba_data/python/efro/util.py
vendored
4
dist/ba_data/python/efro/util.py
vendored
|
|
@ -637,9 +637,11 @@ def compact_id(num: int) -> str:
|
||||||
'abcdefghijklmnopqrstuvwxyz')
|
'abcdefghijklmnopqrstuvwxyz')
|
||||||
|
|
||||||
|
|
||||||
|
# NOTE: Even though this is available as part of typing_extensions, keeping
|
||||||
|
# it in here for now so we don't require typing_extensions as a dependency.
|
||||||
|
# Once 3.11 rolls around we can kill this and use typing.assert_never.
|
||||||
def assert_never(value: NoReturn) -> NoReturn:
|
def assert_never(value: NoReturn) -> NoReturn:
|
||||||
"""Trick for checking exhaustive handling of Enums, etc.
|
"""Trick for checking exhaustive handling of Enums, etc.
|
||||||
|
|
||||||
See https://github.com/python/typing/issues/735
|
See https://github.com/python/typing/issues/735
|
||||||
"""
|
"""
|
||||||
assert False, f'Unhandled value: {value} ({type(value).__name__})'
|
assert False, f'Unhandled value: {value} ({type(value).__name__})'
|
||||||
|
|
|
||||||
BIN
dist/bombsquad_headless
vendored
BIN
dist/bombsquad_headless
vendored
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue