Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DeepStats core functionality without external backend #44

Open
wants to merge 8 commits into
base: mainline
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions d2bs/kolbot/data/deepstats/sample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[
"{\"item_id\":\"k6x1zs56$2604023116:522:3:1:3\",\"name\":\"The Stone of Jordan Ring\",\"fname\":\"Ring\\nThe Stone of Jordan\",\"description\":\"\\\\xffc4The Stone of Jordan (75)\\n\\\\xffc4Ring\\n\\\\xffc0Required Level: 29\\n\\\\xffc3+1 to All Skills\\n\\\\xffc3Adds 1-12 lightning damage\\n\\\\xffc3+20 to Mana\\n\\\\xffc3Increase Maximum Mana 25%\\n\\\\xffc0Area: Catacombs Level 4\\n\\\\xffc0Line: perfect.nip #268$\",\"action\":\"Kept\",\"ilvl\":75,\"lvlreq\":29,\"quality\":7,\"code\":\"rin4\",\"size\":[1,1],\"class_id\":522,\"type\":10,\"ethereal\":false,\"pickit_line\":\"perfect.nip #268\",\"act\":1,\"last_area\":37,\"difficulty\":2,\"player_count\":2,\"char_name\":\"DaBest\",\"char_level\":99,\"char_class\":1,\"char_mf\":416,\"ladder\":true,\"realm\":\"USWest\",\"hardcore\":false,\"expansion\":true,\"can_teleport\":true}"
]
60 changes: 59 additions & 1 deletion d2bs/kolbot/libs/OOG.js
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ var DataFile = {
experience: 0,
deaths: 0,
lastArea: "",
lastAreaID: 0,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding lastAreaID will then also appear in current logging which should be fine but I think you wanted to avoid that.
You could also maybe use sdk.js instead to parse the ID from string.

gold: 0,
level: 0,
name: "",
Expand Down Expand Up @@ -423,7 +424,7 @@ var DataFile = {

print("Error reading DataFile. Using null values.");

return {runs: 0, experience: 0, lastArea: "", gold: 0, level: 0, name: "", gameName: "", ingameTick: 0, handle: 0, nextGame: ""};
return {runs: 0, experience: 0, lastArea: "", lastAreaID: 0, gold: 0, level: 0, name: "", gameName: "", ingameTick: 0, handle: 0, nextGame: ""};
},

getStats: function () {
Expand Down Expand Up @@ -463,6 +464,7 @@ var DataFile = {
}

obj.lastArea = Pather.getAreaName(me.area);
obj.lastAreaID = me.area;

break;
case "gold":
Expand Down Expand Up @@ -499,6 +501,62 @@ var DataFile = {
}
};

const DeepStats = {
create: function () {
let obj = [],
string;

string = JSON.stringify(obj);

Misc.fileAction("data/deepstats/" + me.profile + ".dump.json", 1, string);

return obj;
},

getObj: function () {
let obj, string;

if (!FileTools.exists("data/deepstats/" + me.profile + ".dump.json")) {
DeepStats.create();
}

string = Misc.fileAction("data/deepstats/" + me.profile + ".dump.json", 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit worried about the potential file size.


try {
obj = JSON.parse(string);
} catch (e) {
// If we failed, file might be corrupted, so create a new one
obj = this.create();
}

if (obj) {
return obj;
}

print("Error reading DeepStats file. Using null values.");

return [];
},

updateStats: function (value) {
while (me.ingame && !me.gameReady) {
delay(100);
}

let currentStats, string;

currentStats = this.getObj();

if (typeof value === "string") {
currentStats.push(value);
}

string = JSON.stringify(currentStats);

Misc.fileAction("data/deepstats/" + me.profile + ".dump.json", 1, string);
}
};

var ControlAction = {
mutedKey: false,

Expand Down
12 changes: 12 additions & 0 deletions d2bs/kolbot/libs/common/Config.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,18 @@ var Config = {
SkipException: [],
ScanShrines: [],
Debug: false,
DeepStats: {
StatsEnabled: false,
SOJReportsEnabled: false,
DCloneReportsEnabled: false,
FileLogOnly: false,
API: {
Token: "", // Auth token used to authenticate, if required, to your backend of choice
ReportItem: "", // Item endpoint at your backend of choice
ReportDClone: "", // DClone reporting endpoint at your backend of choice
ReportSOJsSold: "" // SOJs Sale reporting endpoint at your backend of choice
}
},

AutoMule: {
Trigger: [],
Expand Down
64 changes: 62 additions & 2 deletions d2bs/kolbot/libs/common/Misc.js
Original file line number Diff line number Diff line change
Expand Up @@ -1201,6 +1201,15 @@ var Misc = {
return false;
},

getEstimatedBuild: function () {
let counter, build = 0, builds = [49, 53, 56, 59, 64, 97, 106, 112, 147, 149, 151, 152];
for (counter = 0; counter < builds.length; counter++) {
if (me.getSkill(builds[counter], 1) > build) {
build = builds[counter];
}
}
},

getItemDesc: function (unit) {
var i, desc, index,
stringColor = "";
Expand Down Expand Up @@ -1361,7 +1370,7 @@ var Misc = {
return false;
}

var i;
let i;

if (!Config.LogKeys && ["pk1", "pk2", "pk3"].indexOf(unit.code) > -1) {
return false;
Expand Down Expand Up @@ -1397,7 +1406,8 @@ var Misc = {
}
}

var lastArea, code, desc, sock, itemObj,
let lastArea, code, desc, sock, itemObj, deepstatsData,
lastAreaID = 0,
color = -1,
name = unit.fname.split("\n").reverse().join(" ").replace(/ÿc[0-9!"+<:;.*]|\/|\\/g, "").trim();

Expand All @@ -1406,6 +1416,7 @@ var Misc = {

if (action.match("kept", "i")) {
lastArea = DataFile.getStats().lastArea;
lastAreaID = DataFile.getStats().lastAreaID;

if (lastArea) {
desc += ("\n\\xffc0Area: " + lastArea);
Expand Down Expand Up @@ -1583,6 +1594,55 @@ var Misc = {
sockets: this.getItemSockets(unit)
};

if (Config.DeepStats.StatsEnabled) {
deepstatsData = {
item_id: Date.now().toString(36) + "$" + unit.gid + ":" + unit.classid + ":" + unit.location + ":" + unit.x + ":" + unit.y + (unit.getFlag(0x400000) ? ":eth" : ""),
name: name,
fname: unit.fname,
description: desc,
action: action,
ilvl: unit.ilvl,
lvlreq: unit.lvlreq,
quality: unit.quality,
code: code,
class_id: unit.classid,
type: unit.itemType,
ethereal: !!unit.getFlag(0x400000),
last_area: lastAreaID,
difficulty: me.diff,
player_count: this.getPlayerCount(),
char_name: me.charname,
char_level: me.charlvl,
char_class: me.classid,
char_mf: me.getStat(80),
ladder: me.ladder > 0,
realm: me.realm,
hardcore: me.playertype,
expansion: me.gametype === 1,
can_teleport: me.getSkill(54, 1) > 0,
build: this.getEstimatedBuild(),
};

if (Config.DeepStats.FileLogOnly) {
DeepStats.updateStats(JSON.stringify(deepstatsData));
} else if (!Config.DeepStats.API.Token) {
throw new Error("An auth token is required. Set Config.DeepStats.API.Token");
} else {
const HTTP = require("../modules/HTTP");
DeepStats.updateStats(JSON.stringify(deepstatsData));
HTTP({
url: Config.DeepStats.API.ReportItem,
method: "POST",
headers: {
"Authorization": "Token " + Config.DeepStats.API.Token,
"Content-Type": "application/json",
"Connection": "close"
},
data: JSON.stringify(deepstatsData)
});
}
}

D2Bot.printToItemLog(itemObj);

return true;
Expand Down
43 changes: 43 additions & 0 deletions d2bs/kolbot/tools/ToolsThread.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ function main() {
CraftingSystem.buildLists();
Runewords.init();
Cubing.init();
const HTTP = require("../libs/modules/HTTP");

for (i = 0; i < 5; i += 1) {
timerLastDrink[i] = 0;
Expand Down Expand Up @@ -473,6 +474,28 @@ function main() {

if (Config.SoJWaitTime && me.gametype === 1) { // only do this in expansion
D2Bot.printToConsole(param1 + " Stones of Jordan Sold to Merchants on IP " + me.gameserverip.split(".")[3], 7);

if (Config.DeepStats.SOJReportsEnabled) {
if (!Config.DeepStats.API.Token) {
throw new Error("An auth token is required. Set Config.DeepStats.API.Token");
}
let soj_data = {
ip_address: me.gameserverip.split(".")[3],
realm: me.realm,
ladder: me.ladder > 0,
current_count: param1,
};
HTTP({
url: Config.DeepStats.API.ReportSOJsSold,
method: "POST",
headers: {
"Authorization": "Token " + Config.DeepStats.API.Token,
"Content-Type": "application/json",
},
data: JSON.stringify(soj_data)
});
}

Messaging.sendToScript("default.dbj", "soj");
}

Expand All @@ -498,6 +521,26 @@ function main() {

me.maxgametime = 0;

if (Config.DeepStats.DCloneReportsEnabled) {
if (!Config.DeepStats.API.Token) {
throw new Error("An auth token is required. Set Config.DeepStats.API.Token");
}
let dclone_data = {
ip_address: me.gameserverip.split(".")[3],
realm: me.realm,
ladder: me.ladder > 0,
};
HTTP({
url: Config.DeepStats.API.ReportDClone,
method: "POST",
headers: {
"Authorization": "Token " + Config.DeepStats.API.Token,
"Content-Type": "application/json",
},
data: JSON.stringify(dclone_data)
});
}

if (Config.KillDclone) {
load("tools/clonekilla.js");
}
Expand Down