market implement
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name Grepolis Remote Control
|
// @name Grepolis Remote Control
|
||||||
// @namespace http://tampermonkey.net/
|
// @namespace http://tampermonkey.net/
|
||||||
// @version 2.6
|
// @version 2.7
|
||||||
// @description Polls grepo.haunter-pets.top for remote commands and executes them in-game
|
// @description Polls grepo.haunter-pets.top for remote commands and executes them in-game
|
||||||
// @author Dimitrios
|
// @author Dimitrios
|
||||||
// @match https://*.grepolis.com/game/*
|
// @match https://*.grepolis.com/game/*
|
||||||
@@ -414,7 +414,36 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
// Poll for and execute pending commands (build + recruit in parallel)
|
// Execute: Market
|
||||||
|
// ----------------------------------------------------------------
|
||||||
|
async function executeMarketOffer(cmd) {
|
||||||
|
const { town_id, payload } = cmd;
|
||||||
|
const { offer, offer_type, demand, demand_type, max_delivery_time, visibility } = payload;
|
||||||
|
|
||||||
|
const town = uw.ITowns?.getTown?.(town_id) || uw.ITowns?.towns?.[town_id];
|
||||||
|
if (!town) {
|
||||||
|
return { ok: false, msg: `Town ${town_id} not found` };
|
||||||
|
}
|
||||||
|
|
||||||
|
const reactionMs = randInt(800, 2500);
|
||||||
|
log(`Waiting ${reactionMs}ms before firing market offer (reaction time)...`);
|
||||||
|
await sleep(reactionMs);
|
||||||
|
|
||||||
|
uw.gpAjax.ajaxPost('frontend_bridge', 'execute', {
|
||||||
|
model_url: 'CreateOffers/' + town_id,
|
||||||
|
action_name: 'createOffer',
|
||||||
|
captcha: null,
|
||||||
|
arguments: {
|
||||||
|
offer, offer_type, demand, demand_type, max_delivery_time, visibility
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await sleep(500);
|
||||||
|
return { ok: true, msg: `Market offer posted: ${offer} ${offer_type} => ${demand} ${demand_type}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------
|
||||||
|
// Poll for and execute pending commands (build + recruit + market)
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
async function pollAndExecute() {
|
async function pollAndExecute() {
|
||||||
if (paused) return;
|
if (paused) return;
|
||||||
@@ -428,9 +457,10 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build queue and Recruit queue are now independent
|
// Build queue, Recruit queue and Market queue are independent
|
||||||
const buildCmd = cmdData.build;
|
const buildCmd = cmdData.build;
|
||||||
const recruitCmd = cmdData.recruit;
|
const recruitCmd = cmdData.recruit;
|
||||||
|
const marketCmd = cmdData.market;
|
||||||
|
|
||||||
const execute = async (cmd) => {
|
const execute = async (cmd) => {
|
||||||
if (!cmd) return;
|
if (!cmd) return;
|
||||||
@@ -439,6 +469,7 @@
|
|||||||
try {
|
try {
|
||||||
if (cmd.type === 'build') result = await executeBuild(cmd);
|
if (cmd.type === 'build') result = await executeBuild(cmd);
|
||||||
else if (cmd.type === 'recruit') result = await executeRecruit(cmd);
|
else if (cmd.type === 'recruit') result = await executeRecruit(cmd);
|
||||||
|
else if (cmd.type === 'market_offer') result = await executeMarketOffer(cmd);
|
||||||
else result = { ok: false, msg: `Unknown type: ${cmd.type}` };
|
else result = { ok: false, msg: `Unknown type: ${cmd.type}` };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
result = { ok: false, msg: `Exception: ${e.message}` };
|
result = { ok: false, msg: `Exception: ${e.message}` };
|
||||||
@@ -448,8 +479,8 @@
|
|||||||
reportResult(cmd.id, finalStatus, result.msg);
|
reportResult(cmd.id, finalStatus, result.msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Run both queues concurrently — they do NOT block each other
|
// Run concurrently — they do NOT block each other
|
||||||
await Promise.all([execute(buildCmd), execute(recruitCmd)]);
|
await Promise.all([execute(buildCmd), execute(recruitCmd), execute(marketCmd)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
|
|||||||
@@ -93,13 +93,15 @@ def get_pending_command():
|
|||||||
|
|
||||||
build_cmd = _fetch_pending_of_type(c, 'build')
|
build_cmd = _fetch_pending_of_type(c, 'build')
|
||||||
recruit_cmd = _fetch_pending_of_type(c, 'recruit')
|
recruit_cmd = _fetch_pending_of_type(c, 'recruit')
|
||||||
|
market_cmd = _fetch_pending_of_type(c, 'market_offer')
|
||||||
|
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
'build': build_cmd,
|
'build': build_cmd,
|
||||||
'recruit': recruit_cmd
|
'recruit': recruit_cmd,
|
||||||
|
'market': market_cmd
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -144,8 +144,8 @@ def create_command():
|
|||||||
return jsonify({'error': f'missing field: {field}'}), 400
|
return jsonify({'error': f'missing field: {field}'}), 400
|
||||||
|
|
||||||
cmd_type = data['type']
|
cmd_type = data['type']
|
||||||
if cmd_type not in ('build', 'recruit'):
|
if cmd_type not in ('build', 'recruit', 'market_offer'):
|
||||||
return jsonify({'error': 'type must be build or recruit'}), 400
|
return jsonify({'error': 'type must be build, recruit, or market_offer'}), 400
|
||||||
|
|
||||||
# Reject if the Tampermonkey client is offline (no state push in last 150 s)
|
# Reject if the Tampermonkey client is offline (no state push in last 150 s)
|
||||||
conn = get_db()
|
conn = get_db()
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ window.sendCommand = async function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
payload = { building_id };
|
payload = { building_id };
|
||||||
} else {
|
} else if (type === 'recruit') {
|
||||||
const unit_id = document.getElementById('unit-select').value;
|
const unit_id = document.getElementById('unit-select').value;
|
||||||
const amount = parseInt(document.getElementById('recruit-amount').value) || 1;
|
const amount = parseInt(document.getElementById('recruit-amount').value) || 1;
|
||||||
const uData = town.unit_data?.[unit_id];
|
const uData = town.unit_data?.[unit_id];
|
||||||
@@ -142,6 +142,15 @@ window.sendCommand = async function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
payload = { unit_id, amount };
|
payload = { unit_id, amount };
|
||||||
|
} else if (type === 'market_offer') {
|
||||||
|
const offer = parseInt(document.getElementById('market-offer-amount').value) || 1000;
|
||||||
|
const offer_type = document.getElementById('market-offer-type').value;
|
||||||
|
const demand = parseInt(document.getElementById('market-demand-amount').value) || 1000;
|
||||||
|
const demand_type = document.getElementById('market-demand-type').value;
|
||||||
|
const max_delivery_time = parseInt(document.getElementById('market-max-time').value) || 1800;
|
||||||
|
const visibility = document.getElementById('market-visibility').value;
|
||||||
|
|
||||||
|
payload = { offer, offer_type, demand, demand_type, max_delivery_time, visibility };
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ window.onCmdTypeChange = function() {
|
|||||||
document.getElementById('build-options').style.display = type === 'build' ? '' : 'none';
|
document.getElementById('build-options').style.display = type === 'build' ? '' : 'none';
|
||||||
document.getElementById('recruit-options').style.display = type === 'recruit' ? '' : 'none';
|
document.getElementById('recruit-options').style.display = type === 'recruit' ? '' : 'none';
|
||||||
document.getElementById('amount-group').style.display = type === 'recruit' ? '' : 'none';
|
document.getElementById('amount-group').style.display = type === 'recruit' ? '' : 'none';
|
||||||
|
document.getElementById('market-options').style.display = type === 'market_offer' ? '' : 'none';
|
||||||
};
|
};
|
||||||
|
|
||||||
window.renderBuildingDropdown = function() {
|
window.renderBuildingDropdown = function() {
|
||||||
|
|||||||
@@ -71,6 +71,7 @@
|
|||||||
<select id="cmd-type" onchange="onCmdTypeChange()">
|
<select id="cmd-type" onchange="onCmdTypeChange()">
|
||||||
<option value="build">Build / Upgrade</option>
|
<option value="build">Build / Upgrade</option>
|
||||||
<option value="recruit">Recruit Troops</option>
|
<option value="recruit">Recruit Troops</option>
|
||||||
|
<option value="market_offer">Παζάρι - Προσφορά</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -117,6 +118,60 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Market options -->
|
||||||
|
<div class="form-group" id="market-options" style="display:none">
|
||||||
|
<div style="display:flex; gap:10px; margin-bottom:10px;">
|
||||||
|
<div style="flex:1;">
|
||||||
|
<label>Προσφορά</label>
|
||||||
|
<input type="number" id="market-offer-amount" value="1000" min="1" max="99999" style="width:100%;">
|
||||||
|
</div>
|
||||||
|
<div style="flex:1;">
|
||||||
|
<label>Πόρος Προσφοράς</label>
|
||||||
|
<select id="market-offer-type">
|
||||||
|
<option value="wood">Ξύλο</option>
|
||||||
|
<option value="stone">Πέτρα</option>
|
||||||
|
<option value="iron">Ασήμι</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="display:flex; gap:10px; margin-bottom:10px;">
|
||||||
|
<div style="flex:1;">
|
||||||
|
<label>Ζήτηση</label>
|
||||||
|
<input type="number" id="market-demand-amount" value="1000" min="1" max="99999" style="width:100%;">
|
||||||
|
</div>
|
||||||
|
<div style="flex:1;">
|
||||||
|
<label>Πόρος Ζήτησης</label>
|
||||||
|
<select id="market-demand-type">
|
||||||
|
<option value="iron">Ασήμι</option>
|
||||||
|
<option value="stone">Πέτρα</option>
|
||||||
|
<option value="wood">Ξύλο</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="display:flex; gap:10px;">
|
||||||
|
<div style="flex:1;">
|
||||||
|
<label>Χρόνος (Ώρες)</label>
|
||||||
|
<select id="market-max-time">
|
||||||
|
<option value="1800">0.5</option>
|
||||||
|
<option value="3600">1</option>
|
||||||
|
<option value="7200">2</option>
|
||||||
|
<option value="14400">4</option>
|
||||||
|
<option value="28800">8</option>
|
||||||
|
<option value="43200">12</option>
|
||||||
|
<option value="86400">24</option>
|
||||||
|
<option value="172800">48</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div style="flex:1;">
|
||||||
|
<label>Ορατότητα</label>
|
||||||
|
<select id="market-visibility">
|
||||||
|
<option value="all">Όλοι</option>
|
||||||
|
<option value="alliance">Συμμαχία</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group" id="amount-group" style="display:none">
|
<div class="form-group" id="amount-group" style="display:none">
|
||||||
<label>Amount</label>
|
<label>Amount</label>
|
||||||
<input type="number" id="recruit-amount" value="1" min="1" max="9999" style="width:80px;">
|
<input type="number" id="recruit-amount" value="1" min="1" max="9999" style="width:80px;">
|
||||||
|
|||||||
Reference in New Issue
Block a user