Skip to content

Instantly share code, notes, and snippets.

@at15four2020
Last active September 23, 2022 15:27
Show Gist options
  • Save at15four2020/df27d2a0296bd3827eb4f86bf8d53347 to your computer and use it in GitHub Desktop.
Save at15four2020/df27d2a0296bd3827eb4f86bf8d53347 to your computer and use it in GitHub Desktop.
Buy items from the marketplace as soon as they appear.
var GMarketplaceBuyer = (function () {
if (typeof setTimeout == 'undefined') {
load("https://gist.githubusercontent.com/kayhadrin/4bf141103420b79126e434dfcf6d4826/raw/a9174bacb2e4d0d8a619d2575b8de55a291c8786/js-timeout-polyfill.js")
}
if (typeof Promise == 'undefined') {
load("https://cdn.jsdelivr.net/npm/es6-promise/dist/es6-promise.auto.min.js")
}
if (typeof RoomChatManager == 'undefined') {
load("https://gist.github.com/Alynva/7f5dd840fc54fa49e0c538f51b69ac93/raw/RoomChatManager.gprog.js")
}
if (typeof parse_in_MarketPlaceOffers == 'undefined') {
load("https://gist.github.com/at15four2020/2d69302316f3705dec18e6a04c432896/raw/parse_in_MarketPlaceOffers.gprog.js")
}
var timeBetweenBaches = 4 * 1000
var timeBetweenSearchs = 1 * 1000
var timeBetweenPurchases = 1 * 1000
var timeBetweenClearLog = 20 * 1000
var list = {}
var running = false
var clearLogInterval
var buyInterval
var buyOffers = []
var itemsPurchased = 0
function startBuying() {
buyInterval = setInterval(function() {
if (buyOffers.length) {
if (!safeMode || (safeMode && itemsPurchased < safeMode.maxPurchases)) {
sendToServer(HPacketToServer("BuyMarketplaceOffer", [buyOffers.shift()]))
if (safeMode) {
itemsPurchased++ // TODO: this way it's not 100% sure that we got the offer
if (itemsPurchased > safeMode.maxPurchases) {
stopHandler()
if (safeMode.restartAfter >= 0) {
setTimeout(startHandler, safeMode.restartAfter)
}
}
}
}
}
}, timeBetweenPurchases)
}
function startHandler() {
running = true
manager.sendChat(">;>;>;> STARTED <;<;<;<")
tick()
clearLogInterval = setInterval(clear, timeBetweenClearLog)
startBuying()
}
function stopHandler() {
running = false
manager.sendChat(">;>;>;> STOPPED <;<;<;<")
clearInterval(clearLogInterval)
clearInterval(buyInterval)
}
function helpHandler() {
print("\
====== GMarketplaceBuyer loaded! ======\n\
\n\
Buy items from the marketplace as soon as they appear.\n\
\n\
Available in-room chat commands:\n\
\n\
- \"/search text\": search any text in the marketplace. Useful to grab the sprite id of the items.\n\
\n\
- \"/add searchText spriteId price\": add a new item to buy. You must provide the search text that the item can be found, the sprite of that item and the minimum price you want to pay.\n\
- \"/remove spriteId\": stop buying this item, from any search text.\n\
- \"/list\": show in the in-room chat all the items that will be searched.\n\
- \"/export\": print the search code in the log so you can place it in your script and save them.\n\
\n\
- \"/start\": start making searches. You shouldn't navigate in the marketplace manually while running.\n\
- \"/stop\": stop making searches.\n\
\n\
- \"/help\": display this message.\n\
\n\
Available in-script methods:\n\
\n\
- \"GMarketplaceBuyer.config(config: any): void\": \n\
Change the default timings, in milliseconds. Available props:\n\
- \"config.bachesDelay\": wait time before restart to the first search text;\n\
- \"config.searchDelay\": wait time between each search;\n\
- \"config.purchasesDelay\": time between each attempt to buy an offer;\n\
- \"config.clearLogDelay\": interval to clear the log;\n\
\n\
- \"GPlaceRecorder.safeMode(opts: any): void\": \n\
Enable the safe mode to prevent wrong purchases. Available props:\n\
- \"opts.maxPurchases\": number of items purchased before stop the script;\n\
- \"opts.restartAfter\": wait time to restart the script, negative numbers never restart;\n\
\n\
- \"GPlaceRecorder.search(text: string): BuyerObject\": \n\
Start initializing the list of items. The return object must also be used to set the sprite id and the price, and it can be done multiple times in a row. Only after the price is set, the item is added to the list.\n\
Example:\n\
GMarketplaceBuyer\n\
.search(\"abc\")\n\
.buy(1111).price(11)\n\
.buy(2222).price(22)\n\
.buy(3333).price(33)\n\
\n\
======================================\n\
")
}
var manager = RoomChatManager({
inChatHeaderId: "Chat",
outChatHeaderId: "Chat"
})
manager.handleCommand("search", function (message, command) {
var searchText = command.extra
sendOffertsInChat = true
sendToServer(HPacketToServer("GetMarketplaceOffers", [-1, -1, searchText, 1]))
manager.sendChat("Searching for \""+command.extra+"\"")
}, "/")
manager.handleCommand("add", function (message, command) {
var parts = command.extra.split(" ")
var price = Number(parts.pop())
var spriteId = Number(parts.pop())
var text = parts.join(" ")
if (isNaN(price) || isNaN(spriteId) || text == "") {
manager.sendChat("You need to type the search text, the sprite id, and the value to buy.")
return
}
addItem(text, spriteId, price)
manager.sendChat("Added item \""+text+"\" ("+spriteId+") by "+price+"c")
}, "/")
manager.handleCommand("remove", function (message, command) {
var texts = Object.keys(list)
var spriteId = command.extra
for (var i = 0; i < texts.length; i++){
var text = texts[i]
list[text] = list[text].filter(function (elem) {
return elem.spriteId != spriteId
})
manager.sendChat("Stop looking for "+text+"/"+spriteId)
if (!list[text].length)
delete list[text]
}
}, "/")
manager.handleCommand("list", function () {
var texts = Object.keys(list)
if (!texts.length) {
manager.sendChat("Nothing to search.")
} else {
manager.sendChat("Searching for this items:")
texts.forEach(function (text) {
list[text].forEach(function (item) {
manager.sendChat("Search text: " + text + " / Sprite: " + item.spriteId + " / Price: " + item.price, -1)
})
})
}
}, "/")
manager.handleCommand("export", function () {
var texts = Object.keys(list)
if (!texts.length) {
manager.sendChat("Nothing to export.")
} else {
var result = ""
manager.sendChat("Search code printed in the log.")
texts.forEach(function (text) {
result += "GMarketplaceBuyer\n .search(\"" + text + "\")"
list[text].forEach(function (item) {
result += "\n .buy(" + item.spriteId + ").price(" + item.price + ")"
})
result += "\n\n"
})
print(result)
}
}, "/")
manager.handleCommand("start", startHandler, "/")
manager.handleCommand("stop", stopHandler, "/")
manager.handleCommand("help", function() {
manager.sendChat("Help message printed in the log.")
helpHandler()
}, "/")
function addItem(text, spriteId, price) {
if (list[text]){
list[text].push({
spriteId: spriteId,
price: price
})
} else {
list[text] = [{
spriteId: spriteId,
price: price
}]
}
}
function find(array, handler) {
var result = undefined
for (var i = 0; i < array.length; i++) {
if (handler(array[i], i, array)) {
result = array[i]
break
}
}
return result
}
var sendOffertsInChat = false
function handleOffers(message) {
var packet = message.getPacket()
var packetParsed = parse_in_MarketPlaceOffers(packet)
if (sendOffertsInChat) {
if (!packetParsed.items.length) {
manager.sendChat("No items found.")
return
}
manager.sendChat("Here are "+packetParsed.items.length+" results:")
}
for (var i = 0; i < packetParsed.items.length; i++) {
var item = packetParsed.items[i]
var texts = Object.keys(list)
var elemInList = null
texts.forEach(function(text) {
if (elemInList) return
elemInList = find(list[text], function (elem) {
return elem.spriteId == item.spriteId
})
})
if (elemInList && elemInList.price >= item.price) {
manager.sendChat("You should buy "+item.spriteId+" because it is by "+item.price+"c and you asked for "+elemInList.price+"c", 28)
manager.sendChat("Sprite: "+item.spriteId+" / Offer: "+item.offerId, -1)
if (running) buyOffers.push(item.offerId)
}
if (sendOffertsInChat) {
manager.sendChat("Price: " + item.price + " / Avg: " + item.average + " / Amount: " + item.amount + " / Sprite: " + item.spriteId + " / "+item.typeReadable+(item.type == 3 ? " (" + item.ltd.number + "/" + item.ltd.max + ")" : ""), -1)
}
}
if (sendOffertsInChat && packetParsed.totalResults > packetParsed.items.length) {
manager.sendChat("Showing the first "+ packetParsed.items.length +", there are "+(packetParsed.totalResults - packetParsed.items.length)+ " more results ("+ packetParsed.totalResults + " in total).", 0)
}
sendOffertsInChat = false
}
interceptToClient(3545, handleOffers)
function wait(ms) {
return new Promise(function(resolve) { setTimeout(resolve, ms) });
}
function makeSearch(list) {
return new Promise(function (resolve) {
var texto = list[0]
print(texto)
if (!texto) return resolve()
sendToServer(HPacketToServer("GetMarketplaceOffers", [-1, -1, texto, 1]))
wait(timeBetweenSearchs)
.then(function() {
if (list.length > 1) {
return makeSearch(list.slice(1))
}
})
.then(resolve)
})
}
function tick() {
if(!running) return
var texts = Object.keys(list).filter(function(text) {
return list[text].length
})
makeSearch(texts.slice())
.then(function () { return wait(timeBetweenBaches) })
.then(tick)
}
tick()
helpHandler()
var GMarketplaceBuyer = {}
GMarketplaceBuyer.config = function (config) {
timeBetweenBaches = config.bachesDelay
timeBetweenSearchs = config.searchDelay
timeBetweenPurchases = config.purchasesDelay
timeBetweenClearLog = config.clearLogDelay
}
var safeMode = false
GMarketplaceBuyer.safeMode = function (opts) {
safeMode = opts
}
function buildBuyerObject(text) {
var buyer = {}
buyer.buy = function (spriteId) {
var pricer = {}
pricer.price = function (price) {
addItem(text, spriteId, price)
return buildBuyerObject(text)
}
return pricer
}
return buyer
}
GMarketplaceBuyer.search = function (text) {
return buildBuyerObject(text)
}
GMarketplaceBuyer.loadLegacyList = function (newList) {
list = newList
}
return GMarketplaceBuyer
})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment