Преглед на файлове

saving changes so I don't reset them

tags/v0.8.3^2
Shaun преди 3 години
родител
ревизия
42db153f5b
променени са 27 файла, в които са добавени 154 реда и са изтрити 743 реда
  1. +33
    -6
      src/client/ui/factory.js
  2. +34
    -17
      src/client/ui/shared/renderItem.js
  3. +0
    -13
      src/client/ui/templates/inventory/inventory.js
  4. +0
    -150
      src/client/ui/templates/mail/mail.js
  5. +0
    -119
      src/client/ui/templates/mail/styles.less
  6. +0
    -12
      src/client/ui/templates/mail/template.html
  7. +0
    -5
      src/server/components/auth.js
  8. +13
    -3
      src/server/components/auth/checkLoginRewards.js
  9. +1
    -1
      src/server/components/extensions/socialCommands.js
  10. +0
    -39
      src/server/components/inventory.js
  11. +12
    -3
      src/server/components/notice.js
  12. +6
    -0
      src/server/components/player.js
  13. +0
    -2
      src/server/components/stats.js
  14. +2
    -1
      src/server/components/syncer.js
  15. +0
    -1
      src/server/config/clientConfig.js
  16. +1
    -1
      src/server/config/consts.js
  17. +5
    -5
      src/server/config/maps/sewer/events/plagueOfRats.js
  18. +1
    -1
      src/server/config/serverConfig.js
  19. +15
    -0
      src/server/db/ioRethink.js
  20. +0
    -1
      src/server/db/tableNames.js
  21. +13
    -3
      src/server/events/events.js
  22. +14
    -3
      src/server/events/phases/phaseGiveRewards.js
  23. +0
    -9
      src/server/mail/mail.js
  24. +0
    -183
      src/server/mail/mailRethinkDb.js
  25. +0
    -160
      src/server/mail/mailSqlite.js
  26. +3
    -2
      src/server/security/routerConfig.js
  27. +1
    -3
      src/server/world/instancer.js

+ 33
- 6
src/client/ui/factory.js Целия файл

@@ -1,11 +1,13 @@
define([
'ui/uiBase',
'js/system/events',
'js/system/client',
'js/system/globals',
'js/misc/tosAcceptanceValid'
], function (
uiBase,
events,
client,
globals,
tosAcceptanceValid
) {
@@ -29,14 +31,39 @@ define([
});
},

onEnterGame: function () {
onEnterGame: async function () {
events.clearQueue();

globals.clientConfig.uiList.forEach(u => {
if (u.path)
this.buildModUi(u);
else
this.build(u);
await Promise.all(
globals.clientConfig.uiList.map(u => {
const uiType = u.path ? u.path.split('/').pop() : u;

return new Promise(res => {
const doneCheck = () => {
const isDone = this.uis.some(ui => ui.type === uiType);
if (isDone) {
res();

return;
}

setTimeout(doneCheck, 100);
};

this.build(uiType, { path: u.path });

doneCheck();
});
})
);

client.request({
cpn: 'player',
method: 'performAction',
data: {
cpn: 'player',
method: 'notifyServerUiReady'
}
});
},



+ 34
- 17
src/client/ui/shared/renderItem.js Целия файл

@@ -10,34 +10,51 @@ define([
], function (
events
) {
const onHover = (el, item, e) => {
if (item)
this.hoverItem = item;
else
item = this.hoverItem;

let ttPos = null;

if (el) {
ttPos = {
x: ~~(e.clientX + 32),
y: ~~(e.clientY)
};
const renderItemManager = {
hoverItem: null,

onHover: function (el, item, e) {
if (item)
this.hoverItem = item;
else
item = this.hoverItem;

let ttPos = null;

if (el) {
ttPos = {
x: ~~(e.clientX + 32),
y: ~~(e.clientY)
};
}

events.emit('onShowItemTooltip', item, ttPos, true);
},

onKeyDown: function (key) {
if (key === 'shift' && this.hoverItem)
this.onHover();
},

onKeyUp: function (key) {
if (key === 'shift' && this.hoverItem)
this.onHover();
}

events.emit('onShowItemTooltip', item, ttPos, true);
};

events.on('onKeyDown', renderItemManager.onKeyDown.bind(renderItemManager));
events.on('onKeyUp', renderItemManager.onKeyUp.bind(renderItemManager));

const hideTooltip = (el, item, e) => {
events.emit('onHideItemTooltip', item);
};

const addTooltipEvents = (el, item) => {
let moveHandler = onHover.bind(null, el, item);
let moveHandler = renderItemManager.onHover.bind(renderItemManager, el, item);
let downHandler = () => {};
if (isMobile) {
moveHandler = () => {};
downHandler = onHover.bind(null, el, item);
downHandler = renderItemManager.bind(renderItemManager, el, item);
}

el


+ 0
- 13
src/client/ui/templates/inventory/inventory.js Целия файл

@@ -290,10 +290,6 @@ define([
text: 'equip',
callback: this.performItemAction.bind(this, item, 'equip')
},
mail: {
text: 'mail',
callback: this.openMailUi.bind(this, item)
},
split: {
text: 'split stack',
callback: this.splitStackStart.bind(this, item)
@@ -345,9 +341,6 @@ define([
if (item.quantity > 1 && !item.quest)
ctxConfig.push(menuItems.split);

if ((!item.noDrop) && (!item.quest))
ctxConfig.push(menuItems.mail);

ctxConfig.push(menuItems.link);

if (!item.eq && !item.active && !item.noDestroy) {
@@ -548,12 +541,6 @@ define([
});
},

openMailUi: function (item) {
events.emit('onSetMailItem', {
item: item
});
},

onKeyDown: function (key) {
if (key === 'i')
this.toggle();


+ 0
- 150
src/client/ui/templates/mail/mail.js Целия файл

@@ -1,150 +0,0 @@
define([
'js/system/events',
'js/system/client',
'html!ui/templates/mail/template',
'css!ui/templates/mail/styles',
'ui/shared/renderItem'
], function (
events,
client,
template,
styles,
renderItem
) {
return {
tpl: template,

centered: true,

modal: true,
hasClose: true,

hoverItem: null,

item: null,

postRender: function () {
this.onEvent('onSetMailItem', this.onSetItem.bind(this));
this.onEvent('onKeyDown', this.onKeyDown.bind(this));
this.onEvent('onKeyUp', this.onKeyUp.bind(this));

this.find('input').on('keydown', this.onInputKeyDown.bind(this));
this.find('.btnSend').on('click', this.onSendClick.bind(this));
},

onSendClick: function () {
if (!this.item)
return;

let recipient = this.find('.txtRecipient').val();
if (recipient.length === 0)
return;

client.request({
cpn: 'player',
method: 'performAction',
data: {
cpn: 'inventory',
method: 'mailItem',
data: {
itemId: this.item.id,
recipient: recipient
}
},
callback: this.onSend.bind(this)
});
},
onSend: function (res) {
if (res.length > 0) {
events.emit('onGetAnnouncement', {
msg: res,
type: 'failure'
});

return;
}

events.emit('onSendMail');
this.hide();
},

onSetItem: function (msg) {
this.toggle();
this.item = msg.item;

const itemContainer = this.find('.itemContainer').empty();
let item = msg.item;

const itemEl = renderItem(itemContainer, item);

this.find('.txtRecipient').val('');

let moveHandler = this.onHover.bind(this, itemEl, item);
let downHandler = () => {};
if (isMobile) {
moveHandler = () => {};
downHandler = this.onHover.bind(this, itemEl, item);
}

itemEl
.data('item', item)
.on('mousedown', downHandler)
.on('mousemove', moveHandler)
.on('mouseleave', this.hideTooltip.bind(this, itemEl, item));
},

onAfterShow: function () {
this.find('input').focus();
},

hideTooltip: function () {
events.emit('onHideItemTooltip', this.hoverItem);
this.hoverItem = null;
},

onHover: function (el, item, e) {
if (item)
this.hoverItem = item;
else
item = this.hoverItem;

let ttPos = null;

if (el) {
el.removeClass('new');
delete item.isNew;

let elOffset = el.offset();
ttPos = {
x: ~~(elOffset.left + 74),
y: ~~(elOffset.top + 4)
};
}

events.emit('onShowItemTooltip', item, ttPos, true);
},

onKeyDown: function (key) {
if (!this.shown)
return;

if (key === 'shift' && this.hoverItem)
this.onHover();
else if (key === 'esc')
this.toggle();
},

onKeyUp: function (key) {
if (!this.shown)
return;

if (key === 'shift' && this.hoverItem)
this.onHover();
},

onInputKeyDown: function ({ keyCode }) {
if (keyCode === 27)
this.toggle();
}
};
});

+ 0
- 119
src/client/ui/templates/mail/styles.less Целия файл

@@ -1,119 +0,0 @@
@import "../../../css/colors.less";

.uiMail {
display: none;
background-color: @blackB;
border: 5px solid @blackB;
text-align: center;

> .heading {
color: @blueA;
width: 100%;
height: 36px;
background-color: @blackB;

.heading-text {
padding-top: 8px;
margin: auto;
}
}

.bottom {
height: 99px;
background-color: @blackC;
padding: 10px;

.col {
float: left;
width: 80px;
height: 80px;

&.itemContainer {
padding: 4px;

.item {
width: 72px;
height: 72px;
float: left;
position: relative;
cursor: pointer;
box-sizing: border-box;
margin: 4px;
background-color: @blackD;

&.hover {
background-color: fade(@blueA, 10%);
}

.quantity {
left: 6px;
bottom: 3px;
position: absolute;
color: @white;
filter: drop-shadow(0px -2px 0px @blackD)
drop-shadow(0px 2px 0px @blackD)
drop-shadow(2px 0px 0px @blackD)
drop-shadow(-2px 0px 0px @blackD);
-moz-filter: drop-shadow(0px -2px 0px @blackD)
drop-shadow(0px 2px 0px @blackD)
drop-shadow(2px 0px 0px @blackD)
drop-shadow(-2px 0px 0px @blackD);
}

.icon {
width: 64px;
height: 64px;
position: absolute;
left: 4px;
top: 4px;
}

&:hover {
.icon {
filter: brightness(160%);
-moz-filter: brightness(160%);
}

}
}
}

&:nth-child(2) {
width: 200px;
padding-top: 4px;
margin-left: 10px;

> * {
width: 100%;
height: 31px;
}

.btnSend {
height: 35px;
background-color: @blueB;
text-align: center;
padding-top: 12px;
color: @white;
cursor: pointer;
}

input, input:-webkit-autofill {
box-shadow: 0 0 0px 1000px darken(@blackB, 15%) inset;
color: @white;
-webkit-text-fill-color: @white;
margin-bottom: 5px;
text-align: center;
}

/* We duplicate this for firefox which doesn't like the webkit selector */
input {
box-shadow: 0 0 0px 1000px darken(@blackB, 15%) inset;
color: @white;
-webkit-text-fill-color: @white;
margin-bottom: 5px;
text-align: center;
}
}
}
}
}

+ 0
- 12
src/client/ui/templates/mail/template.html Целия файл

@@ -1,12 +0,0 @@
<div class="uiMail">
<div class="heading">
<div class="heading-text">mail item</div>
</div>
<div class="bottom">
<div class="col itemContainer"></div>
<div class="col">
<input class="txtRecipient textbox" type="text" placeholder="recipient">
<div class="btnSend">send</div>
</div>
</div>
</div>

+ 0
- 5
src/server/components/auth.js Целия файл

@@ -4,7 +4,6 @@ const skins = require('../config/skins');
const roles = require('../config/roles');
const profanities = require('../misc/profanities');
const fixes = require('../fixes/fixes');
const mail = require('../mail/mail');
const spirits = require('../config/spirits');
const ga = require('../security/ga');
const events = require('../misc/events');
@@ -44,10 +43,6 @@ module.exports = {
},

onSendRewards: async function (data, character) {
//Bit of a hack. Rethink doesn't have a busy list
if (mail.busy)
delete mail.busy[character.name];

await io.setAsync({
key: this.username,
table: 'accountInfo',


+ 13
- 3
src/server/components/auth/checkLoginRewards.js Целия файл

@@ -1,6 +1,5 @@
const scheduler = require('../../misc/scheduler');
const rewardGenerator = require('../../misc/rewardGenerator');
const mail = require('../../mail/mail');

const calculateDaysSkipped = (oldTime, newTime) => {
let daysSkipped = 1;
@@ -50,6 +49,7 @@ module.exports = async (cpnAuth, data, character, cbDone) => {
)
) {
cbDone();
return;
}

@@ -66,10 +66,20 @@ module.exports = async (cpnAuth, data, character, cbDone) => {
const rewards = rewardGenerator(itemCount);
if (!rewards) {
cbDone();

return;
}

rewards[0].msg = `Daily login reward for ${loginStreak} day${(loginStreak > 1) ? 's' : ''}:`;
const msg = `Daily login reward for ${loginStreak} day${(loginStreak > 1) ? 's' : ''}`;

if (global.mailManager) {
await global.mailManager.sendSystemMail({
to: character.name,
subject: 'Login Rewards',
msg,
items: rewards
});
}

mail.sendMail(character.name, rewards, cbDone);
cbDone();
};

+ 1
- 1
src/server/components/extensions/socialCommands.js Целия файл

@@ -37,7 +37,7 @@ let commandRoles = {
getItem: 10,
getGold: 10,
setLevel: 10,
godMode: 10,
godMode: 0,
clearInventory: 10,
completeQuests: 10,
getReputation: 10,


+ 0
- 39
src/server/components/inventory.js Целия файл

@@ -383,45 +383,6 @@ module.exports = {
}, this);
},

mailItem: async function (msg) {
let item = this.findItem(msg.itemId);

if (!item || item.noDrop || item.quest) {
this.resolveCallback(msg);
return;
}

let res = await io.getAsync({
key: msg.recipient,
table: 'character'
});

if (!res) {
this.resolveCallback(msg, 'Recipient does not exist');
return;
} else if (!this.findItem(msg.itemId))
return;

const resolveTrans = transactions.register();

let blocked = false;
if (res.components) {
let social = res.components.find(f => f.type === 'social');
if (social.blockedPlayers && social.blockedPlayers.includes(this.obj.name))
blocked = true;
}

const mappedItem = this.simplifyItem(item);
this.destroyItem(item.id);

if (!blocked)
await this.obj.instance.mail.sendMail(msg.recipient, [mappedItem]);

this.resolveCallback(msg);

resolveTrans();
},

hookItemEvents: function (items) {
items = items || this.items;
if (!items.push)


+ 12
- 3
src/server/components/notice.js Целия файл

@@ -12,6 +12,7 @@ module.exports = {

init: function (blueprint) {
this.msg = blueprint.msg;
this.msgFunction = blueprint.msgFunction;
this.actions = blueprint.actions || {};
this.announce = blueprint.announce;
this.maxLevel = blueprint.maxLevel || 0;
@@ -32,6 +33,12 @@ module.exports = {

let cpn = null;

if (typeof(action) === 'function') {
action(obj);
return;
}

if (action.targetId) {
let target = this.obj.instance.objects.find(o => o.id === action.targetId);
if (target) {
@@ -58,13 +65,15 @@ module.exports = {

this.callAction(obj, 'enter');

if (!this.msg)
if (!this.msg && !this.msgFunction)
return;

const msg = this.msg || this.msgFunction(obj);

if (this.announce) {
this.syncer.queue('onGetAnnouncement', {
src: this.obj.id,
msg: this.msg
msg
}, [obj.serverId]);

return;
@@ -72,7 +81,7 @@ module.exports = {

this.syncer.queue('onGetDialogue', {
src: this.obj.id,
msg: this.msg
msg
}, [obj.serverId]);
},



+ 6
- 0
src/server/components/player.js Целия файл

@@ -268,5 +268,11 @@ module.exports = {
msg.data.data.callbackId = atlas.registerCallback(msg.callback);

atlas.performAction(this.obj, msg.data);
},

notifyServerUiReady: function () {
this.obj.instance.eventEmitter.emit('onPlayerUiReady', {
obj: this.obj
});
}
};

+ 0
- 2
src/server/components/stats.js Целия файл

@@ -736,8 +736,6 @@ module.exports = {
let stats = this.stats;
let time = scheduler.getTime();
stats.lastLogin = time;

this.obj.instance.mail.getMail(this.obj.name);
},

getKillStreakCoefficient: function (mobName) {


+ 2
- 1
src/server/components/syncer.js Целия файл

@@ -31,7 +31,8 @@ module.exports = {
this.buffer = [];
},

queue: function (args) {
queue: function (args, a) {
console.log(args, a);
this.buffer.push(args);
},



+ 0
- 1
src/server/config/clientConfig.js Целия файл

@@ -178,7 +178,6 @@ const config = {
'death',
'leaderboard',
'reputation',
'mail',
'wardrobe',
'passives',
'workbench',


+ 1
- 1
src/server/config/consts.js Целия файл

@@ -1,6 +1,6 @@
module.exports = {
//At which interval does each zone tick in ms
tickTime: 350,
tickTime: 100,

//The maximum level a player can reach
maxLevel: 20,


+ 5
- 5
src/server/config/maps/sewer/events/plagueOfRats.js Целия файл

@@ -51,13 +51,13 @@ const descriptionStrings = {
};

const config = {
cron: '0 */3 * * *',
//cron: '* * * * *',
//cron: '0 */3 * * *',
cron: '* * * * *',
idFirstSpawnPhase: 6,
idFailPhase: 19,
maxEscapees: 5,
repeats: [5, 5, 3],
//repeats: [1, 1, 1],
maxEscapees: 5000,
//repeats: [5, 5, 3],
repeats: [1, 1, 1],
rewardItemsPerKill: 3
};



+ 1
- 1
src/server/config/serverConfig.js Целия файл

@@ -8,7 +8,7 @@ module.exports = {
// sqlite
// rethink
//eslint-disable-next-line no-process-env
db: process.env.IWD_DB || 'sqlite',
db: process.env.IWD_DB || 'rethink',
//eslint-disable-next-line no-process-env
dbHost: process.env.IWD_DB_HOST || 'localhost',
//eslint-disable-next-line no-process-env


+ 15
- 0
src/server/db/ioRethink.js Целия файл

@@ -75,6 +75,21 @@ module.exports = {
return res;
},

getFilterAsync: async function ({ table, noDefault, filter }) {
const res = await r
.table(table)
.filter(filter)
.run();

if (res)
return res;

if (!noDefault)
return [];

return null;
},

getAllAsync: async function ({
table,
key,


+ 0
- 1
src/server/db/tableNames.js Целия файл

@@ -6,7 +6,6 @@ const tableNames = [
'login',
'leaderboard',
'customMap',
'mail',
'customChannels',
'error',
'modLog',


+ 13
- 3
src/server/events/events.js Целия файл

@@ -240,15 +240,25 @@ module.exports = {
giveRewards: function (config) {
const { event: { rewards = {} } } = config;

const subject = `${config.name} Rewards`;
const senderName = config.rewardSenderName;

Object.entries(rewards).forEach(e => {
const [ name, rList ] = e;

if (!rList || !rList.length)
return;

rList[0].msg = `${config.name} reward:`;

this.instance.mail.sendMail(name, rList);
if (global.mailManager) {
global.mailManager.sendSystemMail({
to: name,
from: senderName,
subject,
msg: '',
items: rList,
notify: true
});
}
});

if ((config.events) && (config.events.afterGiveRewards))


+ 14
- 3
src/server/events/phases/phaseGiveRewards.js Целия файл

@@ -2,15 +2,26 @@ module.exports = {
init: function (event) {
const { config, rewards, eventManager } = event;

const { name: eventName, rewardSenderName } = config;

const subject = `${eventName} Rewards`;

Object.entries(rewards).forEach(e => {
const [ name, rList ] = e;

if (!rList | !rList.length)
return;

rList[0].msg = `${config.name} reward:`;

this.instance.mail.sendMail(name, rList);
if (global.mailManager) {
global.mailManager.sendSystemMail({
to: name,
from: rewardSenderName,
subject,
msg: '',
items: rList,
notify: true
});
}
});

if ((config.events) && (config.events.afterGiveRewards))


+ 0
- 9
src/server/mail/mail.js Целия файл

@@ -1,9 +0,0 @@
let serverConfig = require('../config/serverConfig');

const moduleMap = {
sqlite: 'Sqlite',
rethink: 'RethinkDb'
};
const modulePath = `./mail${moduleMap[serverConfig.db]}`;

module.exports = require(modulePath);

+ 0
- 183
src/server/mail/mailRethinkDb.js Целия файл

@@ -1,183 +0,0 @@
//This lock system is so stupid. But until we rewrite mail (no more auto-fetch)
// We need a way to stop race conditions (listener picking up mail when we just want to getMail normally)
const locks = {};

module.exports = {
init: function (instance) {
this.instance = instance;

this.listen();
},

listen: function () {
io
.subscribe('mail')
.then(cursor => {
cursor.each(async (err, data) => {
let doc = data.new_val;
if (!doc)
return;

let player = this.instance.objects.objects.find(o => o.name === doc.id && o.player);
if (!player)
return;

if (locks[player.name])
return;

locks[player.name] = 1;

let items = doc.value;
let inventory = player.inventory;
let stash = player.stash;

let sentMessages = [];

items.forEach(function (r) {
if (r.removeAll) {
for (let i = 0; i < inventory.items.length; i++) {
let item = inventory.items[i];
if ((r.nameLike) && (item.name.indexOf(r.nameLike) > -1)) {
inventory.destroyItem(item.id, item.quantity ? item.quantity : null);
i--;
}
}

if (stash) {
for (let i = 0; i < stash.items.length; i++) {
let item = stash.items[i];
if ((r.nameLike) && (item.name.indexOf(r.nameLike) > -1)) {
stash.destroyItem(item.id);
i--;
}
}
}
} else {
if ((r.msg) && (!sentMessages.some(s => (s === r.msg)))) {
player.social.notifySelf({
message: r.msg,
className: 'color-greenB'
});

sentMessages.push(r.msg);
delete r.msg;
} else {
player.social.notifySelf({
message: 'You have received a mail',
className: 'color-greenB',
subType: 'mail'
});
}

delete r.pos;
delete r.quickSlot;
inventory.getItem(r, false, false, false, true);
}
});

await io.deleteAsync({
key: doc.id,
table: 'mail'
});

delete locks[player.name];
});
});
},

getMail: async function (playerName) {
let items = await io.getAsync({
key: playerName,
table: 'mail'
});

if (!items || !(items instanceof Array))
return;

let player = this.instance.objects.objects.find(o => o.name === playerName && o.player);
if (!player)
return;

if (locks[playerName])
return;

locks[playerName] = 1;

let inventory = player.inventory;
let stash = player.stash;

let sentMessages = [];

items.forEach(function (r) {
if (r.removeAll) {
for (let i = 0; i < inventory.items.length; i++) {
let item = inventory.items[i];
if ((r.nameLike) && (item.name.indexOf(r.nameLike) > -1)) {
inventory.destroyItem(item.id, item.quantity ? item.quantity : null);
i--;
}
}

if (stash) {
for (let i = 0; i < stash.items.length; i++) {
let item = stash.items[i];
if ((r.nameLike) && (item.name.indexOf(r.nameLike) > -1)) {
stash.destroyItem(item.id);
i--;
}
}
}
} else {
if ((r.msg) && (!sentMessages.some(s => (s === r.msg)))) {
player.social.notifySelf({
message: r.msg,
className: 'color-greenB'
});

sentMessages.push(r.msg);
delete r.msg;
} else {
player.social.notifySelf({
message: 'You have received a mail',
className: 'color-greenB',
subType: 'mail'
});
}

delete r.pos;
delete r.quickSlot;
inventory.getItem(r, false, false, false, true);
}
});

await io.deleteAsync({
key: playerName,
table: 'mail'
});

delete locks[playerName];
},

sendMail: async function (playerName, items, callback) {
if (await io.exists({
key: playerName,
table: 'mail'
})) {
await io.append({
key: playerName,
table: 'mail',
value: items,
field: 'value'
});
} else {
await io.setAsync({
key: playerName,
table: 'mail',
value: items
});
}

if (callback)
callback();
}
};

+ 0
- 160
src/server/mail/mailSqlite.js Целия файл

@@ -1,160 +0,0 @@
module.exports = {
queue: {},
busy: {},

init: function (instance) {
this.instance = instance;
},

getMail: async function (playerName, noBlock) {
if (!noBlock)
this.busy[playerName] = (this.busy[playerName] || 0) + 1;

let player = this.instance.objects.objects.find(o => o.name === playerName && o.player);
if (!player) {
process.send({
method: 'callDifferentThread',
playerName: playerName,
data: {
module: 'mail',
method: 'getMail',
args: [playerName]
}
});

this.busy[playerName]--;

this.processQueue(playerName);
return;
}

let result = await io.getAsync({
key: playerName,
table: 'mail',
noParse: true
});

this.busy[playerName]--;

await this.onGetMail(player, result);
},

onGetMail: async function (player, result) {
if (result === 'null')
result = null;
else if (result) {
result = result.split('`').join('\'');
//Hack for weird google datastore error
if (result[0] === '<')
return;
}

result = JSON.parse(result || '[]');

let sentMessages = [];

let inventory = player.inventory;
let stash = player.stash;

result.forEach(function (r) {
if (r.removeAll) {
for (let i = 0; i < inventory.items.length; i++) {
let item = inventory.items[i];
if ((r.nameLike) && (item.name.indexOf(r.nameLike) > -1)) {
inventory.destroyItem(item.id, item.quantity ? item.quantity : null);
i--;
}
}

if (stash) {
for (let i = 0; i < stash.items.length; i++) {
let item = stash.items[i];
if ((r.nameLike) && (item.name.indexOf(r.nameLike) > -1)) {
stash.destroyItem(item.id);
i--;
}
}
}
} else {
if ((r.msg) && (!sentMessages.some(s => (s === r.msg)))) {
player.social.notifySelf({
message: r.msg,
className: 'color-greenB'
});

sentMessages.push(r.msg);
delete r.msg;
} else {
player.social.notifySelf({
message: 'You have received a mail',
className: 'color-greenB',
subType: 'mail'
});
}
inventory.getItem(r, false, false, false, true);
}
});

await io.setAsync({
key: player.name,
table: 'mail',
value: ''
});

this.processQueue(player.name);
},

processQueue: function (playerName) {
if (this.busy[playerName])
return;

let queue = this.queue[playerName];
if (!queue)
return;

delete this.queue[playerName];
this.sendMail(playerName, queue);
},

sendMail: async function (playerName, items, callback) {
if (this.busy[playerName]) {
let queue = this.queue[playerName];
if (!queue)
queue = this.queue[playerName] = [];

queue.push(...extend([], items));
return;
}

//Only maintain the busy queue on child threads
//since the parent thread never actually distributes items
if (process.send)
this.busy[playerName] = (this.busy[playerName] || 0) + 1;

if (!items.push)
items = [items];

let result = await io.getAsync({
key: playerName,
table: 'mail',
noParse: true
});

if (result === 'null')
result = null;

result = JSON.parse(result || '[]');

result.push(...items);

const itemString = JSON.stringify(result).split('\'').join('`');

await io.setAsync({
key: playerName,
table: 'mail',
value: itemString
});

(callback || this.getMail.bind(this, playerName, true))();
}
};

+ 3
- 2
src/server/security/routerConfig.js Целия файл

@@ -10,7 +10,7 @@ const routerConfig = {
dialogue: ['talk'],
gatherer: ['gather'],
quests: ['complete'],
inventory: ['combineStacks', 'splitStack', 'useItem', 'moveItem', 'learnAbility', 'unlearnAbility', 'dropItem', 'destroyItem', 'salvageItem', 'stashItem', 'mailItem', 'sortInventory'],
inventory: ['combineStacks', 'splitStack', 'useItem', 'moveItem', 'learnAbility', 'unlearnAbility', 'dropItem', 'destroyItem', 'salvageItem', 'stashItem', 'sortInventory'],
equipment: ['equip', 'unequip', 'setQuickSlot', 'useQuickSlot', 'inspect'],
stash: ['withdraw', 'open'],
trade: ['buySell'],
@@ -18,7 +18,8 @@ const routerConfig = {
wardrobe: ['open', 'apply'],
stats: ['respawn'],
passives: ['tickNode', 'untickNode'],
workbench: ['open', 'craft', 'getRecipe']
workbench: ['open', 'craft', 'getRecipe'],
player: ['notifyServerUiReady']
},
globalAllowed: {
clientConfig: ['getClientConfig'],


+ 1
- 3
src/server/world/instancer.js Целия файл

@@ -8,7 +8,6 @@ let spellCallbacks = require('../config/spells/spellCallbacks');
let questBuilder = require('../config/quests/questBuilder');
let events = require('../events/events');
let scheduler = require('../misc/scheduler');
let mail = require('../mail/mail');
let herbs = require('../config/herbs');
let eventEmitter = require('../misc/events');
const transactions = require('../security/transactions');
@@ -39,7 +38,6 @@ module.exports = {
questBuilder,
events,
zone: map.zone,
mail,
map,
scheduler,
eventEmitter,
@@ -63,7 +61,7 @@ module.exports = {

map.clientMap.zoneId = this.zoneId;

[resourceSpawner, syncer, objects, questBuilder, events, mail].forEach(i => i.init(fakeInstance));
[resourceSpawner, syncer, objects, questBuilder, events].forEach(i => i.init(fakeInstance));

this.tick();
},


Зареждане…
Отказ
Запис