Some progress with server status UI

This commit is contained in:
Henrik Rydgård committed 2026-03-30 11:34:19 -06:00
1 parent 90f52b88a1
commit cfc5d74602
56 files changed
+299 -138

No files matched your search

+4
View File
@@ -1,5 +1,7 @@
#pragma once
#ifdef _WIN32
#include <winapifamily.h>
// Utility file for using the MS CRT's memory tracking.
@@ -21,3 +23,5 @@
#endif // _DEBUG
#endif
#endif // _WIN32
+1 -1
View File
@@ -451,7 +451,7 @@ void Choice::GetContentDimensionsBySpec(const UIContext &dc, MeasureSpec horiz,
float scale = dc.CalculateTextScale(text_, availWidth);
float textW = 0.0f, textH = 0.0f;
dc.MeasureTextRect(dc.GetTheme().uiFont, scale, scale, text_, availWidth, &textW, &textH, FLAG_WRAP_TEXT);
textW += 2; // We need a small fudge factor here, not sure why yet.
textW += 4; // We need a small fudge factor here, not sure why yet.
totalH = std::max(totalH, textH);
totalW += textW;
if (image_.isValid()) {
+1
View File
@@ -284,6 +284,7 @@ public:
void Update() override;
// If you call this at creation, call it AFTER adding the subviews!
void SetOpen(bool open) {
_dbg_assert_(open_);
*open_ = open;
+14 -1
View File
@@ -150,7 +150,9 @@ static bool ParseServerListEntriesJSON(std::string_view json) {
entry.location = server.getStringOr("location", "");
entry.description = server.getStringOr("description", "");
entry.mode = equals(server.getStringOr("data_mode", ""), "AemuPostoffice") ? AdhocDataMode::AemuPostoffice : AdhocDataMode::P2P;
entry.statusUrl = server.getStringOr("status_data_json", "");
entry.dataJsonUrl = server.getStringOr("status_data_json", "");
entry.statusXmlUrl = server.getStringOr("status_xml", "");
entry.statusWebUrl = server.getStringOr("status_web", "");
if (entry.host.empty()) {
// Skipping invalid entry.
@@ -252,6 +254,17 @@ std::vector<AdhocServerListEntry> AdhocGetServerList(AdhocLoadListMode loadMode)
return g_proAdhocServerList;
}
bool AdhocGetServerByHost(std::string_view host, AdhocServerListEntry *dest) {
std::vector<AdhocServerListEntry> entries = AdhocGetServerList(AdhocLoadListMode::CacheOnlySync);
for (auto &entry : entries) {
if (equals(host, entry.host)) {
*dest = entry;
return true;
}
}
return false;
}
static AdhocDataMode AdhocGetServerDataMode(std::string_view server) {
std::vector<AdhocServerListEntry> list = AdhocGetServerList(AdhocLoadListMode::CacheOnlySync);
for (const auto &item : list) {
+4 -1
View File
@@ -111,7 +111,9 @@ struct AdhocServerListEntry {
std::string discord;
std::string location;
std::string description;
std::string statusUrl; // Usually empty or /data.json.
std::string dataJsonUrl;
std::string statusXmlUrl;
std::string statusWebUrl;
AdhocDataMode mode = AdhocDataMode::P2P;
};
@@ -122,6 +124,7 @@ enum class AdhocLoadListMode {
void AdhocLoadServerList(AdhocLoadListMode loadMode);
std::vector<AdhocServerListEntry> AdhocGetServerList(AdhocLoadListMode loadMode);
bool AdhocGetServerByHost(std::string_view host, AdhocServerListEntry *dest); // CacheOnlySync is enforced.
class PointerWrap;
+3 -2
View File
@@ -611,9 +611,10 @@ fn generate_prompt(filenames: &[String], section: &str, value: &str, extra: &str
let base_str = format!("Please translate '{value}' from US English to all of these languages: {languages}.
Output in json format, a single dictionary, key=value. Include en_US first (the original string).
For context, the string will be in the translation section '{section}', and these strings are UI strings for my PSP emulator application.
Keep the strings relatively short, try not to let them become more than 60% longer than the original string.
{extra}
Keep the strings relatively short, try not to let them become more than 60% longer than the original string unless necessary.
Do not output any text before or after the list of translated strings, do not ask followups.
{extra}");
");
base_str
}
+173 -131
View File
@@ -1,9 +1,9 @@
#include <algorithm>
#include "ppsspp_config.h"
#undef new
#include "ext/rapidjson/include/rapidjson/document.h"
#include "Common/DbgNew.h"
//#include "rapidjson/document.h"
#include "AdhocServerScreen.h"
#include "Core/Util/GameDB.h"
@@ -16,27 +16,8 @@
#include "Core/HLE/sceNetAdhoc.h"
#include "UI/MiscViews.h"
struct User {
std::string name;
std::vector<int> pdp_ports;
std::vector<int> ptp_ports;
};
struct Group {
std::string name;
int usercount;
std::vector<User> users;
};
struct Game {
std::string name;
int usercount;
std::vector<Group> groups;
std::vector<std::string> game_ids;
};
static void UpgradeName(std::string *str) {
if (str->size() == 9) { // TODO: Make a better check
static void UpgradeGameName(std::string *str) {
if (str->size() == 9) { // TODO: Make a better heuristic, we might make some failed lookup into the DB.
// It's probably a game ID. Convert it to a name using the database.
std::vector<GameDBInfo> infos;
if (g_gameDB.GetGameInfos(*str, &infos)) {
@@ -45,32 +26,32 @@ static void UpgradeName(std::string *str) {
}
}
std::vector<Game> ParseDataJson(std::string_view json) {
std::vector<AdhocGame> ParseDataJson(std::string_view json) {
rapidjson::Document d;
d.Parse(json.data(), json.size());
std::vector<Game> gameList;
std::vector<AdhocGame> gameList;
if (d.HasParseError() || !d.HasMember("games")) return gameList;
const auto& gamesArray = d["games"];
for (auto& g : gamesArray.GetArray()) {
Game game;
AdhocGame game;
game.name = g["name"].GetString();
UpgradeName(&game.name);
UpgradeGameName(&game.name);
// Handle string-to-int conversion for usercount
game.usercount = std::stoi(g["usercount"].GetString());
if (g.HasMember("groups")) {
for (auto& grp : g["groups"].GetArray()) {
Group group;
AdhocGroup group;
group.name = grp["name"].GetString();
group.usercount = std::stoi(grp["usercount"].GetString());
if (grp.HasMember("users")) {
for (auto& u : grp["users"].GetArray()) {
User user;
AdhocUser user;
user.name = u["name"].GetString();
for (auto& p : u["pdp_ports"].GetArray())
@@ -141,7 +122,60 @@ private:
bool hasRelay_ = false;
};
static UI::View *CreateLinkButton(std::string url) {
class AdhocServerCompactInfo : public UI::LinearLayout {
public:
AdhocServerCompactInfo(const AdhocServerListEntry &entry, UI::LayoutParams *layoutParams = nullptr);
void Draw(UIContext &dc) override {
UI::LinearLayout::Draw(dc);
// Underline
dc.Draw()->DrawImageCenterTexel(dc.GetTheme().whiteImage, bounds_.x, bounds_.y2() - 2, bounds_.x2(), bounds_.y2(), dc.GetTheme().popupTitleStyle.fgColor);
}
void GetContentDimensions(const UIContext &dc, float &w, float &h) const override {
w = 500; h = 100;
}
private:
AdhocServerListEntry entry_;
};
AdhocServerCompactInfo::AdhocServerCompactInfo(const AdhocServerListEntry &entry, UI::LayoutParams *layoutParams)
: UI::LinearLayout(ORIENT_HORIZONTAL, new UI::LinearLayoutParams(UI::FILL_PARENT, UI::WRAP_CONTENT, UI::Margins(5.0f, 0.0f))), entry_(entry) {
using namespace UI;
SetSpacing(5.0f);
LinearLayout *lines = Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(Margins(5, 5))));
lines->SetSpacing(0.0f);
TextView *name = lines->Add(new TextView(entry.name));
std::string secondLine = entry.host;
auto n = GetI18NCategory(I18NCat::NETWORKING);
if (!entry.location.empty()) {
secondLine += ": " + entry.location;
}
lines->Add(new TextView(secondLine))->SetTextSize(TextSize::Small)->SetWordWrap();
Add(new Spacer(0.0f, new LinearLayoutParams(1.0f, Margins(0.0f, 5.0f))));
if (entry.mode == AdhocDataMode::AemuPostoffice) {
TextView *relay = Add(new TextView(n->T("Relay"), new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT, Gravity::G_VCENTER, Margins(10.0))));
}
Add(new Choice(ImageID("I_FILE_COPY"), new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)))->OnClick.Add([host = entry_.host](UI::EventParams &) {
System_CopyStringToClipboard(host);
});
}
static UI::View *CreateInfoItemWithButton(std::string_view text, ImageID buttonImage, std::function<void(UI::EventParams &)> onClick) {
using namespace UI;
LinearLayout *line = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, Margins(12, 0)));
line->Add(new TextView(text, new LinearLayoutParams(0.0f, Gravity::G_VCENTER)));
line->Add(new Spacer(0, new LinearLayoutParams(1.0f)));
line->Add(new Choice(buttonImage, new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)))->OnClick.Add(onClick);
return line;
}
static UI::View *CreateLinkButton(std::string url, std::string_view title = "") {
using namespace UI;
// steal strings from all over the place
@@ -149,14 +183,14 @@ static UI::View *CreateLinkButton(std::string url) {
auto st = GetI18NCategory(I18NCat::STORE);
ImageID icon = ImageID("I_LINK_OUT_QUESTION");
std::string title;
if (startsWith(url, "https://discord")) {
icon = ImageID("I_LOGO_DISCORD");
title = cr->T("Discord");
if (title.empty())
title = cr->T("Discord");
} else {
icon = ImageID("I_LINK_OUT");
title = st->T("Website");
if (title.empty())
title = st->T("Website");
}
Choice *choice = new Choice(title, icon, new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT));
@@ -168,92 +202,120 @@ static UI::View *CreateLinkButton(std::string url) {
// Later, this might also show games-in-progress.
// For now, it's just a simple metadata viewer.
class AdhocServerInfoScreen : public UI::PopupScreen {
public:
AdhocServerInfoScreen(const AdhocServerListEntry &entry)
: PopupScreen(entry.name, T(I18NCat::DIALOG, "Back")), entry_(entry) {
AdhocServerInfoScreen::AdhocServerInfoScreen(const AdhocServerListEntry &entry)
: UI::PopupScreen("", T(I18NCat::DIALOG, "Back")), entry_(entry) {
if (!entry.statusUrl.empty()) {
statusRequest_ = g_DownloadManager.StartDownload(entry.statusUrl, Path(), http::RequestFlags::KeepInMemory | http::RequestFlags::Cached24H, nullptr, "status");
if (!entry.dataJsonUrl.empty()) {
statusRequest_ = g_DownloadManager.StartDownload(entry.dataJsonUrl, Path(), http::RequestFlags::KeepInMemory, nullptr, "status");
}
}
void AdhocServerInfoScreen::CreatePopupContents(UI::ViewGroup *parent) {
using namespace UI;
auto pa = GetI18NCategory(I18NCat::PAUSE);
auto di = GetI18NCategory(I18NCat::DIALOG);
auto ni = GetI18NCategory(I18NCat::NETWORKING);
Margins contentMargins(12, 0);
parent->Add(new AdhocServerCompactInfo(entry_, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, contentMargins)));
parent->Add(new Spacer(5.0f));
ScrollView *scroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f));
LinearLayout *content = new LinearLayout(ORIENT_VERTICAL);
content->SetSpacing(6.0f);
if (!entry_.ip.empty()) {
content->Add(new InfoItem(entry_.ip, ""));
}
TextView *desc = content->Add(new TextView(entry_.description, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, contentMargins)));
desc->SetTextSize(TextSize::Small);
desc->SetWordWrap();
if (!entry_.web.empty() || !entry_.discord.empty()) {
LinearLayout *buttonStrip = content->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
buttonStrip->SetSpacing(8);
if (!entry_.web.empty()) {
buttonStrip->Add(CreateLinkButton(entry_.web));
}
} // PopupScreen will translate Back on its own
const char *tag() const override { return "AdhocServerInfo"; }
protected:
bool FillVertical() const override { return false; }
UI::Size PopupWidth() const override { return 500; }
bool ShowButtons() const override { return true; }
void CreatePopupContents(UI::ViewGroup *parent) override {
using namespace UI;
auto pa = GetI18NCategory(I18NCat::PAUSE);
auto di = GetI18NCategory(I18NCat::DIALOG);
auto ni = GetI18NCategory(I18NCat::NETWORKING);
ScrollView *scroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f));
LinearLayout *content = new LinearLayout(ORIENT_VERTICAL);
Margins contentMargins(10, 0);
content->SetSpacing(0.0f);
LinearLayout *hostLine = content->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, Margins(12, 0))));
hostLine->Add(new TextView(entry_.host, new LinearLayoutParams(0.0f, Gravity::G_VCENTER)));
hostLine->Add(new Spacer(0, new LinearLayoutParams(1.0f)));
hostLine->Add(new Choice(ImageID("I_FILE_COPY"), new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)))->OnClick.Add([host = entry_.host](UI::EventParams &) {
System_CopyStringToClipboard(host);
});
if (!entry_.ip.empty()) {
content->Add(new InfoItem(entry_.ip, ""));
if (!entry_.discord.empty()) {
buttonStrip->Add(CreateLinkButton(entry_.discord));
}
content->Add(new InfoItem(entry_.location, ""));
content->Add(new InfoItem(ni->T("Relay server mode"), entry_.mode == AdhocDataMode::AemuPostoffice ? di->T("Yes") : di->T("No")));
TextView *desc = content->Add(new TextView(entry_.description, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, Margins(12))));
desc->SetTextSize(TextSize::Small);
desc->SetWordWrap();
}
if (!entry_.web.empty() || !entry_.discord.empty()) {
LinearLayout *buttonStrip = content->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, Margins(12))));
buttonStrip->SetSpacing(8);
if (!entry_.web.empty()) {
buttonStrip->Add(CreateLinkButton(entry_.web));
}
if (!entry_.discord.empty()) {
buttonStrip->Add(CreateLinkButton(entry_.discord));
}
if (entry_.dataJsonUrl.empty()) {
content->Add(CreateInfoItemWithButton(ni->T("This server has no data.json status page"), ImageID("I_LINK_OUT_QUESTION"), [](UI::EventParams &e) {
System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://www.ppsspp.org/docs/multiplayer/adhoc-server-status/");
}));
if (!entry_.statusWebUrl.empty()) {
content->Add(CreateLinkButton(entry_.statusWebUrl, ni->T("Status on web")));
}
if (entry_.statusUrl.empty()) {
content->Add(new TextView("This server has no data.json status page."));
if (!entry_.statusXmlUrl.empty()) {
content->Add(CreateLinkButton(entry_.statusXmlUrl, ni->T("Status on web")));
}
} else {
if (games_.empty()) {
content->Add(new TextView(ni->T("No games in progress on this server")));
} else {
if (games_.empty()) {
content->Add(new TextView("No games are currently being played on this server."));
} else {
// TODO: Do something more sophisticated here, like showing groups and users. For now, just show game names.
for (const auto &game : games_) {
content->Add(new TextView(game.name));
for (const AdhocGame &game : games_) {
CollapsibleSection *gameSection = content->Add(new CollapsibleSection(StringFromFormat("%s (players: %d groups: %d)", game.name.c_str(), game.usercount, (int)game.groups.size())));
for (const AdhocGroup &group : game.groups) {
gameSection->Add(new TextView(StringFromFormat(" %s (players: %d)", group.name.c_str(), group.usercount)))->SetTextSize(TextSize::Small);
for (const AdhocUser &user : group.users) {
std::string portInfo;
if (!user.pdp_ports.empty()) {
portInfo += "PDP: ";
for (int port : user.pdp_ports) {
portInfo += std::to_string(port) + " ";
}
}
if (!user.ptp_ports.empty()) {
portInfo += "PTP: ";
for (int port : user.ptp_ports) {
portInfo += std::to_string(port) + " ";
}
}
gameSection->Add(new TextView(StringFromFormat(" %s %s", user.name.c_str(), portInfo.c_str())))->SetTextSize(TextSize::Tiny);
}
}
gameSection->SetOpen(false); // NOTE: Must be last!
}
}
}
scroll->Add(content);
parent->Add(scroll);
}
void AdhocServerInfoScreen::update() {
UI::PopupScreen::update();
if (statusRequest_ && statusRequest_->Done()) {
std::string json;
statusRequest_->buffer().TakeAll(&json);
games_ = ParseDataJson(json);
statusRequest_.reset();
RecreateViews();
}
}
void AddDeleteButton(std::string *editValue, ScreenManager *screenManager, UI::ViewGroup *viewGroup, const AdhocServerListEntry &entry) {
using namespace UI;
Choice *deleteButton = viewGroup->Add(new Choice(ImageID("I_TRASHCAN"), new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT, Gravity::G_VCENTER, Margins(0, 0, 10, 0))));
deleteButton->OnClick.Add([host = entry.host, screenManager, editValue](UI::EventParams &e) {
auto di = GetI18NCategory(I18NCat::DIALOG);
const std::string quotedHost = "\"" + host + "\"";
const std::string message = ApplySafeSubstitutions(di->T("Are you sure you want to delete %1?"), quotedHost);
screenManager->push(new UI::MessagePopupScreen(di->T("Delete"), message, di->T("Delete"), di->T("Cancel"), [host, editValue](bool confirmed) {
if (confirmed) {
RemoveNoCase(g_Config.vCustomAdhocServerList, host);
RemoveNoCase(g_Config.vCustomAdhocServerListWithRelay, host);
if (*editValue == host) {
// Reset to socom.cc, which will always be in a list.
*editValue = DefaultProAdhocServer();
}
}
}
scroll->Add(content);
parent->Add(scroll);
}
void update() override {
UI::PopupScreen::update();
if (statusRequest_ && statusRequest_->Done()) {
std::string json;
statusRequest_->buffer().TakeAll(&json);
games_ = ParseDataJson(json);
statusRequest_.reset();
RecreateViews();
}
}
private:
AdhocServerListEntry entry_;
std::vector<Game> games_;
std::shared_ptr<http::Request> statusRequest_;
};
}));
});
}
class AdhocServerRow : public UI::LinearLayout {
public:
@@ -303,26 +365,6 @@ private:
AdhocServerListEntry entry_;
};
void AddDeleteButton(std::string *editValue, ScreenManager *screenManager, UI::ViewGroup *viewGroup, const AdhocServerListEntry &entry) {
using namespace UI;
Choice *deleteButton = viewGroup->Add(new Choice(ImageID("I_TRASHCAN"), new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT, Gravity::G_VCENTER, Margins(0, 0, 10, 0))));
deleteButton->OnClick.Add([host = entry.host, screenManager, editValue](UI::EventParams &e) {
auto di = GetI18NCategory(I18NCat::DIALOG);
const std::string quotedHost = "\"" + host + "\"";
const std::string message = ApplySafeSubstitutions(di->T("Are you sure you want to delete %1?"), quotedHost);
screenManager->push(new UI::MessagePopupScreen(di->T("Delete"), message, di->T("Delete"), di->T("Cancel"), [host, editValue](bool confirmed) {
if (confirmed) {
RemoveNoCase(g_Config.vCustomAdhocServerList, host);
RemoveNoCase(g_Config.vCustomAdhocServerListWithRelay, host);
if (*editValue == host) {
// Reset to socom.cc, which will always be in a list.
*editValue = DefaultProAdhocServer();
}
}
}));
});
}
AdhocServerRow::AdhocServerRow(std::string *editValue, const AdhocServerListEntry &entry, bool showDeleteButton, ScreenManager *screenManager, UI::LayoutParams *layoutParams)
: UI::LinearLayout(ORIENT_HORIZONTAL, new UI::LinearLayoutParams(UI::FILL_PARENT, UI::WRAP_CONTENT, UI::Margins(5.0f, 0.0f))), value_(editValue), entry_(entry) {
using namespace UI;
+42
View File
@@ -9,6 +9,48 @@
#include "Common/UI/PopupScreens.h"
#include "Core/Config.h" // for AdhocServerListEntry!
#include "Common/UI/Notice.h"
#include "Core/HLE/sceNetAdhoc.h"
struct AdhocUser {
std::string name;
std::vector<int> pdp_ports;
std::vector<int> ptp_ports;
};
struct AdhocGroup {
std::string name;
int usercount;
std::vector<AdhocUser> users;
};
struct AdhocGame {
std::string name;
int usercount;
std::vector<AdhocGroup> groups;
std::vector<std::string> game_ids;
};
// Later, this might also show games-in-progress.
// For now, it's just a simple metadata viewer.
class AdhocServerInfoScreen : public UI::PopupScreen {
public:
AdhocServerInfoScreen(const AdhocServerListEntry &entry);
const char *tag() const override { return "AdhocServerInfo"; }
protected:
bool FillVertical() const override { return false; }
UI::Size PopupWidth() const override { return 650; }
bool ShowButtons() const override { return true; }
void CreatePopupContents(UI::ViewGroup *parent) override;
void update() override;
private:
AdhocServerListEntry entry_;
std::vector<AdhocGame> games_;
std::shared_ptr<http::Request> statusRequest_;
};
class AdhocServerScreen : public UI::PopupScreen {
public:
+9
View File
@@ -1032,6 +1032,15 @@ void GameSettingsScreen::CreateNetworkingSettings(UI::ViewGroup *networkingSetti
serverRow->Add(new Choice(ImageID("I_EDIT_TEXT"), new LinearLayoutParams(ITEM_HEIGHT, ITEM_HEIGHT)))->OnClick.Add([this](UI::EventParams &) {
AskToEditCurrentServer(GetRequesterToken(), screenManager());
});
} else if (!g_Config.sProAdhocServer.empty()) {
AdhocServerListEntry entry;
if (AdhocGetServerByHost(g_Config.sProAdhocServer, &entry)) {
Choice *status = networkingSettings->Add(new Choice(ApplySafeSubstitutions(n->T("Server status: %1"), g_Config.sProAdhocServer)));
status->SetIconLeft(ImageID("I_INFO"));
status->OnClick.Add([this, entry](UI::EventParams &) {
screenManager()->push(new AdhocServerInfoScreen(entry));
});
}
}
static const char *relayModes[] = {"Auto", "Yes", "No"};
+1 -1
View File
@@ -80,7 +80,7 @@ static void AfterSaveStateAction(SaveState::Status status, std::string_view mess
class ScreenshotViewScreen : public UI::PopupScreen {
public:
ScreenshotViewScreen(const Path &screenshotFilename, std::string_view saveStatePrefix, std::string_view title, int slot, Path gamePath)
: PopupScreen(title), screenshotFilename_(screenshotFilename), saveStatePrefix_(saveStatePrefix), slot_(slot), gamePath_(gamePath), title_(title) {} // PopupScreen will translate Back on its own
: PopupScreen(title), screenshotFilename_(screenshotFilename), saveStatePrefix_(saveStatePrefix), slot_(slot), gamePath_(gamePath), title_(title) {}
int GetSlot() const {
return slot_;
+2 -1
View File
@@ -7,7 +7,8 @@
"web": "",
"location": "France",
"description": "For players looking to play any games",
"data_mode": "AemuPostoffice"
"data_mode": "AemuPostoffice",
"status_xml": "https://www.socom.cc/status.xml"
},
{
"name": "Madness Gaming Network",
+1
View File
@@ -1044,6 +1044,7 @@ Relay = الترحيل # AI translated
Relay server mode = وضع خادم الترحيل # AI translated
Send = إرسال
Send Discord Presence information = Send Discord "Rich Presence" information
Server status: %1 = حالة الخادم: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = نقل الملفات
+1
View File
@@ -1036,6 +1036,7 @@ Relay = Rejimi
Relay server mode = Relay server rejimi # AI translated
Send = Göndər
Send Discord Presence information = Discord "Bol Varlıq" bilgisini göndər
Server status: %1 = Server vəziyyəti: %1 # AI translated
Some network functionality in this game is not working = Bu oyundakı bəzi bağlantı işləvsəlliklər işləmir
To play in Infrastructure Mode, you must enter a username = İnfrastruktur Modunda oynamaq üçün işlədici adı yazmalısınız
Transfer files = Faylları köçürmək
+1
View File
@@ -1003,6 +1003,7 @@ Relay = Релей # AI translated
Relay server mode = Рэжым сервера перасылкі # AI translated
Send = Адправіць
Send Discord Presence information = Send Discord "Rich Presence" information
Server status: %1 = Статус сервера: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Перадаць файлы
+1
View File
@@ -1036,6 +1036,7 @@ Relay = Реле # AI translated
Relay server mode = Режим на релейния сървър # AI translated
Send = Send
Send Discord Presence information = Send Discord "Rich Presence" information
Server status: %1 = Статус на сървъра: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Прехвърляне на файлове
+1
View File
@@ -1036,6 +1036,7 @@ Relay = Relleu # AI translated
Relay server mode = Mode de servidor de relleu # AI translated
Send = Send
Send Discord Presence information = Send Discord "Rich Presence" information
Server status: %1 = Estat del servidor: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Transferir fitxers
+1
View File
@@ -1036,6 +1036,7 @@ Relay = Reléového # AI translated
Relay server mode = Režim reléového serveru # AI translated
Send = Send
Send Discord Presence information = Send Discord "Rich Presence" information
Server status: %1 = Stav serveru: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Přenos souborů
+1
View File
@@ -1036,6 +1036,7 @@ Relay = Relay # AI translated
Relay server mode = Relayserver-tilstand # AI translated
Send = Send
Send Discord Presence information = Send Discord "Rich Presence" information
Server status: %1 = Serverstatus: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Overfør filer
+1
View File
@@ -1035,6 +1035,7 @@ Relay = Relay # AI translated
Relay server mode = Relay-Server-Modus # AI translated
Send = Senden
Send Discord Presence information = Discord "Rich Presence"-Information senden
Server status: %1 = Serverstatus: %1 # AI translated
Some network functionality in this game is not working = Einige Netzwerkfunktionen in diesem Spiel funktionieren nicht
To play in Infrastructure Mode, you must enter a username = Um im Infrastrukturmodus zu spielen, musst du einen Benutzernamen eingeben
Transfer files = Dateien übertragen
+1
View File
@@ -1036,6 +1036,7 @@ Relay = Relay # AI translated
Relay server mode = Mode server relay # AI translated
Send = Send
Send Discord Presence information = Send Discord "Rich Presence" information
Server status: %1 = Status server: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Transfer file
+1
View File
@@ -1028,6 +1028,7 @@ Relay = Relay
Relay server mode = Relay server mode
Send = Send
Send Discord Presence information = Send Discord "Rich Presence" information
Server status: %1 = Server status: %1
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Transfer files
+1
View File
@@ -1037,6 +1037,7 @@ Relay = Retransm. # AI translated
Relay server mode = Modo servidor de retransmisión # AI translated
Send = Enviar
Send Discord Presence information = Enviar información de "Rich Presence" a Discord
Server status: %1 = Estado del servidor: %1 # AI translated
Some network functionality in this game is not working = Algunas funciones de red en este juego no funcionan.
To play in Infrastructure Mode, you must enter a username = Para jugar en el modo Infraestructura, debes introducir un nombre de usuario
Transfer files = Transferir archivos
+1
View File
@@ -1036,6 +1036,7 @@ Relay = Retransm. # AI translated
Relay server mode = Modo de servidor de retransmisión # AI translated
Send = Enviar
Send Discord Presence information = Enviar información al Discord "Rich Presence"
Server status: %1 = Estado del servidor: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Transferir archivos
+1
View File
@@ -1036,6 +1036,7 @@ Relay = حالت رله # AI translated
Relay server mode = حالت سرور رله # AI translated
Send = ارسال
Send Discord Presence information = ارسال اطلاعات "Rich Presence" به دیسکورد
Server status: %1 = وضعیت سرور: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = انتقال فایل‌ها
+1
View File
@@ -1036,6 +1036,7 @@ Relay = Väylä # AI translated
Relay server mode = Väyläpalvelimen tila # AI translated
Send = Send
Send Discord Presence information = Send Discord "Rich Presence" information
Server status: %1 = Palvelimen tila: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Siirrä tiedostoja
+1
View File
@@ -1030,6 +1030,7 @@ Relay = Relais
Relay server mode = Mode serveur relais
Send = Envoyer
Send Discord Presence information = Envoyer l'information "Rich Presence" de Discord
Server status: %1 = État du serveur: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Transférer des fichiers
+1
View File
@@ -1036,6 +1036,7 @@ Relay = Retransm. # AI translated
Relay server mode = Modo servidor de retransmisión # AI translated
Send = Send
Send Discord Presence information = Send Discord "Rich Presence" information
Server status: %1 = Estado do servidor: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Transferir arquivos
+1
View File
@@ -1036,6 +1036,7 @@ Relay = Αναμετάδοση
Relay server mode = Λειτουργία διακομιστή αναμετάδοσης # AI translated
Send = Send
Send Discord Presence information = Αποστολή "Rich Presence" πληροφοριών σε Discord
Server status: %1 = Κατάσταση διακομιστή: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Μεταφορά αρχείων
+1
View File
@@ -1036,6 +1036,7 @@ Relay = מצב שרת ריליי # AI translated
Relay server mode = מצב שרת ריליי # AI translated
Send = Send
Send Discord Presence information = Send Discord "Rich Presence" information
Server status: %1 = מצב השרת: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = העבר קבצים
+1
View File
@@ -1036,6 +1036,7 @@ Relay = Relay
Relay server mode = מצב שרת ריליי # AI translated
Send = שלח
Send Discord Presence information = Send Discord "Rich Presence" information
Server status: %1 = מצב השרת: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = קבצים העבר
+1
View File
@@ -1036,6 +1036,7 @@ Relay = Relay # AI translated
Relay server mode = Način relay servera # AI translated
Send = Send
Send Discord Presence information = Šalji Discord "Rich Presence" informaciju
Server status: %1 = Status poslužitelja: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Prenesi datoteke
+1
View File
@@ -1036,6 +1036,7 @@ Relay = Relay # AI translated
Relay server mode = Relay szerver mód # AI translated
Send = Küldés
Send Discord Presence information = "Rich Presence" információ küldése Discordnak
Server status: %1 = Szerver állapot: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Fájlok átvitele
+1
View File
@@ -1036,6 +1036,7 @@ Relay = Relay # AI translated
Relay server mode = Mode server relay # AI translated
Send = Kirim
Send Discord Presence information = Kirim informasi "Kritik dan Saran" ke Discord
Server status: %1 = Status server: %1 # AI translated
Some network functionality in this game is not working = Beberapa fungsi jaringan dalam game ini tidak berfungsi
To play in Infrastructure Mode, you must enter a username = Untuk bermain dalam Mode Infrastruktur, Anda harus memasukkan nama pengguna
Transfer files = Transfer file
+1
View File
@@ -1004,6 +1004,7 @@ Relay = Relay # AI translated
Relay server mode = Modalità server relay # AI translated
Send = Invia
Send Discord Presence information = Invia informazioni Discord "Rich Presence"
Server status: %1 = Stato del server: %1 # AI translated
Some network functionality in this game is not working = Alcune funzionalità di rete in questo gioco non funzionano
To play in Infrastructure Mode, you must enter a username = Per giocare in modalità Infrastruttura, è necessario inserire un nome utente
Transfer files = Trasferisci file
+1
View File
@@ -1003,6 +1003,7 @@ Relay = リレー # AI translated
Relay server mode = リレサーバーモード # AI translated
Send = 送信する
Send Discord Presence information = Discordのプレゼンス情報を送信する
Server status: %1 = サーバーの状態: %1 # AI translated
Some network functionality in this game is not working = このゲームの一部のネットワーク機能が動作していません
To play in Infrastructure Mode, you must enter a username = インフラストラクチャモードでプレイするには、ユーザー名を入力する必要があります
Transfer files = ファイルを転送
+1
View File
@@ -1036,6 +1036,7 @@ Relay = Relay # AI translated
Relay server mode = Mode server relay # AI translated
Send = Send
Send Discord Presence information = Send Discord "Rich Presence" information
Server status: %1 = Status server: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Transfer file
+1
View File
@@ -1003,6 +1003,7 @@ Relay = 릴레이 # AI translated
Relay server mode = 릴레이 서버 모드 # AI translated
Send = 보내기
Send Discord Presence information = 디스코드 "리치 프레즌스" 정보 보내기
Server status: %1 = 서버 상태: %1 # AI translated
Some network functionality in this game is not working = 이 게임의 일부 네트워크 기능이 작동하지 않았음
To play in Infrastructure Mode, you must enter a username = 인프라 모드에서 플레이하려면 사용자 이름을 입력해야 함
Transfer files = 파일 전송
+1
View File
@@ -1017,6 +1017,7 @@ Relay = Relê # AI translated
Relay server mode = Rejim serverê relê # AI translated
Send = Send
Send Discord Presence information = Send Discord "Rich Presence" information
Server status: %1 = Rewşa serverê: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Pelanên transfer bike
+1
View File
@@ -1036,6 +1036,7 @@ Relay = Relay # AI translated
Relay server mode = ແບບເຄື່ອງລົດລາ # AI translated
Send = Send
Send Discord Presence information = Send Discord "Rich Presence" information
Server status: %1 = ສະຖານທີ່ສະເລີຍ: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = ເກັບໃສ່ໄຟລ໌
+1
View File
@@ -1036,6 +1036,7 @@ Relay = Relės
Relay server mode = Relės serverio režimas # AI translated
Send = Send
Send Discord Presence information = Send Discord "Rich Presence" information
Server status: %1 = Serverio būsena: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Perkelti failus
+1
View File
@@ -1036,6 +1036,7 @@ Relay = Mod pelayan relay # AI translated
Relay server mode = Relay # AI translated
Send = Send
Send Discord Presence information = Send Discord "Rich Presence" information
Server status: %1 = Status pelayan: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Pindahkan fail
+1
View File
@@ -1036,6 +1036,7 @@ Relay = Relay # AI translated
Relay server mode = Relayservermodus # AI translated
Send = Send
Send Discord Presence information = Send Discord "Rich Presence" information
Server status: %1 = Serverstatus: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Bestanden overdragen
+1
View File
@@ -1036,6 +1036,7 @@ Relay = Relay # AI translated
Relay server mode = Relayservermodus # AI translated
Send = Send
Send Discord Presence information = Send Discord "Rich Presence" information
Server status: %1 = Serverstatus: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Overfør filer
+1
View File
@@ -1041,6 +1041,7 @@ Relay = Relay # AI translated
Relay server mode = Tryb serwera relay # AI translated
Send = Wyślij
Send Discord Presence information = Przesyłaj informacje Discord Rich Presence
Server status: %1 = Status serwera: %1 # AI translated
Some network functionality in this game is not working = Niektóre funkcje sieciowe w tej grze nie działają
To play in Infrastructure Mode, you must enter a username = Aby grać w trybie infrastruktury, musisz wprowadzić nazwę użytkownika.
Transfer files = Przenieś pliki
+1
View File
@@ -1028,6 +1028,7 @@ Relay = Transmissão
Relay server mode = Modo do servidor de transmissão
Send = Enviar
Send Discord Presence information = Enviar informação da "Presença Rica" no Discord
Server status: %1 = Status do servidor: %1 # AI translated
Some network functionality in this game is not working = Algumas funcionalidades da rede neste jogo não estão funcionando
To play in Infrastructure Mode, you must enter a username = Pra jogar no Modo de infra-estrutura você deve inserir um nome de usuário
Transfer files = Transferir arquivos
+1
View File
@@ -1028,6 +1028,7 @@ Relay = Relay # AI translated
Relay server mode = Modo de servidor relay # AI translated
Send = Enviar
Send Discord Presence information = Enviar informação de "Rich Presence" no Discord
Server status: %1 = Estado do servidor: %1 # AI translated
Some network functionality in this game is not working = Algumas funcionalidades de rede deste jogo não são compatíveis
To play in Infrastructure Mode, you must enter a username = Para jogar no modo infraestrutura, deves inserir um apelido
Transfer files = Transferir ficheiros
+1
View File
@@ -1037,6 +1037,7 @@ Relay = Relay # AI translated
Relay server mode = Mod server relay # AI translated
Send = Send
Send Discord Presence information = Send Discord "Rich Presence" information
Server status: %1 = Starea serverului: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Transferați fișiere
+1
View File
@@ -1003,6 +1003,7 @@ Relay = Режим релея
Relay server mode = Режим релейного сервера
Send = Отправить
Send Discord Presence information = Отправлять информацию об игре в Discord
Server status: %1 = Статус сервера: %1 # AI translated
Some network functionality in this game is not working = Некоторые сетевые функции в этой игре не работают
To play in Infrastructure Mode, you must enter a username = Для игры в режиме инфраструктуры необходимо ввести имя пользователя
Transfer files = Передача файлов
+1
View File
@@ -1004,6 +1004,7 @@ Relay = Relay # AI translated
Relay server mode = Relayserverläge # AI translated
Send = Skicka
Send Discord Presence information = Visa Discord "Rich Presence"-information
Server status: %1 = Serverstatus: %1 # AI translated
Some network functionality in this game is not working = Viss nätverksfunktionalitet i detta spel fungerar ej
To play in Infrastructure Mode, you must enter a username = För att spela i infrastrukturläge måste du ange ett användarnamn
Transfer files = Överför filer
+1
View File
@@ -1037,6 +1037,7 @@ Relay = Релей # AI translated
Relay server mode = Режими сервери релей # AI translated
Send = I-Send
Send Discord Presence information = Magpadala ng impormasyon sa 'Rich Presence' ni Discord.
Server status: %1 = Вазъи сервер: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Файли интиқол кунед
+1
View File
@@ -1056,6 +1056,7 @@ Relay = รีเลย์
Relay server mode = โหมดเซิร์ฟเวอร์รีเลย์
Send = ส่ง
Send Discord Presence information = แสดงชื่อเกมที่กำลังเล่นอยู่ไปยังแอพ Discord
Server status: %1 = สถานะเซิร์ฟเวอร์: %1 # AI translated
Some network functionality in this game is not working = ฟังก์ชั่นของเครือข่ายบางอย่างในเกมนี้อาจจะใช้งานไม่ได้
To play in Infrastructure Mode, you must enter a username = การเล่นในโหมด Infrastructure คุณจะต้องป้อนชื่อผู้ใช้งาน
Transfer files = โอนไฟล์
+1
View File
@@ -1038,6 +1038,7 @@ Relay = Relay # AI translated
Relay server mode = Relay sunucu modu # AI translated
Send = Gönder
Send Discord Presence information = Discord Zengin Varlık Bilgisi Gönder
Server status: %1 = Sunucu durumu: %1 # AI translated
Some network functionality in this game is not working = Bu oyundaki bazı ağ işlevleri çalışmıyor
To play in Infrastructure Mode, you must enter a username = Altyapı modunda oynamak için bir kullanıcı adı girmelisiniz
Transfer files = Dosyaları aktar
+1
View File
@@ -1036,6 +1036,7 @@ Relay = Релей # AI translated
Relay server mode = Режим релейного сервера # AI translated
Send = Надіслати
Send Discord Presence information = Відправляти інформацію про гру в Діскорд
Server status: %1 = Статус сервера: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Передати файли
+1
View File
@@ -1036,6 +1036,7 @@ Relay = Relay # AI translated
Relay server mode = Chế độ máy chủ relay # AI translated
Send = Send
Send Discord Presence information = Send Discord "Rich Presence" information
Server status: %1 = Trạng thái máy chủ: %1 # AI translated
Some network functionality in this game is not working = Some network functionality in this game is not working
To play in Infrastructure Mode, you must enter a username = To play in Infrastructure Mode, you must enter a username
Transfer files = Chuyển tệp
+1
View File
@@ -1037,6 +1037,7 @@ Relay = 中继 # AI translated
Relay server mode = 中继服务器模式 # AI translated
Send = 发送
Send Discord Presence information = Discord 显示在线状态
Server status: %1 = 服务器状态: %1 # AI translated
Some network functionality in this game is not working = 此游戏中的某些网络功能不起作用
To play in Infrastructure Mode, you must enter a username = 您必须输入用户名,才能在基础模式下游玩
Transfer files = 传输文件
+1
View File
@@ -1003,6 +1003,7 @@ Relay = 中繼 # AI translated
Relay server mode = 中繼伺服器模式 # AI translated
Send = 傳送
Send Discord Presence information = 傳送 Discord「Rich Presence」資訊
Server status: %1 = 伺服器狀態: %1 # AI translated
Some network functionality in this game is not working = 此遊戲中的某些網路功能無法工作
To play in Infrastructure Mode, you must enter a username = 您必須輸入使用者名稱,才能在基礎模式下游玩
Transfer files = 傳輸檔案