Initial commit

This commit is contained in:
2026-08-24 22:20:36 +02:00
commit 62f7b1278a
251 changed files with 16670 additions and 0 deletions
+34
View File
@@ -0,0 +1,34 @@
const AmmunitionChangeConfirmationPacket = require("../Packets/AmmunitionChangeConfirmation");
module.exports = function (ws, message, player) {
const type = message.getUint8(1);
const id = message.getUint8(2);
let selectedAmmunitionConfirmedID = 0;
let selectedAmmunitionTypeConfirmedID = 0;
switch (type) {
case 1:
selectedAmmunitionConfirmedID = player.inventory.setSelectedAmmunition(id);
selectedAmmunitionTypeConfirmedID = 1;
break;
case 2:
selectedAmmunitionConfirmedID = player.inventory.setSelectedHarpoon(id);
selectedAmmunitionTypeConfirmedID = 2;
break;
};
const ammunitionChangeConfirmation = {
typeID: selectedAmmunitionTypeConfirmedID,
id: selectedAmmunitionConfirmedID
};
console.info(ammunitionChangeConfirmation);
const ammunitionChangeConfirmationPacket = AmmunitionChangeConfirmationPacket(ammunitionChangeConfirmation);
player.map.registerIndividualNetworkPacket(player.id, ammunitionChangeConfirmationPacket);
const metadata = [player.hp.current / player.hp.maximum, player.isAttacking(), 0, player.inventory.selectedAmmunition];
return metadata;
};
+26
View File
@@ -0,0 +1,26 @@
const AttackAbortedPacket = require("../Packets/AttackAborted");
const constants = require("../Data/constants");
const { TYPES } = constants;
const { ENTITY_TYPE_NPC } = TYPES;
module.exports = function (ws, message, player) {
const targetIdentifier = player.abortAttack();
if (!targetIdentifier) return;
const packet = AttackAbortedPacket({
authorID: targetIdentifier.id,
authorTypeID: targetIdentifier.typeID,
targetID: player.id,
targetTypeID: player.typeID
});
player.map.registerIndividualNetworkPacket(player.id, packet);
if (targetIdentifier.typeID === ENTITY_TYPE_NPC) {
const target = player.map.getEntityFromSubgroup(targetIdentifier.id);
if (!target) return;
target.determineMovementState();
};
};
+18
View File
@@ -0,0 +1,18 @@
const constants = require("../Data/constants");
const { TYPES } = constants;
const { ENTITY_TYPE_MONSTER } = TYPES;
module.exports = function (ws, message, player) {
const typeID = message.getUint8(1);
const id = message.getUint32(2);
const wasAttacking = player.isAttacking();
const target = player.map.getEntityFromSubgroup(id);
if (target) {
if (typeID === ENTITY_TYPE_MONSTER) player.initializeAttackWithHarpooner(target);
else player.initializeAttackWithCannon(target);
};
return [player.inventory.selectedAmmunition, player.hp.current / player.hp.maximum, player.position.x, player.position.y, wasAttacking, 0 - 0];
};
+44
View File
@@ -0,0 +1,44 @@
const Reward = require("../Game/Reward");
const rewardCallback = require("../Callbacks/reward");
const MojoRemovedPacket = require("../Packets/MojoRemoved");
const MAXIMUM_BATCH_COUNT_MOJO = 1000;
const cauldronReward = new Reward({
distributionType: 2,
baseReward: {
3: {
5: { amountMinimum: 1500, chance: 16.5 },
6: { amountMinimum: 1500, chance: 16.5 },
7: { amountMinimum: 1500, chance: 16.5 },
8: { amountMinimum: 1500, chance: 16.5 },
9: { amountMinimum: 1500, chance: 16.5 }
},
7: {
10: { amountMinimum: 1, amountMaximum: 5, chance: 16.5 }
},
5: {
17: { amountMinimum: 1, chance: 20 }
}
}
});
module.exports = function (ws, message, player) {
let amount = message.getUint16(1);
if (!amount) return
if (amount > MAXIMUM_BATCH_COUNT_MOJO) amount = MAXIMUM_BATCH_COUNT_MOJO;
const usedAmount = player.inventory.alterAmount(1, 3, amount);
if (!usedAmount) return
const playerInventory = player.inventory.getPosessions();
cauldronReward.single(usedAmount, playerInventory, rewards => rewardCallback({ isRegular: false, authorID: player.id, rewards, source: {} }));
const packet = MojoRemovedPacket(usedAmount);
player.map.registerIndividualNetworkPacket(player.id, packet);
// global.test.accumulateItem(`${player.id}-1-3`, -amount);
};
+13
View File
@@ -0,0 +1,13 @@
const packet_255 = require("../Packets/packet_255");
module.exports = function (ws, message, player) {
if (player.isBeingAttacked()) return;
const shouldCancelDisconnect = player.isDisconnecting() && !player.hasUnexpectedlyLeft;
const packet = packet_255({ packetId: 12, isSuccessful: shouldCancelDisconnect });
player.map.registerIndividualNetworkPacket(player.id, packet);
if (shouldCancelDisconnect) return player.cancelDisconnect();
player.regularDisconnect();
};
+23
View File
@@ -0,0 +1,23 @@
const DesignChangedPacket = require("../Packets/DesignChanged");
const packet_255 = require("../Packets/packet_255");
module.exports = function (ws, message, player) {
const designID = message.getUint16(1);
const newDesignID = player.setDesign(designID);
if (!newDesignID) {
const packet = packet_255({ packetId: 40, isSuccessful: Boolean(newDesignID) })
return player.map.registerIndividualNetworkPacket(player.id, packet);
};
//setTimeout(() => {
const data = {
typeID: player.typeID,
id: player.id,
designID
};
const packet = DesignChangedPacket(data);
player.map.registerNetworkPacket(player.id, packet);
//}, 3000);
};
+75
View File
@@ -0,0 +1,75 @@
const PropertyChangedPacket = require("../Packets/PropertyChanged");
const EquipmentConfirmationPacket = require("../Packets/EquipmentConfirmation");
module.exports = function (ws, message, player) {
let packet = null;
if (player.isAttacking()) {
packet = EquipmentConfirmationPacket(false);
player.map.registerIndividualNetworkPacket(player.id, packet);
return;
};
const equimpentTypeID = message.getUint8(2);
const id = message.getUint8(3);
const equimpents = equimpentTypeID === 1 ? player.inventory.getCannons() : player.inventory.getHarpooners();
const equimpent = equimpents.find(e => e.id === id);
if (!equimpent) return
const playerID = player.id;
const currentRange = equimpentTypeID === 1 ? player.maximumCannonRange : player.maximumHarpoonerRange;
const typeID = equimpentTypeID === 1 ? 3 : 4;
const type = message.getUint8(1);
const quantity = message.getUint8(4);
let propertyChangedPacket = null;
let maximumRange = 0;
if (type) {
if (!equimpent.amountEquipped && equimpent.range > currentRange) {
propertyChangedPacket = PropertyChangedPacket({
playerID,
typeID,
value: equimpent.range
});
maximumRange = equimpent.range;
};
const isEquipmentAlterSuccessful = equimpent.equip(quantity);
packet = EquipmentConfirmationPacket(isEquipmentAlterSuccessful);
} else {
const isEquipmentAlterSuccessful = equimpent.unequip(quantity);
if (!equimpent.amountEquipped) {
for (let i = 0, length = equimpents.length; i < length; i++)
if (equimpents[i].range > maximumRange && equimpents[i].amountEquipped) maximumRange = equimpents[i].range;
if (currentRange > maximumRange)
propertyChangedPacket = PropertyChangedPacket({
playerID,
typeID,
value: maximumRange
});
};
packet = EquipmentConfirmationPacket(isEquipmentAlterSuccessful);
};
if (propertyChangedPacket) {
if (equimpentTypeID === 1) player.maximumCannonRange = maximumRange;
else player.maximumHarpoonerRange = maximumRange;
player.map.registerNetworkPacket(player.id, propertyChangedPacket);
};
player.map.registerIndividualNetworkPacket(player.id, packet);
const metadata = [player.hp.current / player.hp.maximum, equimpentTypeID, 0, quantity];
return metadata;
};
+79
View File
@@ -0,0 +1,79 @@
const GuildDataMemberPacket = require("../Packets/GuildDataMember");
const GuildMemberNewPacket = require("../Packets/GuildMemberNew");
const GuildLeaveConfirmationPacket = require("../Packets/GuildLeaveConfirmation");
const GuildDataCreationFeedbackPacket = require("../Packets/GuildDataCreationFeedback");
const Guild = require("../Game/Guild");
const Game = require("../Game/Game");
const { guilds } = Game;
const constants = require("../Data/constants");
module.exports = async function (ws, message, player) {
if (player.guild.id) return;
const memberAuthor = player.guild.getMember(player.id);
if (memberAuthor) return;
const guildTagLength = message.getUint8(1);
const guildNameLength = message.getUint8(1 + 1 + guildTagLength);
const guildDescriptionLength = message.getUint8(1 + 1 + 1 + guildTagLength + guildNameLength);
const guildTag = message.buffer.slice(2, 2 + guildTagLength);
const guildName = message.buffer.slice(2 + 1 + guildTagLength, 2 + 1 + guildTagLength + guildNameLength);
const guildDescription = message.buffer.slice(2 + 1 + 1 + guildTagLength + guildNameLength, 2 + 1 + 1 + guildNameLength + guildTagLength + guildDescriptionLength);
const guildTagBuffer = Buffer.from(guildTag);
const guildNameBuffer = Buffer.from(guildName);
const guildDescriptionBuffer = Buffer.from(guildDescription);
console.info(player.id, "???")
const guildCreateQuery = await execute("INSERT INTO guilds (tag, name, description, createdBy) VALUES (?, ?, ?, ?)", [guildTagBuffer, guildNameBuffer, guildDescriptionBuffer, player.id]);
if (!guildCreateQuery.data || guildCreateQuery.data.affectedRows !== 1) {
const guildDataCreationFeedback = {
reason: 1
};
const guildDataCreationFeedbackPacket = GuildDataCreationFeedbackPacket(guildDataCreationFeedback);
return player.map.registerIndividualNetworkPacket(player.id, guildDataCreationFeedbackPacket);
};
const guildID = guildCreateQuery.data.insertId;
console.info(guildCreateQuery, guildID, player.id)
const guild = guilds[guildID] = new Guild({
id: guildID,
name: guildNameBuffer,
tag: guildTagBuffer,
description: guildDescriptionBuffer,
ownerID: player.id,
experiencePoints: 0,
taxRates: [0, 0],
timestamps: {
taxRatesEditedAt: 0,
tagEditedAt: 0,
nameEditedAt: 0,
descriptionEditedAt: 0
}
});
player.guild = guild;
const member = {
id: player.id,
permission: 31
};
guild.addMember(member);
const guildStatePacket = GuildLeaveConfirmationPacket(true); // should rename everywhere
player.map.registerNetworkPacket(player.id, guildStatePacket);
const guildMemberNew = {
playerID: player.id,
tag: guild.tag
};
const guildMemberNewPacket = GuildMemberNewPacket(guildMemberNew);
player.map.registerNetworkPacket(player.id, guildMemberNewPacket);
};
+150
View File
@@ -0,0 +1,150 @@
const GuildDataGeneralPacket = require("../Packets/GuildDataGeneral");
const GuildDataMemberPacket = require("../Packets/GuildDataMember");
const GuildDataApplicantPacket = require("../Packets/GuildDataApplicant");
const GuildDataEconomyPacket = require("../Packets/GuildDataEconomy");
const GuildDataIslandPacket = require("../Packets/GuildDataIsland");
const GuildDataIslandTowerPacket = require("../Packets/GuildDataIslandTower");
const LEVELS = require("../Data/levels");
const queries = require("../Data/queries");
const { QUERY_FETCH_GUILD_OFFLINE_MEMBERS } = queries;
const Game = require("../Game/Game");
const { players, guildIslands } = Game;
module.exports = async function (ws, message, player) {
console.info(player.guild.id, player.guild.ownerID)
if (!player.guild.id) return console.info("nuh uh GuildDataMessage");
const applicantsOffline = [];
const playersOffline = [];
const packets = [];
console.info("GuildDataMessage", player.id);
player.guild.members.forEach(member => {
if (!players[member.id]) playersOffline.push(member.id);
else {
const onlinePlayer = players[member.id];
const guildDataMember = {
id: member.id,
permission: member.permission,
isOnline: true,
pirateLevel: onlinePlayer.pirateLevel,
name: onlinePlayer.name
};
const guildMemberPacket = GuildDataMemberPacket(guildDataMember);
packets.push(guildMemberPacket);
};
});
if (playersOffline.length) {
const offlinePlayersQuery = await execute(QUERY_FETCH_GUILD_OFFLINE_MEMBERS, playersOffline);
if (offlinePlayersQuery.data) {
offlinePlayersQuery.data.forEach(offlinePlayer => {
const guildDataMember = {
id: offlinePlayer.id,
isOnline: false,
pirateLevel: LEVELS.pirateLevel(offlinePlayer.amount),
name: offlinePlayer.username
};
const guildMemberPacket = GuildDataMemberPacket(guildDataMember);
packets.push(guildMemberPacket);
});
};
};
player.guild.requests.forEach(request => {
const applicantPlayer = players[request.playerID];
if (!applicantPlayer) applicantsOffline.push(request.playerID);
else {
const guildDataApplicant = {
id: request.playerID,
pirateLevel: applicantPlayer.pirateLevel,
username: applicantPlayer.name
};
const guildDataApplicantPacket = GuildDataApplicantPacket(guildDataApplicant);
packets.push(guildDataApplicantPacket);
};
});
if (applicantsOffline.length) {
const offlineApplicantsQuery = await execute(QUERY_FETCH_GUILD_OFFLINE_MEMBERS, applicantsOffline);
if (offlineApplicantsQuery.data) {
offlineApplicantsQuery.data.forEach(offlineApplicant => {
const guildDataApplicant = {
id: offlineApplicant.id,
pirateLevel: LEVELS.pirateLevel(offlineApplicant.amount),
username: offlineApplicant.username
};
const guildDataApplicantPacket = GuildDataApplicantPacket(guildDataApplicant);
packets.push(guildDataApplicantPacket);
});
};
};
const guildDataGeneral = {
level: player.guild.level,
experience: player.guild.experiencePoints,
size: {
current: player.guild.size,
maximum: player.guild.sizeMaximum
},
taxRates: player.guild.taxRates.map(r => r * 100),
tag: player.guild.tag,
name: player.guild.name,
description: player.guild.description,
timestamps: player.guild.timestamps
};
const guildDataGeneralPacket = GuildDataGeneralPacket(guildDataGeneral);
packets.push(guildDataGeneralPacket);
console.info(guildDataGeneral)
const guildDataEconomy = [];
player.guild.bank.list.each((_, value) => {
guildDataEconomy.push({
id: value.id,
amount: value.amount
});
});
console.info(guildDataEconomy, "guildDataEconomy")
const guildDataEconomyPacket = GuildDataEconomyPacket(guildDataEconomy);
packets.push(guildDataEconomyPacket);
guildIslands.forEach(island => {
if (player.guild.id !== island.guild.id) return;
const islandProperties = {
id: island.id,
mapID: island.locationMapID,
position: island.position,
};
const guildDataIslandPacket = GuildDataIslandPacket(islandProperties);
packets.push(guildDataIslandPacket);
island.towers.forEach(tower => {
const towerProperties = {
entityTypeID: tower.entityTypeID,
id: tower.id,
guildIslandID: island.id,
order: tower.order,
hp: {
current: tower.hp.current
},
isRepairing: tower.isRepairing()
};
const guildDataIslandTowerPacket = GuildDataIslandTowerPacket(towerProperties);
packets.push(guildDataIslandTowerPacket);
});
});
const guildTopic = Game.getTopic(player.guild.topic);
player.topics.addItem(player.guild.topic, guildTopic);
console.info("Sending out general data to", player.id);
player.map.registerIndividualNetworkPacket(player.id, packets);
};
+102
View File
@@ -0,0 +1,102 @@
const GuildDataIdentityModifiedPacket = require("../Packets/GuildDataIdentityModified");
const Game = require("../Game/Game");
const { players } = Game;
const constants = require("../Data/constants");
const { GUILD_COOLDOWNS } = constants;
const { GUILD_COOLDOWN_EDIT_TAG, GUILD_COOLDOWN_EDIT_NAME, GUILD_COOLDOWN_EDIT_DESCRIPTION } = GUILD_COOLDOWNS;
module.exports = async function (ws, message, player) {
if (!player.guild.id) return;
const memberAuthor = player.guild.getMember(player.id);
if (!memberAuthor) return;
const hasEditIdentitiyPermission = memberAuthor.permission & 8;
// if (!hasEditIdentitiyPermission) return;
const guildTagLength = message.getUint8(1);
const guildNameLength = message.getUint8(1 + 1 + guildTagLength);
const guildDescriptionLength = message.getUint8(1 + 1 + 1 + guildTagLength + guildNameLength);
const guildTag = message.buffer.slice(2, 2 + guildTagLength);
const guildName = message.buffer.slice(2 + 1 + guildTagLength, 2 + 1 + guildTagLength + guildNameLength);
const guildDescription = message.buffer.slice(2 + 1 + 1 + guildTagLength + guildNameLength, 2 + 1 + 1 + guildNameLength + guildTagLength + guildDescriptionLength);
const guildTagBuffer = Buffer.from(guildTag);
const guildNameBuffer = Buffer.from(guildName);
const guildDescriptionBuffer = Buffer.from(guildDescription);
const noww = new Date();
const now = noww.getTime();
const isCooldownOverTag = player.guild.timestamps.tagEditedAt * 1000 + GUILD_COOLDOWN_EDIT_TAG < now;
const isCooldownOverName = player.guild.timestamps.nameEditedAt * 1000 + GUILD_COOLDOWN_EDIT_NAME < now;
const isCooldownOverDescription = player.guild.timestamps.descriptionEditedAt * 1000 + GUILD_COOLDOWN_EDIT_DESCRIPTION < now;
console.info(guildTagLength, guildTagBuffer, player.guild.tag, isCooldownOverTag, isCooldownOverName, isCooldownOverDescription);
let queryField = [];
let queryArguments = [];
const r = [0, 0, 0];
if (guildTagLength
&& !guildTagBuffer.equals(player.guild.tag)
&& isCooldownOverTag) {
queryField.push("tag", "tagEditedAt");
queryArguments.push(guildTag, noww);
r[0] = 1;
player.guild.timestamps.tagEditedAt = now / 1000;
};
if (guildNameLength
&& !guildNameBuffer.equals(player.guild.name)
&& isCooldownOverName) {
queryField.push("name", "nameEditedAt");
queryArguments.push(guildName, noww);
r[1] = 1;
player.guild.timestamps.nameEditedAt = now / 1000;
};
if (guildDescriptionLength
&& !guildDescriptionBuffer.equals(player.guild.description)
&& isCooldownOverDescription) {
queryField.push("description", "descriptionEditedAt");
queryArguments.push(guildDescription, noww);
r[2] = 1;
player.guild.timestamps.descriptionEditedAt = now / 1000;
};
if (!queryArguments.length) return console.info("can't modify anything");
queryArguments.push(player.guild.id);
const queryBody = queryField.map(f => `${f} = ?`).join(", ");
const guildIdentityEditQuery = await execute(`UPDATE guilds SET ${queryBody} WHERE id = ?`, queryArguments);
if (!guildIdentityEditQuery.data) return;
if (guildIdentityEditQuery.data.changedRows === 1) {
player.guild.tag = guildTagBuffer;
player.guild.name = guildNameBuffer;
player.guild.description = guildDescriptionBuffer;
console.info(guildTagBuffer, guildNameBuffer, guildDescriptionBuffer);
const guildDataIdentityModified = {
r,
timestamps: {
tagEditedAt: (player.guild.timestamps.tagEditedAt + GUILD_COOLDOWN_EDIT_TAG / 1000),
nameEditedAt: (player.guild.timestamps.nameEditedAt + GUILD_COOLDOWN_EDIT_NAME / 1000),
descriptionEditedAt: (player.guild.timestamps.descriptionEditedAt + GUILD_COOLDOWN_EDIT_DESCRIPTION / 1000)
},
bufferTag: guildTagBuffer,
bufferName: guildNameBuffer,
bufferDescription: guildDescriptionBuffer
};
const topic = Game.getTopic(player.guild.topic);
const guildDataIdentityModifiedPacket = GuildDataIdentityModifiedPacket(guildDataIdentityModified);
topic.push(guildDataIdentityModifiedPacket);
};
};
+30
View File
@@ -0,0 +1,30 @@
const GuildDataTaxRatesModifiedPacket = require("../Packets/GuildDataTaxRatesModified");
const constants = require("../Data/constants");
const { MAXIMUM } = constants;
const { MAX_GUILD_TAX_RATE_GOLD, MAX_GUILD_TAX_RATE_EMERALD } = MAXIMUM;
const queries = require("../Data/queries");
const { QUERY_UPDATE_GUILD_TAX_RATES } = queries;
const Game = require("../Game/Game");
module.exports = async function (ws, message, player) {
if (!player.guild.id) return;
const taxRateGold = message.getUint8(1);
if (taxRateGold > MAX_GUILD_TAX_RATE_GOLD) return;
const taxRateEmerald = message.getUint8(2);
if (taxRateEmerald > MAX_GUILD_TAX_RATE_EMERALD) return;
const guildDataTaxRatesModified = [taxRateGold, taxRateEmerald];
const taxRatesUpdateQuery = await execute(QUERY_UPDATE_GUILD_TAX_RATES, [taxRateGold, taxRateEmerald, player.guild.id]);
if (!taxRatesUpdateQuery.data || taxRatesUpdateQuery.data.affectedRows !== 1) [guildDataTaxRatesModified[0], guildDataTaxRatesModified[1]] = [255, 255];
else player.guild.taxRates = guildDataTaxRatesModified.map(t => t / 100);
const topic = Game.getTopic(player.guild.topic);
const guildDataTaxRatesModifiedPacket = GuildDataTaxRatesModifiedPacket(guildDataTaxRatesModified);
topic.push(guildDataTaxRatesModifiedPacket);
};
+58
View File
@@ -0,0 +1,58 @@
const GuildDataEconomyDonatedPacket = require("../Packets/GuildDataEconomyDonated");
const Game = require("../Game/Game");
module.exports = async function (ws, message, player) {
if (!player.guild.id) return;
if (player.pirateLevel < 10) return console.info("pirate level donate");
const categoryID = 1;
const resourceID = message.getUint8(1);
const amount = message.getUint32(2);
const playerEconomy = player.inventory.getEconomy();
const economyResource = playerEconomy.find(r => r.id === resourceID);
if (economyResource.amount < amount) return console.info("not enough resource", economyResource);
const guildEconomy = player.guild.bank.list.getElement(resourceID);
if (!guildEconomy) return;
let dbConnection = null;
try {
dbConnection = await db.getConnection();
await dbConnection.beginTransaction();
await dbConnection.execute("INSERT INTO resources (playerID, categoryID, itemID, amount) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE amount = ?", [player.id, categoryID, resourceID, economyResource.amount - amount, economyResource.amount - amount]);
await dbConnection.execute("INSERT INTO guildresources (guildID, categoryID, itemID, amount) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE amount = ?", [player.guild.id, categoryID, resourceID, guildEconomy.amount + amount, guildEconomy.amount + amount]);
await dbConnection.commit();
const amountCapped = player.inventory.alterAmount(categoryID, resourceID, amount);
const resource = {
categoryID,
id: resourceID,
amount: amountCapped
};
player.guild.bank.depositTax(resource);
console.info("success desposit", resource);
const topic = Game.getTopic(player.guild.topic);
const guildDataEconomyDonatedPacket = GuildDataEconomyDonatedPacket(resource);
topic.push(guildDataEconomyDonatedPacket);
} catch (e) {
console.info(e)
await dbConnection.rollback();
const resource = {
categoryID,
id: resourceID,
amount: 0
};
const guildDataEconomyDonatedPacket = GuildDataEconomyDonatedPacket(resource);
player.map.registerIndividualNetworkPacket(player.id, guildDataEconomyDonatedPacket);
} finally {
dbConnection.release();
};
};
+69
View File
@@ -0,0 +1,69 @@
const DesignChangedPacket = require("../Packets/DesignChanged");
const PropertyChangedGeneralPacket = require("../Packets/PropertyChangedGeneral");
const HealthChangedAuthorlessPacket = require("../Packets/HealthChangedAuthorless");
const Game = require("../Game/Game");
const { players, guildIslands, packets } = Game;
module.exports = async function (ws, message, player) {
if (!player.guild.id) return;
const guildIslandID = message.getUint8(1);
const guildIsland = guildIslands.find(island => island.id === guildIslandID);
if (!guildIsland) return console.info("guildIslandTowerBuildMessage 1");
const id = message.getUint32(2);
const guildTower = guildIsland.getTower(id);
if (!guildTower) return console.info("guildIslandTowerBuildMessage 2");
const entityTypeID = message.getUint8(6);
const currentHitpointBefore = guildTower.hp.current;
const isUpgradeSuccessful = guildTower.upgrade(entityTypeID);
if (!isUpgradeSuccessful) return console.info("not successful build for tower", guildTower.id, "on guild island", guildIslandID);
console.info("Tower upgrade", guildTower.id, guildIslandID);
const designChanged = {
typeID: guildTower.typeID,
id: guildTower.id,
designID: guildTower.entityTypeID
};
const designChangedPacket = DesignChangedPacket(designChanged);
guildTower.map.registerNetworkPacket(guildTower.id, designChangedPacket);
const propertyChangedGeneral = {
typeID: guildTower.typeID,
id: guildTower.id,
propertyTypeID: 1,
value: guildTower.hp.maximum
};
const propertyChangedGeneral2 = {
typeID: guildTower.typeID,
id: guildTower.id,
propertyTypeID: 2,
value: 0
};
const propertyChangedGeneralPacket = PropertyChangedGeneralPacket(propertyChangedGeneral);
const propertyChangedGeneralPacket2 = PropertyChangedGeneralPacket(propertyChangedGeneral2);
const packets = [propertyChangedGeneralPacket, propertyChangedGeneralPacket2];
const hitpointToAdd = guildTower.hp.maximum - currentHitpointBefore;
if (hitpointToAdd) {
const healthChangedAuthorless = {
targetTypeID: guildTower.typeID,
targetID: guildTower.id,
amount: hitpointToAdd,
type: 1,
isCritical: false
};
const healthChangedAuthorlessPacket = HealthChangedAuthorlessPacket(healthChangedAuthorless);
packets.push(healthChangedAuthorlessPacket);
};
guildTower.map.registerNetworkPacket(guildTower.id, packets);
};
+18
View File
@@ -0,0 +1,18 @@
const Game = require("../Game/Game");
const { players, guildIslands } = Game;
module.exports = async function (ws, message, player) {
if (!player.guild.id) return;
const guildIslandID = message.getUint8(1);
const guildIsland = guildIslands.find(island => island.id === guildIslandID);
if (!guildIsland) return console.info("asd");
const id = message.getUint32(2);
const tower = guildIsland.getTower(id);
if (!tower) return console.info("asd2");
tower.initializeRepair();
console.info("Tower", tower.id, "is being repaired on guild island", guildIslandID);
};
+40
View File
@@ -0,0 +1,40 @@
const GuildSearchResultStateChanged = require("../Packets/GuildSearchResultStateChanged");
const GuildDataApplicantRemove = require("../Packets/GuildDataApplicantRemove");
const Game = require("../Game/Game");
const { players, guilds } = Game;
const QUERY_GUILD_REQUEST_REVOKE = "DELETE FROM guildrequests WHERE guildID = ? AND playerID = ?";
module.exports = async function (ws, message, player) {
const guildID = message.getUint16(1);
const guild = guildID ? guilds[guildID] : player.guild;
if (!guild || !guild.id) return;
if (guild.id === player.guild.id) return;
const playerID = message.getUint32(3);
const targetPlayer = playerID ? players[playerID] : player;
const guildJoinRequestRevokeQuery = await execute(QUERY_GUILD_REQUEST_REVOKE, [guild.id, targetPlayer.id]);
if (!guildJoinRequestRevokeQuery.data) return console.info("shit");
guild.removeRequest(targetPlayer.id);
const guildSearchResultStateChanged = {
id: guild.id,
hasApplied: false
};
const guildSearchResultStateChangedPacket = GuildSearchResultStateChanged(guildSearchResultStateChanged);
targetPlayer.map.registerIndividualNetworkPacket(targetPlayer.id, guildSearchResultStateChangedPacket);
const guildDataApplicantRemove = {
id: targetPlayer.id
};
const guildDataApplicantRemovePacket = GuildDataApplicantRemove(guildDataApplicantRemove);
const topic = Game.getTopic(guild.topic);
topic.push(guildDataApplicantRemovePacket);
};
+55
View File
@@ -0,0 +1,55 @@
const GuildSearchResultStateChangedPacket = require("../Packets/GuildSearchResultStateChanged");
const GuildDataApplicantPacket = require("../Packets/GuildDataApplicant");
const Game = require("../Game/Game");
const { guilds } = Game;
const MAXIMUM_GUILD_REQUEST_MESSAGE_LENGTH = 256;
const QUERY_GUILD_REQUEST_SUBMIT = "INSERT INTO guildrequests (guildID, playerID, message) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE message = ?";
const QUERY_GUILD_REQUEST_SUBMIT_DEFAULT = "INSERT INTO guildrequests (guildID, playerID) VALUES (?, ?) ON DUPLICATE KEY UPDATE message = ?";
module.exports = async function (ws, message, player) {
if (player.guild.id) return;
const guildID = message.getUint16(1);
const guild = guilds[guildID];
if (!guild) return;
// if (guild.hasRequested()) return
const requestMessageLength = message.getUint8(3);
if (requestMessageLength > MAXIMUM_GUILD_REQUEST_MESSAGE_LENGTH) return;
const requestMessage = requestMessageLength > 0 ? message.buffer.slice(4, 4 + requestMessageLength) : "test";
console.info(requestMessage, guildID, "GuildJoinRequestSubmitMessage");
const isRequestSuccessful = guild.addRequest(player.id, requestMessage);
if (!isRequestSuccessful) return console.info("shiitt");
const query = requestMessageLength > 0 ? QUERY_GUILD_REQUEST_SUBMIT : QUERY_GUILD_REQUEST_SUBMIT_DEFAULT;
const queryParameters = requestMessageLength > 0 ? [guildID, player.id, requestMessage, requestMessage] : [guildID, player.id, requestMessage];
const guildJoinRequestSubmitQuery = await execute(query, queryParameters);
console.info(guildJoinRequestSubmitQuery)
if (!guildJoinRequestSubmitQuery.data) return console.info("shit");
const guildSearchResultStateChanged = {
id: guildID,
hasApplied: true
};
const guildSearchResultStateChangedPacket = GuildSearchResultStateChangedPacket(guildSearchResultStateChanged);
player.map.registerIndividualNetworkPacket(player.id, guildSearchResultStateChangedPacket);
const guildDataApplicant = {
id: player.id,
pirateLevel: player.pirateLevel,
username: player.name
};
const guildDataApplicantPacket = GuildDataApplicantPacket(guildDataApplicant);
const topic = Game.getTopic(guild.topic);
topic.push(guildDataApplicantPacket);
};
+91
View File
@@ -0,0 +1,91 @@
const GuildMemberNewPacket = require("../Packets/GuildMemberNew");
const GuildDataMemberPacket = require("../Packets/GuildDataMember");
const GuildLeaveConfirmationPacket = require("../Packets/GuildLeaveConfirmation");
const GuildDataApplicantRemovePacket = require("../Packets/GuildDataApplicantRemove");
const LEVELS = require("../Data/levels");
const queries = require("../Data/queries");
const { QUERY_FETCH_GUILD_OFFLINE_MEMBERS } = queries;
const Game = require("../Game/Game");
const { players } = Game;
module.exports = async function (ws, message, player) {
if (!player.guild.id) return
const playerID = message.getUint32(1);
const guild = player.guild;
const isRequested = guild.hasRequested(playerID);
if (!isRequested) return
const acceptedMember = {
id: playerID
};
const isAcceptSuccessful = guild.addMember(acceptedMember);
if (!isAcceptSuccessful) return;
const topic = Game.getTopic(guild.topic);
const onlinePlayer = players[playerID];
if (onlinePlayer) {
onlinePlayer.guild = guild;
const guildMemberNew = {
playerID: onlinePlayer.id,
tag: player.guild.tag
};
const guildMemberStateConfirmation = GuildLeaveConfirmationPacket(true);
onlinePlayer.map.registerIndividualNetworkPacket(playerID, guildMemberStateConfirmation);
const packet = GuildMemberNewPacket(guildMemberNew);
onlinePlayer.map.registerNetworkPacket(onlinePlayer.id, packet);
const guildDataMember = {
id: onlinePlayer.id,
permission: 0,
isOnline: true,
pirateLevel: onlinePlayer.pirateLevel,
name: onlinePlayer.name
};
const guildMemberPacket = GuildDataMemberPacket(guildDataMember);
topic.push(guildMemberPacket);
const guildDataApplicantRemove = {
id: playerID
};
const guildDataApplicantRemovePacket = GuildDataApplicantRemovePacket(guildDataApplicantRemove);
topic.push(guildDataApplicantRemovePacket);
} else {
const offlinePlayerQuery = await execute(QUERY_FETCH_GUILD_OFFLINE_MEMBERS, [playerID]);
if (!offlinePlayerQuery.data) return;
const { username, amount } = offlinePlayerQuery.data[0];
const guildDataMember = {
id: playerID,
permission: 0,
isOnline: false,
pirateLevel: LEVELS.pirateLevel(amount),
name: username
};
const guildMemberPacket = GuildDataMemberPacket(guildDataMember);
topic.push(guildMemberPacket);
const guildDataApplicantRemove = {
id: playerID
};
const guildDataApplicantRemovePacket = GuildDataApplicantRemovePacket(guildDataApplicantRemove);
topic.push(guildDataApplicantRemovePacket);
};
await execute("INSERT INTO guildmembers (playerID, guildID) VALUES (?, ?)", [playerID, guild.id]);
await execute("DELETE FROM guildrequests WHERE playerID = ?", [playerID]);
};
+57
View File
@@ -0,0 +1,57 @@
const GuildMemberOldPacket = require("../Packets/GuildMemberOld");
const GuildLeaveConfirmationPacket = require("../Packets/GuildLeaveConfirmation");
const GuildDataMemberRemovedPacket = require("../Packets/GuildDataMemberRemoved");
const queries = require("../Data/queries");
const { QUERY_DELETE_GUILD_MEMBER } = queries;
const constants = require("../Data/constants");
const { GUILD_PERMISSIONS } = constants;
const { GUILD_PERMISSION_KICK } = GUILD_PERMISSIONS;
const Game = require("../Game/Game");
const { players, guilds } = Game;
module.exports = async function (ws, message, player) {
const playerID = message.getUint32(1);
const targetKickPlayer = players[playerID];
const guild = targetKickPlayer ? targetKickPlayer.guild : player.guild;
const targetMember = guild.getMember(playerID);
if (!targetMember) return;
const authorMember = guild.getMember(player.id);
if (!authorMember) return;
const permissionKick = authorMember.permission & GUILD_PERMISSION_KICK;
if (playerID !== player.id && !permissionKick) return;
if (playerID === player.id && guild.isLeader(playerID)) return;
const kickResultQuery = await execute(QUERY_DELETE_GUILD_MEMBER, [playerID, 0]);
if (!kickResultQuery.data || kickResultQuery.data.affectedRows !== 1) return;
guild.removeMember(playerID);
const guildDataMemberRemoved = {
id: playerID
};
const guildDataMemberRemovedPacket = GuildDataMemberRemovedPacket(guildDataMemberRemoved);
// player.map.registerIndividualNetworkPacket(player.id, guildDataMemberRemovedPacket);
const topic = Game.getTopic(guild.topic);
topic.push(guildDataMemberRemovedPacket);
if (!targetKickPlayer) return;
targetKickPlayer.topics.removeItem(targetKickPlayer.guild.topic);
console.info("removed guild topic from player", targetKickPlayer.guild.topic);
targetKickPlayer.guild = guilds[0];
const guildLeaveConfirmation = GuildLeaveConfirmationPacket(false);
targetKickPlayer.map.registerIndividualNetworkPacket(playerID, guildLeaveConfirmation);
const guildMemberOld = { playerID };
const guildMemberOldPacket = GuildMemberOldPacket(guildMemberOld);
targetKickPlayer.map.registerNetworkPacket(playerID, guildMemberOldPacket);
};
+70
View File
@@ -0,0 +1,70 @@
const GuildSearchResultPacket = require("../Packets/GuildSearchResult");
const queries = require("../Data/queries");
const { QUERY_DELETE_GUILD_MEMBER } = queries;
const constants = require("../Data/constants");
const { GUILD_PERMISSIONS } = constants;
const { GUILD_PERMISSION_KICK } = GUILD_PERMISSIONS;
const Game = require("../Game/Game");
const { players, guilds } = Game;
const dec = new TextDecoder();
module.exports = async function (ws, message, player) {
const guildTagLength = message.getUint8(1);
const guildNameLength = message.getUint8(1 + guildTagLength + 1);
if (!guildTagLength && !guildNameLength) return;
const guildTagView = new DataView(message.buffer, 2, guildTagLength);
const guildTag = dec.decode(guildTagView);
const guildNameView = new DataView(message.buffer, 2 + guildTagLength + 1, guildNameLength);
const guildName = dec.decode(guildNameView);
const guildSearchResult = await execute("SELECT guilds.id, guilds.tag, guilds.name, d.size AS size, CASE WHEN guildrequests.playerID IS NULL THEN 0 ELSE 1 END AS hasApplied FROM guilds LEFT JOIN guildrequests ON guilds.id = guildrequests.guildID AND guildrequests.playerID = ? JOIN (SELECT guildID, COUNT(*) AS size FROM guildmembers GROUP BY guildID) AS d ON guilds.id = d.guildID WHERE guilds.tag = ? OR guilds.name LIKE ?", [player.id, guildTag, + `%${guildName}%`]);
if (!guildSearchResult.data) return;
const packets = [];
const length = guildSearchResult.data.length;
if (!length) {
const guildSearchResult = {
id: 0,
tag: "",
name: "",
size: {
current: 0,
maximum: 0
},
hasApplied: false,
isLastEntry: true
};
const guildSearchResultPacket = GuildSearchResultPacket(guildSearchResult);
packets.push(guildSearchResultPacket);
} else {
guildSearchResult.data.forEach((g, i) => {
const guild = guilds[g.id];
const sizeMaximum = guild ? guild.sizeMaximum : 0;
const guildSearchResult = {
id: g.id,
tag: g.tag,
name: g.name,
size: {
current: g.size,
maximum: sizeMaximum
},
hasApplied: g.hasApplied,
isLastEntry: i === length - 1
};
const guildSearchResultPacket = GuildSearchResultPacket(guildSearchResult);
packets.push(guildSearchResultPacket);
});
};
player.map.registerIndividualNetworkPacket(player.id, packets);
};
+75
View File
@@ -0,0 +1,75 @@
const ItemBoughtPacket = require("../Packets/ItemBought");
const packet_57 = require("../Packets/packet_57");
const BASE_SHOP = require("../Data/shop");
const { SHOP, SHOP_ENTRIES_BUY } = BASE_SHOP;
module.exports = async function (ws, message, player) {
const categoryID = message.getUint8(1);
const itemID = message.getUint8(2);
const rawAmount = message.getUint32(3);
let bought = {
categoryID,
id: itemID,
amount: 0
};
const itemToBuy = SHOP.find(entry => entry.categoryID === categoryID && entry.itemID === itemID);
console.info(categoryID, itemID, SHOP)
if (!itemToBuy) {
const boughtItemConfirmationPacket = ItemBoughtPacket(bought);
return player.map.registerIndividualNetworkPacket(player.id, boughtItemConfirmationPacket);
};
const isItemAvailable = itemToBuy.isAvailable(player);
if (!isItemAvailable) return;
if (SHOP_ENTRIES_BUY[player.id] && SHOP_ENTRIES_BUY[player.id]?.[categoryID]?.[itemID] >= itemToBuy.maximumPlayerAmount) {
bought = {
categoryID,
id: itemID,
amount: 0
};
const boughtItemConfirmationPacket = ItemBoughtPacket(bought);
return player.map.registerIndividualNetworkPacket(player.id, boughtItemConfirmationPacket);
};
const amount = rawAmount; // Math.min(rawAmount, (itemToBuy.maximumPlayerAmount || Infinity) - alreadyBoughtAmount)
bought.amount = amount;
player.rewardCallback({
isRegular: true,
authorID: player.id,
source: {},
rewards: [{
categoryID,
id: itemID,
amount
}]
});
player.inventory.refreshSingle({
categoryID: 1,
id: itemToBuy.currencyType,
amount: itemToBuy.currencyAmount * amount * -1
});
const packets = [];
const boughtItemConfirmationPacket = ItemBoughtPacket(bought);
packets.push(boughtItemConfirmationPacket);
console.info("bought", bought);
if (false && alreadyBoughtAmount + amount >= itemToBuy.maximumPlayerAmount) {
const removeShopEntryPacket = packet_57({
id: itemID,
shopCategoryID: itemToBuy.shopCategoryID
});
packets.push(removeShopEntryPacket);
};
player.map.registerIndividualNetworkPacket(player.id, packets);
};
+113
View File
@@ -0,0 +1,113 @@
const AttackerInformationPacket = require("../Packets/AttackerInformation");
const HealthChangedPacket = require("../Packets/HealthChanged");
const ItemUsedPacket = require("../Packets/ItemUsed");
const itemTable = require("../Data/items");
const constants = require("../Data/constants");
const { CATEGORIES, AFFECTS, TYPES } = constants;
const { CATEGORY_ITEM } = CATEGORIES;
const { AFFECT_HITPOINT, AFFECT_SAILING_SPEED } = AFFECTS;
const { ENTITY_TYPE_PLAYER } = TYPES;
module.exports = function (ws, message, player) {
const itemID = message.getUint8(6);
const itemScheme = itemTable[itemID];
if (!itemScheme) return;
if (!player.isAlive) return;
const targetTypeID = message.getUint8(1);
const targetID = message.getUint32(2);
if (targetTypeID === player.typeID && targetID === player.id) return; // ???
const inventoryItem = player.inventory.getItem(itemID);
const resolution = {
statusID: itemScheme.statusID,
itemID,
amountToRemove: 0,
isActive: !inventoryItem.isActive
};
if (itemScheme.statusID && itemScheme.isDurable) {
const index = player.activeStatusEffects.findIndex(id => id === itemScheme.statusID);
if (index === -1) player.activeStatusEffects.push(itemScheme.statusID);
else player.activeStatusEffects.splice(index, 1);
};
const metadata = [player.hp.current / player.hp.maximum, player.isAttacking(), itemID, inventoryItem.isActive ? 0 : 1];
if (inventoryItem.isActive) {
const packet = ItemUsedPacket(resolution);
player.map.registerIndividualNetworkPacket(player.id, packet);
player.inventory.disable(itemID);
return metadata;
};
const aliveTarget = itemScheme.isSelf ? player : player.map.getAliveEntityFromSubgroup(targetTypeID, targetID);
const amount = 1;
if (!itemScheme.isSelf && !aliveTarget) return;
const targetMapMode = itemScheme.isSelf ? player.map.type : aliveTarget.map.type;
if (itemScheme.allowedTargetTypes && !itemScheme.allowedTargetTypes[targetMapMode].includes(targetTypeID)) return;
if (inventoryItem.nextUseAt > performance.now()) return;
const isInRange = !itemScheme.isSelf && Math.pow(aliveTarget.position.x - player.position.x, 2) + Math.pow(aliveTarget.position.y - player.position.y, 2) < Math.pow(itemScheme.range, 2);
if (itemScheme.range && !isInRange) return;
if (inventoryItem.affects.includes(AFFECT_HITPOINT) && itemScheme.scale > 0 && aliveTarget.hp.maximum === aliveTarget.hp.current) return;
const item = inventoryItem.activate(amount);
if (!item) return;
resolution.amountToRemove = item.removedAmount;
const packet = ItemUsedPacket(resolution);
player.map.registerIndividualNetworkPacket(player.id, packet);
if (!itemScheme.isSelf) {
const attackInitialized = {
authorID: player.id,
authorTypeID: player.typeID
};
const attackInitializedPacket = AttackerInformationPacket(attackInitialized);
player.map.registerIndividualNetworkPacket(aliveTarget.id, attackInitializedPacket);
};
item.affects.forEach(affects => {
switch (affects) {
case AFFECT_HITPOINT:
const healthUpdate = item.scale > 0 ?
aliveTarget.increaseCurrentHitpoint(item.scale) :
aliveTarget.decreaseCurrentHitpoint(item.scale, { authorSessionID: player.sessionID, authorGuildID: player.guild.id, authorID: player.id, authorTypeID: player.typeID });
if (aliveTarget.typeID === ENTITY_TYPE_PLAYER && aliveTarget.isAtMaximumHitpoints()) aliveTarget.cancelRepair();
const data = {
authorTypeID: player.typeID,
authorID: player.id,
targetTypeID: aliveTarget.typeID,
targetID: aliveTarget.id,
amount: healthUpdate.normalizedAmount,
isCritical: false,
type: item.scale > 0
};
const packet = HealthChangedPacket(data);
player.map.registerNetworkPacket(player.id, packet);
break;
case AFFECT_SAILING_SPEED:
aliveTarget.changeSpeed(item.scale);
aliveTarget.setReusableSingleEvent(itemScheme.iid, item.time, -item.scale);
break;
};
});
return metadata;
};
+25
View File
@@ -0,0 +1,25 @@
const LeaderboardPositionsPacket = require("../Packets/LeaderboardPositions");
const leaderboards = require("../Data/leaderboard");
module.exports = async function (ws, message, player) {
const leaderboardPositionsData = leaderboards.map(async (leaderboard, i) => {
const leaderboardPositionFromDB = await execute(`SELECT 1 + COUNT(*) AS position FROM leaderboard_${i + 1} WHERE amount > COALESCE((SELECT amount FROM leaderboard_${i + 1} WHERE id = ?), 0)`, [player.id]);
if (!leaderboardPositionFromDB.data)
return {
selfPosition: 0,
totalPositionsLength: leaderboard.size
};
const selfPosition = leaderboardPositionFromDB.data[0].position;
return {
selfPosition: selfPosition > leaderboard.size ? 0 : selfPosition,
totalPositionsLength: leaderboard.size
};
});
const leaderboardPositions = await Promise.all(leaderboardPositionsData);
const leaderboardPositionsPacket = LeaderboardPositionsPacket(leaderboardPositions);
player.map.registerIndividualNetworkPacket(player.id, leaderboardPositionsPacket);
};
+42
View File
@@ -0,0 +1,42 @@
const LeaderboardPagePacket = require("../Packets/LeaderboardPage");
const leaderboards = require("../Data/leaderboard");
module.exports = async function (ws, message, player) {
const leaderboardID = message.getUint8(1);
const leaderboard = leaderboards[leaderboardID];
if (!leaderboard) return console.time("leaderboard 1");
const page = message.getUint16(2);
if (!leaderboard.size) {
const leaderboardCountFromDB = await execute(`SELECT COUNT(*) AS count FROM leaderboard_${leaderboardID + 1}`);
if (!leaderboardCountFromDB.data) return console.info("leaderboard 2");
leaderboard.size = leaderboardCountFromDB.data[0].count;
};
const lastPage = Math.ceil(leaderboard.size / 10);
if (page <= 0 || page > lastPage) return;
let entries = null;
const startingFrom = (page - 1) * 10;
const cachedEntries = leaderboard.cache[page];
if (cachedEntries) entries = cachedEntries;
else {
const leaderboardFromDB = await query(`SELECT accounts.id, accounts.username, leaderboard_${leaderboardID + 1}.amount FROM leaderboard_${leaderboardID + 1} INNER JOIN accounts ON accounts.id = leaderboard_${leaderboardID + 1}.id ORDER BY amount DESC LIMIT ?, 10`, [startingFrom])
if (!leaderboardFromDB.data) return console.info("leaderboard 3");
entries = leaderboardFromDB.data
leaderboard.cache[page] = entries;
};
const leaderboardPacket = LeaderboardPagePacket.init(leaderboardID, entries.length);
entries.forEach(e => leaderboardPacket.update({
username: e.username,
amount: e.amount
}));
player.map.registerIndividualNetworkPacket(player.id, leaderboardPacket.get());
};
+3
View File
@@ -0,0 +1,3 @@
module.exports = function (ws, message, player) {
player.setSingleEvent(15, 0);
};
+44
View File
@@ -0,0 +1,44 @@
const PlayerWorker = global.PlayerWorker;
module.exports = function (ws, message, player) {
if (!player.isAlive) return;
const worldX = message.getUint16(1);
const worldY = message.getUint16(3);
const destination = player.map.grid.getCell(worldX, worldY);
if (!player.map.grid.isValidNode(destination)) return
const { xw, xh } = player.previousDestination;
if (destination.xw === xw && destination.xh === xh) return;
const position = player.isMoving ? { x: player.nextNode[0], y: player.nextNode[1] } : player.position;
const { x, y } = position;
const currentPosition = player.map.grid.getCell(x, y);
if (currentPosition.xw === destination.xw && currentPosition.xh === destination.xh) return;
player.previousDestination = destination;
if (player.isMoving) {
player.intermediateMovementWasStarted = true;
player.isNewPathReady = false;
player.isLastNodeFinished = false;
player.scheduledPath = [];
};
player.cancelDisconnect();
if (!player.movementRequestTracker) player.movementRequestTracker = 1;
else player.movementRequestTracker++;
PlayerWorker.postMessage({
destination,
position,
id: player.id,
mapId: player.map.id,
wasMoving: player.isMoving,
movementRequestTracker: player.movementRequestTracker
});
return [x, y, worldX, worldY, player.hp.current / player.hp.maximum, player.attackers.length, player.isAttacking()];
};
+42
View File
@@ -0,0 +1,42 @@
const QuestRemovalPacket = require("../Packets/QuestRemoval");
const QuestAddedPacket = require("../Packets/QuestAdded");
const quests = require("../Data/quests");
module.exports = async function (ws, message, player) {
const questID = message.getUint16(1);
const questScheme = quests[questID - 1];
if (!questScheme) return;
const isLevelInRange = questScheme.minimumLevel <= player.pirateLevel && questScheme.maximumLevel >= player.pirateLevel;
// if (!isLevelInRange) return console.info("in range");
if (player.quests.has(questID)) {
const questDisableQuery = await execute("INSERT INTO quests (playerID, questID) VALUES (?, ?) ON DUPLICATE KEY UPDATE state = ?", [player.id, questID, 1]);
if (!questDisableQuery.data) return;
const questRemoval = {
questID,
isSuccessful: false
};
const questRemovalPacket = QuestRemovalPacket(questRemoval);
player.map.registerIndividualNetworkPacket(player.id, questRemovalPacket);
console.info("quest removed")
return player.quests.remove(questID);
};
const quest = player.quests.add(questID);
if (!quest) return;
const questEnableQuery = await execute("INSERT INTO quests (playerID, questID) VALUES (?, ?) ON DUPLICATE KEY UPDATE state = ?", [player.id, questID, 0]);
if (!questEnableQuery.data) return;
const questAdded = {
questID
};
const questAddedPacket = QuestAddedPacket(questAdded);
player.map.registerIndividualNetworkPacket(player.id, questAddedPacket);
console.info("quest added", questAdded);
};
+242
View File
@@ -0,0 +1,242 @@
const MainPlayerPacket = require("../Packets/MainPlayer");
const ObtainedDesignsPacket = require("../Packets/ObtainedDesigns");
const PropertyChangedPacket = require("../Packets/PropertyChanged");
const AttackInformationPacket = require("../Packets/AttackInformation");
const AttackerInformationPacket = require("../Packets/AttackerInformation");
const QuestsPacket = require("../Packets/Quests");
const QuestsCompletedAmountPacket = require("../Packets/QuestsCompletedAmount");
const CannonballsPacket = require("../Packets/Cannonballs");
const HarpoonsPacket = require("../Packets/Harpoons");
const ItemsPacket = require("../Packets/Items");
const EquipmentCapacitiesMaximumPacket = require("../Packets/EquipmentCapacitiesMaximum");
const StatusPointsPacket = require("../Packets/StatusPoints");
const EconomyPacket = require("../Packets/Economy");
const ActiveStatusEffectsPacket = require("../Packets/ActiveStatusEffects");
const EquipmentsPacket = require("../Packets/Equipments");
const GuildMemberNewPacket = require("../Packets/GuildMemberNew");
const WorldMapGuildEntryPacket = require("../Packets/WorldMapGuildEntry");
const RankThresholdPointsPacket = require("../Packets/RankThresholdPoints");
const RankPointPacket = require("../Packets/RankPoint");
const GuildDataMemberChangedPacket = require("../Packets/GuildDataMemberChanged");
const ShopEntryPacket = require("../Packets/ShopEntry");
const Entity = require("../Game/Entity");
const Game = require("../Game/Game");
const { guildIslands } = Game;
const packet_58 = require("../Packets/packet_58");
const packet_57 = require("../Packets/packet_57");
const BASE_SHOP = require("../Data/shop");
const { SHOP, SHOP_ENTRIES_BUY } = BASE_SHOP;
const leaderboards = require("../Data/leaderboard");
module.exports = async function (ws, message, player) {
if (player.isAvailable) return;
player.hasUnexpectedlyLeft = false;
const connectingPlayer = player.getProperties();
const connectingPlayerPacket = MainPlayerPacket(connectingPlayer);
player.map.registerIndividualNetworkPacket(player.id, connectingPlayerPacket);
const designIDs = player.inventory.getDesignIDs();
const designsPacket = ObtainedDesignsPacket(designIDs);
const questPacketInitialized = QuestsPacket.init();
Object.values(player.quests.list).forEach(quest => {
const questPacket = {
id: quest.id,
progression: quest.getProgression(),
currentComplete: quest.currentComplete
};
questPacketInitialized.update(questPacket);
});
const sightPacket = PropertyChangedPacket({
typeID: 1,
value: player.sight / 12
});
const questsCompletedAmountPacket = QuestsCompletedAmountPacket(player.quests.completedQuestsAmount);
const ammunitionPacket = CannonballsPacket({
ammunition: player.inventory.getAmmunitions(),
selected: player.inventory.selectedAmmunition
});
const harpoonPacket = HarpoonsPacket({
harpoon: player.inventory.getHarpoons(),
selected: player.inventory.selectedHarpoon
});
const items = player.inventory.getItems();
const itemPacket = ItemsPacket(items);
const resourceSharedLimiter = player.inventory.resourceSharedLimiter;
const maximumEquipmentCapacities = [resourceSharedLimiter.cannon.quantity.maximum, resourceSharedLimiter.harpooner.quantity.maximum, resourceSharedLimiter.sail.quantity.maximum, resourceSharedLimiter.pirate.quantity.maximum];
const propertiesPacket = EquipmentCapacitiesMaximumPacket(maximumEquipmentCapacities);
const statusPointsPacket = StatusPointsPacket({ statusPoints: player.statusPoints });
const economy = player.inventory.getEconomy();
const currencyPacket = EconomyPacket(economy);
const activeStatusEffectsPacket = ActiveStatusEffectsPacket(player.activeStatusEffects);
/*
const asd = await gameRedis.keys("*");
asd.forEach(key => {
const data = gameRedis.getAsync(key);
});*/
/*
const playerIrrelevantEntries = !global.unavailablePlayerShopEntries[player.id] ? [] : Object.keys(global.unavailablePlayerShopEntries[player.id]);
const globalIrrelevantEntries = Object.keys(global.unavailableGlobalShopEntries);
const irrelevantShopEntries = [];
const shopEntryIDTracker = {};
playerIrrelevantEntries.forEach(id => {
if (!shopEntryIDTracker[id]) irrelevantShopEntries.push(id);
shopEntryIDTracker[id] = true;
});
globalIrrelevantEntries.forEach(id => {
if (!shopEntryIDTracker[id]) irrelevantShopEntries.push(id);
shopEntryIDTracker[id] = true;
});
*/
const irrelevantShopEntriesPacket = packet_58([]);
const cannons = player.inventory.getCannons();
const harpooners = player.inventory.getHarpooners();
const equipmentsPacket = EquipmentsPacket.init(cannons.length + harpooners.length);
cannons.forEach(c => equipmentsPacket.update(c.getProperties()));
harpooners.forEach(h => equipmentsPacket.update(h.getProperties()));
const packets = [statusPointsPacket, designsPacket, sightPacket, equipmentsPacket.get(), questsCompletedAmountPacket, questPacketInitialized.get(), itemPacket, ammunitionPacket, harpoonPacket, propertiesPacket, currencyPacket, activeStatusEffectsPacket, irrelevantShopEntriesPacket];
/*
const currentDate = new Date();
const currentMonth = currentDate.getMonth() + 1;
const currentDay = currentDate.getDay() - 1;
const currentLoginReward = loginReward[currentMonth][currentDay];
if (currentLoginReward) {
const loginReward = new Reward({
distributionType: 2,
baseReward: currentLoginReward
});
setTimeout(() => loginReward.single(1, player.inventory, rewards => rewardCallback({ isRegular: true, authorID: player.id, rewards })));
};
*/
if (player.guild.id) {
const guildMemberNew = {
playerID: player.id,
tag: player.guild.tag
};
const guildMemberNewPacket = GuildMemberNewPacket(guildMemberNew);
packets.push(guildMemberNewPacket);
const guildDataMemberChanged = {
id: player.id,
isOnline: true
};
const guildDataMemberChangedPacket = GuildDataMemberChangedPacket(guildDataMemberChanged);
const topic = Game.getTopic(player.guild.topic);
topic.push(guildDataMemberChangedPacket);
};
/* const mapped = {
5: 2
};
for (categoryID in SHOP) {
const category = SHOP[categoryID];
for (itemID in category) {
const entry = category[itemID];
const isEntryAvailable = entry.isAvailable(player);
if (!isEntryAvailable) continue;
const irrelevantShopEntry = {
id: itemID,
shopCategoryID: mapped[categoryID]
};
const packet = packet_57(irrelevantShopEntry);
packets.push(packet);
};
};*/
player.ready();
if (player.isAlive) {
if (player.target) {
const attackInformationPacket = AttackInformationPacket({
authorTypeID: player.target.typeID,
authorID: player.target.id
});
const attackerPacket = AttackerInformationPacket({
authorTypeID: player.target.typeID,
authorID: player.target.id,
isTarget: true,
source: 1
});
packets.push(attackInformationPacket, attackerPacket);
};
player.attackers.forEach(attacker => {
const attackerPacket = AttackerInformationPacket({
authorTypeID: Entity.getType(attacker.attackerEntry) + 1,
authorID: attacker.attackerEntry,
isTarget: false,
source: 1
});
packets.push(attackerPacket);
});
};
guildIslands.forEach(g => {
const worldMapGuildEntryPacketData = {
locationMapID: g.locationMapID,
index: g.index,
bufferTag: g.guild.tag
};
console.info("bufferTag", g.guild.tag)
const worldMapGuildEntryPacket = WorldMapGuildEntryPacket(worldMapGuildEntryPacketData);
packets.push(worldMapGuildEntryPacket);
});
for (let i = 0, length = player.rankingPoints.length; i < length; i++) {
const { id, amount } = player.rankingPoints[i];
const rankPoint = {
rankTypeID: id,
value: amount
};
const rankPointPacket = RankPointPacket(rankPoint);
packets.push(rankPointPacket);
};
SHOP.forEach(shopEntry => {
const shopEntryPacket = ShopEntryPacket(shopEntry);
packets.push(shopEntryPacket);
});
player.map.registerIndividualNetworkPacket(player.id, packets);
};
+20
View File
@@ -0,0 +1,20 @@
const packet_255 = require("../Packets/packet_255");
module.exports = function (ws, message, player) {
let isRepairSuccessful = null;
if (player.isRepairing()) {
player.cancelRepair();
isRepairSuccessful = false;
} else {
player.initializeRepair();
isRepairSuccessful = true;
};
const packet = packet_255({ packetId: 14, isSuccessful: isRepairSuccessful });
ws.send(packet, true, true); // should use central packet distributor
const metadata = [player.hp.current / player.hp.maximum, player.isAttacking()];
return metadata;
};
+5
View File
@@ -0,0 +1,5 @@
module.exports = async function (ws, message, player) {
if (player.isAlive) return;
player.setSingleEvent(14, 0);
};
+34
View File
@@ -0,0 +1,34 @@
const game = require("../Game/Game");
const { players } = game;
const SpyResultPacket = require("../Packets/SpyResult");
module.exports = function (ws, message, player) {
const spyID = message.getUint32(1);
const spiedPlayer = players[spyID];
let spiedPlayerLocation = {};
if (!spiedPlayer) {
spiedPlayerLocation = {
mapID: 255,
x: 0,
y: 0
};
} else if (spiedPlayer.isAlive) {
spiedPlayerLocation = {
mapID: spiedPlayer.map.id,
x: spiedPlayer.position.x,
y: spiedPlayer.position.y
};
} else {
spiedPlayerLocation = {
mapID: 0,
x: 0,
y: 0
};
};
const packet = SpyResultPacket(spiedPlayerLocation);
ws.send(packet, true, true);
};
+13
View File
@@ -0,0 +1,13 @@
const game = require("../Game/Game");
const { players, packets } = game;
module.exports = function (ws, message, player) {
console.info(packets)
const topic = packets.getElement("test");
if (!topic) return console.info("no topic");
if (!player.topics) player.topics = [topic];
else player.topics.push(topic);
console.info("player topics", player.topics);
};
+44
View File
@@ -0,0 +1,44 @@
const Game = require("../Game/Game");
const { players, guilds } = Game;
const buffer = new ArrayBuffer(3 + 250);
const view = new DataView(buffer);
const MAXIMUM_GUILD_REQUEST_MESSAGE_LENGTH = 256;
view.setUint8(0, 10);
view.setUint16(1, 213);
const QUERY_GUILD_REQUEST_SUBMIT = "INSERT INTO guildrequests (guildID, playerID, message) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE message = ?";
const QUERY_GUILD_REQUEST_SUBMIT_DEFAULT = "INSERT INTO guildrequests (guildID, playerID) VALUES (?, ?) ON DUPLICATE KEY UPDATE message = ?";
let str = new Array(250).fill("a").join("");
for (let i = 0, strLen = str.length; i < strLen; i++) {
const charCode = str.charCodeAt(i);
view.setUint8(3 + i, charCode);
};
module.exports = function (ws, message, player) {
const guildID = view.getUint16(1);
const guild = guilds[guildID];
if (!guild) return;
const playerID = 45; // player.id
const requestingPlayer = players[playerID];
// if (!requestingPlayer) return;
// if (requestingPlayer.guild) return console.log("has guild, can't request");
if (guild.hasRequested(playerID)) return console.log("has already requested");
const requestMessageLength = view.byteLength - 3;
console.log(requestMessageLength)
if (requestMessageLength > MAXIMUM_GUILD_REQUEST_MESSAGE_LENGTH) return console.log("request message length is > 256");
const requestMessage = view.byteLength > 3 ? view.buffer.slice(3, view.byteLength) : null;
const isRequestSuccessful = guild.addRequest(playerID, requestMessage);
if (!isRequestSuccessful) return console.log("request was unsuccessful");
const query = view.byteLength > 3 ? QUERY_GUILD_REQUEST_SUBMIT : QUERY_GUILD_REQUEST_SUBMIT_DEFAULT;
const queryParameters = view.byteLength > 3 ? [guildID, playerID, requestMessage, requestMessage] : [guildID, playerID, requestMessage];
console.log(requestMessage)
db.execute(query, queryParameters).then(_ => console.log("guild request is in the db"));
};
+94
View File
@@ -0,0 +1,94 @@
const packetTable = require("../Data/packets");
const { players } = require("../Game/Game");
const actions = [];
global.actions = actions;
const { MongoClient } = require("mongodb");
let db = null;
async function connect() {
const client = new MongoClient("mongodb://localhost:27017");
await client.connect({
maxPoolSize: 100,
minPoolSize: 20,
maxConnecting: 20,
waitQueueTimeoutMS: 0,
socketTimeoutMS: 30000,
connectTimeoutMS: 10000,
retryWrites: false,
directConnection: true
});
return client.db('test');
};
(async function() {
db = await connect();
global.mongodb = db;
return;
setInterval(async () => {
const t = [];
for (let i = 0; i < 32; i++) {
t.push({
playerID: 1,
timestamp: new Date(),
opcode: Math.floor(Math.random() * 120)
});
};
const bulkOps = t.map(doc => ({
insertOne: doc
}));
const n = performance.now();
await db.collection("Actions").insertMany(t, {
ordered: false,
writeConcern: { w: 0 },
bypassDocumentValidation: true
});
/* await db.collection('Actions').bulkWrite(bulkOps, {
ordered: false,
writeConcern: { w: 0 },
bypassDocumentValidation: true
});*/
}, 500);
})();
module.exports = async function (ws, message, isBinary) {
const player = players[ws.accountID];
if (!player) return;
const isLimitReached = ws.limiter.update();
if (isLimitReached) return ws.close();
if (player.isInactive) return; // this shouldn't happen, though
const view = new DataView(message);
const packetID = view.getUint8(0);
const packet = packetTable[packetID];
if (packetID !== 1 && !player.isAvailable) return;
if (!packet) return;
if (packet.expectedSize && packet.expectedSize !== view.byteLength) return console.info("expectedSize", view.byteLength, packet.expectedSize);
if (!packet.isAvailable) return;
player.lastInteractionTimestamp = performance.now();
const metadata = packet.handler(ws, view, player) ?? [];
if (packetID > 1) {
const action = {
ts: new Date(),
pid: player.id,
// opcode: packetID,
// metadata
};
const relevantContext = global.actionContext.getElement(player.id).save(2000);
relevantContext.push(action);
console.info("asd", relevantContext.length)
};
};