tweak: cleanup server-data

This commit is contained in:
Ethan Wood
2026-08-24 16:14:13 +01:00
parent e265cb251c
commit bfc8ccb8e9
62 changed files with 59 additions and 157362 deletions
@@ -1,2 +0,0 @@
.yarn.installed
node_modules/
@@ -1,13 +0,0 @@
-- This resource is part of the default Cfx.re asset pack (cfx-server-data)
-- Altering or recreating for local use only is strongly discouraged.
version '1.0.0'
author 'Cfx.re <[email protected]>'
description 'Builds resources with webpack. To learn more: https://webpack.js.org'
repository 'https://github.com/citizenfx/cfx-server-data'
dependency 'yarn'
server_script 'webpack_builder.js'
fx_version 'adamant'
game 'common'
@@ -1,16 +0,0 @@
{
"name": "webpack-builder",
"version": "1.0.1",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"async": "^3.1.0",
"webpack": "^4.41.2",
"worker-farm": "^1.7.0"
}
}
@@ -1,173 +0,0 @@
const fs = require('fs');
const path = require('path');
const workerFarm = require('worker-farm');
const async = require('async');
let buildingInProgress = false;
let currentBuildingModule = '';
// some modules will not like the custom stack trace logic
const ops = Error.prepareStackTrace;
Error.prepareStackTrace = undefined;
const webpackBuildTask = {
shouldBuild(resourceName) {
const numMetaData = GetNumResourceMetadata(resourceName, 'webpack_config');
if (numMetaData > 0) {
for (let i = 0; i < numMetaData; i++) {
const configName = GetResourceMetadata(resourceName, 'webpack_config');
if (shouldBuild(configName)) {
return true;
}
}
}
return false;
function loadCache(config) {
const cachePath = `cache/${resourceName}/${config.replace(/\//g, '_')}.json`;
try {
return JSON.parse(fs.readFileSync(cachePath, {encoding: 'utf8'}));
} catch {
return null;
}
}
function shouldBuild(config) {
const cache = loadCache(config);
if (!cache) {
return true;
}
for (const file of cache) {
const stats = getStat(file.name);
if (!stats ||
stats.mtime !== file.stats.mtime ||
stats.size !== file.stats.size ||
stats.inode !== file.stats.inode) {
return true;
}
}
return false;
}
function getStat(path) {
try {
const stat = fs.statSync(path);
return stat ? {
mtime: stat.mtimeMs,
size: stat.size,
inode: stat.ino,
} : null;
} catch {
return null;
}
}
},
build(resourceName, cb) {
let buildWebpack = async () => {
let error = null;
const configs = [];
const promises = [];
const numMetaData = GetNumResourceMetadata(resourceName, 'webpack_config');
for (let i = 0; i < numMetaData; i++) {
configs.push(GetResourceMetadata(resourceName, 'webpack_config', i));
}
for (const configName of configs) {
const configPath = GetResourcePath(resourceName) + '/' + configName;
const cachePath = `cache/${resourceName}/${configName.replace(/\//g, '_')}.json`;
try {
fs.mkdirSync(path.dirname(cachePath));
} catch {
}
const config = require(configPath);
const workers = workerFarm(require.resolve('./webpack_runner'));
if (config) {
const resourcePath = path.resolve(GetResourcePath(resourceName));
while (buildingInProgress) {
console.log(`webpack is busy: we are waiting to compile ${resourceName} (${configName})`);
await sleep(3000);
}
console.log(`${resourceName}: started building ${configName}`);
buildingInProgress = true;
currentBuildingModule = resourceName;
promises.push(new Promise((resolve, reject) => {
workers({
configPath,
resourcePath,
cachePath
}, (err, outp) => {
workerFarm.end(workers);
if (err) {
console.error(err.stack || err);
if (err.details) {
console.error(err.details);
}
buildingInProgress = false;
currentBuildingModule = '';
currentBuildingScript = '';
reject("worker farm webpack errored out");
return;
}
if (outp.errors) {
for (const error of outp.errors) {
console.log(error);
}
buildingInProgress = false;
currentBuildingModule = '';
currentBuildingScript = '';
reject("webpack got an error");
return;
}
console.log(`${resourceName}: built ${configName}`);
buildingInProgress = false;
resolve();
});
}));
}
}
try {
await Promise.all(promises);
} catch (e) {
error = e.toString();
}
buildingInProgress = false;
currentBuildingModule = '';
if (error) {
cb(false, error);
} else cb(true);
};
buildWebpack().then();
}
};
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
RegisterResourceBuildTaskFactory('z_webpack', () => webpackBuildTask);
@@ -1,75 +0,0 @@
const webpack = require('webpack');
const path = require('path');
const fs = require('fs');
function getStat(path) {
try {
const stat = fs.statSync(path);
return stat ? {
mtime: stat.mtimeMs,
size: stat.size,
inode: stat.ino,
} : null;
} catch {
return null;
}
}
class SaveStatePlugin {
constructor(inp) {
this.cache = [];
this.cachePath = inp.cachePath;
}
apply(compiler) {
compiler.hooks.afterCompile.tap('SaveStatePlugin', (compilation) => {
for (const file of compilation.fileDependencies) {
this.cache.push({
name: file,
stats: getStat(file)
});
}
});
compiler.hooks.done.tap('SaveStatePlugin', (stats) => {
if (stats.hasErrors()) {
return;
}
fs.writeFile(this.cachePath, JSON.stringify(this.cache), () => {
});
});
}
}
module.exports = (inp, callback) => {
const config = require(inp.configPath);
config.context = inp.resourcePath;
if (config.output && config.output.path) {
config.output.path = path.resolve(inp.resourcePath, config.output.path);
}
if (!config.plugins) {
config.plugins = [];
}
config.plugins.push(new SaveStatePlugin(inp));
webpack(config, (err, stats) => {
if (err) {
callback(err);
return;
}
if (stats.hasErrors()) {
callback(null, stats.toJson());
return;
}
callback(null, {});
});
};
File diff suppressed because it is too large Load Diff
@@ -1,12 +0,0 @@
-- This resource is part of the default Cfx.re asset pack (cfx-server-data)
-- Altering or recreating for local use only is strongly discouraged.
version '1.0.0'
author 'Cfx.re <[email protected]>'
description 'Builds resources with yarn. To learn more: https://classic.yarnpkg.com'
repository 'https://github.com/citizenfx/cfx-server-data'
fx_version 'adamant'
game 'common'
server_script 'yarn_builder.js'
@@ -1,81 +0,0 @@
const path = require('path');
const fs = require('fs');
const child_process = require('child_process');
let buildingInProgress = false;
let currentBuildingModule = '';
const initCwd = process.cwd();
const trimOutput = (data) => {
return `[yarn]\t` + data.toString().replace(/\s+$/, '');
}
const yarnBuildTask = {
shouldBuild(resourceName) {
try {
const resourcePath = GetResourcePath(resourceName);
const packageJson = path.resolve(resourcePath, 'package.json');
const yarnLock = path.resolve(resourcePath, '.yarn.installed');
const packageStat = fs.statSync(packageJson);
try {
const yarnStat = fs.statSync(yarnLock);
if (packageStat.mtimeMs > yarnStat.mtimeMs) {
return true;
}
} catch (e) {
// no yarn.installed, but package.json - install time!
return true;
}
} catch (e) {
}
return false;
},
build(resourceName, cb) {
(async () => {
while (buildingInProgress && currentBuildingModule !== resourceName) {
console.log(`yarn is currently busy: we are waiting to compile ${resourceName}`);
await sleep(3000);
}
buildingInProgress = true;
currentBuildingModule = resourceName;
const proc = child_process.fork(
require.resolve('./yarn_cli.js'),
['install', '--ignore-scripts', '--cache-folder', path.join(initCwd, 'cache', 'yarn-cache'), '--mutex', 'file:' + path.join(initCwd, 'cache', 'yarn-mutex')],
{
cwd: path.resolve(GetResourcePath(resourceName)),
stdio: 'pipe',
});
proc.stdout.on('data', (data) => console.log(trimOutput(data)));
proc.stderr.on('data', (data) => console.error(trimOutput(data)));
proc.on('exit', (code, signal) => {
setImmediate(() => {
if (code != 0 || signal) {
buildingInProgress = false;
currentBuildingModule = '';
cb(false, 'yarn failed!');
return;
}
const resourcePath = GetResourcePath(resourceName);
const yarnLock = path.resolve(resourcePath, '.yarn.installed');
fs.writeFileSync(yarnLock, '');
buildingInProgress = false;
currentBuildingModule = '';
cb(true);
});
});
})();
}
};
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
RegisterResourceBuildTaskFactory('yarn', () => yarnBuildTask);
File diff suppressed because one or more lines are too long
-11
View File
@@ -1,11 +0,0 @@
Citizen.CreateThread(function()
while true do
Wait(0)
if NetworkIsSessionStarted() then
TriggerServerEvent('hardcap:playerActivated')
return
end
end
end)
-14
View File
@@ -1,14 +0,0 @@
-- This resource is part of the default Cfx.re asset pack (cfx-server-data)
-- Altering or recreating for local use only is strongly discouraged.
version '1.0.0'
author 'Cfx.re <[email protected]>'
description 'Limits the number of players to the amount set by sv_maxclients in your server.cfg.'
repository 'https://github.com/citizenfx/cfx-server-data'
client_script 'client.lua'
server_script 'server.lua'
fx_version 'adamant'
games { 'gta5', 'rdr3' }
rdr3_warning 'I acknowledge that this is a prerelease build of RedM, and I am aware my resources *will* become incompatible once RedM ships.'
-31
View File
@@ -1,31 +0,0 @@
local playerCount = 0
local list = {}
RegisterServerEvent('hardcap:playerActivated')
AddEventHandler('hardcap:playerActivated', function()
if not list[source] then
playerCount = playerCount + 1
list[source] = true
end
end)
AddEventHandler('playerDropped', function()
if list[source] then
playerCount = playerCount - 1
list[source] = nil
end
end)
AddEventHandler('playerConnecting', function(name, setReason)
local cv = GetConvarInt('sv_maxclients', 32)
print('Connecting: ' .. name .. '^7')
if playerCount >= cv then
print('Full. :(')
setReason('This server is full (past ' .. tostring(cv) .. ' players).')
CancelEvent()
end
end)
-15
View File
@@ -1,15 +0,0 @@
-- This resource is part of the default Cfx.re asset pack (cfx-server-data)
-- Altering or recreating for local use only is strongly discouraged.
version '1.0.0'
author 'Cfx.re <[email protected]>'
description 'Handles old-style server player management commands.'
repository 'https://github.com/citizenfx/cfx-server-data'
client_script 'rconlog_client.lua'
server_script 'rconlog_server.lua'
fx_version 'adamant'
games { 'gta5', 'rdr3' }
rdr3_warning 'I acknowledge that this is a prerelease build of RedM, and I am aware my resources *will* become incompatible once RedM ships.'
@@ -1,25 +0,0 @@
RegisterNetEvent('rlUpdateNames')
AddEventHandler('rlUpdateNames', function()
local names = {}
for i = 0, 31 do
if NetworkIsPlayerActive(i) then
names[GetPlayerServerId(i)] = { id = i, name = GetPlayerName(i) }
end
end
TriggerServerEvent('rlUpdateNamesResult', names)
end)
Citizen.CreateThread(function()
while true do
Wait(0)
if NetworkIsSessionStarted() then
TriggerServerEvent('rlPlayerActivated')
return
end
end
end)
@@ -1,84 +0,0 @@
RconLog({ msgType = 'serverStart', hostname = 'lovely', maxplayers = 32 })
RegisterServerEvent('rlPlayerActivated')
local names = {}
AddEventHandler('rlPlayerActivated', function()
RconLog({ msgType = 'playerActivated', netID = source, name = GetPlayerName(source), guid = GetPlayerIdentifiers(source)[1], ip = GetPlayerEP(source) })
names[source] = { name = GetPlayerName(source), id = source }
if GetHostId() then
TriggerClientEvent('rlUpdateNames', GetHostId())
end
end)
RegisterServerEvent('rlUpdateNamesResult')
AddEventHandler('rlUpdateNamesResult', function(res)
if source ~= tonumber(GetHostId()) then
print('bad guy')
return
end
for id, data in pairs(res) do
if data then
if data.name then
if not names[id] then
names[id] = data
end
if names[id].name ~= data.name or names[id].id ~= data.id then
names[id] = data
RconLog({ msgType = 'playerRenamed', netID = id, name = data.name })
end
end
else
names[id] = nil
end
end
end)
AddEventHandler('playerDropped', function()
RconLog({ msgType = 'playerDropped', netID = source, name = GetPlayerName(source) })
names[source] = nil
end)
AddEventHandler('chatMessage', function(netID, name, message)
RconLog({ msgType = 'chatMessage', netID = netID, name = name, message = message, guid = GetPlayerIdentifiers(netID)[1] })
end)
-- NOTE: DO NOT USE THIS METHOD FOR HANDLING COMMANDS
-- This resource has not been updated to use newer methods such as RegisterCommand.
AddEventHandler('rconCommand', function(commandName, args)
if commandName == 'status' then
for netid, data in pairs(names) do
local guid = GetPlayerIdentifiers(netid)
if guid and guid[1] and data then
local ping = GetPlayerPing(netid)
RconPrint(netid .. ' ' .. guid[1] .. ' ' .. data.name .. ' ' .. GetPlayerEP(netid) .. ' ' .. ping .. "\n")
end
end
CancelEvent()
elseif commandName:lower() == 'clientkick' then
local playerId = table.remove(args, 1)
local msg = table.concat(args, ' ')
DropPlayer(playerId, msg)
CancelEvent()
elseif commandName:lower() == 'tempbanclient' then
local playerId = table.remove(args, 1)
local msg = table.concat(args, ' ')
TempBanPlayer(playerId, msg)
CancelEvent()
end
end)
@@ -19,6 +19,7 @@ shared_script 'runcode.js'
client_script 'runcode_ui.lua'
ui_page 'web/nui.html'
nui_callback_strict_mode 'false'
files {
'web/nui.html'
}
@@ -1,2 +0,0 @@
node_modules/
.yarn.installed
@@ -1,17 +0,0 @@
-- This resource is part of the default Cfx.re asset pack (cfx-server-data)
-- Altering or recreating for local use only is strongly discouraged.
version '1.0.0'
author 'Cfx.re <[email protected]>'
description 'Handles Social Club conductor session API for RedM. Do not disable.'
repository 'https://github.com/citizenfx/cfx-server-data'
fx_version 'adamant'
game 'rdr3'
rdr3_warning 'I acknowledge that this is a prerelease build of RedM, and I am aware my resources *will* become incompatible once RedM ships.'
dependencies {
'yarn'
}
server_script 'sm_server.js'
@@ -1,6 +0,0 @@
{
"private": true,
"dependencies": {
"@citizenfx/protobufjs": "6.8.8"
}
}
@@ -1,192 +0,0 @@
syntax = "proto3";
package rline;
message RpcErrorData {
string ErrorCodeString = 1;
int32 ErrorCode = 2;
string DomainString = 3;
int32 DomainCode = 4;
bytes DataEx = 5;
};
message RpcError {
int32 ErrorCode = 1;
string ErrorMessage = 2;
RpcErrorData Data = 3;
};
message RpcHeader {
string RequestId = 1;
string MethodName = 2;
RpcError Error = 3;
string srcTid = 4;
};
message RpcMessage {
RpcHeader Header = 1;
bytes Content = 2;
};
message RpcResponseContainer {
bytes Content = 1;
};
message RpcResponseMessage {
RpcHeader Header = 1;
RpcResponseContainer Container = 2;
};
message TokenStuff {
string tkn = 1;
};
message InitSessionResponse {
bytes sesid = 1;
TokenStuff token = 2;
};
message MpGamerHandleDto {
string gh = 1;
};
message MpPeerAddressDto {
string addr = 1;
};
message InitPlayer2_Parameters {
MpGamerHandleDto gh = 1;
MpPeerAddressDto peerAddress = 2;
int32 discriminator = 3;
int32 seamlessType = 4;
uint32 connectionReason = 5;
};
message InitPlayerResult {
uint32 code = 1;
};
message Restriction {
int32 u1 = 1;
int32 u2 = 2;
int32 u3 = 3;
}
message GetRestrictionsData {
repeated Restriction restriction = 1;
repeated string unk2 = 2;
};
message GetRestrictionsResult {
GetRestrictionsData data = 1;
};
message PlayerIdSto {
int32 acctId = 1;
int32 platId = 2;
};
message MpSessionRequestIdDto {
PlayerIdSto requestor = 1;
int32 index = 2;
int32 hash = 3;
};
message QueueForSession_Seamless_Parameters {
MpSessionRequestIdDto requestId = 1;
uint32 optionFlags = 2;
int32 x = 3;
int32 y = 4;
};
message QueueForSessionResult {
uint32 code = 1;
};
message QueueEntered_Parameters {
uint32 queueGroup = 1;
MpSessionRequestIdDto requestId = 2;
uint32 optionFlags = 3;
};
message GuidDto {
fixed64 a = 1;
fixed64 b = 2;
};
message MpTransitionIdDto {
GuidDto value = 1;
};
message MpSessionIdDto {
GuidDto value = 1;
};
message SessionSubcommandEnterSession {
int32 index = 1;
int32 hindex = 2;
uint32 sessionFlags = 3;
uint32 mode = 4;
int32 size = 5;
int32 teamIndex = 6;
MpTransitionIdDto transitionId = 7;
uint32 sessionManagerType = 8;
int32 slotCount = 9;
};
message SessionSubcommandLeaveSession {
uint32 reason = 1;
};
message SessionSubcommandAddPlayer {
PlayerIdSto id = 1;
MpGamerHandleDto gh = 2;
MpPeerAddressDto addr = 3;
int32 index = 4;
};
message SessionSubcommandRemovePlayer {
PlayerIdSto id = 1;
};
message SessionSubcommandHostChanged {
int32 index = 1;
};
message SessionCommand {
uint32 cmd = 1;
string cmdname = 2;
SessionSubcommandEnterSession EnterSession = 3;
SessionSubcommandLeaveSession LeaveSession = 4;
SessionSubcommandAddPlayer AddPlayer = 5;
SessionSubcommandRemovePlayer RemovePlayer = 6;
SessionSubcommandHostChanged HostChanged = 7;
};
message scmds_Parameters {
MpSessionIdDto sid = 1;
int32 ncmds = 2;
repeated SessionCommand cmds = 3;
};
message UriType {
string url = 1;
};
message TransitionReady_PlayerQueue_Parameters {
UriType serverUri = 1;
uint32 serverSandbox = 2;
MpTransitionIdDto id = 3;
uint32 sessionType = 4;
MpSessionRequestIdDto requestId = 5;
MpSessionIdDto transferId = 6;
};
message TransitionToSession_Parameters {
MpTransitionIdDto id = 1;
float x = 2;
float y = 3;
};
message TransitionToSessionResult {
uint32 code = 1;
};
@@ -1,328 +0,0 @@
const protobuf = require("@citizenfx/protobufjs");
const playerDatas = {};
let slotsUsed = 0;
function assignSlotId() {
for (let i = 0; i < 32; i++) {
if (!(slotsUsed & (1 << i))) {
slotsUsed |= (1 << i);
return i;
}
}
return -1;
}
let hostIndex = -1;
const isOneSync = GetConvar("onesync", "off") !== "off";
protobuf.load(GetResourcePath(GetCurrentResourceName()) + "/rline.proto", function(err, root) {
if (err) {
console.log(err);
return;
}
const RpcMessage = root.lookupType("rline.RpcMessage");
const RpcResponseMessage = root.lookupType("rline.RpcResponseMessage");
const InitSessionResponse = root.lookupType("rline.InitSessionResponse");
const InitPlayer2_Parameters = root.lookupType("rline.InitPlayer2_Parameters");
const InitPlayerResult = root.lookupType("rline.InitPlayerResult");
const GetRestrictionsResult = root.lookupType("rline.GetRestrictionsResult");
const QueueForSession_Seamless_Parameters = root.lookupType("rline.QueueForSession_Seamless_Parameters");
const QueueForSessionResult = root.lookupType("rline.QueueForSessionResult");
const QueueEntered_Parameters = root.lookupType("rline.QueueEntered_Parameters");
const TransitionReady_PlayerQueue_Parameters = root.lookupType("rline.TransitionReady_PlayerQueue_Parameters");
const TransitionToSession_Parameters = root.lookupType("rline.TransitionToSession_Parameters");
const TransitionToSessionResult = root.lookupType("rline.TransitionToSessionResult");
const scmds_Parameters = root.lookupType("rline.scmds_Parameters");
function toArrayBuffer(buf) {
var ab = new ArrayBuffer(buf.length);
var view = new Uint8Array(ab);
for (var i = 0; i < buf.length; ++i) {
view[i] = buf[i];
}
return ab;
}
function emitMsg(target, data) {
emitNet('__cfx_internal:pbRlScSession', target, toArrayBuffer(data));
}
function emitSessionCmds(target, cmd, cmdname, msg) {
const stuff = {};
stuff[cmdname] = msg;
emitMsg(target, RpcMessage.encode({
Header: {
MethodName: 'scmds'
},
Content: scmds_Parameters.encode({
sid: {
value: {
a: 2,
b: 2
}
},
ncmds: 1,
cmds: [
{
cmd,
cmdname,
...stuff
}
]
}).finish()
}).finish());
}
function emitAddPlayer(target, msg) {
emitSessionCmds(target, 2, 'AddPlayer', msg);
}
function emitRemovePlayer(target, msg) {
emitSessionCmds(target, 3, 'RemovePlayer', msg);
}
function emitHostChanged(target, msg) {
emitSessionCmds(target, 5, 'HostChanged', msg);
}
onNet('playerDropped', () => {
if (isOneSync) {
return;
}
try {
const oData = playerDatas[source];
delete playerDatas[source];
if (oData && hostIndex === oData.slot) {
const pda = Object.entries(playerDatas);
if (pda.length > 0) {
hostIndex = pda[0][1].slot | 0; // TODO: actually use <=31 slot index *and* check for id
for (const [ id, data ] of Object.entries(playerDatas)) {
emitHostChanged(id, {
index: hostIndex
});
}
} else {
hostIndex = -1;
}
}
if (!oData) {
return;
}
if (oData.slot > -1) {
slotsUsed &= ~(1 << oData.slot);
}
for (const [ id, data ] of Object.entries(playerDatas)) {
emitRemovePlayer(id, {
id: oData.id
});
}
} catch (e) {
console.log(e);
console.log(e.stack);
}
});
function makeResponse(type, data) {
return {
Header: {
},
Container: {
Content: type.encode(data).finish()
}
};
}
const handlers = {
async InitSession(source, data) {
return makeResponse(InitSessionResponse, {
sesid: Buffer.alloc(16),
/*token: {
tkn: 'ACSTOKEN token="meow",signature="meow"'
}*/
});
},
async InitPlayer2(source, data) {
const req = InitPlayer2_Parameters.decode(data);
if (!isOneSync) {
playerDatas[source] = {
gh: req.gh,
peerAddress: req.peerAddress,
discriminator: req.discriminator,
slot: -1
};
}
return makeResponse(InitPlayerResult, {
code: 0
});
},
async GetRestrictions(source, data) {
return makeResponse(GetRestrictionsResult, {
data: {
}
});
},
async ConfirmSessionEntered(source, data) {
return {};
},
async TransitionToSession(source, data) {
const req = TransitionToSession_Parameters.decode(data);
return makeResponse(TransitionToSessionResult, {
code: 1 // in this message, 1 is success
});
},
async QueueForSession_Seamless(source, data) {
const req = QueueForSession_Seamless_Parameters.decode(data);
if (!isOneSync) {
playerDatas[source].req = req.requestId;
playerDatas[source].id = req.requestId.requestor;
playerDatas[source].slot = assignSlotId();
}
setTimeout(() => {
emitMsg(source, RpcMessage.encode({
Header: {
MethodName: 'QueueEntered'
},
Content: QueueEntered_Parameters.encode({
queueGroup: 69,
requestId: req.requestId,
optionFlags: req.optionFlags
}).finish()
}).finish());
if (isOneSync) {
hostIndex = 16
} else if (hostIndex === -1) {
hostIndex = playerDatas[source].slot | 0;
}
emitMsg(source, RpcMessage.encode({
Header: {
MethodName: 'TransitionReady_PlayerQueue'
},
Content: TransitionReady_PlayerQueue_Parameters.encode({
serverUri: {
url: ''
},
requestId: req.requestId,
id: {
value: {
a: 2,
b: 0
}
},
serverSandbox: 0xD656C677,
sessionType: 3,
transferId: {
value: {
a: 2,
b: 2
}
},
}).finish()
}).finish());
setTimeout(() => {
emitSessionCmds(source, 0, 'EnterSession', {
index: (isOneSync) ? 16 : playerDatas[source].slot | 0,
hindex: hostIndex,
sessionFlags: 0,
mode: 0,
size: (isOneSync) ? 0 : Object.entries(playerDatas).filter(a => a[1].id).length,
//size: 2,
//size: Object.entries(playerDatas).length,
teamIndex: 0,
transitionId: {
value: {
a: 2,
b: 0
}
},
sessionManagerType: 0,
slotCount: 32
});
}, 50);
if (!isOneSync) {
setTimeout(() => {
// tell player about everyone, and everyone about player
const meData = playerDatas[source];
const aboutMe = {
id: meData.id,
gh: meData.gh,
addr: meData.peerAddress,
index: playerDatas[source].slot | 0
};
for (const [ id, data ] of Object.entries(playerDatas)) {
if (id == source || !data.id) continue;
emitAddPlayer(source, {
id: data.id,
gh: data.gh,
addr: data.peerAddress,
index: data.slot | 0
});
emitAddPlayer(id, aboutMe);
}
}, 150);
}
}, 250);
return makeResponse(QueueForSessionResult, {
code: 1
});
},
};
async function handleMessage(source, method, data) {
if (handlers[method]) {
return await handlers[method](source, data);
}
return {};
}
onNet('__cfx_internal:pbRlScSession', async (data) => {
const s = source;
try {
const message = RpcMessage.decode(new Uint8Array(data));
const response = await handleMessage(s, message.Header.MethodName, message.Content);
if (!response || !response.Header) {
return;
}
response.Header.RequestId = message.Header.RequestId;
emitMsg(s, RpcResponseMessage.encode(response).finish());
} catch (e) {
console.log(e);
console.log(e.stack);
}
});
});
@@ -1,90 +0,0 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@citizenfx/[email protected]":
version "6.8.8"
resolved "https://registry.yarnpkg.com/@citizenfx/protobufjs/-/protobufjs-6.8.8.tgz#d12edcada06182f3785dea1d35eebf0ebe4fd2c3"
integrity sha512-RBJvHPWNwguEPxV+ALbCZBXAEQf2byP5KtYrYl36Mbb0+Ch7MxpOm+764S+YqYWj/A/iNSW3jXglfJ9hlxjBLA==
dependencies:
"@protobufjs/aspromise" "^1.1.2"
"@protobufjs/base64" "^1.1.2"
"@protobufjs/codegen" "^2.0.4"
"@protobufjs/eventemitter" "^1.1.0"
"@protobufjs/fetch" "^1.1.0"
"@protobufjs/float" "^1.0.2"
"@protobufjs/inquire" "^1.1.0"
"@protobufjs/path" "^1.1.2"
"@protobufjs/pool" "^1.1.0"
"@protobufjs/utf8" "^1.1.0"
"@types/long" "^4.0.0"
"@types/node" "^10.1.0"
long "^4.0.0"
"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf"
integrity sha1-m4sMxmPWaafY9vXQiToU00jzD78=
"@protobufjs/base64@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735"
integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==
"@protobufjs/codegen@^2.0.4":
version "2.0.4"
resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb"
integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==
"@protobufjs/eventemitter@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70"
integrity sha1-NVy8mLr61ZePntCV85diHx0Ga3A=
"@protobufjs/fetch@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45"
integrity sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=
dependencies:
"@protobufjs/aspromise" "^1.1.1"
"@protobufjs/inquire" "^1.1.0"
"@protobufjs/float@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1"
integrity sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=
"@protobufjs/inquire@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089"
integrity sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=
"@protobufjs/path@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d"
integrity sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=
"@protobufjs/pool@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54"
integrity sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=
"@protobufjs/utf8@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=
"@types/long@^4.0.0":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9"
integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==
"@types/node@^10.1.0":
version "10.17.58"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.58.tgz#10682f6016fd866725c36d22ce6bbbd029bf4545"
integrity sha512-Dn5RBxLohjdHFj17dVVw3rtrZAeXeWg+LQfvxDIW/fdPkSiuQk7h3frKMYtsQhtIW42wkErDcy9UMVxhGW4O7w==
long@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==
@@ -1,3 +0,0 @@
--This empty file causes the scheduler.lua to load clientside
--scheduler.lua when loaded inside the sessionmanager resource currently manages remote callbacks.
--Without this, callbacks will only work server->client and not client->server.
@@ -1,13 +0,0 @@
-- This resource is part of the default Cfx.re asset pack (cfx-server-data)
-- Altering or recreating for local use only is strongly discouraged.
version '1.0.0'
author 'Cfx.re <[email protected]>'
description 'Handles the "host lock" for non-OneSync servers. Do not disable.'
repository 'https://github.com/citizenfx/cfx-server-data'
fx_version 'cerulean'
games { 'gta4', 'gta5' }
server_script 'server/host_lock.lua'
client_script 'client/empty.lua'
@@ -1,69 +0,0 @@
-- whitelist c2s events
RegisterServerEvent('hostingSession')
RegisterServerEvent('hostedSession')
-- event handler for pre-session 'acquire'
local currentHosting
local hostReleaseCallbacks = {}
-- TODO: add a timeout for the hosting lock to be held
-- TODO: add checks for 'fraudulent' conflict cases of hosting attempts (typically whenever the host can not be reached)
AddEventHandler('hostingSession', function()
-- if the lock is currently held, tell the client to await further instruction
if currentHosting then
TriggerClientEvent('sessionHostResult', source, 'wait')
-- register a callback for when the lock is freed
table.insert(hostReleaseCallbacks, function()
TriggerClientEvent('sessionHostResult', source, 'free')
end)
return
end
-- if the current host was last contacted less than a second ago
if GetHostId() then
if GetPlayerLastMsg(GetHostId()) < 1000 then
TriggerClientEvent('sessionHostResult', source, 'conflict')
return
end
end
hostReleaseCallbacks = {}
currentHosting = source
TriggerClientEvent('sessionHostResult', source, 'go')
-- set a timeout of 5 seconds
SetTimeout(5000, function()
if not currentHosting then
return
end
currentHosting = nil
for _, cb in ipairs(hostReleaseCallbacks) do
cb()
end
end)
end)
AddEventHandler('hostedSession', function()
-- check if the client is the original locker
if currentHosting ~= source then
-- TODO: drop client as they're clearly lying
print(currentHosting, '~=', source)
return
end
-- free the host lock (call callbacks and remove the lock value)
for _, cb in ipairs(hostReleaseCallbacks) do
cb()
end
currentHosting = nil
end)
EnableEnhancedHostSupport(true)