1
0
mirror of synced 2024-11-14 10:17:37 +01:00

The beginnings of database support

This commit is contained in:
Rin 2022-07-15 15:39:59 +01:00
parent e9464ffc1c
commit a56ca3e53b
7 changed files with 550 additions and 374 deletions

8
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,8 @@
{
// Fuck your 2 spaces
"[prisma]": {
"editor.tabSize": 4,
"editor.detectIndentation": false,
"editor.formatOnSave": true
}
}

View File

@ -2,8 +2,6 @@ Copyright 2022 Project Asakura
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The Software shall not be used to run a public service over the Internet.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,151 @@
-- CreateTable
CREATE TABLE "User" (
"id" SERIAL NOT NULL,
"chipId" TEXT NOT NULL,
"accessCode" TEXT NOT NULL,
"tutorials" BOOLEAN[],
"userBanned" BOOLEAN NOT NULL DEFAULT false,
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "UserItem" (
"dbId" SERIAL NOT NULL,
"category" INTEGER NOT NULL,
"itemId" INTEGER NOT NULL,
"userId" INTEGER NOT NULL,
CONSTRAINT "UserItem_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "Car" (
"userId" INTEGER NOT NULL,
"id" SERIAL NOT NULL,
"name" TEXT NOT NULL,
"manufacturer" INTEGER NOT NULL,
"model" INTEGER NOT NULL,
"visualModel" INTEGER NOT NULL,
"customColor" INTEGER NOT NULL DEFAULT 0,
"defaultColor" INTEGER NOT NULL,
"wheel" INTEGER NOT NULL DEFAULT 0,
"wheelColor" INTEGER NOT NULL DEFAULT 0,
"aero" INTEGER NOT NULL DEFAULT 0,
"bonnet" INTEGER NOT NULL DEFAULT 0,
"wing" INTEGER NOT NULL DEFAULT 0,
"mirror" INTEGER NOT NULL DEFAULT 0,
"neon" INTEGER NOT NULL DEFAULT 0,
"trunk" INTEGER NOT NULL DEFAULT 0,
"plate" INTEGER NOT NULL DEFAULT 0,
"plateColor" INTEGER NOT NULL DEFAULT 0,
"plateNumber" INTEGER NOT NULL DEFAULT 0,
"tunePower" INTEGER NOT NULL DEFAULT 0,
"tuneHandling" INTEGER NOT NULL DEFAULT 0,
"title" TEXT NOT NULL DEFAULT 'New Car',
"level" INTEGER NOT NULL DEFAULT 0,
"windowSticker" BOOLEAN NOT NULL DEFAULT false,
"windowStickerString" TEXT NOT NULL DEFAULT '',
"windowStickerFont" INTEGER NOT NULL DEFAULT 0,
"rivalMarker" INTEGER NOT NULL DEFAULT 0,
"aura" INTEGER NOT NULL DEFAULT 0,
"auraMotif" INTEGER NOT NULL DEFAULT 0,
"ghostLevel" INTEGER NOT NULL DEFAULT 1,
"searchCode" TEXT NOT NULL DEFAULT '000000',
"tuningPoints" INTEGER NOT NULL DEFAULT 0,
"odometer" INTEGER NOT NULL DEFAULT 0,
"playCount" INTEGER NOT NULL DEFAULT 0,
"earnedCustomColor" BOOLEAN NOT NULL DEFAULT false,
"carSettingsDbId" INTEGER NOT NULL,
"vsPlayCount" INTEGER NOT NULL DEFAULT 0,
"vsBurstCount" INTEGER NOT NULL DEFAULT 0,
"vsStarCount" INTEGER NOT NULL DEFAULT 0,
"vsCoolOrWild" INTEGER NOT NULL DEFAULT 0,
"vsSmoothOrRough" INTEGER NOT NULL DEFAULT 0,
"vsTripleStarMedals" INTEGER NOT NULL DEFAULT 0,
"vsDoubleStarMedals" INTEGER NOT NULL DEFAULT 0,
"vsSingleStarMedals" INTEGER NOT NULL DEFAULT 0,
"vsPlainMedals" INTEGER NOT NULL DEFAULT 0,
"ghostPlayCount" INTEGER NOT NULL DEFAULT 0,
"ghostWinCount" INTEGER NOT NULL DEFAULT 0,
"ghostTrophy" INTEGER NOT NULL DEFAULT 0,
"ghostScore" INTEGER NOT NULL DEFAULT 0,
"ghostStamp" INTEGER NOT NULL DEFAULT 0,
"ghostAcquireAllCrowns" BOOLEAN NOT NULL DEFAULT false,
"dressupLevel" INTEGER NOT NULL DEFAULT 0,
"dressupPoint" INTEGER NOT NULL DEFAULT 0,
"stPlayCount" INTEGER NOT NULL DEFAULT 0,
"stClearBits" INTEGER NOT NULL DEFAULT 0,
"stClearDivCount" INTEGER NOT NULL DEFAULT 0,
"stClearCount" INTEGER NOT NULL DEFAULT 0,
"stLoseBits" INTEGER NOT NULL DEFAULT 0,
"stConsecutiveWins" INTEGER NOT NULL DEFAULT 0,
"stConsecutiveWinsMax" INTEGER NOT NULL DEFAULT 0,
"stCompleted100Episodes" BOOLEAN NOT NULL DEFAULT false,
"carStateDbId" INTEGER NOT NULL,
CONSTRAINT "Car_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "CarItem" (
"carId" INTEGER NOT NULL,
"category" INTEGER NOT NULL,
"itemId" INTEGER NOT NULL,
"amount" INTEGER NOT NULL
);
-- CreateTable
CREATE TABLE "CarSettings" (
"dbId" SERIAL NOT NULL,
"view" BOOLEAN NOT NULL DEFAULT true,
"transmission" BOOLEAN NOT NULL DEFAULT false,
"retire" BOOLEAN NOT NULL DEFAULT false,
"meter" INTEGER NOT NULL DEFAULT 0,
"navigationMap" BOOLEAN NOT NULL DEFAULT true,
"volume" INTEGER NOT NULL DEFAULT 1,
"bgm" INTEGER NOT NULL DEFAULT 0,
"nameplate" INTEGER NOT NULL DEFAULT 0,
"nameplateColor" INTEGER NOT NULL DEFAULT 0,
"terminalBackground" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "CarSettings_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "CarState" (
"dbId" SERIAL NOT NULL,
"hasOpponentGhost" BOOLEAN NOT NULL DEFAULT true,
"eventJoined" BOOLEAN NOT NULL DEFAULT false,
"transferred" BOOLEAN NOT NULL DEFAULT false,
"toBeDeleted" BOOLEAN NOT NULL DEFAULT false,
CONSTRAINT "CarState_pkey" PRIMARY KEY ("dbId")
);
-- CreateIndex
CREATE UNIQUE INDEX "User_chipId_key" ON "User"("chipId");
-- CreateIndex
CREATE UNIQUE INDEX "Car_carSettingsDbId_key" ON "Car"("carSettingsDbId");
-- CreateIndex
CREATE UNIQUE INDEX "Car_carStateDbId_key" ON "Car"("carStateDbId");
-- CreateIndex
CREATE UNIQUE INDEX "CarItem_carId_key" ON "CarItem"("carId");
-- AddForeignKey
ALTER TABLE "UserItem" ADD CONSTRAINT "UserItem_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Car" ADD CONSTRAINT "Car_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Car" ADD CONSTRAINT "Car_carSettingsDbId_fkey" FOREIGN KEY ("carSettingsDbId") REFERENCES "CarSettings"("dbId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Car" ADD CONSTRAINT "Car_carStateDbId_fkey" FOREIGN KEY ("carStateDbId") REFERENCES "CarState"("dbId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "CarItem" ADD CONSTRAINT "CarItem_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (i.e. Git)
provider = "postgresql"

View File

@ -6,6 +6,134 @@ generator client {
} }
datasource db { datasource db {
provider = "sqlite" provider = "postgresql"
url = "file:./bayshore.db" url = env("POSTGRES_URL")
}
model User {
id Int @id @default(autoincrement())
chipId String @unique
accessCode String
cars Car[]
unusedTickets UserItem[]
tutorials Boolean[]
userBanned Boolean @default(false)
}
model UserItem {
dbId Int @id @default(autoincrement())
category Int
itemId Int
User User @relation(fields: [userId], references: [id])
userId Int
}
model Car {
user User @relation(fields: [userId], references: [id])
userId Int
// This is the Car object itself
id Int @id @default(autoincrement())
name String
manufacturer Int
model Int
visualModel Int
customColor Int @default(0)
defaultColor Int
wheel Int @default(0)
wheelColor Int @default(0)
aero Int @default(0)
bonnet Int @default(0)
wing Int @default(0)
mirror Int @default(0)
neon Int @default(0)
trunk Int @default(0)
plate Int @default(0)
plateColor Int @default(0)
plateNumber Int @default(0)
tunePower Int @default(0)
tuneHandling Int @default(0)
title String @default("New Car")
level Int @default(0)
windowSticker Boolean @default(false)
windowStickerString String @default("")
windowStickerFont Int @default(0)
rivalMarker Int @default(0)
aura Int @default(0)
auraMotif Int @default(0)
ghostLevel Int @default(1)
searchCode String @default("000000")
// This is more data about the car
tuningPoints Int @default(0)
odometer Int @default(0)
playCount Int @default(0)
earnedCustomColor Boolean @default(false)
carSettingsDbId Int @unique
settings CarSettings @relation(fields: [carSettingsDbId], references: [dbId])
vsPlayCount Int @default(0)
vsBurstCount Int @default(0)
vsStarCount Int @default(0)
vsCoolOrWild Int @default(0)
vsSmoothOrRough Int @default(0)
vsTripleStarMedals Int @default(0)
vsDoubleStarMedals Int @default(0)
vsSingleStarMedals Int @default(0)
vsPlainMedals Int @default(0)
ghostPlayCount Int @default(0)
ghostWinCount Int @default(0)
ghostTrophy Int @default(0)
ghostScore Int @default(0)
ghostStamp Int @default(0)
ghostAcquireAllCrowns Boolean @default(false)
dressupLevel Int @default(0)
dressupPoint Int @default(0)
stPlayCount Int @default(0)
stClearBits Int @default(0)
stClearDivCount Int @default(0)
stClearCount Int @default(0)
stLoseBits Int @default(0)
stConsecutiveWins Int @default(0)
stConsecutiveWinsMax Int @default(0)
stCompleted100Episodes Boolean @default(false)
items CarItem[]
carStateDbId Int @unique
state CarState @relation(fields: [carStateDbId], references: [dbId])
}
model CarItem {
Car Car? @relation(fields: [carId], references: [id])
carId Int @unique
category Int
itemId Int
amount Int
}
model CarSettings {
dbId Int @id @default(autoincrement())
car Car?
view Boolean @default(true)
transmission Boolean @default(false)
retire Boolean @default(false)
meter Int @default(0)
navigationMap Boolean @default(true)
volume Int @default(1)
bgm Int @default(0)
nameplate Int @default(0)
nameplateColor Int @default(0)
terminalBackground Int @default(0)
}
model CarState {
dbId Int @id @default(autoincrement())
car Car?
hasOpponentGhost Boolean @default(true)
eventJoined Boolean @default(false)
transferred Boolean @default(false)
toBeDeleted Boolean @default(false)
} }

View File

@ -14,6 +14,8 @@ globalAgent.options.keepAlive = true;
// @ts-ignore // @ts-ignore
require('http').globalAgent.options.keepAlive = true; require('http').globalAgent.options.keepAlive = true;
export const prisma = new PrismaClient();
const appRouter = Router(); const appRouter = Router();
const PORT_ALLNET = 80; const PORT_ALLNET = 80;

View File

@ -2,9 +2,147 @@ import { Application } from "express";
import { Module } from "../module"; import { Module } from "../module";
import * as wm from "../wmmt/wm.proto"; import * as wm from "../wmmt/wm.proto";
import * as svc from "../wmmt/service.proto"; import * as svc from "../wmmt/service.proto";
import { prisma } from "..";
import { User } from "@prisma/client";
export default class GameModule extends Module { export default class GameModule extends Module {
register(app: Application): void { register(app: Application): void {
app.post('/method/load_user', async (req, res) => {
let body = wm.wm.protobuf.LoadUserRequest.decode(req.body);
let user = await prisma.user.findFirst({
where: {
chipId: body.cardChipId,
accessCode: body.accessCode
},
include: {
cars: {
include: {
state: true,
}
},
}
});
if (!user) {
console.log('no such user');
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
numOfOwnedCars: 0,
cars: [],
spappState: wm.wm.protobuf.SmartphoneAppState.SPAPP_UNREGISTERED,
transferState: wm.wm.protobuf.TransferState.NOT_REGISTERED
};
let user = await prisma.user.create({
data: {
chipId: body.cardChipId,
accessCode: body.accessCode,
tutorials: [
false, //TUTORIAL_ID_STORY
false, //TUTORIAL_ID_TIME_ATTACK
false, //TUTORIAL_ID_GHOST
false, //TUTORIAL_ID_GHOST_CHALLENGE
false, //TUTORIAL_ID_GHOST_LEVEL
false, //TUTORIAL_ID_UNUSED_5
false, //TUTORIAL_ID_GHOST_SEARCH
false, //TUTORIAL_ID_GHOST_COMPETITION
false, //TUTORIAL_ID_HP600_CARD
false, //TUTORIAL_ID_UNUSED_9
false, //TUTORIAL_ID_COMPETITION_QUALIFIED
false, //TUTORIAL_ID_COMPETITION_TERMINAL
false, //TUTORIAL_ID_COMPETITION_NOTICE
false, //TUTORIAL_ID_COMPETITION_FINISHED
false, //TUTORIAL_ID_UNUSED_14
false, //TUTORIAL_ID_UNUSED_15
false, //TUTORIAL_ID_UNUSED_16
false, //TUTORIAL_ID_UNUSED_17
false, //TUTORIAL_ID_UNUSED_18
false, //TUTORIAL_ID_UNUSED_19
false, //TUTORIAL_ID_GHOST_STAMP
false, //TUTORIAL_ID_GHOST_STAMP_DECLINED
false, //TUTORIAL_ID_GHOST_STAMP_FRIENDS
false, //TUTORIAL_ID_TERMINAL_SCRATCH
false, //TUTORIAL_ID_TURN_SCRATCH_SHEET
false, //TUTORIAL_ID_INVITE_FRIEND_CAMPAIGN
false, //TUTORIAL_ID_CAR_COUPON_FULL_TUNED_RECEIVABLE
false, //TUTORIAL_ID_VS_CONTINUE_TICKET
false, //TUTORIAL_ID_UNUSED_28
false, //TUTORIAL_ID_UNUSED_29
false, //TUTORIAL_ID_UNUSED_30
false, //TUTORIAL_ID_DRESS_UP
false, //TUTORIAL_ID_MULTI_GHOST
false, //TUTORIAL_ID_STORY_NEW_FEATURE
false, //TUTORIAL_ID_GHOST_NEW_FEATURE
false, //TUTORIAL_ID_GHOST_REGION_MAP
],
}
});
console.log('user made')
if (!user) {
msg.error = wm.wm.protobuf.ErrorCode.ERR_REQUEST;
}
let resp = wm.wm.protobuf.LoadUserResponse.encode(msg);
let end = resp.finish();
let r = res
.header('Server', 'v388 wangan')
.header('Content-Type', 'application/x-protobuf; revision=8053')
.header('Content-Length', end.length.toString())
.status(200);
r.send(Buffer.from(end));
return;
}
console.log(user);
let carStates = user.cars.map(e => e.state);
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
numOfOwnedCars: user.cars.length,
spappState: wm.wm.protobuf.SmartphoneAppState.SPAPP_UNREGISTERED,
transferState: wm.wm.protobuf.TransferState.TRANSFERRED,
carStates,
cars: user.cars,
userId: user.id,
banapassportAmId: 1,
mbId: 1,
tutorials: user.tutorials
}
if (user.userBanned) {
msg.error = wm.wm.protobuf.ErrorCode.ERR_ID_BANNED;
}
let resp = wm.wm.protobuf.LoadUserResponse.encode(msg);
let end = resp.finish();
let r = res
.header('Server', 'v388 wangan')
.header('Content-Type', 'application/x-protobuf; revision=8053')
.header('Content-Length', end.length.toString())
.status(200);
r.send(Buffer.from(end));
})
app.post('/method/load_drive_information', (req, res) => {
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
noticeWindow: [],
noticeWindowMessage: [],
transferNotice: {
needToSeeTransferred: false,
totalMaxiGold: 0,
numOfPorscheCars: 0,
porscheModels: [],
hasR35: false,
},
restrictedModels: [],
announceFeature: false,
announceMobile: false,
availableTickets: []
}
let resp = wm.wm.protobuf.LoadDriveInformationResponse.encode(msg);
let end = resp.finish();
let r = res
.header('Server', 'v388 wangan')
.header('Content-Type', 'application/x-protobuf; revision=8053')
.header('Content-Length', end.length.toString())
.status(200);
r.send(Buffer.from(end));
})
app.post('/method/load_time_attack_record', (req, res) => { app.post('/method/load_time_attack_record', (req, res) => {
console.log('load TA records'); console.log('load TA records');
let body = wm.wm.protobuf.LoadTimeAttackRecordRequest.decode(req.body); let body = wm.wm.protobuf.LoadTimeAttackRecordRequest.decode(req.body);
@ -59,7 +197,25 @@ export default class GameModule extends Module {
r.send(Buffer.from(end)); r.send(Buffer.from(end));
}) })
app.post('/method/update_car', (req, res) => { app.post('/method/update_car', async (req, res) => {
let body = wm.wm.protobuf.UpdateCarRequest.decode(req.body);
let car = await prisma.car.findFirst({
where: {
id: body.carId
},
include: {
settings: true
}
});
await prisma.carSettings.update({
where: {
dbId: car?.carSettingsDbId,
},
data: {
...body.setting
}
});
let msg = { let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS, error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
} }
@ -73,278 +229,6 @@ export default class GameModule extends Module {
r.send(Buffer.from(end)); r.send(Buffer.from(end));
}) })
//banapass loading
app.post('/method/start_transfer', (req, res) => {
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
userId: 0,
}
let resp = wm.wm.protobuf.StartTransferResponse.encode(msg);
let end = resp.finish();
let r = res
.header('Server', 'v388 wangan')
.header('Content-Type', 'application/x-protobuf; revision=8053')
.header('Content-Length', end.length.toString())
.status(200);
r.send(Buffer.from(end));
})
app.post('/method/load_user', (req, res) => {
//everything after this should be replaced with values from a database, but thats above my pay grade :P
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
unlockAt: 1563072119,
accessCode: "12345678901234567890",
banapassportAmId: 69,
mbid: 69,
userId: 69,
numOfOwnedCars: 1,
spappState: wm.wm.protobuf.SmartphoneAppState.SPAPP_UNREGISTERED,
transferState: wm.wm.protobuf.TransferState.TRANSFERRED,
cars: [
{
carId: 106,
userId: 0,
regionId: 0,
name: "a",
manufacturer: 12,
model: 106,
visualModel: 131,
defaultColor: 0,
customColor: 0,
wheel: 82,
wheelColor: 0,
aero: 0,
bonnet: 0,
wing: 0,
mirror: 0,
neon: 0,
trunk: 0,
plate: 0,
plateColor: 0,
plateNumber: 0,
tunePower: 17,
tuneHandling: 17,
title: "Mobil Spek Mainland BOS!!!!!!",
level: 0,
windowSticker: false,
rivalMarker: 0,
lastPlayedAt: 0,
aura: 0,
auraMotif: 0,
ghostLevel: 12,
country: "JPN",
searchCode: "a",
},
],
carStates: [
{
hasOpponentGhost: false,
toBeDeleted: false,
eventJoined: false,
transferred: false,
driveLastPlayedAt: 0,
},
],
unusedCarTickets: [
{
category: wm.wm.protobuf.ItemCategory.CAT_CAR_TICKET_FREE,
itemId: 5,
},
],
tutorials: [
true, //TUTORIAL_ID_STORY
true, //TUTORIAL_ID_TIME_ATTACK
true, //TUTORIAL_ID_GHOST
true, //TUTORIAL_ID_GHOST_CHALLENGE
true, //TUTORIAL_ID_GHOST_LEVEL
true, //TUTORIAL_ID_UNUSED_5
true, //TUTORIAL_ID_GHOST_SEARCH
true, //TUTORIAL_ID_GHOST_COMPETITION
true, //TUTORIAL_ID_HP600_CARD
true, //TUTORIAL_ID_UNUSED_9
true, //TUTORIAL_ID_COMPETITION_QUALIFIED
true, //TUTORIAL_ID_COMPETITION_TERMINAL
true, //TUTORIAL_ID_COMPETITION_NOTICE
true, //TUTORIAL_ID_COMPETITION_FINISHED
true, //TUTORIAL_ID_UNUSED_14
true, //TUTORIAL_ID_UNUSED_15
true, //TUTORIAL_ID_UNUSED_16
true, //TUTORIAL_ID_UNUSED_17
true, //TUTORIAL_ID_UNUSED_18
true, //TUTORIAL_ID_UNUSED_19
true, //TUTORIAL_ID_GHOST_STAMP
true, //TUTORIAL_ID_GHOST_STAMP_DECLINED
true, //TUTORIAL_ID_GHOST_STAMP_FRIENDS
true, //TUTORIAL_ID_TERMINAL_SCRATCH
true, //TUTORIAL_ID_TURN_SCRATCH_SHEET
true, //TUTORIAL_ID_INVITE_FRIEND_CAMPAIGN
true, //TUTORIAL_ID_CAR_COUPON_FULL_TUNED_RECEIVABLE
true, //TUTORIAL_ID_VS_CONTINUE_TICKET
true, //TUTORIAL_ID_UNUSED_28
true, //TUTORIAL_ID_UNUSED_29
true, //TUTORIAL_ID_UNUSED_30
true, //TUTORIAL_ID_DRESS_UP
true, //TUTORIAL_ID_MULTI_GHOST
true, //TUTORIAL_ID_STORY_NEW_FEATURE
true, //TUTORIAL_ID_GHOST_NEW_FEATURE
true, //TUTORIAL_ID_GHOST_REGION_MAP
],
}
let resp = wm.wm.protobuf.LoadUserResponse.encode(msg);
let end = resp.finish();
let r = res
.header('Server', 'v388 wangan')
.header('Content-Type', 'application/x-protobuf; revision=8053')
.header('Content-Length', end.length.toString())
.status(200);
r.send(Buffer.from(end));
})
app.post('/method/load_drive_information', (req, res) => {
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
noticeWindow: [],
noticeWindowMessage: [],
transferNotice: {
needToSeeTransferred: false,
totalMaxiGold: 0,
numOfPorscheCars: 0,
porscheModels: [],
hasR35: false,
},
restrictedModels: [],
announceFeature: false,
announceMobile: false,
availableTickets: [
{
category: wm.wm.protobuf.ItemCategory.CAT_CAR_TICKET,
itemId: 1,
}
]
}
let resp = wm.wm.protobuf.LoadDriveInformationResponse.encode(msg);
let end = resp.finish();
let r = res
.header('Server', 'v388 wangan')
.header('Content-Type', 'application/x-protobuf; revision=8053')
.header('Content-Length', end.length.toString())
.status(200);
r.send(Buffer.from(end));
})
app.post('/method/load_car', (req, res) => {
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
//everything after this should be replaced with values from a database, but thats above my pay grade :P
car:
{
carId: 106,
userId: 0,
regionId: 0,
name: "a",
manufacturer: 12,
model: 106,
visualModel: 131,
defaultColor: 0,
customColor: 0,
wheel: 82,
wheelColor: 0,
aero: 0,
bonnet: 0,
wing: 0,
mirror: 0,
neon: 0,
trunk: 0,
plate: 0,
plateColor: 0,
plateNumber: 0,
tunePower: 17,
tuneHandling: 17,
title: "Mobil Spek Mainland BOS!!!!!!",
level: 0,
windowSticker: false,
rivalMarker: 0,
lastPlayedAt: 0,
aura: 0,
auraMotif: 0,
ghostLevel: 12,
country: "JPN",
searchCode: "a",
},
tuningPoint: 0,
odometer: 99999999,
playCount: 10,
earnedCustomColor: false,
setting:
{
view: false,
transmission: false,
retire: true,
meter: 1,
navigationMap: true,
volume: 1,
bgm: 0,
nameplate: 0,
nameplateColor: 0,
terminalBackground: 0,
},
vsPlayCount: 69699696,
vsBurstCount: 69696969,
vsStarCount: 696969,
vsStarCountMax: 6969696,
vsCoolOrWild: 0,
vsSmoothOrRough: 0,
vsTripleStarMedals: 69699696,
vsDoubleStarMedals: 0,
vsSingleStarMedals: 0,
vsPlainMedals: 0,
rgPlayCount: 6000,
rgWinCount: 6000,
rgTrophy: 6000,
rgPreviousVersionPlayCount: 6000,
rgScore: 1,
rgStamp: 100,
rgAcquireAllCrowns: true,
dressupLevel: 63,
dressupPoint: 0,
stPlayCount: 0,
stClearBits: 0,
stClearDivCount: 0,
stClearCount: 0,
stLoseBits: 0,
stConsecutiveWins: 699999,
stConsecutiveWinsMax: 420,
stCompleted_100Episodes: false,
ownedItems: [
{
category: wm.wm.protobuf.ItemCategory.CAT_METER,
itemId: 1,
amount: 1,
},
],
auraMotifAutoChange: false,
screenshotCount: 0,
transferred: true,
}
let resp = wm.wm.protobuf.LoadCarResponse.encode(msg);
let end = resp.finish();
let r = res
.header('Server', 'v388 wangan')
.header('Content-Type', 'application/x-protobuf; revision=8053')
.header('Content-Length', end.length.toString())
.status(200);
r.send(Buffer.from(end));
})
app.post('/method/load_stamp_target', (req, res) => { app.post('/method/load_stamp_target', (req, res) => {
let msg = { let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS, error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
@ -359,13 +243,22 @@ export default class GameModule extends Module {
r.send(Buffer.from(end)); r.send(Buffer.from(end));
}) })
app.post('/method/save_scratch_sheet', (req, res) => { // THE GAME DOES NOT FUCKING USE THIS
/*
app.post('/method/create_user', async (req, res) => {
let body = wm.wm.protobuf.CreateUserRequest.decode(req.body);
let user = await prisma.user.create({
data: {
chipId: body.cardChipId,
accessCode: body.accessCode,
}
});
let msg = { let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS, error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
currentSheet: 0, userId: user.id,
numOfScratched: 0,
} }
let resp = wm.wm.protobuf.SaveScratchSheetResponse.encode(msg); let resp = wm.wm.protobuf.CreateUserResponse.encode(msg);
let end = resp.finish(); let end = resp.finish();
let r = res let r = res
.header('Server', 'v388 wangan') .header('Server', 'v388 wangan')
@ -374,12 +267,55 @@ export default class GameModule extends Module {
.status(200); .status(200);
r.send(Buffer.from(end)); r.send(Buffer.from(end));
}) })
*/
app.post('/method/create_car', (req, res) => { app.post('/method/create_car', async (req, res) => {
let body = wm.wm.protobuf.CreateCarRequest.decode(req.body);
console.log(body);
let user: User | null;
if (body.userId) {
user = await prisma.user.findFirst({
where: {
id: body.userId
},
});
} else {
user = await prisma.user.findFirst({
where: {
chipId: body.cardChipId,
accessCode: body.accessCode
},
})
}
console.log(user);
if (!user) throw new Error();
let settings = await prisma.carSettings.create({
data: {}
});
let state = await prisma.carState.create({
data: {}
})
let car = await prisma.car.create({
data: {
userId: user.id,
manufacturer: body.car.manufacturer!!,
defaultColor: body.car.defaultColor!!,
model: body.car.model!!,
visualModel: body.car.visualModel!!,
name: body.car.name!!,
title: body.car.title!!,
level: body.car.level!!,
tunePower: body.car.tunePower!!,
tuneHandling: body.car.tuneHandling!!,
carSettingsDbId: settings.dbId,
carStateDbId: state.dbId
}
})
console.log(`Created new car ${car.name} with ID ${car.id}`);
let msg = { let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS, error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
userId: 69, userId: body.userId,
carId: 8, carId: car.id,
} }
let resp = wm.wm.protobuf.CreateCarResponse.encode(msg); let resp = wm.wm.protobuf.CreateCarResponse.encode(msg);
let end = resp.finish(); let end = resp.finish();
@ -395,8 +331,8 @@ export default class GameModule extends Module {
let msg = { let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS, error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
taRankingUpdatedAt: 0, taRankingUpdatedAt: 0,
ghostBattleCount: 9999, ghostBattleCount: 0,
ghostBattleWinCount: 9999, ghostBattleWinCount: 0,
stampSheetCount: 100, stampSheetCount: 100,
} }
let resp = wm.wm.protobuf.LoadGameHistoryResponse.encode(msg); let resp = wm.wm.protobuf.LoadGameHistoryResponse.encode(msg);
@ -409,30 +345,10 @@ export default class GameModule extends Module {
r.send(Buffer.from(end)); r.send(Buffer.from(end));
}) })
// TODO: make this actually save lmao
app.post('/method/save_game_result', (req, res) => { app.post('/method/save_game_result', (req, res) => {
let msg = { let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS, error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
/*
carId: 8,
gameMode: 4,
playedAt: 0,
playCount: 1,
retired: false,
timeup: false,
odometer: 694201337,
earnedCustomColor: false,
confirmedTutorials: [],
earnedItems: {
category: wm.wm.protobuf.ICarItem[wm.wm.protobuf.ItemCategory.CAT_NUMBER_PLATE],
itemId: 0,
},
earnedUserItems: {
category: wm.wm.protobuf.ICarItem[wm.wm.protobuf.ItemCategory.CAT_NUMBER_PLATE],
itemId: 1,
},
preservedTitles: "ur gay",
neighborCars: 69,
*/
} }
let resp = wm.wm.protobuf.SaveGameResultResponse.encode(msg); let resp = wm.wm.protobuf.SaveGameResultResponse.encode(msg);
let end = resp.finish(); let end = resp.finish();
@ -456,36 +372,6 @@ export default class GameModule extends Module {
.header('Content-Length', end.length.toString()) .header('Content-Length', end.length.toString())
.status(200); .status(200);
r.send(Buffer.from(end)); r.send(Buffer.from(end));
})
//ghost battle stuff
app.post('/method/load_ghost_battle_info', (req, res) => {
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
stampSheetCount: 100,
}
let resp = wm.wm.protobuf.LoadGhostBattleInfoResponse.encode(msg);
let end = resp.finish();
let r = res
.header('Server', 'v388 wangan')
.header('Content-Type', 'application/x-protobuf; revision=8053')
.header('Content-Length', end.length.toString())
.status(200);
r.send(Buffer.from(end));
})
app.post('/method/lock_crown', (req, res) => {
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
}
let resp = svc.wm.protobuf.LockCrownResponse.encode(msg);
let end = resp.finish();
let r = res
.header('Server', 'v388 wangan')
.header('Content-Type', 'application/x-protobuf; revision=8053')
.header('Content-Length', end.length.toString())
.status(200);
r.send(Buffer.from(end));
}) })
} }
} }