Skip to content

Instantly share code, notes, and snippets.

@vaakx-dev
Last active May 7, 2026 09:35
Show Gist options
  • Select an option

  • Save vaakx-dev/564c2cf10d291e3a643324e5908e3031 to your computer and use it in GitHub Desktop.

Select an option

Save vaakx-dev/564c2cf10d291e3a643324e5908e3031 to your computer and use it in GitHub Desktop.
override the ui.playerChip and get icons from gits to show player pfps not rank
// arcon-manifest:
// name: player-pfp-chips
// permissions: [game, util, storage, chat, net, hud, ui, ui.player_chip]
//
// player pfps - peer-to-peer 64x64 player icons over the istrolid "pfp" chat channel
// - upload via right-click your own chip -> Set my icon -> file picker
// - icons broadcast on server join + on demand (REQ from late joiners)
// - block per-name to drop incoming icons and refuse to display cached
(function () {
if (!window.arcon) {
console.error("player_pfps: arcon not found, load arcon.js first");
return;
}
if (!arcon.require({ major: 1, minor: 4 })) return;
if (!arcon.ui_module) {
console.error("player_pfps: arcon-ui not loaded; chip/chat surfaces unavailable");
return;
}
var CHANNEL = "pfp";
var MAX_DIM = 64;
var MAX_CACHE = 800;
var REPLY_THROTTLE_MS = 30000;
var REQ_PREFIX = "REQ ";
var DATAURL_PREFIX = "data:image/";
var BROADCAST_DELAY_MS = 1000;
var REQUEST_DELAY_MS = 2500;
var store = arcon.storage.namespace("pfp");
var cache = store.get("cache", {});
var my_icon = store.get("my_icon", null);
var blocked = store.get("blocked", []);
var blocked_set = {};
for (var i = 0; i < blocked.length; i++) blocked_set[blocked[i]] = true;
var last_reply_at = {};
var seen_hashes = {};
function is_blocked(name) { return !!blocked_set[name]; }
function set_blocked(name, val) {
if (val) {
if (!blocked_set[name]) {
blocked.push(name);
blocked_set[name] = true;
delete cache[name];
store.set("cache", cache);
}
} else {
delete blocked_set[name];
var idx = blocked.indexOf(name);
if (idx >= 0) blocked.splice(idx, 1);
}
store.set("blocked", blocked);
}
function save_my_icon(dataurl) {
my_icon = dataurl;
store.set("my_icon", dataurl);
}
function clear_my_icon() {
my_icon = null;
store.del("my_icon");
var cmd = arcon.game.commander;
if (cmd && cmd.name) {
delete cache[cmd.name];
store.set("cache", cache);
}
}
function save_to_cache(name, dataurl) {
store.lru_set("cache", name, dataurl, MAX_CACHE);
cache = store.get("cache", {});
}
var ch = arcon.chat.channel(CHANNEL);
function broadcast_my_icon() {
if (!my_icon) return;
ch.send(my_icon);
}
function get_known_player_names() {
var players = arcon.game.players();
var names = [];
for (var i = 0; i < players.length; i++) {
var p = players[i];
if (p && p.name && p.name !== "Server") names.push(p.name);
}
return names;
}
function request_unknown_pfps() {
var cmd = arcon.game.commander;
if (!cmd) return;
var unknown = [];
var names = get_known_player_names();
for (var i = 0; i < names.length; i++) {
var n = names[i];
if (n === cmd.name) continue;
if (cache[n]) continue;
if (is_blocked(n)) continue;
unknown.push(n);
}
if (unknown.length === 0) return;
ch.send(REQ_PREFIX + unknown.join(","));
}
ch.on_message(function (msg) {
if (!msg || !msg.name) return;
var cmd = arcon.game.commander;
if (!cmd) return;
if (msg.name === cmd.name) return;
var text = msg.text || "";
if (text.indexOf(REQ_PREFIX) === 0) {
if (is_blocked(msg.name)) return;
var requested = text.slice(REQ_PREFIX.length).split(",");
if (requested.indexOf(cmd.name) === -1) return;
if (!my_icon) return;
var now = Date.now();
if (last_reply_at[msg.name] && now - last_reply_at[msg.name] < REPLY_THROTTLE_MS) return;
last_reply_at[msg.name] = now;
ch.send(my_icon);
return;
}
if (text.indexOf(DATAURL_PREFIX) === 0) {
if (is_blocked(msg.name)) return;
var h = arcon.util.hash(text);
if (seen_hashes[h] && cache[msg.name] === text) return;
seen_hashes[h] = true;
arcon.util.resize_image(text, MAX_DIM).then(function (normalized) {
save_to_cache(msg.name, normalized);
arcon.ui.refresh();
}).catch(function () {});
}
});
arcon.net.on_join_server(function () {
setTimeout(broadcast_my_icon, BROADCAST_DELAY_MS);
setTimeout(request_unknown_pfps, REQUEST_DELAY_MS);
});
var chip = arcon.ui_module.player_chip;
chip.add_icon_provider(function (player) {
var cmd = arcon.game.commander;
if (cmd && cmd.fleet && cmd.fleet.pfp) {
var local = cmd.fleet.pfp[player.name];
if (local) return local;
}
if (is_blocked(player.name)) return null;
return cache[player.name] || null;
});
chip.add_menu_item({
label_fn: function () { return my_icon ? "Change my icon" : "Set my icon"; },
show_for: "self",
on_click: function () { open_upload_picker(); }
});
chip.add_menu_item({
label_fn: function () { return "Remove my icon"; },
show_for: "self",
is_visible: function () { return !!my_icon; },
on_click: function () {
clear_my_icon();
arcon.ui.menu.close();
}
});
chip.add_menu_item({
label_fn: function (p) { return is_blocked(p.name) ? "Unblock pfp" : "Block pfp"; },
show_for: "others",
on_click: function (p) {
set_blocked(p.name, !is_blocked(p.name));
arcon.ui.menu.close();
}
});
function open_upload_picker() {
arcon.ui.menu.close();
arcon.ui.file_picker({
accept: "image/*",
on_pick: function (dataurl) {
arcon.util.resize_image(dataurl, MAX_DIM).then(function (resized) {
show_preview(resized);
}).catch(function () {
console.error("player_pfps: could not load image");
});
}
});
}
function show_preview(dataurl) {
arcon.ui.modal({
title: "Set your icon",
width: 240,
body_fn: function () {
var d = arcon.ui.dom();
d.div(function () {
d.text_align("center");
d.padding(10);
d.img({ src: dataurl, width: 64, height: 64 }, function () {
d.background_color("rgba(255,255,255,.05)");
});
});
},
confirm_label: "Use this",
on_confirm: function () {
save_my_icon(dataurl);
var cmd = arcon.game.commander;
if (cmd && cmd.name) save_to_cache(cmd.name, dataurl);
broadcast_my_icon();
arcon.ui.refresh();
}
});
}
arcon.hud.register("player_pfps", function () {}, {
mode: "any",
config: {
max_dim: MAX_DIM,
max_cache: MAX_CACHE,
reply_throttle_ms: REPLY_THROTTLE_MS,
channel: CHANNEL
}
});
}.call(this));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment