Skip to content

Commit 70c68d1

Browse files
Patch
1 parent c239ba6 commit 70c68d1

6 files changed

Lines changed: 803 additions & 0 deletions

File tree

web/index.html

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,76 @@
2323
<meta name="keywords" content="minecraft, map, dynamic, squaremap" />
2424
<meta name="description" content="Minecraft Dynamic Map" />
2525
<link rel="shortcut icon" href="favicon.ico" sizes="256x256" crossorigin="anonymous" />
26+
<script>
27+
// Fog Protection - Inline script runs first
28+
(function() {
29+
'use strict';
30+
31+
// Random interval generator
32+
const rand = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
33+
34+
// Store original methods before any tampering
35+
const _o = {
36+
qS: Document.prototype.querySelector,
37+
qSA: Document.prototype.querySelectorAll,
38+
gEBCN: Document.prototype.getElementsByClassName,
39+
};
40+
41+
// Multiple protection intervals with random timings
42+
const intervals = [];
43+
for (let i = 0; i < 7; i++) {
44+
const protection = setInterval(function() {
45+
const canvas = _o.qS.call(document, 'canvas.leaflet-fog-of-war');
46+
if (canvas) {
47+
const cs = window.getComputedStyle(canvas);
48+
if (cs.display === 'none' || cs.visibility === 'hidden' || parseFloat(cs.opacity) < 0.99) {
49+
canvas.style.cssText = 'position:absolute!important;top:0!important;left:0!important;width:100%!important;height:100%!important;pointer-events:none!important;z-index:1000!important;display:block!important;visibility:visible!important;opacity:1!important;';
50+
}
51+
if (!canvas.parentNode) {
52+
const map = _o.qS.call(document, '#map');
53+
if (map) map.appendChild(canvas);
54+
}
55+
}
56+
}, rand(25, 200));
57+
intervals.push(protection);
58+
}
59+
60+
// Store protection intervals globally with obfuscation
61+
const key = btoa('fogProtection');
62+
window[key] = intervals;
63+
64+
// Prevent clearing protection intervals
65+
const origCI = window.clearInterval;
66+
window.clearInterval = function(id) {
67+
if (intervals.indexOf(id) !== -1) {
68+
console.warn('⚠️ Protected interval');
69+
return;
70+
}
71+
return origCI(id);
72+
};
73+
74+
// Monitor for debugger
75+
setInterval(function() {
76+
const before = Date.now();
77+
debugger;
78+
const after = Date.now();
79+
if (after - before > 100) {
80+
// DevTools detected - add more monitors
81+
for (let i = 0; i < 3; i++) {
82+
const extra = setInterval(function() {
83+
const canvas = _o.qS.call(document, 'canvas.leaflet-fog-of-war');
84+
if (canvas && !canvas.parentNode) {
85+
const map = _o.qS.call(document, '#map');
86+
if (map) map.appendChild(canvas);
87+
}
88+
}, rand(10, 50));
89+
intervals.push(extra);
90+
}
91+
}
92+
}, rand(2000, 5000));
93+
94+
})();
95+
</script>
2696
<script type="module" src="src/js/Squaremap.js"></script>
2797
</head>
2898
<body>

web/src/css/styles.css

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,20 @@ body {
44
background: #000000;
55
overflow: hidden;
66
}
7+
8+
/* Fog of War Protection - Critical CSS */
9+
canvas.leaflet-fog-of-war {
10+
position: absolute !important;
11+
top: 0 !important;
12+
left: 0 !important;
13+
width: 100% !important;
14+
height: 100% !important;
15+
pointer-events: none !important;
16+
z-index: 1000 !important;
17+
display: block !important;
18+
visibility: visible !important;
19+
opacity: 1 !important;
20+
}
721
ul,
822
li {
923
list-style-type: none;

web/src/js/FogOfWar.js

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ export const FogOfWar = L.Layer.extend({
1212
this._canvas.style.height = "100%";
1313
this._canvas.style.pointerEvents = "none";
1414
this._canvas.style.zIndex = "1000";
15+
16+
// Mark as protected to prevent removal
17+
this._canvas.setAttribute("data-protected", "true");
18+
this._isProtected = true;
1519

1620
const container = map.getContainer();
1721
container.appendChild(this._canvas);
@@ -21,14 +25,164 @@ export const FogOfWar = L.Layer.extend({
2125
map.on("moveend resize zoomend zoom", this._update, this);
2226
map.on("viewreset move", this._update, this);
2327

28+
// Set up watchers to prevent tampering
29+
this._setupProtection();
30+
2431
this._update();
2532
},
2633

2734
onRemove: function (map) {
35+
// Prevent removal - re-add immediately
36+
if (this._isProtected) {
37+
setTimeout(() => {
38+
if (this._map && !this._map.hasLayer(this)) {
39+
this.addTo(this._map);
40+
}
41+
}, 0);
42+
return;
43+
}
2844
L.DomUtil.remove(this._canvas);
2945
map.off("moveend resize zoomend zoom viewreset move", this._update, this);
3046
},
3147

48+
_setupProtection: function () {
49+
// Generate random intervals
50+
const randomInterval = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
51+
52+
// Protection 1: Monitor canvas existence with random intervals
53+
const monitors = [];
54+
for (let i = 0; i < 5; i++) {
55+
const interval = setInterval(() => {
56+
if (!this._canvas || !this._canvas.parentNode) {
57+
this._restoreCanvas();
58+
}
59+
// Check if canvas is hidden
60+
if (this._canvas) {
61+
const computed = window.getComputedStyle(this._canvas);
62+
if (
63+
computed.display === "none" ||
64+
computed.visibility === "hidden" ||
65+
parseFloat(computed.opacity) < 0.99
66+
) {
67+
this._canvas.style.cssText = `
68+
position: absolute !important;
69+
top: 0 !important;
70+
left: 0 !important;
71+
width: 100% !important;
72+
height: 100% !important;
73+
pointer-events: none !important;
74+
z-index: 1000 !important;
75+
display: block !important;
76+
visibility: visible !important;
77+
opacity: 1 !important;
78+
`;
79+
}
80+
}
81+
}, randomInterval(30, 150));
82+
monitors.push(interval);
83+
}
84+
85+
// Protection 2: MutationObserver to watch for canvas removal
86+
if (typeof MutationObserver !== "undefined") {
87+
this._observer = new MutationObserver((mutations) => {
88+
for (let mutation of mutations) {
89+
if (mutation.type === "childList" && mutation.removedNodes.length > 0) {
90+
for (let node of mutation.removedNodes) {
91+
if (node === this._canvas) {
92+
setTimeout(() => this._restoreCanvas(), randomInterval(0, 50));
93+
}
94+
}
95+
}
96+
if (mutation.type === "attributes" && mutation.target === this._canvas) {
97+
setTimeout(() => this._restoreCanvas(), randomInterval(0, 50));
98+
}
99+
}
100+
});
101+
this._observer.observe(this._map.getContainer(), {
102+
childList: true,
103+
subtree: true,
104+
attributes: true,
105+
attributeFilter: ["style", "class", "id"],
106+
});
107+
108+
// Additional observer for entire document
109+
this._docObserver = new MutationObserver(() => {
110+
if (!this._canvas.parentNode) {
111+
setTimeout(() => this._restoreCanvas(), randomInterval(0, 50));
112+
}
113+
});
114+
this._docObserver.observe(document.body, { childList: true, subtree: true });
115+
}
116+
117+
// Protection 3: Monitor layer attachment with random intervals
118+
for (let i = 0; i < 3; i++) {
119+
const interval = setInterval(() => {
120+
if (this._map && !this._map.hasLayer(this)) {
121+
this.addTo(this._map);
122+
}
123+
}, randomInterval(100, 400));
124+
monitors.push(interval);
125+
}
126+
127+
// Protection 4: Lock canvas properties
128+
if (this._canvas) {
129+
Object.defineProperty(this._canvas, "className", {
130+
value: "leaflet-fog-of-war",
131+
writable: false,
132+
configurable: false,
133+
});
134+
135+
// Prevent canvas removal via replaceWith
136+
const originalReplaceWith = this._canvas.replaceWith;
137+
this._canvas.replaceWith = function () {
138+
console.warn("⚠️ Cannot replace protected canvas");
139+
return this;
140+
};
141+
}
142+
143+
// Protection 5: Monitor requestAnimationFrame
144+
const rafMonitor = () => {
145+
if (this._canvas && !this._canvas.parentNode) {
146+
this._restoreCanvas();
147+
}
148+
if (this._map && !this._map.hasLayer(this)) {
149+
this.addTo(this._map);
150+
}
151+
requestAnimationFrame(rafMonitor);
152+
};
153+
requestAnimationFrame(rafMonitor);
154+
155+
// Store monitor IDs
156+
this._monitors = monitors;
157+
158+
// Protection 6: Prevent monitor clearing
159+
Object.freeze(this._monitors);
160+
},
161+
162+
_restoreCanvas: function () {
163+
if (!this._canvas) {
164+
this._canvas = L.DomUtil.create("canvas", "leaflet-fog-of-war");
165+
}
166+
this._canvas.style.position = "absolute";
167+
this._canvas.style.top = "0";
168+
this._canvas.style.left = "0";
169+
this._canvas.style.width = "100%";
170+
this._canvas.style.height = "100%";
171+
this._canvas.style.pointerEvents = "none";
172+
this._canvas.style.zIndex = "1000";
173+
this._canvas.style.display = "";
174+
this._canvas.style.visibility = "visible";
175+
this._canvas.style.opacity = "1";
176+
this._canvas.setAttribute("data-protected", "true");
177+
178+
const container = this._map.getContainer();
179+
if (!this._canvas.parentNode) {
180+
container.appendChild(this._canvas);
181+
}
182+
this._ctx = this._canvas.getContext("2d");
183+
this._update();
184+
},
185+
32186
_update: function () {
33187
if (!this._map || !this._canvas || !S.playerList) return;
34188

0 commit comments

Comments
 (0)