1
0
mirror of https://github.com/shiroikitsu8/Bayshore_6r_legacy.git synced 2024-11-30 18:24:39 +01:00

clean up (still not complete), fix new card restration, block blank card.ini data

This commit is contained in:
Shiroi Kitsu 2023-01-24 09:40:21 +07:00
parent 9c7c80df0e
commit 46e9ba9e5a
25 changed files with 1427 additions and 1146 deletions

View File

@ -24,7 +24,7 @@ import MuchaModule from './mucha';
import { Config } from './config';
import * as Sentry from '@sentry/node';
import * as Tracing from '@sentry/tracing';
import * as common from './util/common';
import * as common from './modules/util/common';
globalAgent.options.keepAlive = true;

View File

@ -1,17 +1,13 @@
import { Application } from "express";
import { Config } from "../config";
import { Module } from "module";
import { prisma } from "..";
import { User } from "@prisma/client";
import Long from "long";
// Import Proto
import * as wm from "../wmmt/wm.proto";
// Import Util
import * as common from "../util/common";
import * as scratch from "../util/scratch";
import * as terminal from "../util/terminal/check_car";
import * as common from "./util/common";
import * as carFunctions from "./cars/functions";
export default class CarModule extends Module {
@ -24,189 +20,24 @@ export default class CarModule extends Module {
let body = wm.wm.protobuf.LoadCarRequest.decode(req.body);
// Get the car (required data only) with the given id
let car = await prisma.car.findFirst({
where: {
carId: body.carId
},
include: {
settings: true,
items: true,
gtWing: true,
lastPlayedPlace: true,
}
});
let car = await carFunctions.getCar(body.carId);
// Error handling if ghostLevel accidentally set to 0 or more than 10
if(car!.ghostLevel < 1)
{
car!.ghostLevel = 1;
}
if(car!.ghostLevel > 11)
{
car!.ghostLevel = 10;
}
// Get Challenger Data
let registeredTarget = await carFunctions.getRegisteredTarget(body.carId);
// Convert the database lose bits to a Long
let longLoseBits = Long.fromString(car!.stLoseBits.toString());
// Get Registered Target
let getTarget = await prisma.ghostRegisteredFromTerminal.findFirst({
where:{
carId: body.carId
}
});
let opponentGhost;
let opponentTrailId;
let opponentCompetitionId;
let registeredTarget: boolean = false;
if(getTarget)
{
console.log('Registered Opponents Available');
let getTargetTrail = await prisma.oCMTop1GhostTrail.findFirst({
where:{
carId: getTarget.opponentCarId,
competitionId: Number(getTarget.competitionId)
},
orderBy:{
periodId: 'desc'
}
});
if(getTargetTrail)
{
let getTargetCar = await prisma.car.findFirst({
where:{
carId: getTarget.opponentCarId
},
include:{
gtWing: true,
lastPlayedPlace: true
}
});
opponentGhost = wm.wm.protobuf.GhostCar.create({
car: {
...getTargetCar!,
tunePower: getTargetTrail!.tunePower,
tuneHandling: getTargetTrail!.tuneHandling,
},
area: getTargetTrail!.area,
ramp: getTargetTrail!.ramp,
path: getTargetTrail!.path,
nonhuman: false,
type: wm.wm.protobuf.GhostType.GHOST_NORMAL,
trailId: getTargetTrail!.dbId
});
opponentTrailId = Number(getTargetTrail!.dbId);
opponentCompetitionId = Number(getTarget.competitionId);
}
registeredTarget = true;
}
// Check opponents stamp target
// Will skip this if user's have Hall of Fame ghost registered
let carsChallengers;
let returnCount = 1;
let opponentTargetCount = 0;
if(registeredTarget === false)
{
opponentTargetCount = await prisma.carStampTarget.count({
where:{
stampTargetCarId: body.carId,
recommended: true,
},
orderBy:{
locked: 'desc'
}
})
if(opponentTargetCount > 0)
{
console.log('Challengers Available');
// Randomize pick
let random: number = 1;
// Randomize it 5 times
for(let i=0; i<5; i++)
{
random = Math.floor(Math.random() * opponentTargetCount);
}
// Try randomize it again if it's 1
if(random === 1)
{
random = Math.floor(Math.random() * opponentTargetCount);
}
// Check opponents target
let opponentTarget = await prisma.carStampTarget.findMany({
where:{
stampTargetCarId: body.carId,
recommended: true,
},
orderBy:{
locked: 'desc'
},
skip: random,
take: 1,
});
// Get all of the friend cars for the carId provided
let challengers = await prisma.carChallenger.findFirst({
where: {
challengerCarId: opponentTarget[0].carId,
carId: body.carId
},
orderBy:{
id: 'desc'
}
});
if(challengers)
{
returnCount = opponentTarget[0].returnCount;
let carTarget = await prisma.car.findFirst({
where:{
carId: challengers.challengerCarId
},
include:{
gtWing: true,
lastPlayedPlace: true
}
})
let result = 0;
if(challengers.result > 0)
{
result = -Math.abs(challengers.result);
}
else{
result = Math.abs(challengers.result);
}
carsChallengers = wm.wm.protobuf.ChallengerCar.create({
car: carTarget!,
stamp: challengers.stamp,
result: result,
area: challengers.area
});
}
}
}
// Get Challenger Data
let opponentsTarget = await carFunctions.getOpponentsTarget(body.carId, registeredTarget.registeredargetAvailable);
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
car: {
...car!,
},
// wm.protobuf.Car;
car: car,
// Other Car Data (tuningPoint, odometer, playCount, etc)
...car,
stLoseBits: car.longLoseBits,
tuningPoint: car!.tuningPoints,
setting: car!.settings,
rgPreviousVersionPlayCount: 0,
@ -214,21 +45,22 @@ export default class CarModule extends Module {
auraMotifAutoChange: false,
screenshotCount: 0,
transferred: false,
...car!,
stLoseBits: longLoseBits,
ownedItems: car!.items,
lastPlayedAt: car!.lastPlayedAt,
announceEventModePrize: true,
// Stamp or Challenger
challenger: carsChallengers || null,
challengerReturnCount: returnCount || null,
numOfChallengers: opponentTargetCount + 1 || null,
challenger: opponentsTarget.challenger,
challengerReturnCount: opponentsTarget.challengerReturnCount,
numOfChallengers: opponentsTarget.numOfChallengers,
// OCM Challenge Top 1
opponentGhost: opponentGhost || null,
opponentTrailId: opponentTrailId || null,
opponentCompetitionId: opponentCompetitionId || null
opponentGhost: registeredTarget.opponentGhost,
opponentTrailId: registeredTarget.opponentTrailId,
opponentCompetitionId: registeredTarget.opponentCompetitionId,
// Owned Item
ownedItems: car.items,
// Announce Event Mode Prize
announceEventModePrize: true
};
// Generate the load car response message
@ -245,274 +77,18 @@ export default class CarModule extends Module {
// Get the request body for the create car request
let body = wm.wm.protobuf.CreateCarRequest.decode(req.body);
// Get the current date/time (unix epoch)
let date = Math.floor(new Date().getTime() / 1000)
// Create the Car
let createCar = await carFunctions.createCar(body);
let tune = createCar.tune;
let carInsert = createCar.carInsert;
// Retrieve user from card chip / user id
let user: User | null;
// User ID provided, use that
if (body.userId) {
user = await prisma.user.findFirst({
where: {
id: body.userId
},
});
} else { // No user id, use card chip
user = await prisma.user.findFirst({
where: {
chipId: body.cardChipId,
accessCode: body.accessCode
},
})
}
// User not found, terminate
if (!user) throw new Error();
// Generate blank car settings object
let settings = await prisma.carSettings.create({
data: {}
});
// Generate blank car state object
let state = await prisma.carState.create({
data: {}
})
let gtWing = await prisma.carGTWing.create({
data: {}
})
// Sets if full tune is used or not
// let fullyTuned = false;
// 0: Stock Tune
// 1: Basic Tune (600 HP)
// 2: Fully Tuned (840 HP)
let tune = 0;
// If a user item has been used
if (body.userItemId)
{
console.log(`Item used - ID ${body.userItemId}`);
// Remove the user item from the database
let item = await prisma.userItem.delete({
where: {
userItemId: body.userItemId
}
});
console.log('Item deleted!');
switch(item.category)
{
case 203: // Car Tune Ticket
// Switch on item id
switch(item.itemId)
{
// Discarded Vehicle Card
case 1: tune = 1; break;
case 2: tune = 1; break;
case 3: tune = 1; break;
// Fully Tuned Ticket
case 5: tune = 2; break;
default: // Unknown item type, throw unsupported error
throw Error("Unsupported itemId: " + item.itemId);
}
break;
case 201: // Special Car Ticket
// Fully tuned special cars
if (scratch.fullyTunedCars.includes(item.itemId))
{
// Car is fully tuned
tune = 2;
}
// Basic tuned special cars
if (scratch.basicTunedCars.includes(item.itemId))
{
// If gift cars fully tuned is set
if (Config.getConfig().gameOptions.giftCarsFullyTuned)
{
// Car is fully tuned
tune = 2;
}
else // Gift cars fully tuned not set
{
// Car is basic tuned
tune = 1;
}
}
// Stock tuned special cars
if (scratch.stockTunedCars.includes(item.itemId))
{
// If gift cars fully tuned is set
if (Config.getConfig().gameOptions.giftCarsFullyTuned)
{
// Car is fully tuned
tune = 2;
}
else // Gift cars fully tuned not set
{
// Car is stock
tune = 0;
}
}
break;
}
console.log(`Item category was ${item.category} and item game ID was ${item.itemId}`);
}
// Other cases, may occur if item is not detected as 'used'
// User item not used, but car has 740 HP by default
else if (body.car &&
(body.car.tunePower == 17) && (body.car.tuneHandling == 17))
{
// Car is fully tuned
tune = 2;
// Check if created car is from terminal scratch car
await terminal.checkScratchCar(body.userId, body.car.visualModel!)
}
// User item not used, but car has 600 HP by default
else if (body.car &&
(body.car.tunePower == 10) && (body.car.tuneHandling == 10))
{
// Car is basic tuned
tune = 1;
}
// User item not used, but gift cars fully tuned switch is set
else if (Config.getConfig().gameOptions.giftCarsFullyTuned)
{
// List of event / exclusive car IDs
let event_cars = [
0x7A, // Mini
0x82, // S660
0x83, // S2000
0x89, // NDERC
0x8B, // GS130 (Starts at 20 Stories by default)
];
// If the car visual model is not null and is in the list of event cars
if (body.car.visualModel && event_cars.includes(body.car.visualModel))
{
// Set full tune used to be true
tune = 2;
}
}
// Randomize regionId
let regionId: number = 18;
// Randomize it 5 times
for(let i=0; i<5; i++)
{
regionId = Math.floor(Math.random() * 47) + 1;
}
// Try randomize it again if it's 1
if(regionId === 1)
{
regionId = Math.floor(Math.random() * 47) + 1;
}
// Check if user's other car have unique window sticker
let windowSticker = await carFunctions.getWindowSticker(body.userId);
let additionalWindowStickerInsert = windowSticker.additionalWindowStickerInsert
// Default car values
let carInsert = {
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,
carGTWingDbId: gtWing.dbId,
regionId: regionId,
lastPlayedAt: date,
lastPlayedPlaceId: 1, // Server Default
};
// Check if user have more than one cars
let checkWindowSticker = await prisma.car.findFirst({
where: {
userId: body.userId
},
select: {
windowStickerString: true,
windowStickerFont: true
}
});
let additionalWindowStickerInsert = {
}
// If more than one cars, get the window sticker string
if(checkWindowSticker)
{
additionalWindowStickerInsert = {
windowStickerString: checkWindowSticker.windowStickerString,
windowStickerFont: checkWindowSticker.windowStickerFont,
}
}
// Additional car values (for basic / full tune)
let additionalInsert = {
}
// Switch on tune status
switch(tune)
{
// 0: Stock, nothing extra
case 1: // Basic Tune
// Updated default values
carInsert.level = 2; // C8
carInsert.tunePower = 10; // 600 HP
carInsert.tuneHandling = 10; // 600 HP
// Additional basic tune values
additionalInsert = {
ghostLevel: 4,
stClearBits: 0,
stLoseBits: 0,
stClearCount: 20,
stClearDivCount: 1,
stConsecutiveWins: 20,
stConsecutiveWinsMax: 20
};
break;
case 2: // Fully Tuned
// Updated default values
carInsert.level = 8; // C3
carInsert.tunePower = 17; // 740 HP
carInsert.tuneHandling = 17; // 740 HP
// Additional full tune values
additionalInsert = {
ghostLevel: 10,
stClearBits: 0,
stLoseBits: 0,
stClearCount: 80,
stClearDivCount: 4,
stConsecutiveWins: 80,
stConsecutiveWinsMax: 80
};
}
/// Switch on tune status
let getCarTune = await carFunctions.getCarTune(tune, carInsert);
let additionalInsert = getCarTune.additionalInsert;
// Insert the car into the database
let car = await prisma.car.create({
@ -524,30 +100,26 @@ export default class CarModule extends Module {
});
// Get the user's current car order
let carOrder = user.carOrder;
// Add the new car to the front of the id
carOrder.unshift(car.carId);
// Add the car to the front of the order
await prisma.user.update({
where: {
id: user.id
},
data: {
carOrder: carOrder
}
});
console.log(`Created new car ${car.name} with ID ${car.carId}`);
let carOrder = createCar.user.carOrder;
await carFunctions.carOrder(carOrder, car, createCar.user.id);
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
// User ID
accessCode: body.accessCode,
banapassportAmId: body.banapassportAmId,
//mbid: number|null,
// Car Data
carId: car.carId,
car,
...carInsert,
...additionalInsert
...additionalInsert,
// Expiring Full Tuned Ticket
//fullTunedCarCouponUnreceivableAt: number|null
}
// Generate the load car response message
@ -564,105 +136,21 @@ export default class CarModule extends Module {
// Get the request body for the update car request
let body = wm.wm.protobuf.UpdateCarRequest.decode(req.body);
// Get the ghost result for the car
let cars = body?.car;
// Update the car
await carFunctions.updateCar(body);
// Declare data
let data : any;
// Update the car setting
await carFunctions.updateCarSetting(body);
// Car is set
if (cars)
{
// Get current date
let date = Math.floor(new Date().getTime() / 1000);
// Update the car window Sticker
await carFunctions.updateCarWindowSticker(body);
// Car update data
data = {
customColor: common.sanitizeInput(cars.customColor),
wheel: common.sanitizeInput(cars.wheel),
wheelColor: common.sanitizeInput(cars.wheelColor),
aero: common.sanitizeInput(cars.aero),
bonnet: common.sanitizeInput(cars.bonnet),
wing: common.sanitizeInput(cars.wing),
mirror: common.sanitizeInput(cars.mirror),
neon: common.sanitizeInput(cars.neon),
trunk: common.sanitizeInput(cars.trunk),
plate: common.sanitizeInput(cars.plate),
plateColor: common.sanitizeInput(cars.plateColor),
plateNumber: common.sanitizeInput(cars.plateNumber),
windowSticker: common.sanitizeInput(cars.windowSticker),
windowDecoration: common.sanitizeInput(cars.windowDecoration),
rivalMarker: common.sanitizeInput(cars.rivalMarker),
aura: common.sanitizeInput(cars.aura),
auraMotif: common.sanitizeInput(cars.auraMotif),
rgStamp: common.sanitizeInputNotZero(body.rgStamp),
lastPlayedAt: date
}
// Update the car info
await prisma.car.update({
where: {
carId: body.carId
},
data: data
})
}
// Get the car with the given id
let car = await prisma.car.findFirst({
where: {
carId: body.carId
},
include: {
settings: true,
gtWing: true,
lastPlayedPlace: true
}
});
// Update the car settings
await prisma.carSettings.update({
where: {
dbId: car?.carSettingsDbId,
},
data: {
...body.setting
}
});
// Update the user data
let userData = await prisma.car.findFirst({
where:{
carId: body.carId
},
select:{
userId: true,
windowStickerString: true
}
})
// Newer window sticker string is different from the older one
// Check if window sticker string is not null
// (windowStickerString value when changing custom color in driver unit is undefined)
if(body.car?.windowStickerString)
{
if(userData!.windowStickerString !== body.car.windowStickerString){
console.log('Updating Window Sticker');
await prisma.car.updateMany({
where: {
userId: userData!.userId
},
data: {
windowStickerString: body.car.windowStickerString,
windowStickerFont: body.car.windowStickerFont!
}
})
}
}
// Update the car Custom Wing
await carFunctions.updateCarCustomWing(body);
// Get car item (custom color or discarded card)
if(body.earnedItems.length !== 0){
if(body.earnedItems.length !== 0)
{
console.log('Car Item reward available, continuing ...');
for(let i=0; i<body.earnedItems.length; i++){
await prisma.carItem.create({
@ -676,54 +164,6 @@ export default class CarModule extends Module {
}
}
// Update the GT Wing (custom wing) info
// Get the GT Wing data for the car
let gtWing = body.car?.gtWing;
let dataGTWing: any;
// GT Wing is set
if (gtWing)
{
dataGTWing = {
pillar: common.sanitizeInput(gtWing.pillar),
pillarMaterial: common.sanitizeInput(gtWing.pillarMaterial),
mainWing: common.sanitizeInput(gtWing.mainWing),
mainWingColor: common.sanitizeInput(gtWing.mainWingColor),
wingTip: common.sanitizeInput(gtWing.wingTip),
material: common.sanitizeInput(gtWing.material),
}
await prisma.carGTWing.update({
where: {
dbId: body.carId
},
data: dataGTWing
})
}
// Check if this is in getting new custom color screen or not
else if(body.car?.carId !== null && body.car?.carId !== undefined)
{
// GT Wing not set
if(gtWing === undefined || gtWing === null)
{
dataGTWing = {
pillar: 0,
pillarMaterial: 0,
mainWing: 0,
mainWingColor: 0,
wingTip: 0,
material: 0,
}
await prisma.carGTWing.update({
where: {
dbId: body.carId
},
data: dataGTWing
})
}
}
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,

View File

@ -0,0 +1,86 @@
import { Config } from "../../config";
import { prisma } from "../..";
// Import Util
import * as scratch from "../terminal/scratch";
// Create Car With Item
export async function createCarWithItem(userItemId: number)
{
console.log(`Item used - ID ${userItemId}`);
// Remove the user item from the database
let item = await prisma.userItem.delete({
where: {
userItemId: userItemId
}
});
let tune = 0;
console.log('Item deleted!');
switch(item.category)
{
case 203: // Car Tune Ticket
// Switch on item id
switch(item.itemId)
{
// Discarded Vehicle Card
case 1: tune = 1; break;
case 2: tune = 1; break;
case 3: tune = 1; break;
// Fully Tuned Ticket
case 5: tune = 2; break;
default: // Unknown item type, throw unsupported error
throw Error("Unsupported itemId: " + item.itemId);
}
break;
case 201: // Special Car Ticket
// Fully tuned special cars
if (scratch.fullyTunedCars.includes(item.itemId))
{
// Car is fully tuned
tune = 2;
}
// Basic tuned special cars
if (scratch.basicTunedCars.includes(item.itemId))
{
// If gift cars fully tuned is set
if (Config.getConfig().gameOptions.giftCarsFullyTuned)
{
// Car is fully tuned
tune = 2;
}
else // Gift cars fully tuned not set
{
// Car is basic tuned
tune = 1;
}
}
// Stock tuned special cars
if (scratch.stockTunedCars.includes(item.itemId))
{
// If gift cars fully tuned is set
if (Config.getConfig().gameOptions.giftCarsFullyTuned)
{
// Car is fully tuned
tune = 2;
}
else // Gift cars fully tuned not set
{
// Car is stock
tune = 0;
}
}
break;
}
console.log(`Item category was ${item.category} and item game ID was ${item.itemId}`);
return { tune }
}

View File

@ -0,0 +1,632 @@
import { prisma } from "../..";
import { User } from "@prisma/client";
import { Config } from "../../config";
import Long from "long";
// Import Proto
import { wm } from "../../wmmt/wm.proto";
import * as wmproto from "../../wmmt/wm.proto";
// Import Util
import * as common from "../util/common";
import * as car_tune from "./car_tune";
import * as terminal from "../terminal/check_car";
// Get Car Data
export async function getCar(carId: number)
{
// Get the car (required data only) with the given id
let car = await prisma.car.findFirst({
where: {
carId: carId
},
include: {
settings: true,
items: true,
gtWing: true,
lastPlayedPlace: true,
}
});
// Error handling if ghostLevel accidentally set to 0 or more than 10
if(car!.ghostLevel < 1)
{
car!.ghostLevel = 1;
}
if(car!.ghostLevel > 11)
{
car!.ghostLevel = 10;
}
// Convert the database lose bits to a Long
let longLoseBits = Long.fromString(car!.stLoseBits.toString());
return { ...car!, longLoseBits }
}
// Get Opponents Target
export async function getRegisteredTarget(carId: number)
{
// Get Registered Target
let getTarget = await prisma.ghostRegisteredFromTerminal.findFirst({
where:{
carId: carId
}
});
let opponentGhost;
let opponentTrailId;
let opponentCompetitionId;
let registeredargetAvailable: boolean = false;
if(getTarget)
{
console.log('Registered Opponents Available');
let getTargetTrail = await prisma.oCMTop1GhostTrail.findFirst({
where:{
carId: getTarget.opponentCarId,
competitionId: Number(getTarget.competitionId)
},
orderBy:{
periodId: 'desc'
}
});
if(getTargetTrail)
{
let getTargetCar = await prisma.car.findFirst({
where:{
carId: getTarget.opponentCarId
},
include:{
gtWing: true,
lastPlayedPlace: true
}
});
opponentGhost = wmproto.wm.protobuf.GhostCar.create({
car: {
...getTargetCar!,
tunePower: getTargetTrail!.tunePower,
tuneHandling: getTargetTrail!.tuneHandling,
},
area: getTargetTrail!.area,
ramp: getTargetTrail!.ramp,
path: getTargetTrail!.path,
nonhuman: false,
type: wmproto.wm.protobuf.GhostType.GHOST_NORMAL,
trailId: getTargetTrail!.dbId
});
opponentTrailId = Number(getTargetTrail!.dbId);
opponentCompetitionId = Number(getTarget.competitionId);
}
registeredargetAvailable = true;
}
return { opponentGhost, opponentTrailId, opponentCompetitionId, registeredargetAvailable }
}
// Get Opponents Target
export async function getOpponentsTarget(carId: number, registeredargetAvailable: boolean)
{
// Check opponents stamp target
// Will skip this if user's have Hall of Fame ghost registered
let challenger;
let challengerReturnCount = 1;
let opponentTargetCount = 0;
let numOfChallengers: number = 0;
if(registeredargetAvailable === false)
{
// Check opponents target
opponentTargetCount = await prisma.carStampTarget.count({
where:{
stampTargetCarId: carId,
recommended: true,
},
orderBy:{
locked: 'desc'
}
});
if(opponentTargetCount > 0)
{
console.log('Challengers Available');
// Randomize pick
let random: number = 1;
// Randomize it 5 times
for(let i=0; i<5; i++)
{
random = Math.floor(Math.random() * opponentTargetCount);
}
// Try randomize it again if it's 1
if(random === 1)
{
random = Math.floor(Math.random() * opponentTargetCount);
}
// Check opponents target
let opponentTarget = await prisma.carStampTarget.findMany({
where:{
stampTargetCarId: carId,
recommended: true,
},
orderBy:{
locked: 'desc'
},
skip: random,
take: 1,
});
// Get Opponents Challengers
let carChallengers = await prisma.carChallenger.findFirst({
where: {
challengerCarId: opponentTarget[0].carId,
carId: carId
},
orderBy:{
id: 'desc'
}
});
// Challengers Available
if(carChallengers)
{
// Get Shuttle
challengerReturnCount = opponentTarget[0].returnCount;
// Get Car Target
let carTarget = await prisma.car.findFirst({
where:{
carId: carChallengers.challengerCarId
},
include:{
gtWing: true,
lastPlayedPlace: true
}
});
// Car Target Available
if(carTarget)
{
// Get Advantage
let result = 0;
if(carChallengers.result > 0)
{
result = -Math.abs(carChallengers.result);
}
else{
result = Math.abs(carChallengers.result);
}
// Push the data
challenger = wmproto.wm.protobuf.ChallengerCar.create({
car: carTarget,
stamp: carChallengers.stamp,
result: result,
area: carChallengers.area
});
}
}
// Get Number of Challengers
numOfChallengers = opponentTarget.length + 1;
}
}
return { challenger, challengerReturnCount, numOfChallengers }
}
// Create Car
export async function createCar(body: wm.protobuf.CreateCarRequest)
{
// Get the current date/time (unix epoch)
let date = Math.floor(new Date().getTime() / 1000);
// Retrieve user from card chip / user id
let user: User | null;
// User ID provided, use that
if (body.userId)
{
user = await prisma.user.findFirst({
where: {
id: body.userId
},
});
}
// No user id, use card chip
else
{
user = await prisma.user.findFirst({
where: {
chipId: body.cardChipId,
accessCode: body.accessCode
},
});
}
// User not found, terminate
if (!user) throw new Error();
// Generate blank car settings object
let settings = await prisma.carSettings.create({
data: {}
});
// Generate blank car state object
let state = await prisma.carState.create({
data: {}
});
let gtWing = await prisma.carGTWing.create({
data: {}
});
// Sets if full tune is used or not
// let fullyTuned = false;
// 0: Stock Tune
// 1: Basic Tune (600 HP)
// 2: Fully Tuned (840 HP)
let tune = 0;
// If a user item has been used
if (body.userItemId)
{
let carUtilFunctions = await car_tune.createCarWithItem(body.userItemId);
tune = carUtilFunctions.tune;
}
// Other cases, may occur if item is not detected as 'used'
// User item not used, but car has 740 HP by default
else if (body.car && body.car.tunePower == 17 && body.car.tuneHandling == 17)
{
// Car is fully tuned
tune = 2;
// Check if created car is from terminal scratch car
await terminal.checkScratchCar(body.userId, body.car.visualModel!)
}
// User item not used, but car has 600 HP by default
else if (body.car && body.car.tunePower == 10 && body.car.tuneHandling == 10)
{
// Car is basic tuned
tune = 1;
}
// User item not used, but gift cars fully tuned switch is set
else if (Config.getConfig().gameOptions.giftCarsFullyTuned)
{
// List of event / exclusive car IDs
let event_cars = [
0x7A, // Mini
0x82, // S660
0x83, // S2000
0x89, // NDERC
0x8B, // GS130 (Starts at 20 Stories by default)
];
// If the car visual model is not null and is in the list of event cars
if (body.car.visualModel && event_cars.includes(body.car.visualModel))
{
// Set full tune used to be true
tune = 2;
}
}
// Randomize regionId
let regionId: number = 18;
// Randomize it 5 times
for(let i=0; i<5; i++)
{
regionId = Math.floor(Math.random() * 47) + 1;
}
// Try randomize it again if it's 1
if(regionId === 1)
{
regionId = Math.floor(Math.random() * 47) + 1;
}
// Error handling if regionId is above 47
if(regionId > 47)
{
regionId = 47
}
// Default car values
let carInsert = {
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,
carGTWingDbId: gtWing.dbId,
regionId: regionId,
lastPlayedAt: date,
lastPlayedPlaceId: 1, // Server Default
};
return { carInsert, tune, user }
}
// Get Window Sticker
export async function getWindowSticker(userId: number)
{
// Check if user have more than one cars
let checkWindowSticker = await prisma.car.findFirst({
where: {
userId: userId
},
select: {
windowStickerString: true,
windowStickerFont: true
}
});
let additionalWindowStickerInsert = {};
// If more than one cars, get the window sticker string
if(checkWindowSticker)
{
additionalWindowStickerInsert = {
windowStickerString: checkWindowSticker.windowStickerString,
windowStickerFont: checkWindowSticker.windowStickerFont,
}
}
return { additionalWindowStickerInsert }
}
// Get Car Tune
export async function getCarTune(tune: number, carInsert: any)
{
// Additional car values (for basic / full tune)
let additionalInsert = {};
switch(tune)
{
// 0: Stock, nothing extra
case 1: // Basic Tune
// Updated default values
carInsert.level = 2; // C8
carInsert.tunePower = 10; // 600 HP
carInsert.tuneHandling = 10; // 600 HP
// Additional basic tune values
additionalInsert = {
ghostLevel: 4,
stClearBits: 0,
stLoseBits: 0,
stClearCount: 20,
stClearDivCount: 1,
stConsecutiveWins: 20,
stConsecutiveWinsMax: 20
};
break;
case 2: // Fully Tuned
// Updated default values
carInsert.level = 8; // C3
carInsert.tunePower = 17; // 740 HP
carInsert.tuneHandling = 17; // 740 HP
// Additional full tune values
additionalInsert = {
ghostLevel: 10,
stClearBits: 0,
stLoseBits: 0,
stClearCount: 80,
stClearDivCount: 4,
stConsecutiveWins: 80,
stConsecutiveWinsMax: 80
};
}
return { additionalInsert }
}
// Car Order
export async function carOrder(carOrder: any, car: any, userId: number)
{
// Add the new car to the front of the id
carOrder.unshift(car.carId);
// Add the car to the front of the order
await prisma.user.update({
where: {
id: userId
},
data: {
carOrder: carOrder
}
});
console.log(`Created new car ${car.name} with ID ${car.carId}`);
}
// Update Car
export async function updateCar(body: wm.protobuf.UpdateCarRequest)
{
// Get the ghost result for the car
let cars = body?.car;
// Declare data
let data: any;
// Get the current date/time (unix epoch)
let date = Math.floor(new Date().getTime() / 1000);
// Car is set
if (cars)
{
// Car update data
data = {
customColor: common.sanitizeInput(cars.customColor),
wheel: common.sanitizeInput(cars.wheel),
wheelColor: common.sanitizeInput(cars.wheelColor),
aero: common.sanitizeInput(cars.aero),
bonnet: common.sanitizeInput(cars.bonnet),
wing: common.sanitizeInput(cars.wing),
mirror: common.sanitizeInput(cars.mirror),
neon: common.sanitizeInput(cars.neon),
trunk: common.sanitizeInput(cars.trunk),
plate: common.sanitizeInput(cars.plate),
plateColor: common.sanitizeInput(cars.plateColor),
plateNumber: common.sanitizeInput(cars.plateNumber),
windowSticker: common.sanitizeInput(cars.windowSticker),
windowDecoration: common.sanitizeInput(cars.windowDecoration),
rivalMarker: common.sanitizeInput(cars.rivalMarker),
aura: common.sanitizeInput(cars.aura),
auraMotif: common.sanitizeInput(cars.auraMotif),
rgStamp: common.sanitizeInputNotZero(body.rgStamp),
lastPlayedAt: date
};
// Update the car info
await prisma.car.update({
where: {
carId: body.carId
},
data: data
});
}
}
// Update Car Setting
export async function updateCarSetting(body: wm.protobuf.UpdateCarRequest)
{
// Get the car with the given id
let car = await prisma.car.findFirst({
where: {
carId: body.carId
},
include: {
settings: true,
gtWing: true,
lastPlayedPlace: true
}
});
// Update the car settings
await prisma.carSettings.update({
where: {
dbId: car?.carSettingsDbId,
},
data: {
...body.setting
}
});
}
// Update car Window Sticker
export async function updateCarWindowSticker(body: wm.protobuf.UpdateCarRequest)
{
// Update the user data
let userData = await prisma.car.findFirst({
where:{
carId: body.carId
},
select:{
userId: true,
windowStickerString: true
}
});
// Newer window sticker string is different from the older one
// Check if window sticker string is not null
// (windowStickerString value when changing custom color in driver unit is undefined)
if(body.car?.windowStickerString)
{
if(userData!.windowStickerString !== body.car.windowStickerString){
console.log('Updating Window Sticker');
await prisma.car.updateMany({
where: {
userId: userData!.userId
},
data: {
windowStickerString: body.car.windowStickerString,
windowStickerFont: body.car.windowStickerFont!
}
});
}
}
}
// Update Car Custom Wing
export async function updateCarCustomWing(body: wm.protobuf.UpdateCarRequest)
{
// Update the GT Wing (custom wing) info
// Get the GT Wing data for the car
let gtWing = body.car?.gtWing;
let dataGTWing: any;
// GT Wing is set
if (gtWing)
{
dataGTWing = {
pillar: common.sanitizeInput(gtWing.pillar),
pillarMaterial: common.sanitizeInput(gtWing.pillarMaterial),
mainWing: common.sanitizeInput(gtWing.mainWing),
mainWingColor: common.sanitizeInput(gtWing.mainWingColor),
wingTip: common.sanitizeInput(gtWing.wingTip),
material: common.sanitizeInput(gtWing.material),
};
await prisma.carGTWing.update({
where: {
dbId: body.carId
},
data: dataGTWing
});
}
// Check if this is in getting new custom color screen or not
else if(body.car?.carId !== null && body.car?.carId !== undefined)
{
// GT Wing not set
if(gtWing === undefined || gtWing === null)
{
dataGTWing = {
pillar: 0,
pillarMaterial: 0,
mainWing: 0,
mainWingColor: 0,
wingTip: 0,
material: 0,
};
await prisma.carGTWing.update({
where: {
dbId: body.carId
},
data: dataGTWing
});
}
}
}

View File

@ -7,12 +7,13 @@ import { Config } from "../config";
import * as wm from "../wmmt/wm.proto";
// Import Util
import * as common from "../util/common";
import * as meter_reward from "../util/games/meter_reward";
import * as story from "../util/games/story";
import * as time_attack from "../util/games/time_attack";
import * as ghost from "../util/games/ghost";
import * as versus from "../util/games/versus";
import * as common from "./util/common";
import * as gameFunction from "./game/functions";
import * as meter_reward from "./util/meter_reward";
import * as story from "./game/story";
import * as time_attack from "./game/time_attack";
import * as ghost from "./game/ghost";
import * as versus from "./game/versus";
export default class GameModule extends Module {
@ -35,15 +36,10 @@ export default class GameModule extends Module {
}
});
// Declare some variable
// Default value is 'false', inside 'BASE_PATH/src/util/games/ghost.ts' file
let ghostModePlay;
// Default value is 'true', inside 'BASE_PATH/src/util/games/ghost.ts' file
let updateNewTrail;
// Default value is 'false', inside 'BASE_PATH/src/util/games/ghost.ts' file
let OCMModePlay;
// Declare some variable for message response
let ghostModePlay:boolean = false;
let updateNewTrail:boolean = true;
let OCMModePlay:boolean = false;
// Switch on the gamemode
switch (body.gameMode)
@ -100,96 +96,15 @@ export default class GameModule extends Module {
}
}
// Get car item
// Car item reward from the game is available
if(body.earnedItems.length !== 0)
{
console.log('Car Item reward available, continuing ...');
for(let i=0; i<body.earnedItems.length; i++){
await prisma.carItem.create({
data: {
carId: body.carId,
category: body.earnedItems[i].category,
itemId: body.earnedItems[i].itemId,
amount: 1
}
});
}
}
// Get user item
// User item reward from the game is available
if(body.earnedUserItems.length !== 0)
{
console.log('User Item reward available, continuing ...');
for(let i=0; i<body.earnedUserItems.length; i++){
await prisma.userItem.create({
data: {
category: body.earnedUserItems[i].category,
itemId: body.earnedUserItems[i].itemId,
userId: body.car!.userId!,
earnedAt: 0,
type: 0
}
});
}
}
// Check if earned some items
await gameFunction.getItem(body);
// Check playet at timestamp
let timestamps = 0;
if(body.car?.lastPlayedAt !== undefined && body.car?.lastPlayedAt !== null)
{
if(body.car.lastPlayedAt !== 0)
{
timestamps = body.car.lastPlayedAt;
}
else
{
timestamps = Math.floor(new Date().getTime() / 1000);
}
}
// Update Car Data
await gameFunction.updateCar(body, car);
// Check P & H must not more than 34 (fully tuned value)
let tunePower = 0;
let tuneHandling = 0;
let totalTune = body.car!.tunePower + body.car!.tuneHandling;
if(totalTune <= 34)
{
tunePower = body.car!.tunePower;
tuneHandling = body.car!.tuneHandling;
}
// Update car
await prisma.car.update({
where: {
carId: body.carId,
},
data: {
aura: body.car!.aura!,
auraMotif: body.car!.auraMotif!,
odometer: body.odometer,
playCount: body.playCount,
level: body.car!.level!,
title: body.car!.title!,
tunePower: tunePower,
tuneHandling: tuneHandling,
windowSticker: body.car!.windowSticker!,
lastPlayedAt: timestamps,
regionId: body.car!.regionId!,
rgStamp: common.sanitizeInputNotZero(body.rgResult?.rgStamp),
stampSheetCount: common.sanitizeInputNotZero(body.rgResult?.stampSheetCount)
}
})
// Update car settings
await prisma.carSettings.update({
where: {
dbId: car!.carSettingsDbId
},
data: {
...body.setting
}
});
// Update Car Order and Save Tutorial
await gameFunction.updateOrderTutorial(body);
// Every n*100 play give reward
// Check this feature config
@ -202,61 +117,15 @@ export default class GameModule extends Module {
await meter_reward.giveMeterRewards(body);
}
// Update user
let user = await prisma.user.findFirst({
where: {
id: body.car!.userId!
}
});
// User object exists
if (user)
{
// Get user tutorials
let storedTutorials = user!.tutorials;
// Update any seen tutorials
body.confirmedTutorials.forEach(
(idx) => storedTutorials[idx] = true
);
// Get the order of the user's cars
let carOrder = user?.carOrder;
// Get the index of the selected car
let index = carOrder.indexOf(body.carId);
// Only splice array when item is found
if (index > -1)
{
carOrder.splice(index, 1); // 2nd parameter means remove one item only
}
// Add it back to the front
carOrder.unshift(body.carId);
// Otherwise, just ignore it
// Update the values
await prisma.user.update({
where: {
id: body.car!.userId!
},
data: {
tutorials: storedTutorials,
carOrder: carOrder
}
});
}
// Response data
let msg;
// -----------------------------------------------------------------------------------------------
// Additional Message for Response Data
let additionalSesionIdMsg = {};
// Ghost Battle mode or Crown Ghost Battle game mode is completed
if(ghostModePlay === true && OCMModePlay === false && updateNewTrail === true)
{
msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
additionalSesionIdMsg = {
// Set session for saving ghost trail Ghost Battle Mode or Crown Ghost Battle Mode
ghostSessionId: Math.floor(Math.random() * 100) + 1
@ -265,21 +134,24 @@ export default class GameModule extends Module {
// OCM Battle game mode is completed
else if(ghostModePlay === true && OCMModePlay === true && updateNewTrail === true)
{
msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
additionalSesionIdMsg = {
// Set session for saving ghost trail OCM Ghost Battle Mode
// Set session for saving ghost trail Competition (OCM) Ghost Battle Mode
ghostSessionId: Math.floor(Math.random() * 100) + 101
}
}
// Story mode or TA mode is completed
else
{
msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS
// -----------------------------------------------------------------------------------------------
// No session for saving ghost trail (not playing Ghost Battle Mode / Retiring)
}
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
// Ghost Session ID
...additionalSesionIdMsg,
// Available Tickets (maybe for VS)
//availableTickets: wm.protobuf.UserItem[]
}
// Encode the response
@ -296,9 +168,6 @@ export default class GameModule extends Module {
// Get the request content
let body = wm.wm.protobuf.LoadGameHistoryRequest.decode(req.body);
// Empty list of time attack records for the player's car
let ta_records : wm.wm.protobuf.LoadGameHistoryResponse.TimeAttackRecord[] = [];
// Get the car info
let car = await prisma.car.findFirst({
where: {
@ -310,242 +179,26 @@ export default class GameModule extends Module {
}
});
// Get the car's time attack records
let records = await prisma.timeAttackRecord.findMany({
where: {
carId: body.carId
}
});
// Get Time Attack Record
let taRecords = await gameFunction.getTimeAttackRecord(body);
// Loop over all of the records
for(let record of records)
{
// This code could probably be done with less DB calls in the future
// Calculate the total rank, total participants for the record
let wholeData = await prisma.timeAttackRecord.findMany({
where: {
course: record.course
},
orderBy: {
time: 'asc'
}
});
// Get the overall number of participants
let wholeParticipants = wholeData.length;
// Whole rank (default: 1)
let wholeRank = 1;
// Loop over all of the participants
for(let row of wholeData)
{
// If the car ID does not match
if (row.carId !== body.carId)
{
// Increment whole rank
wholeRank++;
}
else // Model ID matches
{
// Break the loop
break;
}
}
// Calculate the model rank, model participants for the record
let modelData = await prisma.timeAttackRecord.findMany({
where: {
course: record.course,
model: record.model
},
orderBy: {
time: 'asc'
}
});
// Get the overall number of participants (with the same car model)
let modelParticipants = modelData.length;
// Model rank (default: 1)
let modelRank = 1;
// Loop over all of the participants
for(let row of modelData)
{
// If the car ID does not match
if (row.carId !== body.carId)
{
// Increment whole rank
modelRank++;
}
else // Model ID matches
{
// Break the loop
break;
}
}
// Generate the time attack record object and add it to the list
ta_records.push(wm.wm.protobuf.LoadGameHistoryResponse.TimeAttackRecord.create({
course: record.course,
time: record.time,
tunePower: record.tunePower,
tuneHandling: record.tuneHandling,
wholeParticipants: wholeParticipants,
wholeRank: wholeRank,
modelParticipants: modelParticipants,
modelRank: modelRank
}));
}
// Get user ghost battle mode history data
let ghostHistoryData = await prisma.ghostBattleRecord.findMany({
where: {
carId: body.carId,
},
orderBy: {
playedAt: 'desc'
},
take: 3
});
// Empty list of ghost battle history records for the player's car
let list_ghostHistoryData: wm.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord[] = [];
for(let i=0; i<ghostHistoryData.length; i++){
// User car setting
let carSetings = wm.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.GhostCarSetting.create({
tunePower: ghostHistoryData![i].tunePower,
tuneHandling: ghostHistoryData![i].tuneHandling,
});
// ----Ghost Opponent 1----
let ghostOpponentCar = await prisma.car.findFirst({
where: {
carId: ghostHistoryData![i].opponent1CarId!
}
});
// If opponent is default ghost or random ghost
if(!(ghostOpponentCar)){
ghostOpponentCar = await prisma.car.findFirst({});
ghostOpponentCar!.name = '';
ghostOpponentCar!.manufacturer = 12;
ghostOpponentCar!.model = 105;
ghostOpponentCar!.visualModel = 130;
ghostOpponentCar!.regionId = 18;
ghostOpponentCar!.country = 'GLB';
}
// Get Opponent 1 tune
ghostOpponentCar!.tunePower = ghostHistoryData![i].opponent1TunePower!;
ghostOpponentCar!.tuneHandling = ghostHistoryData![i].opponent1TuneHandling!;
// Get the Data
let ghostOpponent = wm.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.GhostBattleRecordCar.create({
car: {
...ghostOpponentCar!
},
result: ghostHistoryData![i].opponent1Result!
});
// ------------------------
// ----Ghost Opponent 2 & 3----
// Empty list of ghost battle records for the player's car
let ghostMob: wm.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.GhostBattleRecordCar[] = [];
// ----Ghost Opponent 2----
if(ghostHistoryData[i]?.opponent2CarId !== null && ghostHistoryData[i]?.opponent2CarId !== undefined)
{
let ghostOpponentCar2 = await prisma.car.findFirst({
where: {
carId: ghostHistoryData![i].opponent2CarId!
}
});
// If opponent is default ghost or random ghost
if(!(ghostOpponentCar2)){
ghostOpponentCar2 = await prisma.car.findFirst({});
ghostOpponentCar2!.name = '';
ghostOpponentCar2!.manufacturer = 12;
ghostOpponentCar2!.model = 105;
ghostOpponentCar2!.visualModel = 130;
ghostOpponentCar2!.regionId = 18;
ghostOpponentCar2!.country = 'GLB';
}
// Get Opponent 2 tune
ghostOpponentCar2!.tunePower = ghostHistoryData![i].opponent2TunePower!;
ghostOpponentCar2!.tuneHandling = ghostHistoryData![i].opponent2TuneHandling!;
// Get the Data
ghostMob.push(wm.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.GhostBattleRecordCar.create({
car: {
...ghostOpponentCar2!
},
result: ghostHistoryData![i].opponent2Result!
}));
}
// ------------------------
// ----Ghost Opponent 3----
if(ghostHistoryData[i]?.opponent3CarId !== null && ghostHistoryData[i]?.opponent3CarId !== undefined)
{
let ghostOpponentCar3 = await prisma.car.findFirst({
where: {
carId: ghostHistoryData![i].opponent3CarId!
}
});
// If opponent is default ghost or random ghost
if(!(ghostOpponentCar3)){
ghostOpponentCar3 = await prisma.car.findFirst({});
ghostOpponentCar3!.name = '';
ghostOpponentCar3!.manufacturer = 12;
ghostOpponentCar3!.model = 105;
ghostOpponentCar3!.visualModel = 130;
ghostOpponentCar3!.regionId = 18;
ghostOpponentCar3!.country = 'GLB';
}
// Get Opponent 3 tune
ghostOpponentCar3!.tunePower = ghostHistoryData![i].opponent3TunePower!;
ghostOpponentCar3!.tuneHandling = ghostHistoryData![i].opponent3TuneHandling!;
// Get the Data
ghostMob.push(wm.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.GhostBattleRecordCar.create({
car: {
...ghostOpponentCar3!
},
result: ghostHistoryData![i].opponent3Result!
}));
}
// ----------------------------
// Push the ghost battle history data
list_ghostHistoryData.push(wm.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.create({
carSetting: carSetings,
opponent: ghostOpponent,
mobs: ghostMob || null,
area: ghostHistoryData![i].area,
playedAt: ghostHistoryData![i].playedAt,
playedShopName: ghostHistoryData![i].playedShopName
}));
}
// Get current date
let date = Math.floor(new Date().getTime() / 1000);
// Get Ghost Battle Record
let ghostBattleRecord = await gameFunction.getGhostBattleRecord(body);
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
taRecords: ta_records,
taRankingUpdatedAt: date,
ghostHistory: list_ghostHistoryData,
// Time Attack Record
taRecords: taRecords.ta_records,
taRankingUpdatedAt: taRecords.date,
// Ghost Battle Record
ghostHistory: ghostBattleRecord.ghostBattle_records,
ghostBattleCount: car!.rgPlayCount,
ghostBattleWinCount: car!.rgWinCount,
// Stamp Sheet
stampSheetCount: car!.stampSheetCount,
stampSheet: car!.stampSheet
}
@ -572,5 +225,27 @@ export default class GameModule extends Module {
// Send the response to the client
common.sendResponse(message, res);
})
// Save Screenshot
app.post('/method/save_screenshot', async (req, res) => {
// Get the information from the request
let body = wm.wm.protobuf.SaveScreenshotRequest.decode(req.body);
// TODO: Actual stuff here
// This is literally just bare-bones so the shit boots
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
};
// Encode the response
let message = wm.wm.protobuf.SaveScreenshotResponse.encode(msg);
// Send the response to the client
common.sendResponse(message, res);
});
}
}

View File

@ -0,0 +1,411 @@
import { prisma } from "../..";
// Import Proto
import { wm } from "../../wmmt/wm.proto";
import * as wmproto from "../../wmmt/wm.proto";
// Import Util
import * as common from "../util/common";
// Get some item
export async function getItem(body: wm.protobuf.SaveGameResultRequest)
{
// Get car item
// Car item reward from the game is available
if(body.earnedItems.length !== 0)
{
console.log('Car Item reward available, continuing ...');
for(let i=0; i<body.earnedItems.length; i++){
await prisma.carItem.create({
data: {
carId: body.carId,
category: body.earnedItems[i].category,
itemId: body.earnedItems[i].itemId,
amount: 1
}
});
}
}
// Get user item
// User item reward from the game is available
if(body.earnedUserItems.length !== 0)
{
console.log('User Item reward available, continuing ...');
for(let i=0; i<body.earnedUserItems.length; i++){
await prisma.userItem.create({
data: {
category: body.earnedUserItems[i].category,
itemId: body.earnedUserItems[i].itemId,
userId: body.car!.userId!,
earnedAt: 0,
type: 0
}
});
}
}
}
// Update the Car
export async function updateCar(body: wm.protobuf.SaveGameResultRequest, car: any)
{
// Check playet at timestamp
let timestamps = 0;
if(body.car?.lastPlayedAt !== undefined && body.car?.lastPlayedAt !== null)
{
if(body.car.lastPlayedAt !== 0)
{
timestamps = body.car.lastPlayedAt;
}
else
{
timestamps = Math.floor(new Date().getTime() / 1000);
}
}
// Check P & H must not more than 34 (fully tuned value)
let tunePower = 0;
let tuneHandling = 0;
let totalTune = body.car!.tunePower + body.car!.tuneHandling;
if(totalTune <= 34)
{
tunePower = body.car!.tunePower;
tuneHandling = body.car!.tuneHandling;
}
// Update car
await prisma.car.update({
where: {
carId: body.carId,
},
data: {
aura: body.car!.aura!,
auraMotif: body.car!.auraMotif!,
odometer: body.odometer,
playCount: body.playCount,
level: body.car!.level!,
title: body.car!.title!,
tunePower: tunePower,
tuneHandling: tuneHandling,
windowSticker: body.car!.windowSticker!,
lastPlayedAt: timestamps,
regionId: body.car!.regionId!,
rgStamp: common.sanitizeInputNotZero(body.rgResult?.rgStamp),
stampSheetCount: common.sanitizeInputNotZero(body.rgResult?.stampSheetCount)
}
})
// Update car settings
await prisma.carSettings.update({
where: {
dbId: car!.carSettingsDbId
},
data: {
...body.setting
}
});
}
// Update Car Order and Saving Tutorial
export async function updateOrderTutorial(body: wm.protobuf.SaveGameResultRequest)
{
// Get User
let user = await prisma.user.findFirst({
where: {
id: body.car!.userId!
}
});
// User Available
if (user)
{
// Get user tutorials
let storedTutorials = user!.tutorials;
// Update any seen tutorials
body.confirmedTutorials.forEach(
(idx) => storedTutorials[idx] = true
);
// Get the order of the user's cars
let carOrder = user?.carOrder;
// Get the index of the selected car
let index = carOrder.indexOf(body.carId);
// Only splice array when item is found
if (index > -1)
{
carOrder.splice(index, 1); // 2nd parameter means remove one item only
}
// Add it back to the front
carOrder.unshift(body.carId);
// Otherwise, just ignore it
// Update the values
await prisma.user.update({
where: {
id: body.car!.userId!
},
data: {
tutorials: storedTutorials,
carOrder: carOrder
}
});
}
}
// Get User's Time Attack Record
export async function getTimeAttackRecord(body: wm.protobuf.LoadGameHistoryRequest)
{
// Empty list of time attack records for the player's car
let ta_records : wmproto.wm.protobuf.LoadGameHistoryResponse.TimeAttackRecord[] = [];
// Get the car's time attack records
let records = await prisma.timeAttackRecord.findMany({
where: {
carId: body.carId
}
});
// Loop over all of the records
for(let record of records)
{
// This code could probably be done with less DB calls in the future
// Calculate the total rank, total participants for the record
let wholeData = await prisma.timeAttackRecord.findMany({
where: {
course: record.course
},
orderBy: {
time: 'asc'
}
});
// Get the overall number of participants
let wholeParticipants = wholeData.length;
// Whole rank (default: 1)
let wholeRank = 1;
// Loop over all of the participants
for(let row of wholeData)
{
// If the car ID does not match
if (row.carId !== body.carId)
{
// Increment whole rank
wholeRank++;
}
else // Model ID matches
{
// Break the loop
break;
}
}
// Calculate the model rank, model participants for the record
let modelData = await prisma.timeAttackRecord.findMany({
where: {
course: record.course,
model: record.model
},
orderBy: {
time: 'asc'
}
});
// Get the overall number of participants (with the same car model)
let modelParticipants = modelData.length;
// Model rank (default: 1)
let modelRank = 1;
// Loop over all of the participants
for(let row of modelData)
{
// If the car ID does not match
if (row.carId !== body.carId)
{
// Increment whole rank
modelRank++;
}
else // Model ID matches
{
// Break the loop
break;
}
}
// Generate the time attack record object and add it to the list
ta_records.push(wmproto.wm.protobuf.LoadGameHistoryResponse.TimeAttackRecord.create({
course: record.course,
time: record.time,
tunePower: record.tunePower,
tuneHandling: record.tuneHandling,
wholeParticipants: wholeParticipants,
wholeRank: wholeRank,
modelParticipants: modelParticipants,
modelRank: modelRank
}));
}
// Get the current date/time (unix epoch)
let date = Math.floor(new Date().getTime() / 1000);
return { ta_records, date }
}
// Get User's Ghost Battle Record
export async function getGhostBattleRecord(body: wm.protobuf.LoadGameHistoryRequest)
{
// Get user ghost battle mode history data
let ghostHistoryData = await prisma.ghostBattleRecord.findMany({
where: {
carId: body.carId,
},
orderBy: {
playedAt: 'desc'
},
take: 3
});
// Empty list of ghost battle history records for the player's car
let ghostBattle_records: wmproto.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord[] = [];
for(let i=0; i<ghostHistoryData.length; i++)
{
// User car setting
let carSetings = wmproto.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.GhostCarSetting.create({
tunePower: ghostHistoryData![i].tunePower,
tuneHandling: ghostHistoryData![i].tuneHandling,
});
// ----Ghost Opponent 1----
let ghostOpponentCar = await prisma.car.findFirst({
where: {
carId: ghostHistoryData![i].opponent1CarId!
}
});
// If opponent is default ghost or random ghost
if(!(ghostOpponentCar))
{
ghostOpponentCar = await prisma.car.findFirst({});
ghostOpponentCar!.name = '';
ghostOpponentCar!.manufacturer = 12;
ghostOpponentCar!.model = 105;
ghostOpponentCar!.visualModel = 130;
ghostOpponentCar!.regionId = 18;
ghostOpponentCar!.country = 'IDN';
}
// Get Opponent 1 tune
ghostOpponentCar!.tunePower = ghostHistoryData![i].opponent1TunePower!;
ghostOpponentCar!.tuneHandling = ghostHistoryData![i].opponent1TuneHandling!;
// Get the Data
let ghostOpponent = wmproto.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.GhostBattleRecordCar.create({
car: {
...ghostOpponentCar!
},
result: ghostHistoryData![i].opponent1Result!
});
// ------------------------
// ----Ghost Opponent 2 & 3----
// Empty list of ghost battle records for the player's car
let ghostMob: wmproto.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.GhostBattleRecordCar[] = [];
// ----Ghost Opponent 2----
if(ghostHistoryData[i]?.opponent2CarId !== null && ghostHistoryData[i]?.opponent2CarId !== undefined)
{
let ghostOpponentCar2 = await prisma.car.findFirst({
where: {
carId: ghostHistoryData![i].opponent2CarId!
}
});
// If opponent is default ghost or random ghost
if(!(ghostOpponentCar2))
{
ghostOpponentCar2 = await prisma.car.findFirst({});
ghostOpponentCar2!.name = '';
ghostOpponentCar2!.manufacturer = 12;
ghostOpponentCar2!.model = 105;
ghostOpponentCar2!.visualModel = 130;
ghostOpponentCar2!.regionId = 18;
ghostOpponentCar2!.country = 'IDN';
}
// Get Opponent 2 tune
ghostOpponentCar2!.tunePower = ghostHistoryData![i].opponent2TunePower!;
ghostOpponentCar2!.tuneHandling = ghostHistoryData![i].opponent2TuneHandling!;
// Get the Data
ghostMob.push(wmproto.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.GhostBattleRecordCar.create({
car: {
...ghostOpponentCar2!
},
result: ghostHistoryData![i].opponent2Result!
}));
}
// ------------------------
// ----Ghost Opponent 3----
if(ghostHistoryData[i]?.opponent3CarId !== null && ghostHistoryData[i]?.opponent3CarId !== undefined)
{
let ghostOpponentCar3 = await prisma.car.findFirst({
where: {
carId: ghostHistoryData![i].opponent3CarId!
}
});
// If opponent is default ghost or random ghost
if(!(ghostOpponentCar3))
{
ghostOpponentCar3 = await prisma.car.findFirst({});
ghostOpponentCar3!.name = '';
ghostOpponentCar3!.manufacturer = 12;
ghostOpponentCar3!.model = 105;
ghostOpponentCar3!.visualModel = 130;
ghostOpponentCar3!.regionId = 18;
ghostOpponentCar3!.country = 'IDN';
}
// Get Opponent 3 tune
ghostOpponentCar3!.tunePower = ghostHistoryData![i].opponent3TunePower!;
ghostOpponentCar3!.tuneHandling = ghostHistoryData![i].opponent3TuneHandling!;
// Get the Data
ghostMob.push(wmproto.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.GhostBattleRecordCar.create({
car: {
...ghostOpponentCar3!
},
result: ghostHistoryData![i].opponent3Result!
}));
}
// ----------------------------
// Push the ghost battle history data
ghostBattle_records.push(wmproto.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.create({
carSetting: carSetings,
opponent: ghostOpponent,
mobs: ghostMob || null,
area: ghostHistoryData![i].area,
playedAt: ghostHistoryData![i].playedAt,
playedShopName: ghostHistoryData![i].playedShopName
}));
}
return { ghostBattle_records }
}

View File

@ -5,9 +5,9 @@ import { wm } from "../../wmmt/wm.proto";
import wmproto from "../../wmmt/wm.proto";
// Import Util
import * as common from "../../util/common";
import * as ghost_history from "../ghost/ghost_history";
import * as ghost_stamp from "../ghost/ghost_stamp";
import * as common from "../util/common";
import * as ghost_history from "../../util/ghost/ghost_history";
import * as ghost_stamp from "../../util/ghost/ghost_stamp";
// Save ghost battle result
export async function saveGhostBattleResult(body: wm.protobuf.SaveGameResultRequest, car: any)

View File

@ -5,8 +5,8 @@ import { prisma } from "../..";
import { wm } from "../../wmmt/wm.proto";
// Import Util
import * as common from "../common";
import * as check_step from "../games/games_util/check_step";
import * as common from "../util/common";
import * as check_step from "./games_util/check_step";
// Save story result

View File

@ -4,7 +4,7 @@ import { prisma } from "../..";
import { wm } from "../../wmmt/wm.proto";
// Import Util
import * as common from "../common";
import * as common from "../util/common";
// Save versus battle result

View File

@ -10,7 +10,7 @@ import * as wm from "../wmmt/wm.proto";
import * as wmsrv from "../wmmt/service.proto";
// Import Util
import * as common from "../util/common";
import * as common from "./util/common";
import * as ghost_save_trail from "../util/ghost/ghost_save_trail";
import * as ghost_trail from "../util/ghost/ghost_trail";
import * as ghost_area from "../util/ghost/ghost_area";
@ -747,11 +747,11 @@ export default class GhostModule extends Module {
// Response data
let msg = {
carId: pCarId,
area: pArea,
ramp: rampVal,
path: pathVal,
area: 18,
ramp: 37,
path: 56,
playedAt: playedAt,
trail: ghostTrail
trail: new Uint8Array([1, 2, 3, 4])
};
// Encode the response

View File

View File

@ -7,7 +7,7 @@ import { Config } from "../config";
import * as wm from "../wmmt/wm.proto";
// Import Util
import * as common from "../util/common";
import * as common from "./util/common";
import * as ghost_ocm from "../util/ghost/ghost_ocm";
import * as ghost_ocm_area from "../util/ghost/ghost_ocm_area";
@ -462,9 +462,6 @@ export default class GhostModule extends Module {
carId: ocmTallyRecord!.carId,
competitionId: ocmEventDate!.competitionId,
periodId: period_id,
area: areaVal,
ramp: rampVal,
path: pathVal,
},
orderBy:{
playedAt: 'desc'
@ -494,6 +491,9 @@ export default class GhostModule extends Module {
// Set Ghost stuff Value
cars!.lastPlayedAt = checkGhostTrail.playedAt
ghostTrailId = checkGhostTrail.dbId!;
areaVal = Number(checkGhostTrail.area);
rampVal = Number(checkGhostTrail.ramp);
pathVal = Number(checkGhostTrail.path);
ghostTypes = wm.wm.protobuf.GhostType.GHOST_NORMAL;
}
}
@ -508,9 +508,6 @@ export default class GhostModule extends Module {
carId: 999999999,
competitionId: ocmEventDate!.competitionId,
periodId: 0,
area: areaVal,
ramp: rampVal,
path: pathVal
},
orderBy:{
playedAt: 'desc'
@ -553,7 +550,10 @@ export default class GhostModule extends Module {
});
// Set Ghost stuff Value
ghostTrailId = checkGhostTrail!.dbId!;
ghostTrailId = checkGhostTrail!.dbId;
areaVal = Number(checkGhostTrail!.area);
rampVal = Number(checkGhostTrail!.ramp);
pathVal = Number(checkGhostTrail!.path);
ghostTypes = wm.wm.protobuf.GhostType.GHOST_NORMAL;
}
else if(ocmEventDate!.competitionCloseAt < date && ocmEventDate!.competitionEndAt > date)

View File

@ -9,7 +9,7 @@ import * as wm from "../wmmt/wm.proto";
import * as wmsrv from "../wmmt/service.proto";
// Import Util
import * as common from "../util/common";
import * as common from "./util/common";
export default class ResourceModule extends Module {

View File

@ -1,12 +1,12 @@
import { Application } from "express";
import { Module } from "module";
import { prisma } from "..";
// Import Proto
import * as wm from "../wmmt/wm.proto";
// Import Util
import * as common from "../util/common";
import * as common from "./util/common";
import * as startupFunctions from "./startup/functions";
export default class StartupModule extends Module {
@ -21,85 +21,9 @@ export default class StartupModule extends Module {
// Get current date
let date = Math.floor(new Date().getTime() / 1000);
// Get current / previous active OCM Event
let ocmEventDate = await prisma.oCMEvent.findFirst({
where: {
// qualifyingPeriodStartAt is less than current date
qualifyingPeriodStartAt: { lte: date },
// competitionEndAt is greater than current date
competitionEndAt: { gte: date },
},
orderBy: {
competitionEndAt: 'desc',
}
});
let pastEvent = 0;
if(!(ocmEventDate))
{
ocmEventDate = await prisma.oCMEvent.findFirst({
orderBy:{
competitionId: 'desc'
}
});
pastEvent = 1;
}
// Declare GhostCompetitionSchedule
let competitionSchedule;
let lastCompetitionId: number = 0;
if(ocmEventDate)
{
let pastDay = date - ocmEventDate.competitionEndAt
if(pastDay < 604800)
{
console.log("OCM Event Available");
// Creating GhostCompetitionSchedule
competitionSchedule = wm.wm.protobuf.GhostCompetitionSchedule.create({
// OCM Competition ID (1 = C1 (Round 16), 4 = Nagoya (Round 19), 8 = Hiroshima (Round 21))
competitionId: ocmEventDate.competitionId,
// OCM Qualifying Start Timestamp
qualifyingPeriodStartAt: ocmEventDate.qualifyingPeriodStartAt,
// OCM Qualifying Close Timestamp
qualifyingPeriodCloseAt: ocmEventDate.qualifyingPeriodCloseAt,
// OCM Competition (Main Draw) Start Timestamp
competitionStartAt: ocmEventDate.competitionStartAt,
// OCM Competition (Main Draw) Close Timestamp
competitionCloseAt: ocmEventDate.competitionCloseAt,
// OCM Competition (Main Draw) End Timestamp
competitionEndAt: ocmEventDate.competitionEndAt,
// idk what this is
lengthOfPeriod: ocmEventDate.lengthOfPeriod,
// idk what this is
lengthOfInterval: ocmEventDate.lengthOfInterval,
// Area for the event (GID_RUNAREA_*, 8 is GID_RUNAREA_NAGOYA)
area: ocmEventDate.area,
// idk what this is
minigamePatternId: ocmEventDate.minigamePatternId
});
}
if(pastEvent === 1)
{
console.log("Previous OCM Event Available");
lastCompetitionId = ocmEventDate.competitionId
}
}
// Get Competition (OCM) Event Date
let getCompetitionSchedule = await startupFunctions.competitionSchedule(date, null);
let additionalCompetitionMsg = getCompetitionSchedule.additionalCompetitionMsg;
// Response data
let msg = {
@ -116,8 +40,9 @@ export default class StartupModule extends Module {
pluses: 0,
releaseAt: 0 // idk what this is
},
latestCompetitionId: lastCompetitionId || null,
competitionSchedule: competitionSchedule || null // OCM Event Available or not
// Competition (OCM)
...additionalCompetitionMsg
}
// Encode the response
@ -148,6 +73,7 @@ export default class StartupModule extends Module {
common.sendResponse(message, res);
});
// Ping
app.post('/method/ping', (req, res) => {
@ -167,6 +93,7 @@ export default class StartupModule extends Module {
})
// Register System Stats
app.post('/method/register_system_stats', async (req, res) => {
let body = wm.wm.protobuf.RegisterSystemStatsRequest.decode(req.body);
@ -187,6 +114,7 @@ export default class StartupModule extends Module {
})
// Update Event Mode Serial
app.post('/method/update_event_mode_serial', async (req, res) => {
let body = wm.wm.protobuf.UpdateEventModeSerialRequest.decode(req.body);
@ -197,7 +125,10 @@ export default class StartupModule extends Module {
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
serialError: wm.wm.protobuf.EventModeSerialErrorCode.SERIAL_NO_INPUT
serialError: wm.wm.protobuf.EventModeSerialErrorCode.SERIAL_SUCCESS,
eventModeSerial: body.eventModeSerial || '285013990002',
startAt: 0,
endAt: 2147483647
}
// Encode the response
@ -208,6 +139,7 @@ export default class StartupModule extends Module {
})
// Submit Client Log
app.post('/method/submit_client_log', async (req, res) => {
let body = wm.wm.protobuf.SubmitClientLogRequest.decode(req.body);

View File

@ -0,0 +1,115 @@
import { prisma } from "../..";
// Import Proto
import * as wm from "../../wmmt/wm.proto";
// Get Competition (OCM) Schedule
export async function competitionSchedule(date: any, competitionId: any)
{
// Get the Competition (OCM) schedule
let ghostCompetitionSchedule;
// Request by compedtitionId
if(competitionId)
{
ghostCompetitionSchedule = await prisma.oCMEvent.findFirst({
where: {
competitionId: competitionId
},
orderBy: {
competitionId: 'desc'
}
});
}
// Request by date
else
{
ghostCompetitionSchedule = await prisma.oCMEvent.findFirst({
where: {
// qualifyingPeriodStartAt is less than current date
qualifyingPeriodStartAt: { lte: Number(date) },
// competitionEndAt is greater than current date
competitionEndAt: { gte: Number(date) },
}
});
}
// Other variable
let competitionSchedule;
let lastCompetitionId: number = 0;
let additionalCompetitionMsg = {};
// Currently no Active Competition (OCM) Event.. Getting Previous Competition (OCM) Event
let pastEvent = 0;
if(!(ghostCompetitionSchedule))
{
ghostCompetitionSchedule = await prisma.oCMEvent.findFirst({
orderBy:{
competitionId: 'desc'
}
});
pastEvent = 1;
}
// Previous / Current Competition (OCM) available
if(ghostCompetitionSchedule)
{
console.log('Ghost Competition (OCM) Available');
let pastDay = date - ghostCompetitionSchedule.competitionEndAt;
if(pastDay < 604800)
{
// Creating GhostCompetitionSchedule
competitionSchedule = wm.wm.protobuf.GhostCompetitionSchedule.create({
// Competition ID
competitionId: ghostCompetitionSchedule.competitionId,
// Competition Qualifying Start Timestamp
qualifyingPeriodStartAt: ghostCompetitionSchedule.qualifyingPeriodStartAt,
// Competition Qualifying Close Timestamp
qualifyingPeriodCloseAt: ghostCompetitionSchedule.qualifyingPeriodCloseAt,
// Competition (Main Draw) Start Timestamp
competitionStartAt: ghostCompetitionSchedule.competitionStartAt,
// Competition (Main Draw) Close Timestamp
competitionCloseAt: ghostCompetitionSchedule.competitionCloseAt,
// Competition (Main Draw) End Timestamp
competitionEndAt: ghostCompetitionSchedule.competitionEndAt,
// Competition (Main Draw) length per periods
lengthOfPeriod: ghostCompetitionSchedule.lengthOfPeriod,
// Competition (Main Draw) interval (for tallying) per periods
lengthOfInterval: ghostCompetitionSchedule.lengthOfInterval,
// Area for the Competition Event (GID_RUNAREA_*)
area: ghostCompetitionSchedule.area,
// idk what this is
minigamePatternId: ghostCompetitionSchedule.minigamePatternId
});
}
// It's previous Competition (OCM) event
if(pastEvent === 1)
{
lastCompetitionId = ghostCompetitionSchedule.competitionId;
}
// Competition (OCM) Response Message
additionalCompetitionMsg = {
latestCompetitionId: lastCompetitionId,
competitionSchedule: competitionSchedule,
}
}
return { additionalCompetitionMsg, competitionSchedule }
}

View File

@ -8,8 +8,8 @@ import { Car } from "@prisma/client";
import * as wm from "../wmmt/wm.proto";
// Import Util
import * as scratch from "../util/scratch";
import * as common from "../util/common";
import * as scratch from "./terminal/scratch";
import * as common from "./util/common";
export default class TerminalModule extends Module {
@ -1003,24 +1003,6 @@ export default class TerminalModule extends Module {
});
app.post('/method/save_screenshot', async (req, res) => {
// Get the information from the request
let body = wm.wm.protobuf.SaveScreenshotRequest.decode(req.body);
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
};
// Encode the response
let message = wm.wm.protobuf.SaveScreenshotResponse.encode(msg);
// Send the response to the client
common.sendResponse(message, res);
});
/*
app.post('/method/load_unreceived_user_items', async (req, res) => {

View File

@ -1,5 +1,6 @@
import { prisma } from "../..";
// Sends the server response to the client
export async function checkScratchCar(userId: number, visualModel: number)
{

View File

@ -1,8 +1,8 @@
import { prisma } from "..";
import { Config } from "../config";
import { prisma } from "../..";
import { Config } from "../../config";
//Import Proto
import * as wm from "../wmmt/wm.proto";
import * as wm from "../../wmmt/wm.proto";
// *** CONSTANTS ***

View File

@ -6,7 +6,7 @@ import { prisma } from "..";
import * as wm from "../wmmt/wm.proto";
// Import Util
import * as common from "../util/common";
import * as common from "./util/common";
export default class TimeAttackModule extends Module {

View File

@ -7,8 +7,8 @@ import { prisma } from "..";
import * as wm from "../wmmt/wm.proto";
// Import Util
import * as scratch from "../util/scratch";
import * as common from "../util/common";
import * as scratch from "./terminal/scratch";
import * as common from "./util/common";
export default class UserModule extends Module {
@ -19,6 +19,13 @@ export default class UserModule extends Module {
// Get the request body for the load user request
let body = wm.wm.protobuf.LoadUserRequest.decode(req.body);
// Block blank card.ini data
if(body.cardChipId.match(/7F5C9744F11111114326.*/))
{
body.cardChipId = '';
body.accessCode = '';
}
// Get the user from the database
let user = await prisma.user.findFirst({
@ -69,7 +76,7 @@ export default class UserModule extends Module {
}
// Check if new card registration is allowed or not
let newCardsBanned = Config.getConfig().gameOptions.newCardsBanned;
let newCardsBanned = Config.getConfig().gameOptions.newCardsBanned || 0;
// New card registration is allowed
if (newCardsBanned === 0)

View File

@ -4,7 +4,7 @@ import { Config } from "../../config";
import { wm } from "../../wmmt/wm.proto";
// Import Util
import * as common from "../../util/common";
import * as common from "../../modules/util/common";
import * as ghost_stamp from "../ghost/ghost_stamp";
import * as ghost_get_area_from_path from "../ghost/ghost_util/ghost_get_area_from_path";