biggest refactor ever...
- use kxs-ts-gen for TypeScript schemas
- update schema files, so they're tidier (no need for typescript-generator workarounds)
- version bumps (kotlin, gradle, tstl, factorio, kotest)
- improve kxs binary format (use okio)
- move schema files package ('events' wasn't needed)
- tidy up topic creation, naming. base it off classes, make util functions
This commit is contained in:
parent
db14865ca9
commit
3fff57d46d
82 changed files with 2545 additions and 1914 deletions
|
|
@ -1,20 +0,0 @@
|
|||
// Generated by TypeScriptGenerator - do not edit this file manually
|
||||
|
||||
interface FactorioModInfo {
|
||||
currentVersion: string | null;
|
||||
modName: string;
|
||||
previousVersion: string | null;
|
||||
}
|
||||
|
||||
interface FactorioGameDataUpdate {
|
||||
newVersion: string | null;
|
||||
oldVersion: string | null;
|
||||
}
|
||||
|
||||
interface FactorioConfigurationUpdate extends KafkatorioPacket {
|
||||
allMods: FactorioModInfo[];
|
||||
factorioData: FactorioGameDataUpdate;
|
||||
modVersion: string;
|
||||
packetType: PacketType;
|
||||
tick: uint;
|
||||
}
|
||||
|
|
@ -0,0 +1,217 @@
|
|||
// Generated by TypeScriptGenerator - do not edit this file manually
|
||||
|
||||
export interface KafkatorioPacket2 {
|
||||
modVersion: string;
|
||||
tick: Tick;
|
||||
data: KafkatorioPacketData2;
|
||||
}
|
||||
|
||||
export type Tick = UInt;
|
||||
|
||||
export type KafkatorioPacketData2 =
|
||||
| KafkatorioPacketData2.ConfigurationUpdate
|
||||
| KafkatorioPacketData2.ConsoleChatUpdate
|
||||
| KafkatorioPacketData2.ConsoleCommandUpdate
|
||||
| KafkatorioPacketData2.EntityUpdate
|
||||
| KafkatorioPacketData2.MapChunkUpdate
|
||||
| KafkatorioPacketData2.PlayerUpdate
|
||||
| KafkatorioPacketData2.PrototypesUpdate
|
||||
| KafkatorioPacketData2.SurfaceUpdate;
|
||||
|
||||
export namespace KafkatorioPacketData2 {
|
||||
export enum Type {
|
||||
ConfigurationUpdate = "dev.adamko.kafkatorio.schema2.ConfigurationUpdate",
|
||||
ConsoleChatUpdate = "dev.adamko.kafkatorio.schema2.ConsoleChatUpdate",
|
||||
ConsoleCommandUpdate = "dev.adamko.kafkatorio.schema2.ConsoleCommandUpdate",
|
||||
PrototypesUpdate = "dev.adamko.kafkatorio.schema2.PrototypesUpdate",
|
||||
SurfaceUpdate = "dev.adamko.kafkatorio.schema2.SurfaceUpdate",
|
||||
EntityUpdate = "dev.adamko.kafkatorio.schema2.EntityUpdate",
|
||||
MapChunkUpdate = "dev.adamko.kafkatorio.schema2.MapChunkUpdate",
|
||||
PlayerUpdate = "dev.adamko.kafkatorio.schema2.PlayerUpdate",
|
||||
}
|
||||
|
||||
export interface ConfigurationUpdate {
|
||||
type: KafkatorioPacketData2.Type.ConfigurationUpdate;
|
||||
factorioData: ConfigurationUpdateGameData;
|
||||
allMods: ConfigurationUpdateModData[];
|
||||
modStartupSettingsChange: boolean;
|
||||
migrationApplied: boolean;
|
||||
}
|
||||
|
||||
export interface ConsoleChatUpdate {
|
||||
type: KafkatorioPacketData2.Type.ConsoleChatUpdate;
|
||||
authorPlayerIndex: PlayerIndex | null;
|
||||
content: string;
|
||||
}
|
||||
|
||||
export interface ConsoleCommandUpdate {
|
||||
type: KafkatorioPacketData2.Type.ConsoleCommandUpdate;
|
||||
authorPlayerIndex: PlayerIndex | null;
|
||||
command: string;
|
||||
parameters: string;
|
||||
}
|
||||
|
||||
export interface PrototypesUpdate {
|
||||
type: KafkatorioPacketData2.Type.PrototypesUpdate;
|
||||
prototypes: FactorioPrototype2[];
|
||||
}
|
||||
|
||||
export interface SurfaceUpdate {
|
||||
type: KafkatorioPacketData2.Type.SurfaceUpdate;
|
||||
index: SurfaceIndex;
|
||||
daytime: Double;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface EntityUpdate {
|
||||
type: KafkatorioPacketData2.Type.EntityUpdate;
|
||||
key: EntityUpdateKey;
|
||||
eventCounts?: { [key: string]: UInt } | null;
|
||||
chunkPosition?: MapChunkPosition | null;
|
||||
graphicsVariation?: UByte | null;
|
||||
health?: Float | null;
|
||||
isActive?: boolean | null;
|
||||
isRotatable?: boolean | null;
|
||||
lastUser?: UInt | null;
|
||||
localisedDescription?: string | null;
|
||||
localisedName?: string | null;
|
||||
prototype?: PrototypeName | null;
|
||||
}
|
||||
|
||||
export interface MapChunkUpdate {
|
||||
type: KafkatorioPacketData2.Type.MapChunkUpdate;
|
||||
key: MapChunkUpdateKey;
|
||||
eventCounts?: { [key: string]: UInt } | null;
|
||||
player?: PlayerIndex | null;
|
||||
robot?: EntityIdentifiersData | null;
|
||||
force?: ForceIndex | null;
|
||||
tileDictionary?: MapTileDictionary | null;
|
||||
isDeleted?: boolean | null;
|
||||
}
|
||||
|
||||
export interface PlayerUpdate {
|
||||
type: KafkatorioPacketData2.Type.PlayerUpdate;
|
||||
key: PlayerUpdateKey;
|
||||
eventCounts?: { [key: string]: UInt } | null;
|
||||
characterUnitNumber?: UnitNumber | null;
|
||||
chatColour?: Colour | null;
|
||||
colour?: Colour | null;
|
||||
name?: string | null;
|
||||
afkTime?: Tick | null;
|
||||
ticksToRespawn?: Tick | null;
|
||||
forceIndex?: ForceIndex | null;
|
||||
isAdmin?: boolean | null;
|
||||
isConnected?: boolean | null;
|
||||
isShowOnMap?: boolean | null;
|
||||
isSpectator?: boolean | null;
|
||||
lastOnline?: Tick | null;
|
||||
onlineTime?: Tick | null;
|
||||
position?: MapEntityPosition | null;
|
||||
surfaceIndex?: SurfaceIndex | null;
|
||||
tag?: string | null;
|
||||
diedCause?: EntityIdentifiersData | null;
|
||||
bannedReason?: string | null;
|
||||
kickedReason?: string | null;
|
||||
disconnectReason?: string | null;
|
||||
isRemoved?: boolean | null;
|
||||
}
|
||||
}
|
||||
|
||||
export type UInt = uint;
|
||||
|
||||
export interface ConfigurationUpdateGameData {
|
||||
oldVersion?: string | null;
|
||||
newVersion?: string | null;
|
||||
}
|
||||
|
||||
export type PlayerIndex = UInt;
|
||||
|
||||
export type SurfaceIndex = UInt;
|
||||
|
||||
export type Double = double;
|
||||
|
||||
export interface EntityUpdateKey {
|
||||
unitNumber: UnitNumber;
|
||||
name: string;
|
||||
protoType: string;
|
||||
}
|
||||
|
||||
export type MapChunkPosition = [
|
||||
x: Int,
|
||||
y: Int,
|
||||
];
|
||||
|
||||
export type UByte = uint8;
|
||||
|
||||
export type Float = float;
|
||||
|
||||
export type PrototypeName = string;
|
||||
|
||||
export interface MapChunkUpdateKey {
|
||||
chunkPosition: MapChunkPosition;
|
||||
surfaceIndex: SurfaceIndex;
|
||||
}
|
||||
|
||||
export interface EntityIdentifiersData {
|
||||
unitNumber?: UnitNumber | null;
|
||||
name: string;
|
||||
protoType: string;
|
||||
}
|
||||
|
||||
export type ForceIndex = UInt;
|
||||
|
||||
export interface MapTileDictionary {
|
||||
tilesXY: { [key: string]: { [key: string]: PrototypeKey } };
|
||||
protos: { [key: PrototypeName]: PrototypeKey };
|
||||
}
|
||||
|
||||
export interface PlayerUpdateKey {
|
||||
index: PlayerIndex;
|
||||
}
|
||||
|
||||
export type UnitNumber = UInt;
|
||||
|
||||
export interface Colour {
|
||||
red?: Float;
|
||||
green?: Float;
|
||||
blue?: Float;
|
||||
alpha?: Float;
|
||||
}
|
||||
|
||||
export type MapEntityPosition = [
|
||||
x: Double,
|
||||
y: Double,
|
||||
];
|
||||
|
||||
export type Int = int;
|
||||
|
||||
export interface ConfigurationUpdateModData {
|
||||
modName: string;
|
||||
currentVersion?: string | null;
|
||||
previousVersion?: string | null;
|
||||
}
|
||||
|
||||
export type FactorioPrototype2 =
|
||||
| FactorioPrototype2.MapTile;
|
||||
|
||||
export namespace FactorioPrototype2 {
|
||||
export enum Type {
|
||||
MapTile = "dev.adamko.kafkatorio.schema.prototypes.FactorioPrototype2.MapTile",
|
||||
}
|
||||
|
||||
export interface MapTile {
|
||||
type: FactorioPrototype2.Type.MapTile;
|
||||
name: PrototypeName;
|
||||
layer: UInt;
|
||||
mapColour: Colour;
|
||||
collisionMasks: List;
|
||||
order: string;
|
||||
canBeMined: boolean;
|
||||
}
|
||||
}
|
||||
|
||||
export type Byte = int8;
|
||||
|
||||
export type List = any;
|
||||
|
||||
export type PrototypeKey = Int;
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
// Generated by TypeScriptGenerator - do not edit this file manually
|
||||
|
||||
type ObjectName = "LuaSurface" | "ConsoleChatMessage";
|
||||
|
||||
interface FactorioObjectData {
|
||||
objectName: ObjectName;
|
||||
}
|
||||
|
||||
interface SurfaceData extends FactorioObjectData {
|
||||
daytime: double;
|
||||
index: uint;
|
||||
name: string;
|
||||
objectName: ObjectName;
|
||||
}
|
||||
|
||||
interface ConsoleChatMessage extends FactorioObjectData {
|
||||
authorPlayerIndex: uint | null;
|
||||
content: string;
|
||||
objectName: ObjectName;
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
// Generated by TypeScriptGenerator - do not edit this file manually
|
||||
|
||||
type PrototypeObjectName = "LuaTilePrototype";
|
||||
|
||||
interface FactorioPrototype {
|
||||
prototypeObjectName: PrototypeObjectName;
|
||||
}
|
||||
|
||||
interface FactorioPrototypes extends KafkatorioPacket {
|
||||
modVersion: string;
|
||||
packetType: PacketType;
|
||||
prototypes: FactorioPrototype[];
|
||||
tick: uint;
|
||||
}
|
||||
|
||||
interface MapTilePrototype extends FactorioPrototype {
|
||||
canBeMined: boolean;
|
||||
collisionMasks: string[];
|
||||
layer: uint;
|
||||
mapColour: Colour;
|
||||
name: string;
|
||||
order: string;
|
||||
prototypeObjectName: PrototypeObjectName;
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
// Generated by TypeScriptGenerator - do not edit this file manually
|
||||
|
||||
type PacketType = "EVENT" | "CONFIG" | "PROTOTYPES" | "UPDATE";
|
||||
|
||||
interface KafkatorioPacket {
|
||||
modVersion: string;
|
||||
packetType: PacketType;
|
||||
tick: uint;
|
||||
}
|
||||
|
||||
interface FactorioEvent extends KafkatorioPacket {
|
||||
data: FactorioObjectData;
|
||||
eventType: string;
|
||||
modVersion: string;
|
||||
packetType: PacketType;
|
||||
tick: uint;
|
||||
}
|
||||
|
||||
interface Colour {
|
||||
alpha: float;
|
||||
blue: float;
|
||||
green: float;
|
||||
red: float;
|
||||
}
|
||||
|
||||
interface EntityIdentifiers {
|
||||
name: string;
|
||||
type: string;
|
||||
unitNumber: uint | null;
|
||||
}
|
||||
|
||||
interface EntityIdentifiersData extends EntityIdentifiers {
|
||||
name: string;
|
||||
type: string;
|
||||
unitNumber: uint | null;
|
||||
}
|
||||
|
||||
interface MapEntityPosition {
|
||||
x: double;
|
||||
y: double;
|
||||
}
|
||||
|
||||
interface MapChunkPosition {
|
||||
x: int;
|
||||
y: int;
|
||||
}
|
||||
|
||||
interface MapTileDictionary {
|
||||
protos: { [key: string]: string };
|
||||
tilesXY: { [key: string]: { [key: string]: string } };
|
||||
}
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
// Generated by TypeScriptGenerator - do not edit this file manually
|
||||
|
||||
type FactorioEventUpdateType = "PLAYER" | "MAP_CHUNK" | "ENTITY";
|
||||
|
||||
interface FactorioEventUpdateKey {
|
||||
updateType: FactorioEventUpdateType;
|
||||
}
|
||||
|
||||
interface FactorioEventUpdate extends FactorioEventUpdateKey {
|
||||
eventCounts: { [key: string]: uint } | null;
|
||||
updateType: FactorioEventUpdateType;
|
||||
}
|
||||
|
||||
interface FactorioEventUpdatePacket extends KafkatorioPacket {
|
||||
modVersion: string;
|
||||
packetType: PacketType;
|
||||
tick: uint;
|
||||
update: FactorioEventUpdate;
|
||||
}
|
||||
|
||||
interface PlayerUpdateKey extends FactorioEventUpdateKey {
|
||||
index: uint;
|
||||
}
|
||||
|
||||
interface PlayerUpdate extends FactorioEventUpdate, PlayerUpdateKey {
|
||||
afkTime: uint | null;
|
||||
bannedReason: string | null;
|
||||
characterUnitNumber: uint | null;
|
||||
chatColour: Colour | null;
|
||||
colour: Colour | null;
|
||||
diedCause: EntityIdentifiersData | null;
|
||||
disconnectReason: string | null;
|
||||
eventCounts: { [key: string]: uint } | null;
|
||||
forceIndex: uint | null;
|
||||
index: uint;
|
||||
isAdmin: boolean | null;
|
||||
isConnected: boolean | null;
|
||||
isRemoved: boolean | null;
|
||||
isShowOnMap: boolean | null;
|
||||
isSpectator: boolean | null;
|
||||
kickedReason: string | null;
|
||||
lastOnline: uint | null;
|
||||
name: string | null;
|
||||
onlineTime: uint | null;
|
||||
position: MapEntityPosition | null;
|
||||
surfaceIndex: uint | null;
|
||||
tag: string | null;
|
||||
ticksToRespawn: uint | null;
|
||||
updateType: FactorioEventUpdateType;
|
||||
}
|
||||
|
||||
interface EntityUpdateKey extends EntityIdentifiers, FactorioEventUpdateKey {
|
||||
name: string;
|
||||
type: string;
|
||||
unitNumber: uint;
|
||||
}
|
||||
|
||||
interface EntityUpdate extends FactorioEventUpdate, EntityUpdateKey {
|
||||
chunkPosition: MapChunkPosition | null;
|
||||
eventCounts: { [key: string]: uint } | null;
|
||||
graphicsVariation: uint8 | null;
|
||||
health: float | null;
|
||||
isActive: boolean | null;
|
||||
isRotatable: boolean | null;
|
||||
lastUser: uint | null;
|
||||
localisedDescription: string | null;
|
||||
localisedName: string | null;
|
||||
name: string;
|
||||
prototype: string | null;
|
||||
type: string;
|
||||
unitNumber: uint;
|
||||
updateType: FactorioEventUpdateType;
|
||||
}
|
||||
|
||||
interface MapChunkUpdateKey extends FactorioEventUpdateKey {
|
||||
chunkPosition: MapChunkPosition;
|
||||
surfaceIndex: uint;
|
||||
}
|
||||
|
||||
interface MapChunkUpdate extends FactorioEventUpdate, MapChunkUpdateKey {
|
||||
chunkPosition: MapChunkPosition;
|
||||
eventCounts: { [key: string]: uint } | null;
|
||||
force: uint | null;
|
||||
isDeleted: boolean | null;
|
||||
player: uint | null;
|
||||
robot: EntityIdentifiersData | null;
|
||||
surfaceIndex: uint;
|
||||
tileDictionary: MapTileDictionary | null;
|
||||
updateType: FactorioEventUpdateType;
|
||||
}
|
||||
41
modules/events-mod/src/main/typescript/main/PacketEmitter.ts
Normal file
41
modules/events-mod/src/main/typescript/main/PacketEmitter.ts
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import {
|
||||
KafkatorioPacket2,
|
||||
KafkatorioPacketData2
|
||||
} from "../generated/kafkatorio-schema/kafkatorio-schema";
|
||||
import {KafkatorioKeyedPacketData} from "./types";
|
||||
|
||||
export class KafkatorioPacketEmitter {
|
||||
|
||||
emitInstantPacket<DATA extends KafkatorioPacketData2>(
|
||||
data: DATA,
|
||||
) {
|
||||
KafkatorioPacketEmitter.emitPacket<KafkatorioPacket2>({
|
||||
data: data,
|
||||
modVersion: global.MOD_VERSION,
|
||||
tick: game.tick,
|
||||
})
|
||||
}
|
||||
|
||||
emitKeyedPacket<DATA extends KafkatorioKeyedPacketData>(
|
||||
data: DATA,
|
||||
) {
|
||||
KafkatorioPacketEmitter.emitPacket<KafkatorioPacket2>({
|
||||
data: data,
|
||||
modVersion: global.MOD_VERSION,
|
||||
tick: game.tick,
|
||||
})
|
||||
}
|
||||
|
||||
/** Emit a serialised KafkatorioPacket */
|
||||
private static emitPacket<T extends KafkatorioPacket2>(packet: T) {
|
||||
let data = game.table_to_json(packet)
|
||||
localised_print(`KafkatorioPacket: ${data}`)
|
||||
// rcon.print(`KafkatorioPacket: ${data}`)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
const PacketEmitter = new KafkatorioPacketEmitter()
|
||||
|
||||
export default PacketEmitter
|
||||
|
|
@ -1,10 +1,12 @@
|
|||
import KafkatorioSettings from "../settings/KafkatorioSettings";
|
||||
import {KafkatorioKeyedPacketData} from "../types";
|
||||
|
||||
export namespace EventUpdates {
|
||||
|
||||
|
||||
declare const global: {
|
||||
cache: LuaTable<string, CacheEntry<FactorioEventUpdateType>>,
|
||||
/** Map the hash of the key, as a string, a cache entry */
|
||||
cache: LuaTable<string, CacheEntry<KafkatorioKeyedPacketData>>,
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -19,7 +21,7 @@ export namespace EventUpdates {
|
|||
|
||||
if (force == true || isAnythingUndefined) {
|
||||
log("Initialising global.cache")
|
||||
global.cache = new LuaTable<string, CacheEntry<FactorioEventUpdateType>>()
|
||||
global.cache = new LuaTable<string, CacheEntry<KafkatorioKeyedPacketData>>()
|
||||
}
|
||||
log(`Finished initialising EventDataCache`)
|
||||
}
|
||||
|
|
@ -29,12 +31,13 @@ export namespace EventUpdates {
|
|||
* Update the cache data without restarting the 'time-to-emit' countdown, so that the data won't
|
||||
* be emitted more than once per {@link CacheEntry.expirationDurationTicks}.
|
||||
*/
|
||||
public throttle<TYPE extends FactorioEventUpdateType>(
|
||||
key: CacheKey<TYPE>,
|
||||
mutate: CacheDataMutator<TYPE>,
|
||||
public throttle<PACKET extends KafkatorioKeyedPacketData>(
|
||||
key: PacketKey<PACKET>,
|
||||
type: PacketType<PACKET>,
|
||||
mutate: CacheDataMutator<PACKET>,
|
||||
expirationDurationTicks?: uint,
|
||||
) {
|
||||
this.update(key, mutate, false, expirationDurationTicks)
|
||||
this.update(key, type, mutate, false, expirationDurationTicks)
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -42,23 +45,26 @@ export namespace EventUpdates {
|
|||
* Update the cache data and reset the 'time-to-emit' countdown, so the data won't be emitted
|
||||
* until there's an inactivity gap of {@link CacheEntry.expirationDurationTicks}.
|
||||
*/
|
||||
public debounce<TYPE extends FactorioEventUpdateType>(
|
||||
key: CacheKey<TYPE>,
|
||||
mutate: CacheDataMutator<TYPE>,
|
||||
public debounce<PACKET extends KafkatorioKeyedPacketData>(
|
||||
key: PacketKey<PACKET>,
|
||||
type: PacketType<PACKET>,
|
||||
mutate: CacheDataMutator<PACKET>,
|
||||
expirationDurationTicks?: uint,
|
||||
) {
|
||||
this.update(key, mutate, true, expirationDurationTicks)
|
||||
this.update(key, type, mutate, true, expirationDurationTicks)
|
||||
}
|
||||
|
||||
|
||||
private update<TYPE extends FactorioEventUpdateType>(
|
||||
key: CacheKey<TYPE>,
|
||||
mutate: CacheDataMutator<TYPE>,
|
||||
private update<PACKET extends KafkatorioKeyedPacketData>(
|
||||
key: PacketKey<PACKET>,
|
||||
type: PacketType<PACKET>,
|
||||
mutate: CacheDataMutator<PACKET>,
|
||||
resetLastUpdated: boolean,
|
||||
expirationDurationTicks?: uint,
|
||||
) {
|
||||
const entry: CacheEntry<TYPE> = this.getCacheEntry(key) ?? this.createCacheEntry(key, mutate)
|
||||
mutate(entry.data)
|
||||
const entry: CacheEntry<PACKET> = this.getCacheEntry(key) ??
|
||||
Manager.createCacheEntry(key, type)
|
||||
mutate(entry.packet)
|
||||
if (resetLastUpdated) {
|
||||
entry.lastUpdatedTick = game.tick
|
||||
}
|
||||
|
|
@ -72,8 +78,8 @@ export namespace EventUpdates {
|
|||
* Usage example: If an urgent update comes in, then the expiration can be reduced so that
|
||||
* it's transmitted sooner.
|
||||
*/
|
||||
public setExpiration(
|
||||
key: CacheKey<FactorioEventUpdateType>,
|
||||
public setExpiration<PACKET extends KafkatorioKeyedPacketData>(
|
||||
key: PacketKey<PACKET>,
|
||||
expirationDurationTicks: uint,
|
||||
) {
|
||||
const entry = this.getCacheEntry(key)
|
||||
|
|
@ -83,15 +89,16 @@ export namespace EventUpdates {
|
|||
}
|
||||
|
||||
|
||||
public extractExpired(): Array<FactorioEventUpdate> {
|
||||
// use in/out v4.7.0 https://github.com/microsoft/TypeScript/pull/48240
|
||||
public extractExpired(): Array<KafkatorioKeyedPacketData> {
|
||||
let countExpired = 0
|
||||
let countTotal = 0
|
||||
const expiredData: Array<FactorioEventUpdate> = []
|
||||
const expiredData: Array<KafkatorioKeyedPacketData> = []
|
||||
for (let [key, entry] of global.cache) {
|
||||
countTotal++
|
||||
if (this.isExpired(entry)) {
|
||||
countExpired++
|
||||
expiredData.push(entry.data)
|
||||
expiredData.push(entry.packet)
|
||||
global.cache.delete(key)
|
||||
}
|
||||
}
|
||||
|
|
@ -102,15 +109,15 @@ export namespace EventUpdates {
|
|||
}
|
||||
|
||||
|
||||
private getCacheEntry<TYPE extends FactorioEventUpdateType>(
|
||||
key: CacheKey<TYPE>
|
||||
): CacheEntry<TYPE> | undefined {
|
||||
const hash = game.encode_string(game.table_to_json(key))!!
|
||||
private getCacheEntry<PACKET extends KafkatorioKeyedPacketData>(
|
||||
key: PacketKey<PACKET>
|
||||
): CacheEntry<PACKET> | undefined {
|
||||
const hash = Manager.hashKey(key)
|
||||
if (!global.cache.has(hash)) {
|
||||
return undefined
|
||||
}
|
||||
const value: CacheEntry<any> = global.cache.get(hash)
|
||||
if (this.isEntryInstanceOf(value, key.updateType)) {
|
||||
if (this.isEntryInstanceOf(value, key)) {
|
||||
return value
|
||||
} else {
|
||||
// Type mismatch. This shouldn't happen...
|
||||
|
|
@ -119,40 +126,53 @@ export namespace EventUpdates {
|
|||
}
|
||||
|
||||
|
||||
private createCacheEntry<TYPE extends FactorioEventUpdateType>(
|
||||
key: CacheKey<TYPE>,
|
||||
mutate: CacheDataMutator<TYPE>,
|
||||
): CacheEntry<TYPE> {
|
||||
const data: CacheData<TYPE> = <CacheData<TYPE>>{...key}
|
||||
mutate(data)
|
||||
let entry: CacheEntry<TYPE> = new CacheEntry<TYPE>(data)
|
||||
const hash = game.encode_string(game.table_to_json(key))!!
|
||||
private static createCacheEntry<PACKET extends KafkatorioKeyedPacketData>(
|
||||
key: PacketKey<PACKET>,
|
||||
type: PacketType<PACKET>,
|
||||
): CacheEntry<PACKET> {
|
||||
const data: PACKET = <PACKET>{
|
||||
type: type,
|
||||
key: key,
|
||||
}
|
||||
let entry: CacheEntry<PACKET> = new CacheEntry<PACKET>(data)
|
||||
const hash = Manager.hashKey(key)
|
||||
global.cache.set(hash, entry)
|
||||
return entry
|
||||
}
|
||||
|
||||
|
||||
isExpired<TYPE extends FactorioEventUpdateType>(entry: CacheEntry<TYPE>): boolean {
|
||||
const expiryDuration = entry.expirationDurationTicks
|
||||
??
|
||||
KafkatorioSettings.getEventCacheExpirationTicks(entry.data.updateType)
|
||||
return game.tick - entry.lastUpdatedTick > expiryDuration
|
||||
isExpired<TYPE extends KafkatorioKeyedPacketData>(entry: CacheEntry<TYPE>): boolean {
|
||||
const expiryDuration =
|
||||
entry.expirationDurationTicks
|
||||
?? KafkatorioSettings.getEventCacheExpirationTicks(entry.packet)
|
||||
|
||||
if (expiryDuration == undefined) {
|
||||
return true
|
||||
} else {
|
||||
return game.tick - entry.lastUpdatedTick > expiryDuration
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
isEntryInstanceOf<TYPE extends FactorioEventUpdateType>(
|
||||
isEntryInstanceOf<PACKET extends KafkatorioKeyedPacketData>(
|
||||
entry: CacheEntry<any> | undefined,
|
||||
updateType: TYPE,
|
||||
): entry is CacheEntry<TYPE> {
|
||||
return this.isDataInstanceOf<TYPE>(entry?.data, updateType)
|
||||
key: PacketKey<PACKET>,
|
||||
): entry is CacheEntry<PACKET> {
|
||||
return this.isDataInstanceOf(entry?.packet, key)
|
||||
}
|
||||
|
||||
|
||||
isDataInstanceOf<TYPE extends FactorioEventUpdateType>(
|
||||
data: CacheData<any> | undefined,
|
||||
updateType: TYPE,
|
||||
): data is CacheData<TYPE> {
|
||||
return data != undefined && data.updateType == updateType
|
||||
isDataInstanceOf<PACKET extends KafkatorioKeyedPacketData>(
|
||||
packet: PACKET | undefined,
|
||||
key: PacketKey<PACKET>,
|
||||
): packet is PACKET {
|
||||
return packet != undefined && packet.key == key
|
||||
}
|
||||
|
||||
private static hashKey<PACKET extends KafkatorioKeyedPacketData>(
|
||||
key: PacketKey<PACKET>,
|
||||
): string {
|
||||
return game.encode_string(game.table_to_json(key))!!
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -166,54 +186,56 @@ export namespace EventUpdates {
|
|||
}
|
||||
|
||||
|
||||
/** Map a {@link FactorioEventUpdateType} to a {@link FactorioEventUpdate} DTO */
|
||||
type ConvertToUpdate<TYPE extends FactorioEventUpdateType> =
|
||||
TYPE extends "PLAYER" ? PlayerUpdate :
|
||||
TYPE extends "MAP_CHUNK" ? MapChunkUpdate :
|
||||
TYPE extends "ENTITY" ? EntityUpdate :
|
||||
never
|
||||
// export type KeyedPacketType = Exclude<KafkatorioPacketDataType,
|
||||
// "CONFIG" | "CONSOLE_CHAT" | "CONSOLE_COMMAND" | "PROTOTYPES" | "SURFACE">
|
||||
|
||||
// /** Map a {@link KeyedPacketType} to a {@link KafkatorioPacketData} DTO */
|
||||
// type ConvertToUpdate<TYPE extends KafkatorioKeyedPacketData> =
|
||||
// TYPE extends "PLAYER" ? PlayerUpdate :
|
||||
// TYPE extends "MAP_CHUNK" ? MapChunkUpdate :
|
||||
// TYPE extends "ENTITY" ? EntityUpdate :
|
||||
// never
|
||||
|
||||
|
||||
/** Map a {@link FactorioEventUpdateType} to a {@link FactorioEventUpdateKey} */
|
||||
type ConvertToUpdateKey<TYPE extends FactorioEventUpdateType> =
|
||||
TYPE extends "PLAYER" ? PlayerUpdateKey :
|
||||
TYPE extends "MAP_CHUNK" ? MapChunkUpdateKey :
|
||||
TYPE extends "ENTITY" ? EntityUpdateKey :
|
||||
never
|
||||
// /** Map a {@link KeyedPacketType} to a {@link KafkatorioKeyedPacketKey} */
|
||||
// type ConvertToUpdateKey<TYPE extends KafkatorioKeyedPacketData> =
|
||||
// TYPE extends "PLAYER" ? PlayerUpdateKey :
|
||||
// TYPE extends "MAP_CHUNK" ? MapChunkUpdateKey :
|
||||
// TYPE extends "ENTITY" ? EntityUpdateKey :
|
||||
// never
|
||||
|
||||
|
||||
/** Make `updateType` specific */
|
||||
export type CacheKey<TYPE extends FactorioEventUpdateType> =
|
||||
CacheTyped<TYPE>
|
||||
& Omit<ConvertToUpdateKey<TYPE>, "updateType">
|
||||
// /** Make `updateType` specific */
|
||||
export type PacketKey<PACKET extends KafkatorioKeyedPacketData> = PACKET["key"]
|
||||
export type PacketType<PACKET extends KafkatorioKeyedPacketData> = PACKET["type"]
|
||||
//
|
||||
//
|
||||
// /** Make `updateType` specific */
|
||||
// export type CacheData<TYPE extends KafkatorioKeyedPacketData> =
|
||||
// CacheTyped<TYPE>
|
||||
// & Omit<ConvertToUpdate<TYPE>, "updateType">
|
||||
//
|
||||
//
|
||||
// export type CacheTyped<TYPE extends KafkatorioKeyedPacketData> = {
|
||||
// readonly updateType: TYPE
|
||||
// }
|
||||
|
||||
|
||||
/** Make `updateType` specific */
|
||||
export type CacheData<TYPE extends FactorioEventUpdateType> =
|
||||
CacheTyped<TYPE>
|
||||
& Omit<ConvertToUpdate<TYPE>, "updateType">
|
||||
export type CacheDataMutator<PACKET extends KafkatorioKeyedPacketData> = (packet: PACKET) => void
|
||||
|
||||
|
||||
export type CacheTyped<TYPE extends FactorioEventUpdateType> = {
|
||||
readonly updateType: TYPE
|
||||
}
|
||||
|
||||
|
||||
export type CacheDataMutator<TYPE extends FactorioEventUpdateType> =
|
||||
(data: CacheData<TYPE>) => void
|
||||
|
||||
|
||||
class CacheEntry<TYPE extends FactorioEventUpdateType> {
|
||||
class CacheEntry<PACKET extends KafkatorioKeyedPacketData> {
|
||||
lastUpdatedTick: uint = game.tick
|
||||
expirationDurationTicks?: uint
|
||||
|
||||
data: CacheData<TYPE>
|
||||
packet: PACKET
|
||||
|
||||
constructor(
|
||||
data: CacheData<TYPE>,
|
||||
packet: PACKET,
|
||||
expirationDurationTicks?: uint,
|
||||
) {
|
||||
this.data = data
|
||||
|
||||
this.packet = packet
|
||||
this.expirationDurationTicks = expirationDurationTicks
|
||||
}
|
||||
}
|
||||
|
|
@ -222,4 +244,5 @@ export namespace EventUpdates {
|
|||
}
|
||||
|
||||
const EventUpdatesManager = new EventUpdates.Manager()
|
||||
|
||||
export default EventUpdatesManager
|
||||
|
|
|
|||
|
|
@ -1,23 +1,16 @@
|
|||
import {emitPacket} from "../emitKafkatorioPacket";
|
||||
import EventCacheService from "./EventDataCache";
|
||||
import packetEmitter from "../PacketEmitter";
|
||||
import {KafkatorioKeyedPacketData} from "../types";
|
||||
|
||||
/** Every 0.1 seconds */
|
||||
script.on_nth_tick(6, (nthTick: NthTickEventData) => {
|
||||
const cachedEvents: Array<FactorioEventUpdate> = EventCacheService.extractExpired()
|
||||
const cachedEvents: Array<KafkatorioKeyedPacketData> = EventCacheService.extractExpired()
|
||||
|
||||
if (cachedEvents.length > 0) {
|
||||
log(`nth tick ${nthTick.tick} has ${cachedEvents.length} events`)
|
||||
|
||||
for (const event of cachedEvents) {
|
||||
|
||||
const packet: FactorioEventUpdatePacket = {
|
||||
tick: nthTick.tick,
|
||||
modVersion: global.MOD_VERSION,
|
||||
packetType: "UPDATE",
|
||||
update: event,
|
||||
}
|
||||
|
||||
emitPacket(packet)
|
||||
packetEmitter.emitKeyedPacket(event)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,25 +1,33 @@
|
|||
import {emitPacket} from "../emitKafkatorioPacket";
|
||||
import PacketEmitter from "../PacketEmitter";
|
||||
import {
|
||||
ConfigurationUpdateGameData,
|
||||
ConfigurationUpdateModData,
|
||||
KafkatorioPacketData2
|
||||
} from "../../generated/kafkatorio-schema/kafkatorio-schema";
|
||||
import Type = KafkatorioPacketData2.Type;
|
||||
import ConfigurationUpdate = KafkatorioPacketData2.ConfigurationUpdate;
|
||||
|
||||
export function emitConfigurationUpdate(changeData: ConfigurationChangedData) {
|
||||
|
||||
emitPacket<FactorioConfigurationUpdate>({
|
||||
modVersion: global.MOD_VERSION,
|
||||
packetType: "CONFIG",
|
||||
const configUpdateData: ConfigurationUpdate = {
|
||||
type: Type.ConfigurationUpdate,
|
||||
migrationApplied: changeData.migration_applied,
|
||||
modStartupSettingsChange: changeData.mod_startup_settings_changed,
|
||||
allMods: allMods(changeData),
|
||||
factorioData: factorioData(changeData),
|
||||
tick: game.tick,
|
||||
})
|
||||
factorioData: factorioData(changeData)
|
||||
}
|
||||
|
||||
PacketEmitter.emitInstantPacket(configUpdateData)
|
||||
}
|
||||
|
||||
function factorioData(changeData: ConfigurationChangedData): FactorioGameDataUpdate {
|
||||
function factorioData(changeData: ConfigurationChangedData): ConfigurationUpdateGameData {
|
||||
return {
|
||||
oldVersion: changeData.old_version ?? null,
|
||||
newVersion: changeData.new_version ?? null,
|
||||
}
|
||||
}
|
||||
|
||||
function allMods(e: ConfigurationChangedData): FactorioModInfo[] {
|
||||
function allMods(e: ConfigurationChangedData): ConfigurationUpdateModData[] {
|
||||
|
||||
let namesOfChangedMods: string[] = Object.keys(e.mod_changes)
|
||||
let namesOfCurrentMods: string[] = Object.keys(script.active_mods)
|
||||
|
|
@ -33,7 +41,7 @@ function allMods(e: ConfigurationChangedData): FactorioModInfo[] {
|
|||
let currentVer = script.active_mods[modName] ?? e.mod_changes[modName].new_version ?? null
|
||||
let previousVer = e.mod_changes[modName]?.old_version ?? null
|
||||
|
||||
return <FactorioModInfo>{
|
||||
return <ConfigurationUpdateModData>{
|
||||
modName: modName,
|
||||
currentVersion: currentVer,
|
||||
previousVersion: previousVer,
|
||||
|
|
|
|||
|
|
@ -1,30 +1,37 @@
|
|||
import {Converters} from "../events/converters";
|
||||
import {emitPacket} from "../emitKafkatorioPacket";
|
||||
import PacketEmitter from "../PacketEmitter";
|
||||
import {
|
||||
FactorioPrototype2,
|
||||
KafkatorioPacketData2
|
||||
} from "../../generated/kafkatorio-schema/kafkatorio-schema";
|
||||
import Type = KafkatorioPacketData2.Type;
|
||||
import PrototypesUpdate = KafkatorioPacketData2.PrototypesUpdate;
|
||||
|
||||
|
||||
export function emitPrototypes() {
|
||||
emitPacket<FactorioPrototypes>({
|
||||
modVersion: global.MOD_VERSION,
|
||||
packetType: "PROTOTYPES",
|
||||
|
||||
const data: PrototypesUpdate = {
|
||||
prototypes: prototypes(),
|
||||
tick: game.tick,
|
||||
})
|
||||
type: Type.PrototypesUpdate,
|
||||
}
|
||||
|
||||
PacketEmitter.emitInstantPacket(data)
|
||||
}
|
||||
|
||||
function prototypes(): FactorioPrototype[] {
|
||||
let prototypes: FactorioPrototype[] = []
|
||||
function prototypes(): FactorioPrototype2[] {
|
||||
let prototypes: FactorioPrototype2[] = []
|
||||
|
||||
prototypes.push(...getMapTilePrototypes())
|
||||
|
||||
return prototypes
|
||||
}
|
||||
|
||||
function getMapTilePrototypes(): MapTilePrototype[] {
|
||||
let tiles: MapTilePrototype[] = []
|
||||
function getMapTilePrototypes(): FactorioPrototype2.MapTile[] {
|
||||
let tiles: FactorioPrototype2.MapTile[] = []
|
||||
for (let [, tile] of game.tile_prototypes) {
|
||||
tiles.push(
|
||||
<MapTilePrototype>{
|
||||
prototypeObjectName: tile.object_name,
|
||||
<FactorioPrototype2.MapTile>{
|
||||
type: FactorioPrototype2.Type.MapTile,
|
||||
|
||||
name: tile.name,
|
||||
order: tile.order,
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
/** Emit a serialised KafkatorioPacket */
|
||||
export function emitPacket<T extends KafkatorioPacket>(packet: T) {
|
||||
let data = game.table_to_json(packet)
|
||||
localised_print(`KafkatorioPacket: ${data}`)
|
||||
// rcon.print(`KafkatorioPacket: ${data}`)
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import {EventName} from "../types";
|
||||
import {Colour} from "../../generated/kafkatorio-schema/kafkatorio-schema";
|
||||
|
||||
export namespace Converters {
|
||||
|
||||
|
|
@ -62,15 +63,6 @@ export namespace Converters {
|
|||
// return result
|
||||
// }
|
||||
|
||||
export function surfaceToTable(surface: LuaSurface): SurfaceData {
|
||||
return {
|
||||
objectName: surface.object_name,
|
||||
|
||||
name: surface.name,
|
||||
index: surface.index,
|
||||
daytime: surface.daytime,
|
||||
}
|
||||
}
|
||||
|
||||
// export function mapEntityPosition(mapPos: MapPositionTable): MapEntityPosition {
|
||||
// return {
|
||||
|
|
@ -102,14 +94,6 @@ export namespace Converters {
|
|||
}
|
||||
}
|
||||
|
||||
export function consoleChat(content: string, playerIndex?: uint): ConsoleChatMessage {
|
||||
return {
|
||||
objectName: "ConsoleChatMessage",
|
||||
|
||||
authorPlayerIndex: playerIndex ?? null,
|
||||
content: content
|
||||
}
|
||||
}
|
||||
|
||||
// export function convertTile(tile: LuaTile): MapTile {
|
||||
// return {
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
import {emitPacket} from "../emitKafkatorioPacket";
|
||||
|
||||
/** Emit a serialised event */
|
||||
export function emitEvent<T extends FactorioObjectData>(eventData: T, tick: uint, eventType: string) {
|
||||
emitPacket({
|
||||
data: eventData,
|
||||
packetType: "EVENT",
|
||||
eventType: eventType,
|
||||
modVersion: global.MOD_VERSION,
|
||||
tick: tick,
|
||||
})
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
import {Converters} from "./converters"
|
||||
import {emitEvent} from "./emitEvent";
|
||||
import PacketEmitter from "../PacketEmitter";
|
||||
import {KafkatorioPacketData2} from "../../generated/kafkatorio-schema/kafkatorio-schema";
|
||||
import Type = KafkatorioPacketData2.Type;
|
||||
|
||||
// export function handlePlayerUpdate(tick: uint, eventType: string, playerIndex: uint) {
|
||||
// let player: LuaPlayer = game.players[playerIndex]
|
||||
|
|
@ -29,24 +30,23 @@ import {emitEvent} from "./emitEvent";
|
|||
// emitEvent(table, tick, eventType)
|
||||
// }
|
||||
|
||||
|
||||
export function handleSurfaceUpdate(
|
||||
tick: uint,
|
||||
event: OnTickEvent,
|
||||
eventType: string,
|
||||
surface: LuaSurface,
|
||||
) {
|
||||
let table = Converters.surfaceToTable(surface)
|
||||
emitEvent(table, tick, eventType)
|
||||
const update: KafkatorioPacketData2.SurfaceUpdate = {
|
||||
type: Type.SurfaceUpdate,
|
||||
|
||||
name: surface.name,
|
||||
index: surface.index,
|
||||
daytime: surface.daytime
|
||||
}
|
||||
|
||||
PacketEmitter.emitInstantPacket(update)
|
||||
}
|
||||
|
||||
export function handleConsoleChat(
|
||||
tick: uint,
|
||||
eventType: string,
|
||||
playerIndex: uint | undefined,
|
||||
message: string,
|
||||
) {
|
||||
let table = Converters.consoleChat(message, playerIndex)
|
||||
emitEvent(table, tick, eventType)
|
||||
}
|
||||
|
||||
// export function handleChunkUpdate(
|
||||
// tick: uint,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
import PacketEmitter from "../PacketEmitter";
|
||||
import {KafkatorioPacketData2} from "../../generated/kafkatorio-schema/kafkatorio-schema";
|
||||
import Type = KafkatorioPacketData2.Type;
|
||||
|
||||
script.on_event(
|
||||
defines.events.on_console_chat,
|
||||
(event: OnConsoleChatEvent) => {
|
||||
const update: KafkatorioPacketData2.ConsoleChatUpdate = {
|
||||
type: Type.ConsoleChatUpdate,
|
||||
|
||||
authorPlayerIndex: event.player_index ?? null,
|
||||
content: event.message
|
||||
}
|
||||
PacketEmitter.emitInstantPacket(update)
|
||||
}
|
||||
)
|
||||
|
||||
script.on_event(
|
||||
defines.events.on_console_command,
|
||||
(event: OnConsoleCommandEvent) => {
|
||||
const update: KafkatorioPacketData2.ConsoleCommandUpdate = {
|
||||
type: Type.ConsoleCommandUpdate,
|
||||
|
||||
authorPlayerIndex: event.player_index ?? null,
|
||||
command: event.command,
|
||||
parameters: event.parameters,
|
||||
}
|
||||
|
||||
PacketEmitter.emitInstantPacket(update)
|
||||
}
|
||||
)
|
||||
|
|
@ -1,20 +1,25 @@
|
|||
import {isEventType} from "./eventTypeCheck";
|
||||
import {Converters} from "./converters";
|
||||
import EventUpdatesManager, {EventUpdates} from "../cache/EventDataCache";
|
||||
import CacheKey = EventUpdates.CacheKey;
|
||||
import CacheData = EventUpdates.CacheData;
|
||||
import {
|
||||
KafkatorioPacketData2,
|
||||
MapChunkPosition,
|
||||
MapTileDictionary
|
||||
} from "../../generated/kafkatorio-schema/kafkatorio-schema";
|
||||
import CacheKey = EventUpdates.PacketKey;
|
||||
import Type = KafkatorioPacketData2.Type;
|
||||
|
||||
|
||||
type MapChunkUpdater = (data: CacheData<"MAP_CHUNK">) => void
|
||||
type MapChunkUpdater = (data: KafkatorioPacketData2.MapChunkUpdate) => void
|
||||
|
||||
|
||||
const mapProtoNameToKey: { [key: string]: string } = {}
|
||||
const mapProtoNameToKey: { [key: string]: uint } = {}
|
||||
let protoIndex: uint = 0
|
||||
|
||||
|
||||
function getProtoKey(protoName: string): string {
|
||||
function getProtoKey(protoName: string): uint {
|
||||
if (mapProtoNameToKey[protoName] == undefined) {
|
||||
mapProtoNameToKey[protoName] = `${protoIndex++}`
|
||||
mapProtoNameToKey[protoName] = protoIndex++
|
||||
}
|
||||
return mapProtoNameToKey[protoName]
|
||||
}
|
||||
|
|
@ -22,7 +27,7 @@ function getProtoKey(protoName: string): string {
|
|||
|
||||
function mapTilesUpdateDebounce(
|
||||
surface: LuaSurface | undefined,
|
||||
chunkPosition: ChunkPositionTable,
|
||||
chunkPosition: MapChunkPosition,
|
||||
tiles: TileRead[],
|
||||
eventName: string,
|
||||
updater?: MapChunkUpdater,
|
||||
|
|
@ -33,14 +38,14 @@ function mapTilesUpdateDebounce(
|
|||
return
|
||||
}
|
||||
|
||||
const key: CacheKey<"MAP_CHUNK"> = {
|
||||
const key: KafkatorioPacketData2.MapChunkUpdate["key"] = {
|
||||
surfaceIndex: surface.index,
|
||||
chunkPosition: chunkPosition,
|
||||
updateType: "MAP_CHUNK",
|
||||
}
|
||||
|
||||
EventUpdatesManager.debounce<"MAP_CHUNK">(
|
||||
EventUpdatesManager.debounce<KafkatorioPacketData2.MapChunkUpdate>(
|
||||
key,
|
||||
Type.MapChunkUpdate,
|
||||
data => {
|
||||
data.tileDictionary ??= <MapTileDictionary>{
|
||||
tilesXY: {},
|
||||
|
|
@ -53,7 +58,7 @@ function mapTilesUpdateDebounce(
|
|||
const yString = `${tile.position.y}`
|
||||
const protoKey = getProtoKey(tile.name)
|
||||
|
||||
data.tileDictionary.protos[protoKey] = tile.name
|
||||
data.tileDictionary.protos[tile.name] = protoIndex
|
||||
|
||||
data.tileDictionary.tilesXY[xString] ??= {}
|
||||
data.tileDictionary.tilesXY[xString][yString] = protoKey
|
||||
|
|
@ -105,7 +110,7 @@ export function handleChunkGeneratedEvent(
|
|||
let tiles = getTiles(e.surface, e.area)
|
||||
mapTilesUpdateDebounce(
|
||||
e.surface,
|
||||
e.position,
|
||||
[e.position.x, e.position.y],
|
||||
tiles,
|
||||
Converters.eventNameString(e.name),
|
||||
undefined,
|
||||
|
|
@ -114,22 +119,22 @@ export function handleChunkGeneratedEvent(
|
|||
}
|
||||
|
||||
|
||||
script.on_event(
|
||||
defines.events.on_chunk_charted,
|
||||
(e: OnChunkChartedEvent) => {
|
||||
log(`on_chunk_charted ${e.tick}`)
|
||||
|
||||
// const surface = getSurface(e.surface_index)
|
||||
// if (surface == undefined) {
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// let tiles = getTiles(surface, e.area)
|
||||
// mapTilesUpdateDebounce(surface, e.position, tiles, (data => {
|
||||
// data.force = e.force.index
|
||||
// }))
|
||||
}
|
||||
)
|
||||
// script.on_event(
|
||||
// defines.events.on_chunk_charted,
|
||||
// (e: OnChunkChartedEvent) => {
|
||||
// log(`on_chunk_charted ${e.tick}`)
|
||||
//
|
||||
// // const surface = getSurface(e.surface_index)
|
||||
// // if (surface == undefined) {
|
||||
// // return
|
||||
// // }
|
||||
// //
|
||||
// // let tiles = getTiles(surface, e.area)
|
||||
// // mapTilesUpdateDebounce(surface, e.position, tiles, (data => {
|
||||
// // data.force = e.force.index
|
||||
// // }))
|
||||
// }
|
||||
// )
|
||||
|
||||
|
||||
script.on_event(
|
||||
|
|
@ -155,14 +160,19 @@ function groupTiles(tiles: TileRead[]): Map<MapChunkPosition, TileRead[]> {
|
|||
|
||||
const mapChunkPositionToTiles = new Map<MapChunkPosition, TileRead[]>()
|
||||
for (const tile of tiles) {
|
||||
const chunkPosition = {
|
||||
x: math.floor((tile.position.x / 32)),
|
||||
y: math.floor((tile.position.y / 32)),
|
||||
}
|
||||
const chunkPosition: MapChunkPosition = [
|
||||
math.floor((tile.position.x / 32)),
|
||||
math.floor((tile.position.y / 32)),
|
||||
]
|
||||
if (!mapChunkPositionToTiles.has(chunkPosition)) {
|
||||
mapChunkPositionToTiles.set(chunkPosition, [])
|
||||
}
|
||||
mapChunkPositionToTiles.get(chunkPosition)?.push(tile)
|
||||
// https://github.com/TypeScriptToLua/TypeScriptToLua/issues/1256
|
||||
// mapChunkPositionToTiles.get(chunkPosition)?.push(tile)
|
||||
const tiles = mapChunkPositionToTiles.get(chunkPosition)
|
||||
if (tiles != null) {
|
||||
tiles.push(tile)
|
||||
}
|
||||
}
|
||||
return mapChunkPositionToTiles
|
||||
}
|
||||
|
|
@ -183,7 +193,7 @@ function convertOldPosition(
|
|||
}
|
||||
|
||||
|
||||
function onBuildTileEvent(event: OnPlayerBuiltTileEvent | OnRobotBuiltTileEvent) {
|
||||
function handleBuiltTileEvent(event: OnPlayerBuiltTileEvent | OnRobotBuiltTileEvent) {
|
||||
|
||||
const surface = getSurface(event.surface_index)
|
||||
if (surface == undefined) {
|
||||
|
|
@ -209,7 +219,7 @@ function onBuildTileEvent(event: OnPlayerBuiltTileEvent | OnRobotBuiltTileEvent)
|
|||
data.robot = {
|
||||
unitNumber: event.robot?.unit_number ?? null,
|
||||
name: event.robot.name,
|
||||
type: event.robot.type,
|
||||
protoType: event.robot.type,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
@ -225,28 +235,25 @@ function onBuildTileEvent(event: OnPlayerBuiltTileEvent | OnRobotBuiltTileEvent)
|
|||
|
||||
script.on_event(defines.events.on_player_built_tile, (e: OnPlayerBuiltTileEvent) => {
|
||||
log(`on_player_built_tile ${e.tick}`)
|
||||
onBuildTileEvent(e)
|
||||
handleBuiltTileEvent(e)
|
||||
})
|
||||
script.on_event(defines.events.on_robot_built_tile, (e: OnRobotBuiltTileEvent) => {
|
||||
log(`on_robot_built_tile ${e.tick}`)
|
||||
onBuildTileEvent(e)
|
||||
handleBuiltTileEvent(e)
|
||||
})
|
||||
|
||||
// script.on_event(
|
||||
// defines.events.on_player_mined_tile,
|
||||
// (e: OnPlayerMinedTileEvent) => {
|
||||
// // need to group tiles by ChunkPosition...
|
||||
//
|
||||
// }
|
||||
// )
|
||||
|
||||
// script.on_event(
|
||||
// defines.events.on_robot_mined_tile,
|
||||
// (e: OnRobotMinedTileEvent) => {
|
||||
// // need to group tiles by ChunkPosition...
|
||||
// function handleMinedTileEvent(event: OnPlayerMinedTileEvent | OnRobotMinedTileEvent) {
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// )
|
||||
// script.on_event(defines.events.on_player_mined_tile, (e: OnPlayerMinedTileEvent) => {
|
||||
// log(`on_player_mined_tile ${e.tick}`)
|
||||
// handleMinedTileEvent(e)
|
||||
// })
|
||||
// script.on_event(defines.events.on_robot_mined_tile, (e: OnRobotMinedTileEvent) => {
|
||||
// log(`on_robot_mined_tile ${e.tick}`)
|
||||
// handleMinedTileEvent(e)
|
||||
// })
|
||||
|
||||
|
||||
script.on_event(
|
||||
|
|
@ -260,17 +267,15 @@ script.on_event(
|
|||
}
|
||||
|
||||
for (const position of e.positions) {
|
||||
const key: CacheKey<"MAP_CHUNK"> = {
|
||||
const key: CacheKey<KafkatorioPacketData2.MapChunkUpdate> = {
|
||||
surfaceIndex: surface.index,
|
||||
chunkPosition: position,
|
||||
updateType: "MAP_CHUNK",
|
||||
chunkPosition: [position.x, position.y],
|
||||
}
|
||||
|
||||
EventUpdatesManager.debounce<"MAP_CHUNK">(
|
||||
EventUpdatesManager.debounce<KafkatorioPacketData2.MapChunkUpdate>(
|
||||
key,
|
||||
data => {
|
||||
data.isDeleted = true
|
||||
},
|
||||
Type.MapChunkUpdate,
|
||||
data => data.isDeleted = true,
|
||||
0, // deletion is important - emit ASAP
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,20 @@
|
|||
import {Converters} from "./converters";
|
||||
import EventUpdatesManager, {EventUpdates} from "../cache/EventDataCache";
|
||||
import CacheData = EventUpdates.CacheData;
|
||||
import EventUpdatesManager from "../cache/EventDataCache";
|
||||
import {KafkatorioPacketData2} from "../../generated/kafkatorio-schema/kafkatorio-schema";
|
||||
import Type = KafkatorioPacketData2.Type;
|
||||
|
||||
|
||||
type PlayerUpdater = (player: LuaPlayer, data: CacheData<"PLAYER">) => void
|
||||
type PlayerUpdater = (player: LuaPlayer, data: KafkatorioPacketData2.PlayerUpdate) => void
|
||||
|
||||
function playerUpdateThrottle(
|
||||
playerIndex: uint,
|
||||
eventName: string,
|
||||
mutate: PlayerUpdater,
|
||||
) {
|
||||
EventUpdatesManager.throttle<"PLAYER">(
|
||||
{index: playerIndex, updateType: "PLAYER"},
|
||||
|
||||
EventUpdatesManager.throttle<KafkatorioPacketData2.PlayerUpdate>(
|
||||
{index: playerIndex},
|
||||
Type.PlayerUpdate,
|
||||
data => {
|
||||
const player = game.players[playerIndex]
|
||||
if (player != undefined) {
|
||||
|
|
@ -36,7 +39,7 @@ function playerUpdateThrottle(
|
|||
// )
|
||||
// }
|
||||
|
||||
function playerOnlineInfo(player: LuaPlayer, data: CacheData<"PLAYER">) {
|
||||
function playerOnlineInfo(player: LuaPlayer, data: KafkatorioPacketData2.PlayerUpdate) {
|
||||
data.lastOnline = player.last_online
|
||||
data.onlineTime = player.online_time
|
||||
data.afkTime = player.afk_time
|
||||
|
|
@ -73,7 +76,7 @@ script.on_event(
|
|||
e.player_index,
|
||||
Converters.eventNameString(e.name),
|
||||
(player, data) => {
|
||||
data.position = player.position
|
||||
data.position = [player.position.x, player.position.y]
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -86,7 +89,7 @@ script.on_event(
|
|||
e.player_index,
|
||||
Converters.eventNameString(e.name),
|
||||
(player, data) => {
|
||||
data.position = player.position
|
||||
data.position = [player.position.x, player.position.y]
|
||||
data.surfaceIndex = player.surface.index
|
||||
}
|
||||
)
|
||||
|
|
@ -106,7 +109,7 @@ script.on_event(
|
|||
data.diedCause = {
|
||||
unitNumber: e.cause.unit_number ?? null,
|
||||
name: e.cause.name,
|
||||
type: e.cause.type
|
||||
protoType: e.cause.type
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import {handleConsoleChat, handleSurfaceUpdate,} from "./handlers";
|
||||
import {Queue} from "../queue/queue";
|
||||
import {isEventType} from "./eventTypeCheck";
|
||||
import {Converters} from "./converters";
|
||||
import KafkatorioSettings from "../settings/KafkatorioSettings";
|
||||
import {handleChunkGeneratedEvent} from "./onMapChunkEventListeners";
|
||||
import {handleSurfaceUpdate} from "./handlers";
|
||||
|
||||
|
||||
// script.on_event(
|
||||
|
|
@ -34,13 +34,8 @@ script.on_event(
|
|||
(e: OnTickEvent) => {
|
||||
if (e.tick % 1000 == 0) {
|
||||
for (const [, surface] of game.surfaces) {
|
||||
handleSurfaceUpdate(e.tick, Converters.eventNameString(e.name), surface)
|
||||
handleSurfaceUpdate(e, Converters.eventNameString(e.name), surface)
|
||||
}
|
||||
|
||||
// let packets = new KafkatorioPacketQueue().dequeueValues(1)
|
||||
// for (const packet of packets) {
|
||||
// emitPacket(packet)
|
||||
// }
|
||||
}
|
||||
|
||||
if (e.tick % 7 == 0) {
|
||||
|
|
@ -64,21 +59,6 @@ script.on_event(
|
|||
}
|
||||
)
|
||||
|
||||
script.on_event(
|
||||
defines.events.on_console_chat,
|
||||
(e: OnConsoleChatEvent) => {
|
||||
handleConsoleChat(e.tick, Converters.eventNameString(e.name), e.player_index, e.message)
|
||||
}
|
||||
)
|
||||
|
||||
// script.on_event(
|
||||
// defines.events.on_chunk_generated,
|
||||
// (e: OnChunkGeneratedEvent) => {
|
||||
// handleChunkUpdate(e.tick, mapEventIdToName.get(e.name), e.surface.index, e.position,
|
||||
// e.area) } ) script.on_event( [ defines.events.on_player_built_tile,
|
||||
// defines.events.on_robot_built_tile, ], (builtTilesEvent) => { handleTilesUpdate(
|
||||
// builtTilesEvent.tick, mapEventIdToName.get(builtTilesEvent.name), builtTilesEvent.surface_index,
|
||||
// builtTilesEvent.tile, builtTilesEvent.tiles, ) } )
|
||||
|
||||
script.on_event(
|
||||
defines.events.on_runtime_mod_setting_changed,
|
||||
|
|
|
|||
|
|
@ -1,52 +1,57 @@
|
|||
import {Data, DoubleSettingDefinition} from "typed-factorio/settings/types"
|
||||
import {KafkatorioKeyedPacketData, KafkatorioKeyedPacketTypes} from "../types";
|
||||
import {KafkatorioPacketData2} from "../../generated/kafkatorio-schema/kafkatorio-schema";
|
||||
|
||||
export class KafkatorioSettingsConfig {
|
||||
|
||||
|
||||
private static eventCacheExpirationDefaultSeconds: Record<FactorioEventUpdateType, uint> = {
|
||||
"PLAYER": 0.25,
|
||||
"MAP_CHUNK": 30,
|
||||
"ENTITY": 5,
|
||||
private static eventCacheExpirationDefaultSeconds: Record<KafkatorioKeyedPacketTypes, double> = {
|
||||
"dev.adamko.kafkatorio.schema2.PlayerUpdate": 0.5,
|
||||
"dev.adamko.kafkatorio.schema2.MapChunkUpdate": 30,
|
||||
"dev.adamko.kafkatorio.schema2.EntityUpdate": 5,
|
||||
}
|
||||
|
||||
|
||||
private eventCacheExpirationTicks: Record<FactorioEventUpdateType, double> = {
|
||||
"PLAYER": KafkatorioSettingsConfig.eventCacheExpirationDefaultSeconds["PLAYER"],
|
||||
"MAP_CHUNK": KafkatorioSettingsConfig.eventCacheExpirationDefaultSeconds["MAP_CHUNK"],
|
||||
"ENTITY": KafkatorioSettingsConfig.eventCacheExpirationDefaultSeconds["ENTITY"],
|
||||
private eventCacheExpirationTicks: Record<KafkatorioKeyedPacketTypes, double> = {
|
||||
"dev.adamko.kafkatorio.schema2.PlayerUpdate":
|
||||
KafkatorioSettingsConfig.eventCacheExpirationDefaultSeconds[KafkatorioPacketData2.Type.PlayerUpdate],
|
||||
"dev.adamko.kafkatorio.schema2.MapChunkUpdate":
|
||||
KafkatorioSettingsConfig.eventCacheExpirationDefaultSeconds[KafkatorioPacketData2.Type.MapChunkUpdate],
|
||||
"dev.adamko.kafkatorio.schema2.EntityUpdate":
|
||||
KafkatorioSettingsConfig.eventCacheExpirationDefaultSeconds[KafkatorioPacketData2.Type.EntityUpdate],
|
||||
}
|
||||
|
||||
|
||||
public getEventCacheExpirationTicks(type: FactorioEventUpdateType): uint {
|
||||
return this.eventCacheExpirationTicks[type]
|
||||
public getEventCacheExpirationTicks(packet: KafkatorioKeyedPacketData): uint {
|
||||
return this.eventCacheExpirationTicks[packet.type]
|
||||
}
|
||||
|
||||
private static types: KafkatorioKeyedPacketTypes[] = [
|
||||
KafkatorioPacketData2.Type.PlayerUpdate,
|
||||
KafkatorioPacketData2.Type.MapChunkUpdate,
|
||||
KafkatorioPacketData2.Type.EntityUpdate,
|
||||
]
|
||||
|
||||
loadSettings(): void {
|
||||
const types: FactorioEventUpdateType[] = ["PLAYER", "MAP_CHUNK", "ENTITY"]
|
||||
for (const type of types) {
|
||||
public loadSettings(): void {
|
||||
for (const type of KafkatorioSettingsConfig.types) {
|
||||
const seconds: double = settings.global[KafkatorioSettingsConfig.cacheDurationSettingName(type)].value as double
|
||||
this.eventCacheExpirationTicks[type] = seconds * 60 // convert ticks to seconds
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
initialiseSettings(data: Data): void {
|
||||
data.extend(
|
||||
[
|
||||
this.createDefaultCacheDuration("PLAYER"),
|
||||
this.createDefaultCacheDuration("MAP_CHUNK"),
|
||||
this.createDefaultCacheDuration("ENTITY"),
|
||||
]
|
||||
public initialiseSettings(data: Data): void {
|
||||
const settings = KafkatorioSettingsConfig.types.map(
|
||||
type => KafkatorioSettingsConfig.createDefaultCacheDuration(type)
|
||||
)
|
||||
data.extend(settings)
|
||||
}
|
||||
|
||||
|
||||
private createDefaultCacheDuration(
|
||||
type: FactorioEventUpdateType,
|
||||
private static createDefaultCacheDuration(
|
||||
type: KafkatorioKeyedPacketTypes,
|
||||
defaultExpirationSeconds: uint = KafkatorioSettingsConfig.eventCacheExpirationDefaultSeconds[type],
|
||||
): DoubleSettingDefinition {
|
||||
return <DoubleSettingDefinition>{
|
||||
return {
|
||||
type: "double-setting",
|
||||
name: KafkatorioSettingsConfig.cacheDurationSettingName(type),
|
||||
setting_type: "runtime-global",
|
||||
|
|
@ -58,13 +63,12 @@ export class KafkatorioSettingsConfig {
|
|||
}
|
||||
|
||||
|
||||
private static cacheDurationSettingName(type: FactorioEventUpdateType): string {
|
||||
return `kafkatorio_event-cache_default-expiration-duration-seconds_${type}`
|
||||
private static cacheDurationSettingName(type: KafkatorioKeyedPacketTypes): string {
|
||||
return `kafkatorio_event-cache_default-expiration-duration-seconds_${type.replaceAll(".", "-")}`
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
const KafkatorioSettings = new KafkatorioSettingsConfig()
|
||||
|
||||
export default KafkatorioSettings
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import {KafkatorioPacketData2} from "../generated/kafkatorio-schema/kafkatorio-schema";
|
||||
|
||||
export type EventName = keyof typeof defines.events
|
||||
|
||||
|
||||
|
|
@ -15,3 +17,10 @@ type ExcludeNullKeys<TYPE> = Pick<TYPE, NonNullKeys<TYPE>>
|
|||
type NonNullableKeys<TYPE> = {
|
||||
[KEY in keyof TYPE]: NonNullable<TYPE[KEY]>;
|
||||
}
|
||||
|
||||
|
||||
type KafkatorioKeyedPacketData = Extract<KafkatorioPacketData2, { key: object }>
|
||||
|
||||
type KafkatorioKeyedPacketTypes = KafkatorioKeyedPacketData["type"];
|
||||
|
||||
type KafkatorioKeyedPacketKeys = KafkatorioKeyedPacketData["key"];
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
{
|
||||
"name": "kafkatorio-events-mod",
|
||||
"version": "0.3.2",
|
||||
"version": "0.4.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"enhanced-resolve": {
|
||||
"version": "5.9.2",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz",
|
||||
"integrity": "sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==",
|
||||
"version": "5.9.3",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz",
|
||||
"integrity": "sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.2.4",
|
||||
"tapable": "^2.2.0"
|
||||
|
|
@ -19,9 +19,9 @@
|
|||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.2.9",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
|
||||
"integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ=="
|
||||
"version": "4.2.10",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
|
||||
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="
|
||||
},
|
||||
"has": {
|
||||
"version": "1.0.3",
|
||||
|
|
@ -75,19 +75,19 @@
|
|||
"integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ=="
|
||||
},
|
||||
"typed-factorio": {
|
||||
"version": "0.19.1",
|
||||
"resolved": "https://registry.npmjs.org/typed-factorio/-/typed-factorio-0.19.1.tgz",
|
||||
"integrity": "sha512-/iLa916Cw33vC6wgmCb4cPLjmvUA2zVviTx/vy80iEvpOHjoNkuHkGSsmvss1aItwUKUlHaLi3k0fK5OPiw1iA=="
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/typed-factorio/-/typed-factorio-1.0.0.tgz",
|
||||
"integrity": "sha512-8JYdjizJKMUhEpaZ7SoVLQ+toe0XTebK/Zh/Iwwvs29x8Ml758XACX5Bn71LJK22u3obgu7YN2yn2GxZbQ554g=="
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz",
|
||||
"integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg=="
|
||||
"version": "4.6.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz",
|
||||
"integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw=="
|
||||
},
|
||||
"typescript-to-lua": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript-to-lua/-/typescript-to-lua-1.3.4.tgz",
|
||||
"integrity": "sha512-9NkUOSUd9tufvwCGiWJ6Z1edizYcECUfjdZJZfDRKTEXKIddbAdV3IFR6u5gxvYYRfXhfNV6IKvqHS2HxHFs6w==",
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript-to-lua/-/typescript-to-lua-1.4.3.tgz",
|
||||
"integrity": "sha512-oGJO1BqXKSxdfwavfOzthelxaQVAc7ykJ4Z/BF96nAWz35nmuLyv9FOSS132TgzLmV02859ndMuTYZtiVnN6jQ==",
|
||||
"requires": {
|
||||
"enhanced-resolve": "^5.8.2",
|
||||
"resolve": "^1.15.1",
|
||||
|
|
|
|||
|
|
@ -1,28 +1,24 @@
|
|||
{
|
||||
"name": "kafkatorio-events-mod",
|
||||
"version": "0.3.2",
|
||||
"version": "0.4.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "tstl",
|
||||
"dev": "tstl --watch"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"node": "~14.19.1"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"dependencies": {
|
||||
"lua-types": "^2.11.0",
|
||||
"typescript-to-lua": "1.3.4",
|
||||
"typed-factorio": "0.19.1",
|
||||
"typescript": "4.6.2"
|
||||
"typescript-to-lua": "1.4.3",
|
||||
"typed-factorio": "1.0.0",
|
||||
"typescript": "4.6.3"
|
||||
},
|
||||
"// @types/node": "^12.0.8",
|
||||
"license": "UNLICENSED",
|
||||
"peerDependencies": {
|
||||
},
|
||||
"optionalDependencies": {
|
||||
},
|
||||
"bundledDependencies": [
|
||||
]
|
||||
"peerDependencies": {},
|
||||
"optionalDependencies": {},
|
||||
"bundledDependencies": []
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue