@screeps/engine
Version:
This is a module for Screeps standalone server. See [main repository](https://github.com/screeps/screeps) for more info.
261 lines (235 loc) • 9.97 kB
JavaScript
'use strict';
var _ = require('lodash'),
utils = require('../utils'),
driver = utils.getRuntimeDriver(),
C = driver.constants,
util = require('util');
exports.make = function (runtimeData, intents, register) {
var ordersCreatedDuringTick = 0,
cachedOrders = {},
cachedHistory = {},
_incomingTransactions,
_outgoingTransactions,
_orders;
function _getOrders(resourceType) {
if (!resourceType) {
resourceType = 'all';
}
if (!cachedOrders[resourceType]) {
if (resourceType != 'all' && !_.contains(C.RESOURCES_ALL, resourceType) && !_.contains(C.INTERSHARD_RESOURCES, resourceType)) {
return {};
}
cachedOrders[resourceType] = JSON.parse(JSON.stringify(runtimeData.market.orders[resourceType]) || '{}');
for (var i in cachedOrders[resourceType]) {
cachedOrders[resourceType][i].price /= 1000;
}
}
return cachedOrders[resourceType];
}
var market = {
calcTransactionCost: register.wrapFn(function (amount, roomName1, roomName2) {
var distance = utils.calcRoomsDistance(roomName1, roomName2, true);
return utils.calcTerminalEnergyCost(amount, distance);
}),
getAllOrders: register.wrapFn(function (filter) {
var orders = _getOrders(filter && filter.resourceType);
return _.filter(orders, filter);
}),
getHistory: register.wrapFn(function (resourceType) {
if (!resourceType) {
resourceType = 'all';
}
if (!cachedHistory[resourceType]) {
if (resourceType != 'all' && !_.contains(C.RESOURCES_ALL, resourceType) && !_.contains(C.INTERSHARD_RESOURCES, resourceType)) {
return {};
}
cachedHistory[resourceType] = JSON.parse(JSON.stringify(runtimeData.market.history[resourceType] || {}));
}
return cachedHistory[resourceType];
}),
getOrderById: register.wrapFn(function (id) {
if (this.orders[id]) {
return JSON.parse(JSON.stringify(this.orders[id]));
}
const order = runtimeData.market.orders.all[id];
if (order) {
const result = JSON.parse(JSON.stringify(order));
result.price /= 1000;
return result;
}
return null;
}),
createOrder: register.wrapFn(function (type, resourceType, price, totalAmount, roomName) {
if (_.isObject(type)) {
var type = type.type,
resourceType = type.resourceType,
price = type.price,
totalAmount = type.totalAmount,
roomName = type.roomName;
}
if (!_.contains(C.RESOURCES_ALL, resourceType) && !_.contains(C.INTERSHARD_RESOURCES, resourceType)) {
return C.ERR_INVALID_ARGS;
}
if (type != C.ORDER_BUY && type != C.ORDER_SELL) {
return C.ERR_INVALID_ARGS;
}
price = parseFloat(price);
totalAmount = parseInt(totalAmount);
if (!price || price <= 0 || !totalAmount) {
return C.ERR_INVALID_ARGS;
}
if (price * totalAmount * C.MARKET_FEE > this.credits) {
return C.ERR_NOT_ENOUGH_RESOURCES;
}
if (!_.contains(C.INTERSHARD_RESOURCES, resourceType) && (!roomName || !_.any(runtimeData.userObjects, { type: 'terminal', room: roomName }))) {
return C.ERR_NOT_OWNER;
}
if (_.size(this.orders) + ordersCreatedDuringTick >= C.MARKET_MAX_ORDERS) {
return C.ERR_FULL;
}
ordersCreatedDuringTick++;
intents.pushByName('global', 'createOrder', {
type, resourceType, price, totalAmount, roomName
});
return C.OK;
}),
cancelOrder: register.wrapFn(function (orderId) {
if (!this.orders[orderId]) {
return C.ERR_INVALID_ARGS;
}
intents.pushByName('global', 'cancelOrder', { orderId }, 50);
return C.OK;
}),
deal: register.wrapFn(function (orderId, amount, targetRoomName) {
var order = runtimeData.market.orders.all[orderId];
if (!order) {
return C.ERR_INVALID_ARGS;
}
amount = parseInt(amount);
if (!amount || amount < 0) {
return C.ERR_INVALID_ARGS;
}
if (_.contains(C.INTERSHARD_RESOURCES, order.resourceType)) {
if (order.type == C.ORDER_BUY && (runtimeData.user.resources[order.resourceType] || 0) < amount) {
return C.ERR_NOT_ENOUGH_RESOURCES;
}
} else {
if (!targetRoomName) {
return C.ERR_INVALID_ARGS;
}
var terminal = _.find(runtimeData.userObjects, { type: 'terminal', room: targetRoomName }),
transferCost = this.calcTransactionCost(amount, targetRoomName, order.roomName);
if (!terminal) {
return C.ERR_NOT_OWNER;
}
if (!terminal.store || terminal.store[C.RESOURCE_ENERGY] < transferCost) {
return C.ERR_NOT_ENOUGH_RESOURCES;
}
if (terminal.cooldownTime > runtimeData.time) {
return C.ERR_TIRED;
}
if (order.type == C.ORDER_BUY) {
if (order.resourceType != C.RESOURCE_ENERGY && (!terminal.store[order.resourceType] || terminal.store[order.resourceType] < amount) || order.resourceType == C.RESOURCE_ENERGY && terminal.store[C.RESOURCE_ENERGY] < amount + transferCost) {
return C.ERR_NOT_ENOUGH_RESOURCES;
}
}
}
if (order.type == C.ORDER_SELL && (runtimeData.user.money || 0) < amount * order.price) {
return C.ERR_NOT_ENOUGH_RESOURCES;
}
if (!intents.pushByName('global', 'deal', { orderId, targetRoomName, amount }, 10)) {
return C.ERR_FULL;
}
return C.OK;
}),
changeOrderPrice: register.wrapFn(function (orderId, newPrice) {
var order = this.orders[orderId];
if (!order) {
return C.ERR_INVALID_ARGS;
}
newPrice = parseFloat(newPrice);
if (!newPrice || newPrice <= 0) {
return C.ERR_INVALID_ARGS;
}
if (newPrice > order.price && (newPrice - order.price) * order.remainingAmount * C.MARKET_FEE > this.credits) {
return C.ERR_NOT_ENOUGH_RESOURCES;
}
intents.pushByName('global', 'changeOrderPrice', {
orderId, newPrice
}, 50);
return C.OK;
}),
extendOrder: register.wrapFn(function (orderId, addAmount) {
var order = this.orders[orderId];
if (!order) {
return C.ERR_INVALID_ARGS;
}
addAmount = parseInt(addAmount);
if (!addAmount || addAmount <= 0) {
return C.ERR_INVALID_ARGS;
}
if (order.price * addAmount * C.MARKET_FEE > this.credits) {
return C.ERR_NOT_ENOUGH_RESOURCES;
}
intents.pushByName('global', 'extendOrder', {
orderId, addAmount
}, 50);
return C.OK;
})
};
Object.defineProperties(market, {
credits: {
enumerable: true,
get() {
return (runtimeData.user.money || 0) / 1000;
}
},
incomingTransactions: {
enumerable: true,
get() {
if (!_incomingTransactions) {
_incomingTransactions = _.map(runtimeData.transactions.incoming || [], i => {
i.transactionId = "" + i._id;
delete i._id;
i.sender = i.sender ? { username: runtimeData.users[i.sender].username } : undefined;
i.recipient = i.recipient ? { username: runtimeData.users[i.recipient].username } : undefined;
return i;
});
}
return _incomingTransactions;
}
},
outgoingTransactions: {
enumerable: true,
get() {
if (!_outgoingTransactions) {
_outgoingTransactions = _.map(runtimeData.transactions.outgoing || [], i => {
i.transactionId = "" + i._id;
delete i._id;
i.sender = i.sender ? { username: runtimeData.users[i.sender].username } : undefined;
i.recipient = i.recipient ? { username: runtimeData.users[i.recipient].username } : undefined;
return i;
});
}
return _outgoingTransactions;
}
},
orders: {
enumerable: true,
get() {
if (!_orders) {
_orders = _(runtimeData.market.myOrders).map(i => {
i.id = "" + i._id;
delete i._id;
delete i.user;
i.price /= 1000;
return i;
}).indexBy('id').value();
}
return _orders;
}
}
});
return market;
};
//# sourceMappingURL=../sourcemaps/game/market.js.map