Equipment buying and selling complete
This commit is contained in:
+8
-1
@@ -21,7 +21,14 @@ let excluded = [ //messages that should not be logged
|
|||||||
'News sent',
|
'News sent',
|
||||||
|
|
||||||
'Can\'t train while attacking',
|
'Can\'t train while attacking',
|
||||||
'Can\'t untrain while attacking'
|
'Can\'t untrain while attacking',
|
||||||
|
'Can\'t purchase while attacking',
|
||||||
|
'Can\'t sell while attacking',
|
||||||
|
|
||||||
|
'Purchase made',
|
||||||
|
'Sale made',
|
||||||
|
|
||||||
|
'Cleaned database'
|
||||||
];
|
];
|
||||||
|
|
||||||
const log = (msg, ...args) => {
|
const log = (msg, ...args) => {
|
||||||
|
|||||||
+229
-29
@@ -4,50 +4,54 @@ require('dotenv').config();
|
|||||||
//utilities
|
//utilities
|
||||||
let { log } = require('../common/utilities.js');
|
let { log } = require('../common/utilities.js');
|
||||||
|
|
||||||
const statistics = (connection, req, res, cb) => {
|
let { isAttacking } = require('./combat.js');
|
||||||
|
|
||||||
|
const getStatistics = (cb) => {
|
||||||
|
//TODO: apiVisible field
|
||||||
return cb(undefined, { 'statistics': require('./equipment_statistics.json') });
|
return cb(undefined, { 'statistics': require('./equipment_statistics.json') });
|
||||||
};
|
};
|
||||||
|
|
||||||
const owned = (connection, req, res, cb) => {
|
const getOwned = (connection, id, cb) => {
|
||||||
|
let query = 'SELECT name, quantity FROM equipment WHERE accountId = ?;';
|
||||||
|
connection.query(query, [id], (err, results) => {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
let ret = {};
|
||||||
|
|
||||||
|
Object.keys(results).map((key) => {
|
||||||
|
if (ret[results[key].name] !== undefined) {
|
||||||
|
log('WARNING: Invalid database state, equipment owned', id, JSON.stringify(results));
|
||||||
|
}
|
||||||
|
ret[results[key].name] = results[key].quantity;
|
||||||
|
});
|
||||||
|
|
||||||
|
return cb(undefined, { 'owned': ret });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const equipmentRequest = (connection) => (req, res) => {
|
||||||
//validate the credentials
|
//validate the credentials
|
||||||
let query = 'SELECT COUNT(*) AS total FROM sessions WHERE accountId = ? AND token = ?;';
|
let query = 'SELECT COUNT(*) AS total FROM sessions WHERE accountId = ? AND token = ?;';
|
||||||
connection.query(query, [req.body.id, req.body.token], (err, results) => {
|
connection.query(query, [req.body.id, req.body.token], (err, results) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
|
|
||||||
if (results[0].total !== 1) {
|
if (results[0].total !== 1) {
|
||||||
return cb('Invalid equipment owned credentials');
|
res.status(400).write(log('Invalid equipment credentials', req.body.id, req.body.token));
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let query = 'SELECT name, quantity FROM equipment WHERE accountId = ?;';
|
|
||||||
connection.query(query, [req.body.id], (err, results) => {
|
|
||||||
if (err) throw err;
|
|
||||||
|
|
||||||
let res = {}
|
|
||||||
|
|
||||||
Object.keys(results).map((key) => {
|
|
||||||
if (res[results[key].name] !== undefined) {
|
|
||||||
log('WARNING: Invalid database state, equipment owned', JSON.stringify(results));
|
|
||||||
}
|
|
||||||
res[results[key].name] = results[key].quantity;
|
|
||||||
});
|
|
||||||
|
|
||||||
return cb(undefined, { 'owned': res });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const equipmentRequest = (connection) => (req, res) => {
|
|
||||||
//if no field received, send everything
|
//if no field received, send everything
|
||||||
if (!req.body.field) {
|
if (!req.body.field) {
|
||||||
//compose the returned objects
|
//compose the returned objects
|
||||||
statistics(connection, req, res, (err, statisticsObj) => {
|
return getStatistics((err, statisticsObj) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
res.status(400).write(log(err, req.body.id, req.body.token, req.body.field));
|
res.status(400).write(log(err, req.body.id, req.body.token, req.body.field));
|
||||||
res.end();
|
res.end();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return owned(connection, req, res, (err, ownedObj) => {
|
return getOwned(connection, req.body.id, (err, ownedObj) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
res.status(400).write(log(err, req.body.id, req.body.token, req.body.field));
|
res.status(400).write(log(err, req.body.id, req.body.token, req.body.field));
|
||||||
res.end();
|
res.end();
|
||||||
@@ -59,14 +63,12 @@ const equipmentRequest = (connection) => (req, res) => {
|
|||||||
res.end();
|
res.end();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//send specific fields
|
//send specific fields
|
||||||
switch(req.body.field) {
|
switch(req.body.field) {
|
||||||
case 'statistics':
|
case 'statistics':
|
||||||
return statistics(connection, req, res, (err, obj) => {
|
return getStatistics((err, obj) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
res.status(400).write(log(err, req.body.id, req.body.token, req.body.field));
|
res.status(400).write(log(err, req.body.id, req.body.token, req.body.field));
|
||||||
} else {
|
} else {
|
||||||
@@ -77,7 +79,7 @@ const equipmentRequest = (connection) => (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
case 'owned':
|
case 'owned':
|
||||||
return owned(connection, req, res, (err, obj) => {
|
return getOwned(connection, req.body.id, (err, obj) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
res.status(400).write(log(err, req.body.id, req.body.token, req.body.field));
|
res.status(400).write(log(err, req.body.id, req.body.token, req.body.field));
|
||||||
} else {
|
} else {
|
||||||
@@ -91,8 +93,206 @@ const equipmentRequest = (connection) => (req, res) => {
|
|||||||
res.status(400).write(log('Unknown field received', req.body.id, req.body.token, req.body.field));
|
res.status(400).write(log('Unknown field received', req.body.id, req.body.token, req.body.field));
|
||||||
res.end();
|
res.end();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const purchaseRequest = (connection) => (req, res) => {
|
||||||
|
//validate the credentials
|
||||||
|
let query = 'SELECT COUNT(*) AS total FROM sessions WHERE accountId = ? AND token = ?;';
|
||||||
|
connection.query(query, [req.body.id, req.body.token], (err, credentials) => {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
if (credentials[0].total !== 1) {
|
||||||
|
res.status(400).write(log('Invalid equipment purchase credentials', JSON.stringify(body), body.id, body.token));
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//no purchasing if you're attacking
|
||||||
|
isAttacking(connection, req.body.id, (err, attacking) => {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
if (attacking) {
|
||||||
|
res.status(400).write(log('Can\'t purchase while attacking', req.body.id, req.body. token, req.body.type, req.body.name));
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the player's gold
|
||||||
|
let query = 'SELECT gold, scientists FROM profiles WHERE accountId = ?;';
|
||||||
|
connection.query(query, [req.body.id], (err, results) => {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
//just in case
|
||||||
|
if (results.length === 0) {
|
||||||
|
res.status(400).write(log('Purchase made on unrecognized account', req.body.id, req.body.token));
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the stats for all objects
|
||||||
|
getStatistics((err, { statistics }) => {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
//valid parameters
|
||||||
|
if(!statistics[req.body.type] || !statistics[req.body.type][req.body.name]) {
|
||||||
|
res.status(400).write(log('Invalid equipment purchase parameters', req.body.id, req.body.token, req.body.type, req.body.name));
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//enough gold?
|
||||||
|
if (results[0].gold < statistics[req.body.type][req.body.name].cost) {
|
||||||
|
res.status(400).write(log('Not enough gold', req.body.id, req.body.token, req.body.type, req.body.name));
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//for sale?
|
||||||
|
if (!statistics[req.body.type][req.body.name].visible || !statistics[req.body.type][req.body.name].purchasable) {
|
||||||
|
res.status(400).write(log('Item not for sale', req.body.id, req.body.token, req.body.type, req.body.name));
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//high enough level?
|
||||||
|
if (results[0].scientists < statistics[req.body.type][req.body.name].scientistsRequired) {
|
||||||
|
res.status(400).write(log('Not enough scientists', req.body.id, req.body.token, req.body.type, req.body.name));
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//purchase approved.
|
||||||
|
|
||||||
|
//get the user's current item data (including quantity)
|
||||||
|
let query = 'SELECT * FROM equipment WHERE accountId = ? AND name = ?;';
|
||||||
|
connection.query(query, [req.body.id, req.body.name], (err, results) => {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
//add to or update the record
|
||||||
|
let query;
|
||||||
|
if (results.length > 0) {
|
||||||
|
query = 'UPDATE equipment SET quantity = quantity + 1 WHERE accountId = ? AND name = ? AND type = ?;';
|
||||||
|
} else {
|
||||||
|
query = 'INSERT INTO equipment (accountId, name, type, quantity) VALUES (?, ?, ?, 1);';
|
||||||
|
}
|
||||||
|
|
||||||
|
connection.query(query, [req.body.id, req.body.name, req.body.type], (err) => {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
//remove gold from the user's account
|
||||||
|
let query = 'UPDATE profiles SET gold = gold - ? WHERE accountId = ?;';
|
||||||
|
connection.query(query, [statistics[req.body.type][req.body.name].cost, req.body.id], (err) => {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
//return the new owned data
|
||||||
|
getOwned(connection, req.body.id, (err, results) => {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
res.status(200).json(Object.assign(results));
|
||||||
|
res.end();
|
||||||
|
|
||||||
|
log('Purchase made', req.body.id, req.body.token, req.body.type, req.body.name);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const sellRequest = (connection) => (req, res) => {
|
||||||
|
//validate the credentials
|
||||||
|
let query = 'SELECT COUNT(*) AS total FROM sessions WHERE accountId = ? AND token = ?;';
|
||||||
|
connection.query(query, [req.body.id, req.body.token], (err, credentials) => {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
if (credentials[0].total !== 1) {
|
||||||
|
res.status(400).write(log('Invalid equipment sell credentials', JSON.stringify(body), body.id, body.token));
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//no selling if you're attacking
|
||||||
|
isAttacking(connection, req.body.id, (err, attacking) => {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
if (attacking) {
|
||||||
|
res.status(400).write(log('Can\'t sell while attacking', req.body.id, req.body. token, req.body.type, req.body.name));
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the player's item quantity
|
||||||
|
let query = 'SELECT * FROM equipment WHERE accountId = ? AND type = ? AND name = ?;';
|
||||||
|
connection.query(query, [req.body.id, req.body.type, req.body.name], (err, results) => {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
if (results.length === 0) {
|
||||||
|
res.status(400).write(log('Can\'t sell something you don\'t own', req.body.id, req.body. token, req.body.type, req.body.name));
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the stats for all objects
|
||||||
|
getStatistics((err, { statistics }) => {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
//valid parameters
|
||||||
|
if(!statistics[req.body.type] || !statistics[req.body.type][req.body.name]) {
|
||||||
|
res.status(400).write(log('Invalid equipment sell parameters', req.body.id, req.body.token, req.body.type, req.body.name));
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//for sale?
|
||||||
|
if (!statistics[req.body.type][req.body.name].saleable) {
|
||||||
|
res.status(400).write(log('Item can\'t be sold', req.body.id, req.body.token, req.body.type, req.body.name));
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//sale approved.
|
||||||
|
|
||||||
|
//add gold to the user's account
|
||||||
|
let query = 'UPDATE profiles SET gold = gold + ? WHERE accountId = ?;';
|
||||||
|
connection.query(query, [Math.floor(statistics[req.body.type][req.body.name].cost/2), req.body.id], (err) => {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
//remove the item from the inventory
|
||||||
|
let query = 'UPDATE equipment SET quantity = quantity - 1 WHERE id = ?;';
|
||||||
|
connection.query(query, [results[0].id], (err) => {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
//return the new owned data
|
||||||
|
getOwned(connection, req.body.id, (err, results) => {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
res.status(200).json(Object.assign(results));
|
||||||
|
res.end();
|
||||||
|
|
||||||
|
log('Sale made', req.body.id, req.body.token, req.body.type, req.body.name);
|
||||||
|
|
||||||
|
//Extra: clean the database
|
||||||
|
let query = 'DELETE FROM equipment WHERE quantity <= 0;';
|
||||||
|
connection.query(query, (err) => {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
log('Cleaned database', 'equipment sale');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
equipmentRequest: equipmentRequest
|
equipmentRequest: equipmentRequest,
|
||||||
|
purchaseRequest: purchaseRequest,
|
||||||
|
sellRequest, sellRequest
|
||||||
};
|
};
|
||||||
@@ -49,6 +49,8 @@ combat.runCombatTick(connection);
|
|||||||
|
|
||||||
let equipment = require('./equipment.js');
|
let equipment = require('./equipment.js');
|
||||||
app.post('/equipmentrequest', equipment.equipmentRequest(connection));
|
app.post('/equipmentrequest', equipment.equipmentRequest(connection));
|
||||||
|
app.post('/equipmentpurchaserequest', equipment.purchaseRequest(connection));
|
||||||
|
app.post('/equipmentsellrequest', equipment.sellRequest(connection));
|
||||||
|
|
||||||
//static directories
|
//static directories
|
||||||
app.use('/styles', express.static(path.resolve(__dirname + '/../public/styles')) );
|
app.use('/styles', express.static(path.resolve(__dirname + '/../public/styles')) );
|
||||||
|
|||||||
+2
-1
@@ -1 +1,2 @@
|
|||||||
ALTER TABLE pastCombat CHANGE casualtiesVictor attackerCasualties INTEGER;
|
#NOTE: ALWAYS, ALWAYS, ALWAYS write a script in revert.sql that undoes these changes
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ class CombatLog extends React.Component {
|
|||||||
<p>{this.state.warning}</p>
|
<p>{this.state.warning}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h1 className='centered'>Combat Log</h1>
|
||||||
|
|
||||||
<ButtonHeader />
|
<ButtonHeader />
|
||||||
<PagedCombatLog
|
<PagedCombatLog
|
||||||
setWarning={this.setWarning.bind(this)}
|
setWarning={this.setWarning.bind(this)}
|
||||||
|
|||||||
@@ -55,11 +55,16 @@ class Equipment extends React.Component {
|
|||||||
<p>{this.state.warning}</p>
|
<p>{this.state.warning}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h1 className='centered'>Equipment</h1>
|
||||||
|
<p className='centered'>Equipment sells for half it's cost!</p>
|
||||||
|
<p className='centered'>Scientists: {this.props.scientists} - Gold: {this.props.gold}</p>
|
||||||
|
|
||||||
<EquipmentPanel
|
<EquipmentPanel
|
||||||
getFetch={this.getFetch.bind(this)}
|
getFetch={this.getFetch.bind(this)}
|
||||||
setWarning={this.setWarning.bind(this)}
|
setWarning={this.setWarning.bind(this)}
|
||||||
scientists={this.props.scientists}
|
scientists={this.props.scientists}
|
||||||
gold={this.props.gold}
|
gold={this.props.gold}
|
||||||
|
onSuccess={ () => this.sendRequest('/profilerequest', {username: this.props.username}) }
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -46,8 +46,8 @@ class Equipment extends React.Component {
|
|||||||
<p className='col centered truncate'>{display[key].type}</p>
|
<p className='col centered truncate'>{display[key].type}</p>
|
||||||
<p className='col centered truncate'>{display[key].owned}</p>
|
<p className='col centered truncate'>{display[key].owned}</p>
|
||||||
<p className='col centered truncate'>{display[key].cost}</p>
|
<p className='col centered truncate'>{display[key].cost}</p>
|
||||||
{display[key].purchasable ? <button className='col centered truncate' disabled={true || display[key].cost > this.props.gold}>+ Buy +</button> : <div className='col centered truncate' />}
|
{display[key].purchasable ? <button className='col centered truncate' onClick={() => this.sendRequest('/equipmentpurchaserequest', { name: display[key].name, type: display[key].type }) } disabled={display[key].cost > this.props.gold}>+ Buy +</button> : <div className='col centered truncate' />}
|
||||||
{display[key].saleable ? <button className='col centered truncate' disabled={true || display[key].owned === 0}>- Sell -</button> : <div className='col centered truncate' />}
|
{display[key].saleable ? <button className='col centered truncate' onClick={() => this.sendRequest('/equipmentsellrequest', { name: display[key].name, type: display[key].type }) } disabled={display[key].owned === 0}>- Sell -</button> : <div className='col centered truncate' />}
|
||||||
</div>)}
|
</div>)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -67,9 +67,13 @@ class Equipment extends React.Component {
|
|||||||
|
|
||||||
//on success
|
//on success
|
||||||
this.setState(json);
|
this.setState(json);
|
||||||
|
|
||||||
|
if (this.props.onSuccess) {
|
||||||
|
this.props.onSuccess(json);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (xhr.status === 400 && this.props.setWarning) {
|
else if (xhr.status === 400 && this.props.setWarning) {
|
||||||
this.setWarning(xhr.responseText);
|
this.props.setWarning(xhr.responseText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -121,7 +125,8 @@ Equipment.propTypes = {
|
|||||||
token: PropTypes.number.isRequired,
|
token: PropTypes.number.isRequired,
|
||||||
|
|
||||||
setWarning: PropTypes.func,
|
setWarning: PropTypes.func,
|
||||||
getFetch: PropTypes.func
|
getFetch: PropTypes.func,
|
||||||
|
onSuccess: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStoreToProps = (store) => {
|
const mapStoreToProps = (store) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user