forked from Hay1tsme/artemis
Merge branch 'develop' into idac
This commit is contained in:
commit
0b38778c19
@ -157,6 +157,8 @@ class BaseData:
|
|||||||
|
|
||||||
def fix_bools(self, data: Dict) -> Dict:
|
def fix_bools(self, data: Dict) -> Dict:
|
||||||
for k, v in data.items():
|
for k, v in data.items():
|
||||||
|
if k == "userName" or k == "teamName":
|
||||||
|
continue
|
||||||
if type(v) == str and v.lower() == "true":
|
if type(v) == str and v.lower() == "true":
|
||||||
data[k] = True
|
data[k] = True
|
||||||
elif type(v) == str and v.lower() == "false":
|
elif type(v) == str and v.lower() == "false":
|
||||||
|
12
core/data/schema/versions/SDBT_4_rollback.sql
Normal file
12
core/data/schema/versions/SDBT_4_rollback.sql
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
SET FOREIGN_KEY_CHECKS = 0;
|
||||||
|
|
||||||
|
ALTER TABLE chuni_score_playlog
|
||||||
|
CHANGE COLUMN isClear isClear TINYINT(1) NULL DEFAULT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE chuni_score_best
|
||||||
|
CHANGE COLUMN isSuccess isSuccess TINYINT(1) NULL DEFAULT NULL ;
|
||||||
|
|
||||||
|
ALTER TABLE chuni_score_playlog
|
||||||
|
DROP COLUMN ticketId;
|
||||||
|
|
||||||
|
SET FOREIGN_KEY_CHECKS = 1;
|
12
core/data/schema/versions/SDBT_5_upgrade.sql
Normal file
12
core/data/schema/versions/SDBT_5_upgrade.sql
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
SET FOREIGN_KEY_CHECKS = 0;
|
||||||
|
|
||||||
|
ALTER TABLE chuni_score_playlog
|
||||||
|
CHANGE COLUMN isClear isClear TINYINT(6) NULL DEFAULT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE chuni_score_best
|
||||||
|
CHANGE COLUMN isSuccess isSuccess INT(11) NULL DEFAULT NULL ;
|
||||||
|
|
||||||
|
ALTER TABLE chuni_score_playlog
|
||||||
|
ADD COLUMN ticketId INT(11) NULL AFTER machineType;
|
||||||
|
|
||||||
|
SET FOREIGN_KEY_CHECKS = 1;
|
@ -54,6 +54,7 @@ Games listed below have been tested and confirmed working.
|
|||||||
| 11 | CHUNITHM NEW!! |
|
| 11 | CHUNITHM NEW!! |
|
||||||
| 12 | CHUNITHM NEW PLUS!! |
|
| 12 | CHUNITHM NEW PLUS!! |
|
||||||
| 13 | CHUNITHM SUN |
|
| 13 | CHUNITHM SUN |
|
||||||
|
| 14 | CHUNITHM SUN PLUS |
|
||||||
|
|
||||||
|
|
||||||
### Importer
|
### Importer
|
||||||
@ -73,10 +74,9 @@ The importer for Chunithm will import: Events, Music, Charge Items and Avatar Ac
|
|||||||
Config file is located in `config/chuni.yaml`.
|
Config file is located in `config/chuni.yaml`.
|
||||||
|
|
||||||
| Option | Info |
|
| Option | Info |
|
||||||
| ----------------- | ------------------------------------------------------------------------------------------------------- |
|
|------------------|----------------------------------------------------------------------------------------------------------------|
|
||||||
| `news_msg` | If this is set, the news at the top of the main screen will be displayed (up to Chunithm Paradise Lost) |
|
| `news_msg` | If this is set, the news at the top of the main screen will be displayed (up to Chunithm Paradise Lost) |
|
||||||
| `name` | If this is set, all players that are not on a team will use this one by default. |
|
| `name` | If this is set, all players that are not on a team will use this one by default. |
|
||||||
| `rank_scale` | Scales the in-game ranking based on the number of teams within the database |
|
|
||||||
| `use_login_bonus`| This is used to enable the login bonuses |
|
| `use_login_bonus`| This is used to enable the login bonuses |
|
||||||
| `crypto` | This option is used to enable the TLS Encryption |
|
| `crypto` | This option is used to enable the TLS Encryption |
|
||||||
|
|
||||||
@ -134,12 +134,6 @@ INSERT INTO aime.chuni_profile_team (teamName) VALUES (<teamName>);
|
|||||||
```
|
```
|
||||||
Team names can be regular ASCII, and they will be displayed ingame.
|
Team names can be regular ASCII, and they will be displayed ingame.
|
||||||
|
|
||||||
On smaller installations, you may also wish to enable scaled team rankings. By default, Chunithm determines team ranking within the first 100 teams. This can be configured in the YAML:
|
|
||||||
```yaml
|
|
||||||
team:
|
|
||||||
rank_scale: True # Scales the in-game ranking based on the number of teams within the database, rather than the default scale of ~100 that the game normally uses.
|
|
||||||
```
|
|
||||||
|
|
||||||
### Favorite songs
|
### Favorite songs
|
||||||
You can set the songs that will be in a user's Favorite Songs category using the following SQL entries:
|
You can set the songs that will be in a user's Favorite Songs category using the following SQL entries:
|
||||||
```sql
|
```sql
|
||||||
@ -173,15 +167,6 @@ The importer for crossbeats REV. will import Music.
|
|||||||
|
|
||||||
Config file is located in `config/cxb.yaml`.
|
Config file is located in `config/cxb.yaml`.
|
||||||
|
|
||||||
| Option | Info |
|
|
||||||
| --------------------- | ---------------------------------------------------------- |
|
|
||||||
| `hostname` | Requires a proper `hostname` (not localhost!) to run |
|
|
||||||
| `ssl_enable` | Enables/Disables the use of the `ssl_cert` and `ssl_key` |
|
|
||||||
| `port` | Set your unsecure port number |
|
|
||||||
| `port_secure` | Set your secure/SSL port number |
|
|
||||||
| `ssl_cert`, `ssl_key` | Enter your SSL certificate (requires not self signed cert) |
|
|
||||||
|
|
||||||
|
|
||||||
## maimai DX
|
## maimai DX
|
||||||
|
|
||||||
### Versions
|
### Versions
|
||||||
|
@ -19,6 +19,9 @@ version:
|
|||||||
13:
|
13:
|
||||||
rom: 2.10.00
|
rom: 2.10.00
|
||||||
data: 2.10.00
|
data: 2.10.00
|
||||||
|
14:
|
||||||
|
rom: 2.15.00
|
||||||
|
data: 2.15.00
|
||||||
|
|
||||||
crypto:
|
crypto:
|
||||||
encrypted_only: False
|
encrypted_only: False
|
@ -5,7 +5,7 @@ A network service emulator for games running SEGA'S ALL.NET service, and similar
|
|||||||
Games listed below have been tested and confirmed working. Only game versions older then the version currently active in arcades, or games versions that have not recieved a major update in over one year, are supported.
|
Games listed below have been tested and confirmed working. Only game versions older then the version currently active in arcades, or games versions that have not recieved a major update in over one year, are supported.
|
||||||
|
|
||||||
+ CHUNITHM
|
+ CHUNITHM
|
||||||
+ All versions up to SUN
|
+ All versions up to SUN PLUS
|
||||||
|
|
||||||
+ crossbeats REV.
|
+ crossbeats REV.
|
||||||
+ All versions + omnimix
|
+ All versions + omnimix
|
||||||
|
@ -6,5 +6,5 @@ from titles.chuni.read import ChuniReader
|
|||||||
index = ChuniServlet
|
index = ChuniServlet
|
||||||
database = ChuniData
|
database = ChuniData
|
||||||
reader = ChuniReader
|
reader = ChuniReader
|
||||||
game_codes = [ChuniConstants.GAME_CODE, ChuniConstants.GAME_CODE_NEW]
|
game_codes = [ChuniConstants.GAME_CODE, ChuniConstants.GAME_CODE_NEW, ChuniConstants.GAME_CODE_INT]
|
||||||
current_schema_version = 4
|
current_schema_version = 5
|
@ -240,7 +240,6 @@ class ChuniBase:
|
|||||||
"isDumpUpload": "false",
|
"isDumpUpload": "false",
|
||||||
"isAou": "false",
|
"isAou": "false",
|
||||||
}
|
}
|
||||||
|
|
||||||
def handle_get_user_activity_api_request(self, data: Dict) -> Dict:
|
def handle_get_user_activity_api_request(self, data: Dict) -> Dict:
|
||||||
user_activity_list = self.data.profile.get_profile_activity(
|
user_activity_list = self.data.profile.get_profile_activity(
|
||||||
data["userId"], data["kind"]
|
data["userId"], data["kind"]
|
||||||
@ -420,13 +419,13 @@ class ChuniBase:
|
|||||||
all_entries = self.data.score.get_rival_music(rival_id)
|
all_entries = self.data.score.get_rival_music(rival_id)
|
||||||
|
|
||||||
# Process the entries based on max_count and nextIndex
|
# Process the entries based on max_count and nextIndex
|
||||||
for music in all_entries[next_index:]:
|
for music in all_entries:
|
||||||
music_id = music["musicId"]
|
music_id = music["musicId"]
|
||||||
level = music["level"]
|
level = music["level"]
|
||||||
score = music["scoreMax"]
|
score = music["scoreMax"]
|
||||||
rank = music["scoreRank"]
|
rank = music["scoreRank"]
|
||||||
|
|
||||||
# Create a music entry for the current music_id
|
# Create a music entry for the current music_id if it's unique
|
||||||
music_entry = next((entry for entry in user_rival_music_list if entry["musicId"] == music_id), None)
|
music_entry = next((entry for entry in user_rival_music_list if entry["musicId"] == music_id), None)
|
||||||
if music_entry is None:
|
if music_entry is None:
|
||||||
music_entry = {
|
music_entry = {
|
||||||
@ -436,15 +435,20 @@ class ChuniBase:
|
|||||||
}
|
}
|
||||||
user_rival_music_list.append(music_entry)
|
user_rival_music_list.append(music_entry)
|
||||||
|
|
||||||
# Create a level entry for the current level
|
# Create a level entry for the current level if it's unique or has a higher score
|
||||||
|
level_entry = next((entry for entry in music_entry["userRivalMusicDetailList"] if entry["level"] == level), None)
|
||||||
|
if level_entry is None:
|
||||||
level_entry = {
|
level_entry = {
|
||||||
"level": level,
|
"level": level,
|
||||||
"scoreMax": score,
|
"scoreMax": score,
|
||||||
"scoreRank": rank
|
"scoreRank": rank
|
||||||
}
|
}
|
||||||
music_entry["userRivalMusicDetailList"].append(level_entry)
|
music_entry["userRivalMusicDetailList"].append(level_entry)
|
||||||
|
elif score > level_entry["scoreMax"]:
|
||||||
|
level_entry["scoreMax"] = score
|
||||||
|
level_entry["scoreRank"] = rank
|
||||||
|
|
||||||
# Calculate the length for each "musicId" by counting the levels
|
# Calculate the length for each "musicId" by counting the unique levels
|
||||||
for music_entry in user_rival_music_list:
|
for music_entry in user_rival_music_list:
|
||||||
music_entry["length"] = len(music_entry["userRivalMusicDetailList"])
|
music_entry["length"] = len(music_entry["userRivalMusicDetailList"])
|
||||||
|
|
||||||
@ -452,12 +456,12 @@ class ChuniBase:
|
|||||||
result = {
|
result = {
|
||||||
"userId": data["userId"],
|
"userId": data["userId"],
|
||||||
"rivalId": data["rivalId"],
|
"rivalId": data["rivalId"],
|
||||||
"nextIndex": str(next_index + len(all_entries) if len(all_entries) <= len(user_rival_music_list) else -1),
|
"nextIndex": str(next_index + len(user_rival_music_list[next_index: next_index + max_count]) if max_count <= len(user_rival_music_list[next_index: next_index + max_count]) else -1),
|
||||||
"userRivalMusicList": user_rival_music_list[:max_count]
|
"userRivalMusicList": user_rival_music_list[next_index: next_index + max_count]
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def handle_get_user_favorite_item_api_request(self, data: Dict) -> Dict:
|
def handle_get_user_favorite_item_api_request(self, data: Dict) -> Dict:
|
||||||
user_fav_item_list = []
|
user_fav_item_list = []
|
||||||
|
|
||||||
@ -873,8 +877,11 @@ class ChuniBase:
|
|||||||
if "userPlaylogList" in upsert:
|
if "userPlaylogList" in upsert:
|
||||||
for playlog in upsert["userPlaylogList"]:
|
for playlog in upsert["userPlaylogList"]:
|
||||||
# convert the player names to utf-8
|
# convert the player names to utf-8
|
||||||
|
if playlog["playedUserName1"] is not None:
|
||||||
playlog["playedUserName1"] = self.read_wtf8(playlog["playedUserName1"])
|
playlog["playedUserName1"] = self.read_wtf8(playlog["playedUserName1"])
|
||||||
|
if playlog["playedUserName2"] is not None:
|
||||||
playlog["playedUserName2"] = self.read_wtf8(playlog["playedUserName2"])
|
playlog["playedUserName2"] = self.read_wtf8(playlog["playedUserName2"])
|
||||||
|
if playlog["playedUserName3"] is not None:
|
||||||
playlog["playedUserName3"] = self.read_wtf8(playlog["playedUserName3"])
|
playlog["playedUserName3"] = self.read_wtf8(playlog["playedUserName3"])
|
||||||
self.data.score.put_playlog(user_id, playlog, self.version)
|
self.data.score.put_playlog(user_id, playlog, self.version)
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
class ChuniConstants:
|
class ChuniConstants:
|
||||||
GAME_CODE = "SDBT"
|
GAME_CODE = "SDBT"
|
||||||
GAME_CODE_NEW = "SDHD"
|
GAME_CODE_NEW = "SDHD"
|
||||||
|
GAME_CODE_INT = "SDGS"
|
||||||
|
|
||||||
CONFIG_NAME = "chuni.yaml"
|
CONFIG_NAME = "chuni.yaml"
|
||||||
|
|
||||||
@ -18,7 +19,7 @@ class ChuniConstants:
|
|||||||
VER_CHUNITHM_NEW = 11
|
VER_CHUNITHM_NEW = 11
|
||||||
VER_CHUNITHM_NEW_PLUS = 12
|
VER_CHUNITHM_NEW_PLUS = 12
|
||||||
VER_CHUNITHM_SUN = 13
|
VER_CHUNITHM_SUN = 13
|
||||||
|
VER_CHUNITHM_SUN_PLUS = 14
|
||||||
VERSION_NAMES = [
|
VERSION_NAMES = [
|
||||||
"CHUNITHM",
|
"CHUNITHM",
|
||||||
"CHUNITHM PLUS",
|
"CHUNITHM PLUS",
|
||||||
@ -33,7 +34,8 @@ class ChuniConstants:
|
|||||||
"CHUNITHM PARADISE",
|
"CHUNITHM PARADISE",
|
||||||
"CHUNITHM NEW!!",
|
"CHUNITHM NEW!!",
|
||||||
"CHUNITHM NEW PLUS!!",
|
"CHUNITHM NEW PLUS!!",
|
||||||
"CHUNITHM SUN"
|
"CHUNITHM SUN",
|
||||||
|
"CHUNITHM SUN PLUS"
|
||||||
]
|
]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -31,6 +31,7 @@ from .paradise import ChuniParadise
|
|||||||
from .new import ChuniNew
|
from .new import ChuniNew
|
||||||
from .newplus import ChuniNewPlus
|
from .newplus import ChuniNewPlus
|
||||||
from .sun import ChuniSun
|
from .sun import ChuniSun
|
||||||
|
from .sunplus import ChuniSunPlus
|
||||||
|
|
||||||
|
|
||||||
class ChuniServlet(BaseServlet):
|
class ChuniServlet(BaseServlet):
|
||||||
@ -58,6 +59,7 @@ class ChuniServlet(BaseServlet):
|
|||||||
ChuniNew,
|
ChuniNew,
|
||||||
ChuniNewPlus,
|
ChuniNewPlus,
|
||||||
ChuniSun,
|
ChuniSun,
|
||||||
|
ChuniSunPlus,
|
||||||
]
|
]
|
||||||
|
|
||||||
self.logger = logging.getLogger("chuni")
|
self.logger = logging.getLogger("chuni")
|
||||||
@ -99,8 +101,14 @@ class ChuniServlet(BaseServlet):
|
|||||||
]
|
]
|
||||||
for method in method_list:
|
for method in method_list:
|
||||||
method_fixed = inflection.camelize(method)[6:-7]
|
method_fixed = inflection.camelize(method)[6:-7]
|
||||||
# number of iterations was changed to 70 in SUN
|
# number of iterations was changed to 70 in SUN and then to 36
|
||||||
iter_count = 70 if version >= ChuniConstants.VER_CHUNITHM_SUN else 44
|
if version == ChuniConstants.VER_CHUNITHM_SUN_PLUS:
|
||||||
|
iter_count = 36
|
||||||
|
elif version == ChuniConstants.VER_CHUNITHM_SUN:
|
||||||
|
iter_count = 70
|
||||||
|
else:
|
||||||
|
iter_count = 44
|
||||||
|
|
||||||
hash = PBKDF2(
|
hash = PBKDF2(
|
||||||
method_fixed,
|
method_fixed,
|
||||||
bytes.fromhex(keys[2]),
|
bytes.fromhex(keys[2]),
|
||||||
@ -120,8 +128,8 @@ class ChuniServlet(BaseServlet):
|
|||||||
return (
|
return (
|
||||||
[],
|
[],
|
||||||
[
|
[
|
||||||
("render_POST", "/{version}/ChuniServlet/{endpoint}", {}),
|
("render_POST", "/{game}/{version}/ChuniServlet/{endpoint}", {}),
|
||||||
("render_POST", "/{version}/ChuniServlet/MatchingServer/{endpoint}", {})
|
("render_POST", "/{game}/{version}/ChuniServlet/MatchingServer/{endpoint}", {})
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -142,22 +150,25 @@ class ChuniServlet(BaseServlet):
|
|||||||
|
|
||||||
def get_allnet_info(self, game_code: str, game_ver: int, keychip: str) -> Tuple[str, str]:
|
def get_allnet_info(self, game_code: str, game_ver: int, keychip: str) -> Tuple[str, str]:
|
||||||
if not self.core_cfg.server.is_using_proxy and Utils.get_title_port(self.core_cfg) != 80:
|
if not self.core_cfg.server.is_using_proxy and Utils.get_title_port(self.core_cfg) != 80:
|
||||||
return (f"http://{self.core_cfg.title.hostname}:{Utils.get_title_port(self.core_cfg)}/{game_ver}/", self.core_cfg.title.hostname)
|
return (f"http://{self.core_cfg.title.hostname}:{Utils.get_title_port(self.core_cfg)}/{game_code}/{game_ver}/", self.core_cfg.title.hostname)
|
||||||
|
|
||||||
return (f"http://{self.core_cfg.title.hostname}/{game_ver}/", self.core_cfg.title.hostname)
|
return (f"http://{self.core_cfg.title.hostname}/{game_code}/{game_ver}/", self.core_cfg.title.hostname)
|
||||||
|
|
||||||
def render_POST(self, request: Request, game_code: str, matchers: Dict) -> bytes:
|
def render_POST(self, request: Request, game_code: str, matchers: Dict) -> bytes:
|
||||||
endpoint = matchers['endpoint']
|
endpoint = matchers['endpoint']
|
||||||
version = int(matchers['version'])
|
version = int(matchers['version'])
|
||||||
|
game_code = matchers['game']
|
||||||
|
|
||||||
if endpoint.lower() == "ping":
|
if endpoint.lower() == "ping":
|
||||||
return zlib.compress(b'{"returnCode": "1"}')
|
return zlib.compress(b'{"returnCode": "1"}')
|
||||||
|
|
||||||
req_raw = request.content.getvalue()
|
req_raw = request.content.getvalue()
|
||||||
|
|
||||||
encrtped = False
|
encrtped = False
|
||||||
internal_ver = 0
|
internal_ver = 0
|
||||||
client_ip = Utils.get_ip_addr(request)
|
client_ip = Utils.get_ip_addr(request)
|
||||||
|
|
||||||
|
if game_code == "SDHD" or game_code == "SDBT": # JP
|
||||||
if version < 105: # 1.0
|
if version < 105: # 1.0
|
||||||
internal_ver = ChuniConstants.VER_CHUNITHM
|
internal_ver = ChuniConstants.VER_CHUNITHM
|
||||||
elif version >= 105 and version < 110: # PLUS
|
elif version >= 105 and version < 110: # PLUS
|
||||||
@ -184,8 +195,21 @@ class ChuniServlet(BaseServlet):
|
|||||||
internal_ver = ChuniConstants.VER_CHUNITHM_NEW
|
internal_ver = ChuniConstants.VER_CHUNITHM_NEW
|
||||||
elif version >= 205 and version < 210: # NEW PLUS!!
|
elif version >= 205 and version < 210: # NEW PLUS!!
|
||||||
internal_ver = ChuniConstants.VER_CHUNITHM_NEW_PLUS
|
internal_ver = ChuniConstants.VER_CHUNITHM_NEW_PLUS
|
||||||
elif version >= 210: # SUN
|
elif version >= 210 and version < 215: # SUN
|
||||||
internal_ver = ChuniConstants.VER_CHUNITHM_SUN
|
internal_ver = ChuniConstants.VER_CHUNITHM_SUN
|
||||||
|
elif version >= 215: # SUN
|
||||||
|
internal_ver = ChuniConstants.VER_CHUNITHM_SUN_PLUS
|
||||||
|
elif game_code == "SDGS": # Int
|
||||||
|
if version < 110: # SUPERSTAR
|
||||||
|
internal_ver = ChuniConstants.PARADISE
|
||||||
|
elif version >= 110 and version < 115: # NEW
|
||||||
|
internal_ver = ChuniConstants.VER_CHUNITHM_NEW
|
||||||
|
elif version >= 115 and version < 120: # NEW PLUS!!
|
||||||
|
internal_ver = ChuniConstants.VER_CHUNITHM_NEW_PLUS
|
||||||
|
elif version >= 120 and version < 125: # SUN
|
||||||
|
internal_ver = ChuniConstants.VER_CHUNITHM_SUN
|
||||||
|
elif version >= 125: # SUN PLUS
|
||||||
|
internal_ver = ChuniConstants.VER_CHUNITHM_SUN_PLUS
|
||||||
|
|
||||||
if all(c in string.hexdigits for c in endpoint) and len(endpoint) == 32:
|
if all(c in string.hexdigits for c in endpoint) and len(endpoint) == 32:
|
||||||
# If we get a 32 character long hex string, it's a hash and we're
|
# If we get a 32 character long hex string, it's a hash and we're
|
||||||
@ -250,6 +274,7 @@ class ChuniServlet(BaseServlet):
|
|||||||
self.logger.info(f"v{version} {endpoint} request from {client_ip}")
|
self.logger.info(f"v{version} {endpoint} request from {client_ip}")
|
||||||
self.logger.debug(req_data)
|
self.logger.debug(req_data)
|
||||||
|
|
||||||
|
endpoint = endpoint.replace("C3Exp", "") if game_code == "SDGS" else endpoint
|
||||||
func_to_find = "handle_" + inflection.underscore(endpoint) + "_request"
|
func_to_find = "handle_" + inflection.underscore(endpoint) + "_request"
|
||||||
handler_cls = self.versions[internal_ver](self.core_cfg, self.game_cfg)
|
handler_cls = self.versions[internal_ver](self.core_cfg, self.game_cfg)
|
||||||
|
|
||||||
|
@ -71,11 +71,11 @@ class ChuniNew(ChuniBase):
|
|||||||
"matchErrorLimit": 9999,
|
"matchErrorLimit": 9999,
|
||||||
"romVersion": self.game_cfg.version.version(self.version)["rom"],
|
"romVersion": self.game_cfg.version.version(self.version)["rom"],
|
||||||
"dataVersion": self.game_cfg.version.version(self.version)["data"],
|
"dataVersion": self.game_cfg.version.version(self.version)["data"],
|
||||||
"matchingUri": f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/200/ChuniServlet/",
|
"matchingUri": f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/200/ChuniServlet/",
|
||||||
"matchingUriX": f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/200/ChuniServlet/",
|
"matchingUriX": f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/200/ChuniServlet/",
|
||||||
# might be really important for online battle to connect the cabs via UDP port 50201
|
# might be really important for online battle to connect the cabs via UDP port 50201
|
||||||
"udpHolePunchUri": f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/200/ChuniServlet/",
|
"udpHolePunchUri": f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/200/ChuniServlet/",
|
||||||
"reflectorUri": f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/200/ChuniServlet/",
|
"reflectorUri": f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/200/ChuniServlet/",
|
||||||
},
|
},
|
||||||
"isDumpUpload": False,
|
"isDumpUpload": False,
|
||||||
"isAou": False,
|
"isAou": False,
|
||||||
|
@ -21,16 +21,16 @@ class ChuniNewPlus(ChuniNew):
|
|||||||
]
|
]
|
||||||
ret["gameSetting"][
|
ret["gameSetting"][
|
||||||
"matchingUri"
|
"matchingUri"
|
||||||
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/205/ChuniServlet/"
|
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/205/ChuniServlet/"
|
||||||
ret["gameSetting"][
|
ret["gameSetting"][
|
||||||
"matchingUriX"
|
"matchingUriX"
|
||||||
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/205/ChuniServlet/"
|
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/205/ChuniServlet/"
|
||||||
ret["gameSetting"][
|
ret["gameSetting"][
|
||||||
"udpHolePunchUri"
|
"udpHolePunchUri"
|
||||||
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/205/ChuniServlet/"
|
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/205/ChuniServlet/"
|
||||||
ret["gameSetting"][
|
ret["gameSetting"][
|
||||||
"reflectorUri"
|
"reflectorUri"
|
||||||
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/205/ChuniServlet/"
|
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/205/ChuniServlet/"
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
|
def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
|
||||||
|
@ -24,7 +24,7 @@ course = Table(
|
|||||||
Column("scoreMax", Integer),
|
Column("scoreMax", Integer),
|
||||||
Column("isFullCombo", Boolean),
|
Column("isFullCombo", Boolean),
|
||||||
Column("isAllJustice", Boolean),
|
Column("isAllJustice", Boolean),
|
||||||
Column("isSuccess", Boolean),
|
Column("isSuccess", Integer),
|
||||||
Column("scoreRank", Integer),
|
Column("scoreRank", Integer),
|
||||||
Column("eventId", Integer),
|
Column("eventId", Integer),
|
||||||
Column("lastPlayDate", String(25)),
|
Column("lastPlayDate", String(25)),
|
||||||
@ -32,7 +32,7 @@ course = Table(
|
|||||||
Column("param2", Integer),
|
Column("param2", Integer),
|
||||||
Column("param3", Integer),
|
Column("param3", Integer),
|
||||||
Column("param4", Integer),
|
Column("param4", Integer),
|
||||||
Column("isClear", Boolean),
|
Column("isClear", Integer),
|
||||||
Column("theoryCount", Integer),
|
Column("theoryCount", Integer),
|
||||||
Column("orderId", Integer),
|
Column("orderId", Integer),
|
||||||
Column("playerRating", Integer),
|
Column("playerRating", Integer),
|
||||||
@ -60,7 +60,7 @@ best_score = Table(
|
|||||||
Column("maxComboCount", Integer),
|
Column("maxComboCount", Integer),
|
||||||
Column("isFullCombo", Boolean),
|
Column("isFullCombo", Boolean),
|
||||||
Column("isAllJustice", Boolean),
|
Column("isAllJustice", Boolean),
|
||||||
Column("isSuccess", Boolean),
|
Column("isSuccess", Integer),
|
||||||
Column("fullChain", Integer),
|
Column("fullChain", Integer),
|
||||||
Column("maxChain", Integer),
|
Column("maxChain", Integer),
|
||||||
Column("scoreRank", Integer),
|
Column("scoreRank", Integer),
|
||||||
@ -125,7 +125,7 @@ playlog = Table(
|
|||||||
Column("characterId", Integer),
|
Column("characterId", Integer),
|
||||||
Column("skillId", Integer),
|
Column("skillId", Integer),
|
||||||
Column("playKind", Integer),
|
Column("playKind", Integer),
|
||||||
Column("isClear", Boolean),
|
Column("isClear", Integer),
|
||||||
Column("skillLevel", Integer),
|
Column("skillLevel", Integer),
|
||||||
Column("skillEffect", Integer),
|
Column("skillEffect", Integer),
|
||||||
Column("placeName", String(255)),
|
Column("placeName", String(255)),
|
||||||
@ -136,6 +136,7 @@ playlog = Table(
|
|||||||
Column("judgeHeaven", Integer),
|
Column("judgeHeaven", Integer),
|
||||||
Column("regionId", Integer),
|
Column("regionId", Integer),
|
||||||
Column("machineType", Integer),
|
Column("machineType", Integer),
|
||||||
|
Column("ticketId", Integer),
|
||||||
mysql_charset="utf8mb4"
|
mysql_charset="utf8mb4"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -255,4 +256,3 @@ class ChuniScoreData(BaseData):
|
|||||||
if result is None:
|
if result is None:
|
||||||
return None
|
return None
|
||||||
return result.fetchall()
|
return result.fetchall()
|
||||||
|
|
||||||
|
@ -17,16 +17,16 @@ class ChuniSun(ChuniNewPlus):
|
|||||||
ret["gameSetting"]["dataVersion"] = self.game_cfg.version.version(self.version)["data"]
|
ret["gameSetting"]["dataVersion"] = self.game_cfg.version.version(self.version)["data"]
|
||||||
ret["gameSetting"][
|
ret["gameSetting"][
|
||||||
"matchingUri"
|
"matchingUri"
|
||||||
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/210/ChuniServlet/"
|
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/210/ChuniServlet/"
|
||||||
ret["gameSetting"][
|
ret["gameSetting"][
|
||||||
"matchingUriX"
|
"matchingUriX"
|
||||||
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/210/ChuniServlet/"
|
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/210/ChuniServlet/"
|
||||||
ret["gameSetting"][
|
ret["gameSetting"][
|
||||||
"udpHolePunchUri"
|
"udpHolePunchUri"
|
||||||
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/210/ChuniServlet/"
|
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/210/ChuniServlet/"
|
||||||
ret["gameSetting"][
|
ret["gameSetting"][
|
||||||
"reflectorUri"
|
"reflectorUri"
|
||||||
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/210/ChuniServlet/"
|
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/210/ChuniServlet/"
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
|
def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
|
||||||
|
37
titles/chuni/sunplus.py
Normal file
37
titles/chuni/sunplus.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
from typing import Dict, Any
|
||||||
|
|
||||||
|
from core.config import CoreConfig
|
||||||
|
from titles.chuni.sun import ChuniSun
|
||||||
|
from titles.chuni.const import ChuniConstants
|
||||||
|
from titles.chuni.config import ChuniConfig
|
||||||
|
|
||||||
|
|
||||||
|
class ChuniSunPlus(ChuniSun):
|
||||||
|
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
|
||||||
|
super().__init__(core_cfg, game_cfg)
|
||||||
|
self.version = ChuniConstants.VER_CHUNITHM_SUN_PLUS
|
||||||
|
|
||||||
|
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
|
||||||
|
ret = super().handle_get_game_setting_api_request(data)
|
||||||
|
ret["gameSetting"]["romVersion"] = self.game_cfg.version.version(self.version)["rom"]
|
||||||
|
ret["gameSetting"]["dataVersion"] = self.game_cfg.version.version(self.version)["data"]
|
||||||
|
ret["gameSetting"][
|
||||||
|
"matchingUri"
|
||||||
|
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/215/ChuniServlet/"
|
||||||
|
ret["gameSetting"][
|
||||||
|
"matchingUriX"
|
||||||
|
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/215/ChuniServlet/"
|
||||||
|
ret["gameSetting"][
|
||||||
|
"udpHolePunchUri"
|
||||||
|
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/215/ChuniServlet/"
|
||||||
|
ret["gameSetting"][
|
||||||
|
"reflectorUri"
|
||||||
|
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/215/ChuniServlet/"
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
|
||||||
|
user_data = super().handle_cm_get_user_preview_api_request(data)
|
||||||
|
|
||||||
|
# I don't know if lastDataVersion is going to matter, I don't think CardMaker 1.35 works this far up
|
||||||
|
user_data["lastDataVersion"] = "2.15.00"
|
||||||
|
return user_data
|
@ -45,7 +45,7 @@ class CardMakerBase:
|
|||||||
{
|
{
|
||||||
"modelKind": 0,
|
"modelKind": 0,
|
||||||
"type": 1,
|
"type": 1,
|
||||||
"titleUri": f"{uri}/{self._parse_int_ver(games_ver['chuni'])}/ChuniServlet/",
|
"titleUri": f"{uri}/SDHD/{self._parse_int_ver(games_ver['chuni'])}/ChuniServlet/",
|
||||||
},
|
},
|
||||||
# maimai DX
|
# maimai DX
|
||||||
{
|
{
|
||||||
|
@ -76,14 +76,22 @@ class CxbServlet(BaseServlet):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def get_allnet_info(self, game_code: str, game_ver: int, keychip: str) -> Tuple[str, str]:
|
def get_allnet_info(self, game_code: str, game_ver: int, keychip: str) -> Tuple[str, str]:
|
||||||
if not self.core_cfg.server.is_using_proxy and Utils.get_title_port_ssl(self.core_cfg):
|
title_port_int = Utils.get_title_port(self.core_cfg)
|
||||||
|
title_port_ssl_int = Utils.get_title_port_ssl(self.core_cfg)
|
||||||
|
|
||||||
|
proto = "https" if title_port_ssl_int != 443 else "http"
|
||||||
|
|
||||||
|
if proto == "https":
|
||||||
|
t_port = f":{title_port_ssl_int}" if title_port_ssl_int and not self.core_cfg.server.is_using_proxy else ""
|
||||||
|
|
||||||
|
else:
|
||||||
|
t_port = f":{title_port_int}" if title_port_int and not self.core_cfg.server.is_using_proxy else ""
|
||||||
|
|
||||||
return (
|
return (
|
||||||
f"https://{self.core_cfg.title.hostname}:{self.core_cfg.title.port_ssl}",
|
f"{proto}://{self.core_cfg.title.hostname}{t_port}",
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
|
|
||||||
return (f"https://{self.core_cfg.title.hostname}", "")
|
|
||||||
|
|
||||||
def get_endpoint_matchers(self) -> Tuple[List[Tuple[str, str, Dict]], List[Tuple[str, str, Dict]]]:
|
def get_endpoint_matchers(self) -> Tuple[List[Tuple[str, str, Dict]], List[Tuple[str, str, Dict]]]:
|
||||||
return (
|
return (
|
||||||
[],
|
[],
|
||||||
|
@ -238,6 +238,10 @@ class Mai2Base:
|
|||||||
user_id = data["userId"]
|
user_id = data["userId"]
|
||||||
upsert = data["upsertUserAll"]
|
upsert = data["upsertUserAll"]
|
||||||
|
|
||||||
|
if int(user_id) & 1000000000001 == 1000000000001:
|
||||||
|
self.logger.info("Guest play, ignoring.")
|
||||||
|
return {"returnCode": 1, "apiName": "UpsertUserAllApi"}
|
||||||
|
|
||||||
if "userData" in upsert and len(upsert["userData"]) > 0:
|
if "userData" in upsert and len(upsert["userData"]) > 0:
|
||||||
upsert["userData"][0].pop("accessCode")
|
upsert["userData"][0].pop("accessCode")
|
||||||
upsert["userData"][0].pop("userId")
|
upsert["userData"][0].pop("userId")
|
||||||
|
@ -97,6 +97,10 @@ class Mai2DX(Mai2Base):
|
|||||||
user_id = data["userId"]
|
user_id = data["userId"]
|
||||||
upsert = data["upsertUserAll"]
|
upsert = data["upsertUserAll"]
|
||||||
|
|
||||||
|
if int(user_id) & 1000000000001 == 1000000000001:
|
||||||
|
self.logger.info("Guest play, ignoring.")
|
||||||
|
return {"returnCode": 1, "apiName": "UpsertUserAllApi"}
|
||||||
|
|
||||||
if "userData" in upsert and len(upsert["userData"]) > 0:
|
if "userData" in upsert and len(upsert["userData"]) > 0:
|
||||||
upsert["userData"][0]["isNetMember"] = 1
|
upsert["userData"][0]["isNetMember"] = 1
|
||||||
upsert["userData"][0].pop("accessCode")
|
upsert["userData"][0].pop("accessCode")
|
||||||
|
@ -29,6 +29,12 @@ class SaoServerConfig:
|
|||||||
self.__config, "sao", "server", "auto_register", default=True
|
self.__config, "sao", "server", "auto_register", default=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def use_https(self) -> bool:
|
||||||
|
return CoreConfig.get_config_field(
|
||||||
|
self.__config, "sao", "server", "use_https", default=False
|
||||||
|
)
|
||||||
|
|
||||||
class SaoCryptConfig:
|
class SaoCryptConfig:
|
||||||
def __init__(self, parent_config: "SaoConfig"):
|
def __init__(self, parent_config: "SaoConfig"):
|
||||||
self.__config = parent_config
|
self.__config = parent_config
|
||||||
|
@ -76,13 +76,17 @@ class SaoServlet(BaseServlet):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def get_allnet_info(self, game_code: str, game_ver: int, keychip: str) -> Tuple[str, str]:
|
def get_allnet_info(self, game_code: str, game_ver: int, keychip: str) -> Tuple[str, str]:
|
||||||
if not self.core_cfg.server.is_using_proxy and Utils.get_title_port_ssl(self.core_cfg):
|
port_ssl = Utils.get_title_port_ssl(self.core_cfg)
|
||||||
return (
|
port_normal = Utils.get_title_port(self.core_cfg)
|
||||||
f"https://{self.core_cfg.title.hostname}:{self.core_cfg.title.port_ssl}/",
|
|
||||||
f"{self.core_cfg.title.hostname}/",
|
|
||||||
)
|
|
||||||
|
|
||||||
return (f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/", "")
|
proto = "http"
|
||||||
|
port = f":{port_normal}" if not self.core_cfg.server.is_using_proxy and port_normal != 80 else ""
|
||||||
|
|
||||||
|
if self.game_cfg.server.use_https:
|
||||||
|
proto = "https"
|
||||||
|
port = f":{port_ssl}" if not self.core_cfg.server.is_using_proxy and port_ssl != 443 else ""
|
||||||
|
|
||||||
|
return (f"{proto}://{self.core_cfg.title.hostname}{port}/", "")
|
||||||
|
|
||||||
def get_mucha_info(self, core_cfg: CoreConfig, cfg_dir: str) -> Tuple[bool, str]:
|
def get_mucha_info(self, core_cfg: CoreConfig, cfg_dir: str) -> Tuple[bool, str]:
|
||||||
if not self.game_cfg.server.enable:
|
if not self.game_cfg.server.enable:
|
||||||
@ -96,7 +100,9 @@ class SaoServlet(BaseServlet):
|
|||||||
iv = b""
|
iv = b""
|
||||||
|
|
||||||
req_raw = request.content.read()
|
req_raw = request.content.read()
|
||||||
sao_request = req_raw.hex()
|
if len(req_raw) < 40:
|
||||||
|
self.logger.warn(f"Malformed request to {endpoint} - {req_raw.hex()}")
|
||||||
|
return b""
|
||||||
req_header = SaoRequestHeader(req_raw)
|
req_header = SaoRequestHeader(req_raw)
|
||||||
|
|
||||||
cmd_str = f"{req_header.cmd:04x}"
|
cmd_str = f"{req_header.cmd:04x}"
|
||||||
|
@ -3,11 +3,14 @@ from datetime import datetime, timedelta
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
from core.config import CoreConfig
|
from core.config import CoreConfig
|
||||||
|
from titles.wacca.handlers import Dict
|
||||||
from titles.wacca.lily import WaccaLily
|
from titles.wacca.lily import WaccaLily
|
||||||
from titles.wacca.config import WaccaConfig
|
from titles.wacca.config import WaccaConfig
|
||||||
from titles.wacca.const import WaccaConstants
|
from titles.wacca.const import WaccaConstants
|
||||||
from titles.wacca.handlers import *
|
from titles.wacca.handlers import *
|
||||||
|
|
||||||
|
from core.const import AllnetCountryCode
|
||||||
|
|
||||||
|
|
||||||
class WaccaLilyR(WaccaLily):
|
class WaccaLilyR(WaccaLily):
|
||||||
def __init__(self, cfg: CoreConfig, game_cfg: WaccaConfig) -> None:
|
def __init__(self, cfg: CoreConfig, game_cfg: WaccaConfig) -> None:
|
||||||
@ -36,6 +39,38 @@ class WaccaLilyR(WaccaLily):
|
|||||||
(210003, 0),
|
(210003, 0),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def handle_housing_start_request(self, data: Dict) -> Dict:
|
||||||
|
req = HousingStartRequestV2(data)
|
||||||
|
allnet_region_id = None
|
||||||
|
|
||||||
|
machine = self.data.arcade.get_machine(req.chipId)
|
||||||
|
if machine is not None:
|
||||||
|
arcade = self.data.arcade.get_arcade(machine["arcade"])
|
||||||
|
allnet_region_id = arcade["region_id"]
|
||||||
|
|
||||||
|
if req.appVersion.country == AllnetCountryCode.JAPAN.value:
|
||||||
|
if allnet_region_id is not None:
|
||||||
|
region = WaccaConstants.allnet_region_id_to_wacca_region(
|
||||||
|
allnet_region_id
|
||||||
|
)
|
||||||
|
|
||||||
|
if region is None:
|
||||||
|
region_id = self.region_id
|
||||||
|
else:
|
||||||
|
region_id = region
|
||||||
|
|
||||||
|
else:
|
||||||
|
region_id = self.region_id
|
||||||
|
|
||||||
|
elif req.appVersion.country in WaccaConstants.VALID_COUNTRIES:
|
||||||
|
region_id = WaccaConstants.Region[req.appVersion.country]
|
||||||
|
|
||||||
|
else:
|
||||||
|
region_id = WaccaConstants.Region.NONE
|
||||||
|
|
||||||
|
resp = HousingStartResponseV1(region_id)
|
||||||
|
return resp.make()
|
||||||
|
|
||||||
def handle_user_status_create_request(self, data: Dict) -> Dict:
|
def handle_user_status_create_request(self, data: Dict) -> Dict:
|
||||||
req = UserStatusCreateRequest(data)
|
req = UserStatusCreateRequest(data)
|
||||||
resp = super().handle_user_status_create_request(data)
|
resp = super().handle_user_status_create_request(data)
|
||||||
|
Loading…
Reference in New Issue
Block a user