preprocess map into binary data

This commit is contained in:
evanpelle
2024-08-22 21:01:40 -07:00
parent 7517f933ca
commit ac556ee073
17 changed files with 281 additions and 913 deletions
+2 -3
View File
@@ -35,9 +35,8 @@
* better algorithm for name render placement DONE 8/19/2024
* show how many players in each lobby DONE 8/19/2024
* make boats larger DONE 8/19/2024
* boats same color as owner 8/19/2024
* store map as proto
* make coasts look better
* boats same color as owner DONE 8/19/2024
* make coasts look better DONE 8/22/2024
* have boats not get close to shore
* BUG: boat doesn't work if on lake if other player not on same lake
* Allow boats to attack TerraNullius
File diff suppressed because one or more lines are too long
Binary file not shown.
-219
View File
@@ -1,219 +0,0 @@
import * as $protobuf from "protobufjs";
import Long = require("long");
/** Properties of a TerrainMap. */
export interface ITerrainMap {
/** TerrainMap height */
height?: (number|null);
/** TerrainMap width */
width?: (number|null);
/** TerrainMap terrain */
terrain?: (ITerrainTile[]|null);
}
/** Represents a TerrainMap. */
export class TerrainMap implements ITerrainMap {
/**
* Constructs a new TerrainMap.
* @param [properties] Properties to set
*/
constructor(properties?: ITerrainMap);
/** TerrainMap height. */
public height: number;
/** TerrainMap width. */
public width: number;
/** TerrainMap terrain. */
public terrain: ITerrainTile[];
/**
* Creates a new TerrainMap instance using the specified properties.
* @param [properties] Properties to set
* @returns TerrainMap instance
*/
public static create(properties?: ITerrainMap): TerrainMap;
/**
* Encodes the specified TerrainMap message. Does not implicitly {@link TerrainMap.verify|verify} messages.
* @param message TerrainMap message or plain object to encode
* @param [writer] Writer to encode to
* @returns Writer
*/
public static encode(message: ITerrainMap, writer?: $protobuf.Writer): $protobuf.Writer;
/**
* Encodes the specified TerrainMap message, length delimited. Does not implicitly {@link TerrainMap.verify|verify} messages.
* @param message TerrainMap message or plain object to encode
* @param [writer] Writer to encode to
* @returns Writer
*/
public static encodeDelimited(message: ITerrainMap, writer?: $protobuf.Writer): $protobuf.Writer;
/**
* Decodes a TerrainMap message from the specified reader or buffer.
* @param reader Reader or buffer to decode from
* @param [length] Message length if known beforehand
* @returns TerrainMap
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): TerrainMap;
/**
* Decodes a TerrainMap message from the specified reader or buffer, length delimited.
* @param reader Reader or buffer to decode from
* @returns TerrainMap
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): TerrainMap;
/**
* Verifies a TerrainMap message.
* @param message Plain object to verify
* @returns `null` if valid, otherwise the reason why it is not
*/
public static verify(message: { [k: string]: any }): (string|null);
/**
* Creates a TerrainMap message from a plain object. Also converts values to their respective internal types.
* @param object Plain object
* @returns TerrainMap
*/
public static fromObject(object: { [k: string]: any }): TerrainMap;
/**
* Creates a plain object from a TerrainMap message. Also converts values to other types if specified.
* @param message TerrainMap
* @param [options] Conversion options
* @returns Plain object
*/
public static toObject(message: TerrainMap, options?: $protobuf.IConversionOptions): { [k: string]: any };
/**
* Converts this TerrainMap to JSON.
* @returns JSON object
*/
public toJSON(): { [k: string]: any };
/**
* Gets the default type url for TerrainMap
* @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com")
* @returns The default type url
*/
public static getTypeUrl(typeUrlPrefix?: string): string;
}
/** Properties of a TerrainTile. */
export interface ITerrainTile {
/** TerrainTile name */
name?: (string|null);
/** TerrainTile age */
age?: (number|null);
/** TerrainTile email */
email?: (string|null);
}
/** Represents a TerrainTile. */
export class TerrainTile implements ITerrainTile {
/**
* Constructs a new TerrainTile.
* @param [properties] Properties to set
*/
constructor(properties?: ITerrainTile);
/** TerrainTile name. */
public name: string;
/** TerrainTile age. */
public age: number;
/** TerrainTile email. */
public email: string;
/**
* Creates a new TerrainTile instance using the specified properties.
* @param [properties] Properties to set
* @returns TerrainTile instance
*/
public static create(properties?: ITerrainTile): TerrainTile;
/**
* Encodes the specified TerrainTile message. Does not implicitly {@link TerrainTile.verify|verify} messages.
* @param message TerrainTile message or plain object to encode
* @param [writer] Writer to encode to
* @returns Writer
*/
public static encode(message: ITerrainTile, writer?: $protobuf.Writer): $protobuf.Writer;
/**
* Encodes the specified TerrainTile message, length delimited. Does not implicitly {@link TerrainTile.verify|verify} messages.
* @param message TerrainTile message or plain object to encode
* @param [writer] Writer to encode to
* @returns Writer
*/
public static encodeDelimited(message: ITerrainTile, writer?: $protobuf.Writer): $protobuf.Writer;
/**
* Decodes a TerrainTile message from the specified reader or buffer.
* @param reader Reader or buffer to decode from
* @param [length] Message length if known beforehand
* @returns TerrainTile
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): TerrainTile;
/**
* Decodes a TerrainTile message from the specified reader or buffer, length delimited.
* @param reader Reader or buffer to decode from
* @returns TerrainTile
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): TerrainTile;
/**
* Verifies a TerrainTile message.
* @param message Plain object to verify
* @returns `null` if valid, otherwise the reason why it is not
*/
public static verify(message: { [k: string]: any }): (string|null);
/**
* Creates a TerrainTile message from a plain object. Also converts values to their respective internal types.
* @param object Plain object
* @returns TerrainTile
*/
public static fromObject(object: { [k: string]: any }): TerrainTile;
/**
* Creates a plain object from a TerrainTile message. Also converts values to other types if specified.
* @param message TerrainTile
* @param [options] Conversion options
* @returns Plain object
*/
public static toObject(message: TerrainTile, options?: $protobuf.IConversionOptions): { [k: string]: any };
/**
* Converts this TerrainTile to JSON.
* @returns JSON object
*/
public toJSON(): { [k: string]: any };
/**
* Gets the default type url for TerrainTile
* @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com")
* @returns The default type url
*/
public static getTypeUrl(typeUrlPrefix?: string): string;
}
-532
View File
@@ -1,532 +0,0 @@
/*eslint-disable block-scoped-var, id-length, no-control-regex, no-magic-numbers, no-prototype-builtins, no-redeclare, no-shadow, no-var, sort-vars*/
import * as $protobuf from "protobufjs/minimal";
// Common aliases
const $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
// Exported root namespace
const $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {});
export const TerrainMap = $root.TerrainMap = (() => {
/**
* Properties of a TerrainMap.
* @exports ITerrainMap
* @interface ITerrainMap
* @property {number|null} [height] TerrainMap height
* @property {number|null} [width] TerrainMap width
* @property {Array.<ITerrainTile>|null} [terrain] TerrainMap terrain
*/
/**
* Constructs a new TerrainMap.
* @exports TerrainMap
* @classdesc Represents a TerrainMap.
* @implements ITerrainMap
* @constructor
* @param {ITerrainMap=} [properties] Properties to set
*/
function TerrainMap(properties) {
this.terrain = [];
if (properties)
for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i)
if (properties[keys[i]] != null)
this[keys[i]] = properties[keys[i]];
}
/**
* TerrainMap height.
* @member {number} height
* @memberof TerrainMap
* @instance
*/
TerrainMap.prototype.height = 0;
/**
* TerrainMap width.
* @member {number} width
* @memberof TerrainMap
* @instance
*/
TerrainMap.prototype.width = 0;
/**
* TerrainMap terrain.
* @member {Array.<ITerrainTile>} terrain
* @memberof TerrainMap
* @instance
*/
TerrainMap.prototype.terrain = $util.emptyArray;
/**
* Creates a new TerrainMap instance using the specified properties.
* @function create
* @memberof TerrainMap
* @static
* @param {ITerrainMap=} [properties] Properties to set
* @returns {TerrainMap} TerrainMap instance
*/
TerrainMap.create = function create(properties) {
return new TerrainMap(properties);
};
/**
* Encodes the specified TerrainMap message. Does not implicitly {@link TerrainMap.verify|verify} messages.
* @function encode
* @memberof TerrainMap
* @static
* @param {ITerrainMap} message TerrainMap message or plain object to encode
* @param {$protobuf.Writer} [writer] Writer to encode to
* @returns {$protobuf.Writer} Writer
*/
TerrainMap.encode = function encode(message, writer) {
if (!writer)
writer = $Writer.create();
if (message.height != null && Object.hasOwnProperty.call(message, "height"))
writer.uint32(/* id 1, wireType 0 =*/8).int32(message.height);
if (message.width != null && Object.hasOwnProperty.call(message, "width"))
writer.uint32(/* id 2, wireType 0 =*/16).int32(message.width);
if (message.terrain != null && message.terrain.length)
for (let i = 0; i < message.terrain.length; ++i)
$root.TerrainTile.encode(message.terrain[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
return writer;
};
/**
* Encodes the specified TerrainMap message, length delimited. Does not implicitly {@link TerrainMap.verify|verify} messages.
* @function encodeDelimited
* @memberof TerrainMap
* @static
* @param {ITerrainMap} message TerrainMap message or plain object to encode
* @param {$protobuf.Writer} [writer] Writer to encode to
* @returns {$protobuf.Writer} Writer
*/
TerrainMap.encodeDelimited = function encodeDelimited(message, writer) {
return this.encode(message, writer).ldelim();
};
/**
* Decodes a TerrainMap message from the specified reader or buffer.
* @function decode
* @memberof TerrainMap
* @static
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
* @param {number} [length] Message length if known beforehand
* @returns {TerrainMap} TerrainMap
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
TerrainMap.decode = function decode(reader, length) {
if (!(reader instanceof $Reader))
reader = $Reader.create(reader);
let end = length === undefined ? reader.len : reader.pos + length, message = new $root.TerrainMap();
while (reader.pos < end) {
let tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
message.height = reader.int32();
break;
}
case 2: {
message.width = reader.int32();
break;
}
case 3: {
if (!(message.terrain && message.terrain.length))
message.terrain = [];
message.terrain.push($root.TerrainTile.decode(reader, reader.uint32()));
break;
}
default:
reader.skipType(tag & 7);
break;
}
}
return message;
};
/**
* Decodes a TerrainMap message from the specified reader or buffer, length delimited.
* @function decodeDelimited
* @memberof TerrainMap
* @static
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
* @returns {TerrainMap} TerrainMap
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
TerrainMap.decodeDelimited = function decodeDelimited(reader) {
if (!(reader instanceof $Reader))
reader = new $Reader(reader);
return this.decode(reader, reader.uint32());
};
/**
* Verifies a TerrainMap message.
* @function verify
* @memberof TerrainMap
* @static
* @param {Object.<string,*>} message Plain object to verify
* @returns {string|null} `null` if valid, otherwise the reason why it is not
*/
TerrainMap.verify = function verify(message) {
if (typeof message !== "object" || message === null)
return "object expected";
if (message.height != null && message.hasOwnProperty("height"))
if (!$util.isInteger(message.height))
return "height: integer expected";
if (message.width != null && message.hasOwnProperty("width"))
if (!$util.isInteger(message.width))
return "width: integer expected";
if (message.terrain != null && message.hasOwnProperty("terrain")) {
if (!Array.isArray(message.terrain))
return "terrain: array expected";
for (let i = 0; i < message.terrain.length; ++i) {
let error = $root.TerrainTile.verify(message.terrain[i]);
if (error)
return "terrain." + error;
}
}
return null;
};
/**
* Creates a TerrainMap message from a plain object. Also converts values to their respective internal types.
* @function fromObject
* @memberof TerrainMap
* @static
* @param {Object.<string,*>} object Plain object
* @returns {TerrainMap} TerrainMap
*/
TerrainMap.fromObject = function fromObject(object) {
if (object instanceof $root.TerrainMap)
return object;
let message = new $root.TerrainMap();
if (object.height != null)
message.height = object.height | 0;
if (object.width != null)
message.width = object.width | 0;
if (object.terrain) {
if (!Array.isArray(object.terrain))
throw TypeError(".TerrainMap.terrain: array expected");
message.terrain = [];
for (let i = 0; i < object.terrain.length; ++i) {
if (typeof object.terrain[i] !== "object")
throw TypeError(".TerrainMap.terrain: object expected");
message.terrain[i] = $root.TerrainTile.fromObject(object.terrain[i]);
}
}
return message;
};
/**
* Creates a plain object from a TerrainMap message. Also converts values to other types if specified.
* @function toObject
* @memberof TerrainMap
* @static
* @param {TerrainMap} message TerrainMap
* @param {$protobuf.IConversionOptions} [options] Conversion options
* @returns {Object.<string,*>} Plain object
*/
TerrainMap.toObject = function toObject(message, options) {
if (!options)
options = {};
let object = {};
if (options.arrays || options.defaults)
object.terrain = [];
if (options.defaults) {
object.height = 0;
object.width = 0;
}
if (message.height != null && message.hasOwnProperty("height"))
object.height = message.height;
if (message.width != null && message.hasOwnProperty("width"))
object.width = message.width;
if (message.terrain && message.terrain.length) {
object.terrain = [];
for (let j = 0; j < message.terrain.length; ++j)
object.terrain[j] = $root.TerrainTile.toObject(message.terrain[j], options);
}
return object;
};
/**
* Converts this TerrainMap to JSON.
* @function toJSON
* @memberof TerrainMap
* @instance
* @returns {Object.<string,*>} JSON object
*/
TerrainMap.prototype.toJSON = function toJSON() {
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
};
/**
* Gets the default type url for TerrainMap
* @function getTypeUrl
* @memberof TerrainMap
* @static
* @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com")
* @returns {string} The default type url
*/
TerrainMap.getTypeUrl = function getTypeUrl(typeUrlPrefix) {
if (typeUrlPrefix === undefined) {
typeUrlPrefix = "type.googleapis.com";
}
return typeUrlPrefix + "/TerrainMap";
};
return TerrainMap;
})();
export const TerrainTile = $root.TerrainTile = (() => {
/**
* Properties of a TerrainTile.
* @exports ITerrainTile
* @interface ITerrainTile
* @property {string|null} [name] TerrainTile name
* @property {number|null} [age] TerrainTile age
* @property {string|null} [email] TerrainTile email
*/
/**
* Constructs a new TerrainTile.
* @exports TerrainTile
* @classdesc Represents a TerrainTile.
* @implements ITerrainTile
* @constructor
* @param {ITerrainTile=} [properties] Properties to set
*/
function TerrainTile(properties) {
if (properties)
for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i)
if (properties[keys[i]] != null)
this[keys[i]] = properties[keys[i]];
}
/**
* TerrainTile name.
* @member {string} name
* @memberof TerrainTile
* @instance
*/
TerrainTile.prototype.name = "";
/**
* TerrainTile age.
* @member {number} age
* @memberof TerrainTile
* @instance
*/
TerrainTile.prototype.age = 0;
/**
* TerrainTile email.
* @member {string} email
* @memberof TerrainTile
* @instance
*/
TerrainTile.prototype.email = "";
/**
* Creates a new TerrainTile instance using the specified properties.
* @function create
* @memberof TerrainTile
* @static
* @param {ITerrainTile=} [properties] Properties to set
* @returns {TerrainTile} TerrainTile instance
*/
TerrainTile.create = function create(properties) {
return new TerrainTile(properties);
};
/**
* Encodes the specified TerrainTile message. Does not implicitly {@link TerrainTile.verify|verify} messages.
* @function encode
* @memberof TerrainTile
* @static
* @param {ITerrainTile} message TerrainTile message or plain object to encode
* @param {$protobuf.Writer} [writer] Writer to encode to
* @returns {$protobuf.Writer} Writer
*/
TerrainTile.encode = function encode(message, writer) {
if (!writer)
writer = $Writer.create();
if (message.name != null && Object.hasOwnProperty.call(message, "name"))
writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
if (message.age != null && Object.hasOwnProperty.call(message, "age"))
writer.uint32(/* id 2, wireType 0 =*/16).int32(message.age);
if (message.email != null && Object.hasOwnProperty.call(message, "email"))
writer.uint32(/* id 3, wireType 2 =*/26).string(message.email);
return writer;
};
/**
* Encodes the specified TerrainTile message, length delimited. Does not implicitly {@link TerrainTile.verify|verify} messages.
* @function encodeDelimited
* @memberof TerrainTile
* @static
* @param {ITerrainTile} message TerrainTile message or plain object to encode
* @param {$protobuf.Writer} [writer] Writer to encode to
* @returns {$protobuf.Writer} Writer
*/
TerrainTile.encodeDelimited = function encodeDelimited(message, writer) {
return this.encode(message, writer).ldelim();
};
/**
* Decodes a TerrainTile message from the specified reader or buffer.
* @function decode
* @memberof TerrainTile
* @static
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
* @param {number} [length] Message length if known beforehand
* @returns {TerrainTile} TerrainTile
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
TerrainTile.decode = function decode(reader, length) {
if (!(reader instanceof $Reader))
reader = $Reader.create(reader);
let end = length === undefined ? reader.len : reader.pos + length, message = new $root.TerrainTile();
while (reader.pos < end) {
let tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
message.name = reader.string();
break;
}
case 2: {
message.age = reader.int32();
break;
}
case 3: {
message.email = reader.string();
break;
}
default:
reader.skipType(tag & 7);
break;
}
}
return message;
};
/**
* Decodes a TerrainTile message from the specified reader or buffer, length delimited.
* @function decodeDelimited
* @memberof TerrainTile
* @static
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
* @returns {TerrainTile} TerrainTile
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
TerrainTile.decodeDelimited = function decodeDelimited(reader) {
if (!(reader instanceof $Reader))
reader = new $Reader(reader);
return this.decode(reader, reader.uint32());
};
/**
* Verifies a TerrainTile message.
* @function verify
* @memberof TerrainTile
* @static
* @param {Object.<string,*>} message Plain object to verify
* @returns {string|null} `null` if valid, otherwise the reason why it is not
*/
TerrainTile.verify = function verify(message) {
if (typeof message !== "object" || message === null)
return "object expected";
if (message.name != null && message.hasOwnProperty("name"))
if (!$util.isString(message.name))
return "name: string expected";
if (message.age != null && message.hasOwnProperty("age"))
if (!$util.isInteger(message.age))
return "age: integer expected";
if (message.email != null && message.hasOwnProperty("email"))
if (!$util.isString(message.email))
return "email: string expected";
return null;
};
/**
* Creates a TerrainTile message from a plain object. Also converts values to their respective internal types.
* @function fromObject
* @memberof TerrainTile
* @static
* @param {Object.<string,*>} object Plain object
* @returns {TerrainTile} TerrainTile
*/
TerrainTile.fromObject = function fromObject(object) {
if (object instanceof $root.TerrainTile)
return object;
let message = new $root.TerrainTile();
if (object.name != null)
message.name = String(object.name);
if (object.age != null)
message.age = object.age | 0;
if (object.email != null)
message.email = String(object.email);
return message;
};
/**
* Creates a plain object from a TerrainTile message. Also converts values to other types if specified.
* @function toObject
* @memberof TerrainTile
* @static
* @param {TerrainTile} message TerrainTile
* @param {$protobuf.IConversionOptions} [options] Conversion options
* @returns {Object.<string,*>} Plain object
*/
TerrainTile.toObject = function toObject(message, options) {
if (!options)
options = {};
let object = {};
if (options.defaults) {
object.name = "";
object.age = 0;
object.email = "";
}
if (message.name != null && message.hasOwnProperty("name"))
object.name = message.name;
if (message.age != null && message.hasOwnProperty("age"))
object.age = message.age;
if (message.email != null && message.hasOwnProperty("email"))
object.email = message.email;
return object;
};
/**
* Converts this TerrainTile to JSON.
* @function toJSON
* @memberof TerrainTile
* @instance
* @returns {Object.<string,*>} JSON object
*/
TerrainTile.prototype.toJSON = function toJSON() {
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
};
/**
* Gets the default type url for TerrainTile
* @function getTypeUrl
* @memberof TerrainTile
* @static
* @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com")
* @returns {string} The default type url
*/
TerrainTile.getTypeUrl = function getTypeUrl(typeUrlPrefix) {
if (typeUrlPrefix === undefined) {
typeUrlPrefix = "type.googleapis.com";
}
return typeUrlPrefix + "/TerrainTile";
};
return TerrainTile;
})();
export {$root as default};
+65
View File
@@ -10,6 +10,7 @@
"@types/google-protobuf": "^3.15.12",
"@types/jimp": "^0.2.28",
"@types/msgpack5": "^3.4.6",
"binary-loader": "^0.0.1",
"colord": "^2.9.3",
"crypto": "^1.0.1",
"express": "^4.19.2",
@@ -35,6 +36,7 @@
"@types/sinon": "^17.0.3",
"@types/ws": "^8.5.11",
"babel-jest": "^29.7.0",
"binary-base64-loader": "^1.0.0",
"chai": "^5.1.1",
"concurrently": "^8.2.2",
"css-loader": "^7.1.2",
@@ -44,6 +46,7 @@
"jest": "^29.7.0",
"mocha": "^10.7.0",
"mrmime": "^2.0.0",
"raw-loader": "^4.0.2",
"sinon": "^18.0.0",
"sinon-chai": "^4.0.0",
"style-loader": "^4.0.0",
@@ -4965,6 +4968,42 @@
"node": "*"
}
},
"node_modules/binary-base64-loader": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/binary-base64-loader/-/binary-base64-loader-1.0.0.tgz",
"integrity": "sha512-OCP5fxce6yu8up2lqfHxl2ZpA+2SrGa9og+3dZO2eZOu9po8THpsMM6Amrbu51UlcaNBd5viviDgVy+2FyfYlw==",
"dev": true,
"license": "MIT",
"dependencies": {
"loader-utils": "^2.0.0",
"schema-utils": "^2.7.0"
},
"engines": {
"node": ">=10.13.0"
},
"peerDependencies": {
"webpack": "^4.0.0 || ^5.0.0"
}
},
"node_modules/binary-base64-loader/node_modules/schema-utils": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz",
"integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/json-schema": "^7.0.5",
"ajv": "^6.12.4",
"ajv-keywords": "^3.5.2"
},
"engines": {
"node": ">= 8.9.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
}
},
"node_modules/binary-extensions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
@@ -4977,6 +5016,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/binary-loader": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/binary-loader/-/binary-loader-0.0.1.tgz",
"integrity": "sha512-LujAJL3IhYn4zVWZWAct9B6G5hdonNle+fWsG/u9QyY1OhOVp00jFgygUVr9SrBVw8doddyx9A/VS1/T9co4Dg=="
},
"node_modules/bl": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
@@ -10672,6 +10716,27 @@
"node": ">= 0.8"
}
},
"node_modules/raw-loader": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz",
"integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==",
"dev": true,
"license": "MIT",
"dependencies": {
"loader-utils": "^2.0.0",
"schema-utils": "^3.0.0"
},
"engines": {
"node": ">= 10.13.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"peerDependencies": {
"webpack": "^4.0.0 || ^5.0.0"
}
},
"node_modules/react-is": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+4 -1
View File
@@ -1,7 +1,7 @@
{
"name": "warfront-client",
"scripts": {
"build-world-terrain-map": "node --loader ts-node/esm --experimental-specifier-resolution=node src/scripts/TerrainMapGenerator.ts",
"build-map": "node --loader ts-node/esm --experimental-specifier-resolution=node src/scripts/TerrainMapGenerator.ts",
"build-dev": "webpack --config webpack.config.js --mode development",
"build-prod": "webpack --config webpack.config.js --mode production",
"start:client": "webpack serve --open --node-env development",
@@ -21,6 +21,7 @@
"@types/sinon": "^17.0.3",
"@types/ws": "^8.5.11",
"babel-jest": "^29.7.0",
"binary-base64-loader": "^1.0.0",
"chai": "^5.1.1",
"concurrently": "^8.2.2",
"css-loader": "^7.1.2",
@@ -30,6 +31,7 @@
"jest": "^29.7.0",
"mocha": "^10.7.0",
"mrmime": "^2.0.0",
"raw-loader": "^4.0.2",
"sinon": "^18.0.0",
"sinon-chai": "^4.0.0",
"style-loader": "^4.0.0",
@@ -49,6 +51,7 @@
"@types/google-protobuf": "^3.15.12",
"@types/jimp": "^0.2.28",
"@types/msgpack5": "^3.4.6",
"binary-loader": "^0.0.1",
"colord": "^2.9.3",
"crypto": "^1.0.1",
"express": "^4.19.2",
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

+11 -13
View File
@@ -17,7 +17,7 @@ class Client {
private hasJoined = false
private socket: WebSocket | null = null;
private terrainMap: Promise<TerrainMap>
private terrainMap: TerrainMap
private game: ClientGame
private lobbiesContainer: HTMLElement | null;
@@ -115,18 +115,16 @@ class Client {
this.lobbiesContainer.appendChild(joiningMessage);
}
this.terrainMap.then((map) => {
if (this.game != null) {
return;
}
this.game = createClientGame(getUsername(), new PseudoRandom(Date.now()).nextID(), lobby.id, getConfig(), map);
this.game.join();
const g = this.game
window.addEventListener('beforeunload', function (event) {
// Your function logic here
console.log('Browser is closing');
g.stop()
});
if (this.game != null) {
return;
}
this.game = createClientGame(getUsername(), new PseudoRandom(Date.now()).nextID(), lobby.id, getConfig(), this.terrainMap);
this.game.join();
const g = this.game
window.addEventListener('beforeunload', function (event) {
// Your function logic here
console.log('Browser is closing');
g.stop()
});
}
}
+1 -1
View File
@@ -116,7 +116,7 @@ export class ClientGame {
this.renderer.initialize()
this.input.initialize()
this.gs.addExecution(...this.executor.spawnBots(this.config.numBots()))
//this.gs.addExecution(...this.executor.spawnBots(this.config.numBots()))
this.intervalID = setInterval(() => this.tick(), 10);
}
+39 -53
View File
@@ -1,13 +1,7 @@
import {Jimp as JimpType, JimpConstructors} from '@jimp/core';
import 'jimp';
import {TerrainTile} from '../../generated/protos';
import {Cell} from './Game';
declare const Jimp: JimpType & JimpConstructors;
import binAsString from "!!binary-loader!../../resources/WorldSmall.bin";
export class TerrainMap {
constructor(public readonly tiles: Terrain[][]) { }
terrain(cell: Cell): Terrain {
@@ -30,64 +24,56 @@ export enum TerrainType {
export class Terrain {
public shoreline: boolean = false
public magnitude: number = 0
constructor(public type: TerrainType) { }
}
export async function loadTerrainMap(): Promise<TerrainMap> {
const imageModule = await import(`../../resources/maps/World.png`);
const imageUrl = imageModule.default;
const image = await Jimp.read(imageUrl)
const {width, height} = image.bitmap;
export function loadTerrainMap(): TerrainMap {
const fileData = binAsString;
console.log(`Loaded data length: ${fileData.length} bytes`);
// Extract width and height from the first 4 bytes
const width = (fileData.charCodeAt(1) << 8) | fileData.charCodeAt(0);
const height = (fileData.charCodeAt(3) << 8) | fileData.charCodeAt(2);
console.log(`Decoded dimensions: ${width}x${height}`);
// Log the first 100 bytes of data (including the width and height bytes)
logBinaryAsAscii(fileData, 100);
// Check if the data length matches the expected size
if (fileData.length != width * height + 4) { // +4 for the width and height bytes
throw new Error(`Invalid data: buffer size ${fileData.length} incorrect for ${width}x${height} terrain plus 4 bytes for dimensions.`);
}
const terrain: Terrain[][] = Array(width).fill(null).map(() => Array(height).fill(null));
image.scan(0, 0, width, height, function (x: number, y: number, idx: number) {
const t: TerrainTile = new TerrainTile()
const red = this.bitmap.data[idx + 0];
// Start from the 5th byte (index 4) when processing terrain data
for (let x = 0; x < width; x++) {
for (let y = 0; y < height; y++) {
const packedByte = fileData.charCodeAt(4 + y * width + x); // +4 to skip dimension bytes
const type = (packedByte & 0b10000000) ? TerrainType.Land : TerrainType.Water;
const shoreline = !!(packedByte & 0b01000000);
const magnitude = packedByte & 0b00111111;
if (red > 100) {
terrain[x][y] = new Terrain(TerrainType.Land)
} else {
terrain[x][y] = new Terrain(TerrainType.Water);
terrain[x][y] = new Terrain(type);
terrain[x][y].shoreline = shoreline;
terrain[x][y].magnitude = magnitude;
}
})
process(terrain)
}
return new TerrainMap(terrain);
}
function process(map: Terrain[][]) {
for (let x = 0; x < map.length; x++) {
for (let y = 0; y < map[0].length; y++) {
const terrain = map[x][y]
const ns = neighbors(x, y, map)
if (terrain.type == TerrainType.Land) {
if (ns.filter(t => t.type == TerrainType.Water).length > 0) {
terrain.shoreline = true
}
} else {
if (ns.filter(t => t.type == TerrainType.Land).length > 0) {
terrain.shoreline = true
}
}
function logBinaryAsAscii(data: string, length: number = 8) {
console.log('Binary data (1 = set bit, 0 = unset bit):');
for (let i = 0; i < Math.min(length, data.length); i++) {
let byte = data.charCodeAt(i);
let byteString = '';
for (let j = 7; j >= 0; j--) {
byteString += (byte & (1 << j)) ? '1' : '0';
}
console.log(`Byte ${i}: ${byteString}`);
}
}
function neighbors(x: number, y: number, map: Terrain[][]): Terrain[] {
const ns: Terrain[] = []
if (x > 0) {
ns.push(map[x - 1][y])
}
if (x < map.length - 1) {
ns.push(map[x + 1][y])
}
if (y > 0) {
ns.push(map[x][y - 1])
}
if (y < map[0].length - 1) {
ns.push(map[x][y + 1])
}
return ns
}
+5 -1
View File
@@ -1,5 +1,5 @@
declare module '*.png' {
const content: string;
const content: string;
export default content;
}
declare module '*.jpg' {
@@ -15,3 +15,7 @@ declare module '*.svg' {
const value: string;
export default value;
}
declare module '*.bin' {
const value: string;
export default value;
}
+150 -89
View File
@@ -1,121 +1,182 @@
import PImage from 'pureimage';
import fs from 'fs/promises';
import path from 'path';
import {fileURLToPath} from 'url';
import fs from 'fs/promises';
import {createReadStream, createWriteStream} from 'fs';
import zlib from 'zlib';
import {promisify} from 'util';
import {fileURLToPath} from 'url';
const deflateRaw = promisify(zlib.deflateRaw);
const inflateRaw = promisify(zlib.inflateRaw);
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
interface TerrainMap {
width: number;
height: number;
terrain: TerrainTile[][];
interface Coord {
x: number;
y: number;
}
interface TerrainTile {
isLand: boolean
export class TerrainMap {
constructor(public readonly tiles: Terrain[][]) { }
terrain(coord: Coord): Terrain {
return this.tiles[coord.x][coord.y]
}
width(): number {
return this.tiles.length
}
height(): number {
return this.tiles[0].length
}
}
export async function loadTerrainMap(): Promise<TerrainMap> {
try {
const imagePath = path.resolve(__dirname, '..', '..', 'resources', 'maps', 'World.png');
console.log('Attempting to load image from:', imagePath);
export enum TerrainType {
Land,
Water
}
try {
await fs.access(imagePath);
} catch (error) {
throw new Error(`Image file not found at ${imagePath}. Please ensure the file exists.`);
}
export class Terrain {
public shoreline: boolean = false
public magnitude: number = 0
constructor(public type: TerrainType) { }
}
const readStream = createReadStream(imagePath);
const img = await PImage.decodePNGFromStream(readStream);
export async function loadTerrainMap(): Promise<void> {
const imagePath = path.resolve(__dirname, '..', '..', 'resources', 'maps', 'WorldSmall.png');
console.log('Image loaded successfully');
console.log('Image dimensions:', img.width, 'x', img.height);
const readStream = createReadStream(imagePath);
const img = await PImage.decodePNGFromStream(readStream);
const terrainMap: TerrainMap = {
width: img.width,
height: img.height,
terrain: []
};
console.log('Image loaded successfully');
console.log('Image dimensions:', img.width, 'x', img.height);
// Iterate through each pixel
for (let x = 0; x < img.width; x++) {
terrainMap.terrain[x] = [];
for (let y = 0; y < img.height; y++) {
const color = img.getPixelRGBA(x, y);
const red = (color >> 24) & 0xff;
// Extract the red channel (assuming it represents height)
const height = (color >> 24) & 0xff;
terrainMap.terrain[x][y] = {
isLand: red > 100
};
const terrain: Terrain[][] = Array(img.width).fill(null).map(() => Array(img.height).fill(null));
// Iterate through each pixel
for (let x = 0; x < img.width; x++) {
for (let y = 0; y < img.height; y++) {
const color = img.getPixelRGBA(x, y);
const red = (color >> 24) & 0xff;
if (red > 100) {
terrain[x][y] = new Terrain(TerrainType.Land)
} else {
terrain[x][y] = new Terrain(TerrainType.Water);
}
}
console.log('Terrain data extracted');
}
// Serialize the terrain data using MessagePack
const msg = JSON.stringify(terrainMap)
const compressedData = await deflateRaw(msg);
const shorelineWaters = processShore(terrain)
processDistToLand(shorelineWaters, terrain)
const packed = packTerrain(terrain)
const outputPath = path.join(__dirname, '..', '..', 'resources', 'WorldSmall.bin');
fs.writeFile(outputPath, packed);
}
function processShore(map: Terrain[][]): Coord[] {
const shorelineWaters: Coord[] = []
for (let x = 0; x < map.length; x++) {
for (let y = 0; y < map[0].length; y++) {
const terrain = map[x][y]
const ns = neighbors(x, y, map)
if (terrain.type == TerrainType.Land) {
if (ns.filter(t => t.type == TerrainType.Water).length > 0) {
terrain.shoreline = true
}
} else {
if (ns.filter(t => t.type == TerrainType.Land).length > 0) {
terrain.shoreline = true
shorelineWaters.push({x, y})
}
}
}
}
return shorelineWaters
}
function processDistToLand(shorelineWaters: Coord[], map: Terrain[][]) {
const queue: [Coord, number][] = shorelineWaters.map(coord => [coord, 0]);
const visited = new Set<string>();
// Save the serialized data
const outputPath = path.join(__dirname, 'terrain_data.msgpack');
fs.writeFile(outputPath, compressedData);
console.log('Serialized terrain data saved to:', outputPath);
while (queue.length > 0) {
const [coord, distance] = queue.shift()!;
const key = `${coord.x},${coord.y}`;
return terrainMap
if (visited.has(key)) continue;
visited.add(key);
} catch (error) {
console.error('Error loading or processing the terrain map:', error);
throw error;
const terrain = map[coord.x][coord.y];
if (terrain.type === TerrainType.Water) {
terrain.magnitude = distance;
for (const [dx, dy] of [[-1, 0], [1, 0], [0, -1], [0, 1]]) {
const newX = coord.x + dx;
const newY = coord.y + dy;
if (newX >= 0 && newX < map.length && newY >= 0 && newY < map[0].length) {
queue.push([{x: newX, y: newY}, distance + 1]);
}
}
}
}
}
// Test the function
loadTerrainMap().then(terrainData => {
console.log('Terrain data loaded');
console.log('Terrain data extracted');
}).catch(console.error);
console.log('Processing terrain map...');
async function loadAndDecodeTerrainData(): Promise<TerrainMap> {
try {
// Construct the path to the MessagePack file
const filePath = path.join(__dirname, 'terrain_data.msgpack');
// Read the file
const data = await fs.readFile(filePath);
const inflated = await inflateRaw(data)
const decodedData = JSON.parse(inflated.toString('utf-8')) as TerrainMap
console.log('Terrain data loaded and decoded successfully');
console.log('Dimensions:', decodedData.width, 'x', decodedData.height);
console.log('Sample height at (0,0):', decodedData.terrain[0][0]);
return decodedData;
} catch (error) {
console.error('Error loading or decoding the terrain data:', error);
throw error;
function neighbors(x: number, y: number, map: Terrain[][]): Terrain[] {
const ns: Terrain[] = []
if (x > 0) {
ns.push(map[x - 1][y])
}
if (x < map.length - 1) {
ns.push(map[x + 1][y])
}
if (y > 0) {
ns.push(map[x][y - 1])
}
if (y < map[0].length - 1) {
ns.push(map[x][y + 1])
}
return ns
}
// Usage example
loadAndDecodeTerrainData()
.then(terrainData => {
// You can now use terrainData in your application
console.log('Terrain data ready for use');
})
.catch(console.error);
function packTerrain(map: Terrain[][]): Uint8Array {
const width = map.length;
const height = map[0].length;
const packedData = new Uint8Array(4 + width * height);
// Add width and height to the first 4 bytes
packedData[0] = width & 0xFF;
packedData[1] = (width >> 8) & 0xFF;
packedData[2] = height & 0xFF;
packedData[3] = (height >> 8) & 0xFF;
for (let x = 0; x < width; x++) {
for (let y = 0; y < height; y++) {
const terrain = map[x][y];
let packedByte = 0;
if (terrain.type === TerrainType.Land) {
packedByte |= 0b10000000;
}
if (terrain.shoreline) {
packedByte |= 0b01000000;
}
packedByte |= Math.min(terrain.magnitude, 63);
packedData[4 + y * width + x] = packedByte;
}
}
logBinaryAsBits(packedData)
return packedData;
}
function logBinaryAsBits(data: Uint8Array, length: number = 8) {
const bits = Array.from(data.slice(0, length))
.map(b => b.toString(2).padStart(8, '0'))
.join(' ');
console.log('Binary data (bits):', bits);
}
await loadTerrainMap()
Binary file not shown.
+4
View File
@@ -17,6 +17,10 @@ export default (env, argv) => {
},
module: {
rules: [
{
test: /\.bin$/,
use: 'raw-loader'
},
{
test: /\.ts$/,
use: 'ts-loader',