mirror of
https://github.com/demostf/demo.js
synced 2026-06-04 00:54:14 +02:00
rust code generators
This commit is contained in:
parent
23735c266b
commit
7e69e420db
2 changed files with 172 additions and 9 deletions
182
bin/analyse.js
182
bin/analyse.js
|
|
@ -35,12 +35,58 @@ fs.readFile(argv._[0], function (err, data) {
|
||||||
+ createEventTypeIdMap(state.eventDefinitions) + '\n';
|
+ createEventTypeIdMap(state.eventDefinitions) + '\n';
|
||||||
console.log(definition);
|
console.log(definition);
|
||||||
} else if (argv['create-event-definitions-rs']) {
|
} else if (argv['create-event-definitions-rs']) {
|
||||||
const definitions = Array.from(state.eventDefinitions.values());
|
const definitions = Array.from(state.eventDefinitions.values()).map(definition => {
|
||||||
const definition = 'pub enum GameEvent {'
|
definition.entries = definition.entries.map(entry => {
|
||||||
|
if (entry.name === "type") {
|
||||||
|
entry.name = "kind";
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
return definition;
|
||||||
|
});
|
||||||
|
const definition = 'use std::collections::HashMap;\n' +
|
||||||
|
'use crate::{Result, ParseError};\n' +
|
||||||
|
'use super::gamevent::{FromGameEventValue, GameEventValue, FromRawGameEvent, RawGameEvent};\n' +
|
||||||
|
'use bitstream_reader::BitRead;\n\n' +
|
||||||
|
'// auto generated, nobody in their right mind would write this manually\n\n'
|
||||||
|
+ definitions
|
||||||
|
.map(createEventStructRS)
|
||||||
|
.join('\n') + '\n\n'
|
||||||
|
+ '#[derive(Debug)]\n'
|
||||||
|
+ 'pub enum GameEvent {\n'
|
||||||
+ definitions
|
+ definitions
|
||||||
.map(createEventDefinitionRS)
|
.map(createEventDefinitionRS)
|
||||||
.join(',\n')
|
.join(',\n')
|
||||||
+ '\n}';
|
+ ',\n\tUnknown(RawGameEvent),'
|
||||||
|
+ '\n}\n\n'
|
||||||
|
+ '#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]\n'
|
||||||
|
+ 'pub enum GameEventType {\n'
|
||||||
|
+ definitions
|
||||||
|
.map(createEventTypeDefinitionRS)
|
||||||
|
.join(',\n')
|
||||||
|
+ ',\n\t'
|
||||||
|
+ '\n\tUnknown,'
|
||||||
|
+ '\n}'
|
||||||
|
+ '\n\nimpl GameEventType {'
|
||||||
|
+ '\n\tpub fn from_type_name(name: &str) -> Self {\n'
|
||||||
|
+ '\t\tmatch name {\n'
|
||||||
|
+ definitions
|
||||||
|
.map(createEventTypeDefinitionMatchRS)
|
||||||
|
.join(',\n')
|
||||||
|
+ ',\n\t\t\t_ => GameEventType::Unknown\n'
|
||||||
|
+ '\t\t}\n'
|
||||||
|
+ '\t}\n'
|
||||||
|
+ '}\n'
|
||||||
|
+ '\n\nimpl GameEvent {'
|
||||||
|
+ '\n\tpub fn from_raw_event(event: RawGameEvent) -> Result<Self> {\n'
|
||||||
|
+ '\t\tOk(match event.event_type {\n'
|
||||||
|
+ definitions
|
||||||
|
.map(createEventDefinitionMatch)
|
||||||
|
.join(',\n') + ',\n'
|
||||||
|
+ '\t\t\tGameEventType::Unknown => GameEvent::Unknown(event),\n'
|
||||||
|
+ '\t\t})\n'
|
||||||
|
+ '\t}\n'
|
||||||
|
+ '}\n';
|
||||||
console.log(definition);
|
console.log(definition);
|
||||||
} else if (argv['event-list']) {
|
} else if (argv['event-list']) {
|
||||||
echo(Array.from(match.eventDefinitions.values()));
|
echo(Array.from(match.eventDefinitions.values()));
|
||||||
|
|
@ -53,6 +99,10 @@ fs.readFile(argv._[0], function (err, data) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getEventTypeNameRS(s) {
|
||||||
|
return getEventTypeName(s) + 'Event';
|
||||||
|
}
|
||||||
|
|
||||||
function getEventTypeName(s) {
|
function getEventTypeName(s) {
|
||||||
const name = s.replace(/(\_\w)/g, function (m) {
|
const name = s.replace(/(\_\w)/g, function (m) {
|
||||||
return m[1].toUpperCase();
|
return m[1].toUpperCase();
|
||||||
|
|
@ -81,7 +131,17 @@ function getEventTypeName(s) {
|
||||||
.replace('Localplayer', 'LocalPlayer')
|
.replace('Localplayer', 'LocalPlayer')
|
||||||
.replace('Minigame', 'MiniGame')
|
.replace('Minigame', 'MiniGame')
|
||||||
.replace('Winlimit', 'WinLimit')
|
.replace('Winlimit', 'WinLimit')
|
||||||
|
.replace('Skillrating', 'SkillRating')
|
||||||
|
.replace('Directhit', 'DirectHit')
|
||||||
|
.replace('Chargedeployed', 'ChargeDeployed')
|
||||||
|
.replace('Winddown', 'WindDown')
|
||||||
|
.replace('Stealsandvich', 'StealSandvich')
|
||||||
|
.replace('Pricesheet', 'PriceSheet')
|
||||||
|
.replace('Teambalanced', 'TeamBalanced')
|
||||||
|
.replace('Highfive', 'HighFive')
|
||||||
|
.replace('Powerup', 'PowerUp')
|
||||||
.replace('Hltv', 'HLTV');
|
.replace('Hltv', 'HLTV');
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,10 +166,13 @@ function getEntryTypeDefinitionRS(typeId) {
|
||||||
case 1:
|
case 1:
|
||||||
return 'String';
|
return 'String';
|
||||||
case 2:
|
case 2:
|
||||||
|
return 'f32';
|
||||||
case 3:
|
case 3:
|
||||||
case 4:
|
|
||||||
case 5:
|
|
||||||
return 'u32';
|
return 'u32';
|
||||||
|
case 4:
|
||||||
|
return 'u16';
|
||||||
|
case 5:
|
||||||
|
return 'u8';
|
||||||
case 6:
|
case 6:
|
||||||
return 'bool';
|
return 'bool';
|
||||||
case 7:
|
case 7:
|
||||||
|
|
@ -127,11 +190,110 @@ ${definition.entries.map(entry => ` ${entry.name}: ${getEntryTypeDefinition(ent
|
||||||
}`.trim()
|
}`.trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createEventStructRS(definition) {
|
||||||
|
let structName = getEventTypeNameRS(definition.name);
|
||||||
|
return `#[derive(Debug)]\npub struct ${structName} {
|
||||||
|
${definition.entries.map(entry => `\tpub ${getEntryNameRS(entry.name)}: ${getEntryTypeDefinitionRS(entry.type)},`).join('\n')}
|
||||||
|
}
|
||||||
|
impl FromRawGameEvent for ${getEventTypeNameRS(definition.name)} {
|
||||||
|
fn from_raw_event(values: Vec<GameEventValue>) -> Result<Self> {
|
||||||
|
${definition.entries.map((entry, index) => `\t\tlet ${getEntryNameRS(entry.name)}: ${getEntryTypeDefinitionRS(entry.type)} = {
|
||||||
|
\t\t\tlet value = values.get(${index}).ok_or_else(|| ParseError::UnknownGameEvent("${getEntryNameRS(entry.name)}".to_string()))?;
|
||||||
|
\t\t\t${getEntryTypeDefinitionRS(entry.type)}::from_value(value.clone(), "${getEntryNameRS(entry.name)}")?
|
||||||
|
\t\t};`).join('\n')}
|
||||||
|
Ok(${structName} {
|
||||||
|
${definition.entries.map(entry => `\t\t\t${getEntryNameRS(entry.name)}`).join(',\n')}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
function camelToSnake(str) {
|
||||||
|
return str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getEntryNameRS(name) {
|
||||||
|
return camelToSnake(name)
|
||||||
|
.replace('mapname', 'map_name')
|
||||||
|
.replace('cvarname', 'cvar_name')
|
||||||
|
.replace('cvarvalue', 'cvar_value')
|
||||||
|
.replace('userid', 'user_id')
|
||||||
|
.replace('networkid', 'network_id')
|
||||||
|
.replace('teamid', 'team_id')
|
||||||
|
.replace('teamname', 'team_name')
|
||||||
|
.replace('oldteam', 'old_team')
|
||||||
|
.replace('autoteam', 'auto_team')
|
||||||
|
.replace('entindex', 'ent_index')
|
||||||
|
.replace('weaponid', 'weapon_id')
|
||||||
|
.replace('damagebit', 'damage_bit')
|
||||||
|
.replace('customkill', 'custom_kill')
|
||||||
|
.replace('logclassname', 'log_class_name')
|
||||||
|
.replace('playerpenetratecount', 'player_penetrate_count')
|
||||||
|
.replace('damageamount', 'damage_amount')
|
||||||
|
.replace('showdisguisedcrit', 'show_disguised_crit')
|
||||||
|
.replace('minicrit', 'mini_crit')
|
||||||
|
.replace('allseecrit', 'all_see_crit')
|
||||||
|
.replace('weaponid', 'weapon_id')
|
||||||
|
.replace('bonuseffect', 'bonus_effect')
|
||||||
|
.replace('teamonly', 'team_only')
|
||||||
|
.replace('oldname', 'old_name')
|
||||||
|
.replace('newname', 'new_name')
|
||||||
|
.replace('hintmessage', 'hint_message')
|
||||||
|
.replace('roundslimit', 'rounds_limit')
|
||||||
|
.replace('timelimit', 'time_limit')
|
||||||
|
.replace('fraglimit', 'frag_limit')
|
||||||
|
.replace('numadvanced', 'num_advanced')
|
||||||
|
.replace('numbronze', 'num_bronze')
|
||||||
|
.replace('numsilver', 'num_silver')
|
||||||
|
.replace('numgold', 'num_gold')
|
||||||
|
.replace('oldmode', 'old_mode')
|
||||||
|
.replace('newmode', 'new_mode')
|
||||||
|
.replace('entityid', 'entity_id')
|
||||||
|
.replace('winreason', 'win_reason')
|
||||||
|
.replace('flagcaplimit', 'flag_cap_limit')
|
||||||
|
.replace('cpname', 'cp_name')
|
||||||
|
.replace('capteam', 'cap_team')
|
||||||
|
.replace('captime', 'cap_time')
|
||||||
|
.replace('eventtype', 'event_type')
|
||||||
|
.replace('killstreak', 'kill_stream')
|
||||||
|
.replace('forceupload', 'force_upload')
|
||||||
|
.replace('targetid', 'target_id')
|
||||||
|
.replace('isbuilder', 'is_builder')
|
||||||
|
.replace('objecttype', 'object_type')
|
||||||
|
.replace('namechange', 'name_change')
|
||||||
|
.replace('readystate', 'ready_state')
|
||||||
|
.replace('builderid', 'builder_id')
|
||||||
|
.replace('recedetime', 'recede_time')
|
||||||
|
.replace('ownerid', 'owner_id')
|
||||||
|
.replace('sapperid', 'sapper_id')
|
||||||
|
.replace('itemdef', 'item_def')
|
||||||
|
.replace('bitfield', 'bit_field')
|
||||||
|
.replace('playsound', 'play_sound')
|
||||||
|
.replace('totalhits', 'total_hits')
|
||||||
|
.replace('posx', 'pos_x')
|
||||||
|
.replace('posy', 'pos_y')
|
||||||
|
.replace('posz', 'pos_z')
|
||||||
|
.replace('ineye', 'in_eye')
|
||||||
|
.replace('maxplayers', 'max_players');
|
||||||
|
}
|
||||||
|
|
||||||
|
function createEventTypeDefinitionRS(definition) {
|
||||||
|
return `\t${getEventTypeName(definition.name)} = ${definition.id}`
|
||||||
|
}
|
||||||
|
|
||||||
function createEventDefinitionRS(definition) {
|
function createEventDefinitionRS(definition) {
|
||||||
return ` #[event_type(name = "${definition.name}")]
|
return `\t${getEventTypeName(definition.name)}(${getEventTypeName(definition.name)}Event)`
|
||||||
${getEventTypeName(definition.name)} {
|
}
|
||||||
${definition.entries.map(entry => `\t\t${entry.name}: ${getEntryTypeDefinitionRS(entry.type)};`).join('\n')}
|
|
||||||
}`
|
function createEventDefinitionMatch(definition) {
|
||||||
|
let structName = getEventTypeName(definition.name);
|
||||||
|
return `\t\t\tGameEventType::${structName} => GameEvent::${structName}(${structName}Event::from_raw_event(event.values)?)`
|
||||||
|
}
|
||||||
|
|
||||||
|
function createEventTypeDefinitionMatchRS(definition) {
|
||||||
|
let structName = getEventTypeName(definition.name);
|
||||||
|
return `\t\t\t"${definition.name}" => GameEventType::${structName}`
|
||||||
}
|
}
|
||||||
|
|
||||||
function createEventDefinitionUnion(definitions) {
|
function createEventDefinitionUnion(definitions) {
|
||||||
|
|
@ -176,7 +338,7 @@ const EventNameReplace = new Map([
|
||||||
['ControlpointEndtouch', 'ControlPointEndTouch'],
|
['ControlpointEndtouch', 'ControlPointEndTouch'],
|
||||||
['ControlpointPulseElement', 'ControlPointPulseElement'],
|
['ControlpointPulseElement', 'ControlPointPulseElement'],
|
||||||
['ControlpointFakeCapture', 'ControlPointFakeCapture'],
|
['ControlpointFakeCapture', 'ControlPointFakeCapture'],
|
||||||
['ControlpointFakeCaptureMult', 'ControlPointFakeCaptureMult'],
|
['ControlpointFakeCaptureMult', 'ControlPointFakeCaptureMultiplier'],
|
||||||
['TeamplayWaitingAbouttoend', 'TeamPlayWaitingAboutToEnd'],
|
['TeamplayWaitingAbouttoend', 'TeamPlayWaitingAboutToEnd'],
|
||||||
['TeamplayPointStartcapture', 'TeamPlayPointStartCapture'],
|
['TeamplayPointStartcapture', 'TeamPlayPointStartCapture'],
|
||||||
['FreezecamStarted', 'FreezeCamStarted'],
|
['FreezecamStarted', 'FreezeCamStarted'],
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ export function handleSayText2(packet: SayText2Packet, match: Match) {
|
||||||
user.name = packet.text;
|
user.name = packet.text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match.chat.push({
|
match.chat.push({
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue