Support for X-Verse

This commit is contained in:
alexay7
2025-10-13 20:49:06 +02:00
parent 5a0106014f
commit 3515953249
3 changed files with 51 additions and 27 deletions
+7 -7
View File
@@ -10,7 +10,7 @@ import {
pingMatching,
endMatching,
removeMatchingMember,
getMatchingState,
getMatchingState, mBeginRaidMatchingApi, mGetRaidMatchingStateApi, mEndRaidMatchingApi, mRemoveRaidMatchingMemberApi,
} from './service'
import { mPing, mBeginMatchingApi, mEndMatchingApi, mGetMatchingStateApi, mRemoveMatchingMemberApi, calculateEncryption, gameKeys } from './service/core/encryption'
import { buffer } from 'stream/consumers'
@@ -22,7 +22,7 @@ app.use(function(req, res, next) {
req.body = '';
req.setEncoding('hex');
req.on('data', function(chunk) {
req.on('data', function(chunk) {
req.body += chunk;
});
@@ -41,7 +41,7 @@ app.use((req, res, next) => {
const header = req.headers
if (header['chuni-encoding'] != undefined){
req.body = decrypt(
gameKeys[header['chuni-encoding'].valueOf().toString()],
gameKeys[header['chuni-encoding'].valueOf().toString()],
Buffer.from(req.body, 'hex'))
req.body = zlib.inflateSync(req.body).toString()
req.body = JSON.parse(req.body)
@@ -111,28 +111,28 @@ app.post('/MatchingServer/:api', async (req, res) => {
})
return res.json(await pingMatching())
} else
if (mBeginMatchingApi.includes(api)){
if (mBeginMatchingApi.includes(api) || mBeginRaidMatchingApi.includes(api)){
log.info({
service: 'Yukiotoko Matching',
message: `BeginMatching`,
})
return res.json(await beginMatching(body, req.ip))
} else
if (mEndMatchingApi.includes(api)){
if (mEndMatchingApi.includes(api) || mEndRaidMatchingApi.includes(api)){
log.info({
service: 'Yukiotoko Matching',
message: `EndMatching`,
})
return res.json(await endMatching(body))
} else
if (mRemoveMatchingMemberApi.includes(api)){
if (mRemoveMatchingMemberApi.includes(api) || mRemoveRaidMatchingMemberApi.includes(api)){
log.info({
service: 'Yukiotoko Matching',
message: `RemoveMatchingMember`,
})
return res.json(await removeMatchingMember(body))
} else
if (mGetMatchingStateApi.includes(api)){
if (mGetMatchingStateApi.includes(api) || mGetRaidMatchingStateApi.includes(api)){
log.info({
service: 'Yukiotoko Matching',
message: `GetMatchingState`,
@@ -7,6 +7,10 @@ export var mBeginMatchingApi = ['BeginMatchingApi']
export var mEndMatchingApi = ['EndMatchingApi']
export var mRemoveMatchingMemberApi = ['RemoveMatchingMemberApi']
export var mGetMatchingStateApi = ['GetMatchingStateApi']
export var mBeginRaidMatchingApi = ['BeginRaidMatchingApi']
export var mGetRaidMatchingStateApi = ['GetRaidMatchingStateApi']
export var mEndRaidMatchingApi = ['EndRaidMatchingApi']
export var mRemoveRaidMatchingMemberApi = ['RemoveRaidMatchingMemberApi']
//Insert Keys Here
export const gameKeys = {
+40 -20
View File
@@ -1,6 +1,12 @@
import { db, Prisma } from '@yukiotoko/db'
const convertIso88591ToUtf8 = (input: string): string => {
const convertIso88591ToUtf8 = (input: string, romVersion:string): string => {
// From X-Verse the usernames are sent in UTF-8 instead of ISO-8859-1
const isUtf8 = convertRomVersionToNumber(romVersion) >= 24000
if (isUtf8) {
return input
}
const latin1Bytes = new Uint8Array(input.length)
for (let i = 0; i < input.length; i++) {
latin1Bytes[i] = input.charCodeAt(i)
@@ -10,6 +16,20 @@ const convertIso88591ToUtf8 = (input: string): string => {
return decoder.decode(latin1Bytes)
}
const convertRomVersionToNumber = (romVersion: string): number => {
//Convert rom version string to a number for easier comparison
//Example: "2.40.00" -> 24000
const versionParts = romVersion.split('.')
if (versionParts.length !== 3) {
return 0 // Invalid version format
}
const major = parseInt(versionParts[0]) || 0
const minor = parseInt(versionParts[1]) || 0
const patch = parseInt(versionParts[2]) || 0
return major * 10000 + minor * 100 + patch
}
export const pingMatching = () => {
return { returnCode: 1 }
}
@@ -31,7 +51,7 @@ export const beginMatching = async (body, ip) => {
}
//UserID + Name ban
case 2: {
if (body.matchingMemberInfo.userId == banEntry.value && convertIso88591ToUtf8(body.matchingMemberInfo.userName) == banEntry.value2) {
if (body.matchingMemberInfo.userId == banEntry.value && convertIso88591ToUtf8(body.matchingMemberInfo.userName,body.matchingMemberInfo.romVersion) == banEntry.value2) {
banResult = {
message: "User Is Banned."
}
@@ -60,9 +80,9 @@ export const beginMatching = async (body, ip) => {
var nowdate = new Date()
olddate.setTime(olddate.getTime() + (10*1000))
DeleteAfterDay.setTime(DeleteAfterDay.getTime() + (24*60*60*1000))
//If there is a room that has not been updated in 10 seconds and is not finished
//If there is a room that has not been updated in 10 seconds and is not finished
//(Happens when host test menus while solo), mark the room as finished.
if ((nowdate > olddate) && (room.isFinished == false)){
if ((nowdate > olddate) && (room.isFinished == false)){
await db.chusanUserMatching.updateMany({
where: {
roomId: room.roomId
@@ -71,9 +91,9 @@ export const beginMatching = async (body, ip) => {
isFinished: true
}
})
}
}
// If the room has not been updated in 24 hours, delete the room entirely
if (nowdate > DeleteAfterDay){
if (nowdate > DeleteAfterDay){
await db.chusanUserMatching.deleteMany({
where: {
roomId: room.roomId
@@ -88,7 +108,7 @@ export const beginMatching = async (body, ip) => {
userId: body.matchingMemberInfo.userId,
isFinished: false,
}
})
})
var roomid = 1
// Find the oldest room that is within 2 battle ranks of the player, and the same rom and data version
//Make sure the battle rank id is at the very least 0 when checking
@@ -120,7 +140,7 @@ export const beginMatching = async (body, ip) => {
}
}
]
},
orderBy: {
roomId: 'asc',
@@ -137,8 +157,8 @@ export const beginMatching = async (body, ip) => {
roomid = newest_chusanUserMatching.roomId + 1
}
var host = body.matchingMemberInfo
host.userName = convertIso88591ToUtf8(body.matchingMemberInfo.userName)
host.teamName = convertIso88591ToUtf8(body.matchingMemberInfo.teamName)
host.userName = convertIso88591ToUtf8(body.matchingMemberInfo.userName,body.matchingMemberInfo.romVersion)
host.teamName = convertIso88591ToUtf8(body.matchingMemberInfo.teamName,body.matchingMemberInfo.romVersion)
// Create the room
chusanUserMatching = await db.chusanUserMatching.create({
data: {
@@ -160,8 +180,8 @@ export const beginMatching = async (body, ip) => {
roomid = chusanUserMatching.roomId
const matching_member_list = chusanUserMatching.matchingMemberInfoList as Prisma.JsonArray
var new_member = body.matchingMemberInfo
new_member.userName = convertIso88591ToUtf8(body.matchingMemberInfo.userName,)
new_member.teamName = convertIso88591ToUtf8(body.matchingMemberInfo.teamName,)
new_member.userName = convertIso88591ToUtf8(body.matchingMemberInfo.userName, body.matchingMemberInfo.romVersion)
new_member.teamName = convertIso88591ToUtf8(body.matchingMemberInfo.teamName, body.matchingMemberInfo.romVersion)
matching_member_list.push(new_member)
var isfull =false
if (matching_member_list.length == 4){
@@ -182,7 +202,7 @@ export const beginMatching = async (body, ip) => {
}
// Delete any cabs still looking to UDP that is going to start matching again
// Or delete any rooms that shouldnt exist
await db.chusanUserRooms.deleteMany({
await db.chusanUserRooms.deleteMany({
where: {
OR: [
{
@@ -193,7 +213,7 @@ export const beginMatching = async (body, ip) => {
},
]
}
})
})
const matchingWaitState = {
isFinish: false,
restMSec: 60,
@@ -231,7 +251,7 @@ export const endMatching = async body => {
console.log(averageBattleRanking)
averageBattleRanking = averageBattleRanking / members.length
// Return roles for every player
// 0 = CPU (Need to confirm?) 1 = Host 2 = Client
// 0 = CPU (Need to confirm?) 1 = Host 2 = Client
members.forEach(member => {
if (member!['userId'] == matching_room?.userId){
role_list.push({ role: 1 })
@@ -326,11 +346,11 @@ export const getMatchingState = async body => {
var roomMembers = matching_room!.matchingMemberInfoList as Prisma.JsonArray
var current_member = body.matchingMemberInfo
var allowAnybody = false
current_member.userName = convertIso88591ToUtf8(body.matchingMemberInfo.userName)
current_member.teamName = convertIso88591ToUtf8(body.matchingMemberInfo.teamName)
current_member.userName = convertIso88591ToUtf8(body.matchingMemberInfo.userName,body.matchingMemberInfo.romVersion)
current_member.teamName = convertIso88591ToUtf8(body.matchingMemberInfo.teamName,body.matchingMemberInfo.romVersion)
//If the api packet is from the host, update the time
if (matching_room!.userId == String(current_member.userId)) {
if(matching_room!.matchingMemberInfoList.length == 4) {
restsec = 0
}
@@ -372,7 +392,7 @@ export const getMatchingState = async body => {
},
})
var olddate = new Date(matching_room.updatedAt)
var nowdate = new Date()
var nowdate = new Date()
// if the host has stopped updating the room for 10 seconds(Because of test menu), delete the room because all other clients are softlocked
olddate.setTime(olddate.getTime() + (10*1000))
if ((nowdate > olddate) && (matching_room.isFinished == false)){
@@ -381,7 +401,7 @@ export const getMatchingState = async body => {
id: matching_room.id
}
})
}
}
// If the current room is allowing anybody and only has 1 player in it, try to merge rooms
if((matching_room.restMSec < 45) && (matching_room.matchingMemberInfoList.length == 1)){
var newroom = await db.chusanUserMatching.findFirst({