'))
+ .append($('')
+ .append($(' max. SNARK CACHE SIZE: '))
+ .append($(``))
+ .append($(` ${state.cacheLimit} `))
+ )
+ .append($('')
+ .append($(`Clear`))
+ );
+ $(`input:radio[name=rendering][value=${state.rendering}]`).prop("checked", true);
+ $('#cachingBox').prop("checked", state.caching);
+ $('input:radio[name=rendering]').change(function () { state.rendering = this.value });
+ const [fpsSpan, percentageSpan, cacheLimitSizeSpan] = [$("#fpsSpan"), $("#percentageSpan"), $("#cacheLimitSizeSpan")];
+ $('#fpsRange').change(function () { state.renderingFps = parseInt(this.value) }).on("input", function () { fpsSpan.text(` ${this.value} FPS`) });
+ $('#percentageRange').change(function () { state.renderingPercentage = parseInt(this.value) }).on("input", function () { percentageSpan.text(` ${this.value}%`) });
+
+ $('#cacheLimitSize').change(function () { state.cacheLimit = parseInt(this.value) }).on("input", function () { cacheLimitSizeSpan.text(` ${this.value}`) });
+ $('#cacheClearBtn').click(() => { this.clearSnarkCache(); })
+ }
+
+ destroy() {
+ state.pluginWindow = null;
+ }
+}
+
+export default PerformanceOptimizer;
\ No newline at end of file
diff --git a/client/embedded_plugins/Rage-Cage.ts b/client/embedded_plugins/Rage-Cage.ts
deleted file mode 100644
index 07632342..00000000
--- a/client/embedded_plugins/Rage-Cage.ts
+++ /dev/null
@@ -1,89 +0,0 @@
-class RageCage implements DFPlugin {
- private img: HTMLImageElement;
- private loaded: boolean;
-
- /**
- * As you saw in the README plugin, you can render
- * arbitrary HTML UI into a Dark Forest modal.
- */
- async render(div: HTMLDivElement) {
- // once this plugin is run, let's load a nice image
- // from the internet, in order to draw it on top of
- // planets
- this.img = document.createElement('img');
- this.loaded = false;
- div.appendChild(this.img);
-
- this.img.addEventListener('load', () => {
- // we should only use the image once
- // it actually loads.
- this.loaded = true;
- div.innerText = 'welcome to nicolas cage world';
- });
-
- this.img.src =
- 'https://upload.wikimedia.org/wikipedia/' + 'commons/c/c0/Nicolas_Cage_Deauville_2013.jpg';
-
- // hide the image, it doesn't need to show up
- // in the modal, we only need this img element
- // to load the image.
- this.img.style.display = 'none';
-
- div.style.width = '100px';
- div.style.height = '100px';
- div.innerText = 'loading, please wait!';
- // check out the helpful functions that appear
- // in the Viewport class!
- console.log(ui.getViewport());
- }
-
- /**
- * In addition to rendering HTML UI into a div, plugins
- * can draw directly onto the game UI. This function is
- * optional, but if it exists, it is called in sync with
- * the rest of the game, and allows you to draw onto an
- * HTML5 canvas that lays on top of the rest of the game.
- *
- * In the example below, we render an image on top of every
- * planet.
- *
- * ctx is an instance of CanvasRenderingContext2D.
- */
- draw(ctx: CanvasRenderingContext2D) {
- // don't draw anything until nic cage loads
- if (!this.loaded) return;
-
- // the viewport class provides helpful functions for
- // interacting with the currently-visible area of the
- // game
- const viewport = ui.getViewport();
- const planets = ui.getPlanetsInViewport();
-
- for (const p of planets) {
- // use the Viewport class to determine the pixel
- // coordinates of the planet on the screen
- const pixelCenter = viewport.worldToCanvasCoords(
- // @ts-ignore
- p.location.coords
- );
-
- // how many pixels is the radius of the planet?
- const trueRadius = viewport.worldToCanvasDist(ui.getRadiusOfPlanetLevel(p.planetLevel));
-
- // draw nicolas cage on top of the planet
- ctx.drawImage(
- this.img,
- 50,
- 50,
- 400,
- 400,
- pixelCenter.x - trueRadius,
- pixelCenter.y - trueRadius,
- trueRadius * 2,
- trueRadius * 2
- );
- }
- }
-}
-
-export default RageCage;
diff --git a/client/embedded_plugins/Remote-Explorer.ts b/client/embedded_plugins/Remote-Explorer.ts
index d5bd5a68..5a27e70a 100644
--- a/client/embedded_plugins/Remote-Explorer.ts
+++ b/client/embedded_plugins/Remote-Explorer.ts
@@ -1,7 +1,7 @@
// organize-imports-ignore
-import type { Chunk, WorldCoords } from '@dfdao/types';
+import type { Chunk, WorldCoords } from '@darkforest_eth/types';
//@ts-ignore
-import { locationIdFromDecStr } from 'https://cdn.skypack.dev/@dfdao/serde';
+import { locationIdFromDecStr } from 'https://cdn.skypack.dev/@darkforest_eth/serde';
import {
html,
render,
@@ -287,6 +287,7 @@ function App({
return html`
+
Warning: mimc has been reduced to 5. \nUpdate your explorer!
${miners.map(
(miner: ExtendedMinerManager) => html`
<${MinerUI} key=${miner.url} miner=${miner} onRemove=${remove} />
@@ -330,6 +331,7 @@ class RemoteExplorerPlugin implements DFPlugin {
pattern,
df.getWorldRadius(),
df.planetRarity,
+ df.planetLevelThresholds,
df.getHashConfig(),
false,
() => new RemoteWorker(url)
diff --git a/client/embedded_plugins/Renderer-Showcase.ts b/client/embedded_plugins/Renderer-Showcase.ts
deleted file mode 100644
index 9c8582d7..00000000
--- a/client/embedded_plugins/Renderer-Showcase.ts
+++ /dev/null
@@ -1,938 +0,0 @@
-/* eslint-disable */
-/**
- * Below is a list of class definitions for renderers.
- * These are blank renderers as they have no functionality.
- * The result of using these renderers is the same as disabling the renderer.
- */
-// organize-imports-ignore
-import {
- engineConsts,
- EngineUtils,
- GameGLManager,
- GenericRenderer,
- glsl,
-//@ts-ignore
-} from 'https://cdn.skypack.dev/@dfdao/renderer';
-import {
- AsteroidRendererType,
- AttribType,
- BackgroundRendererType,
- BeltRendererType,
- BlackDomainRendererType,
- CaptureZoneRendererType,
- CanvasCoords,
- Chunk,
- CircleRendererType,
- GameViewport,
- LineRendererType,
- LocatablePlanet,
- LocationId,
- MineBodyRendererType,
- MineRendererType,
- PerlinRendererType,
- Planet,
- PlanetRendererType,
- PlanetRenderInfo,
- PlanetRenderManagerType,
- QuasarBodyRendererType,
- QuasarRayRendererType,
- QuasarRendererType,
- RectRendererType,
- RenderedArtifact,
- RendererType,
- RGBAVec,
- RGBVec,
- RingRendererType,
- RuinsRendererType,
- SpaceRendererType,
- SpacetimeRipRendererType,
- SpriteRendererType,
- TextAlign,
- TextAnchor,
- TextRendererType,
- UIRendererType,
- UniformType,
- UnminedRendererType,
- VoyageRendererType,
- WorldCoords,
- WormholeRendererType,
-//@ts-ignore
-} from 'https://cdn.skypack.dev/@dfdao/types';
-//@ts-ignore
-import { html, render } from 'https://unpkg.com/htm/preact/standalone.module.js';
-
-// Line 78 - 350: Blank Renderer
-// Line 350 - 651: Circle Renderer
-// Line 626 - End: Plugin
-
-
-
-
-// Line 78 - 376
-// "Blank" renderer class definitions
-// When passing in these renderers into the Dark Forest API, the result would be the same as disabling that type of renderer.
-
-class PlanetRenderer implements PlanetRendererType {
- rendererType = RendererType.Planet;
- queuePlanetBody(planet: Planet, centerW: WorldCoords, radiusW: number): void {}
- flush(): void {}
-}
-
-class MineRenderer implements MineRendererType {
- rendererType = RendererType.Mine;
- queueMine(planet: Planet, centerW: WorldCoords, radiusW: number): void {}
- flush(): void {}
-}
-
-class SpacetimeRipRenderer implements SpacetimeRipRendererType {
- rendererType = RendererType.SpacetimeRip;
- queueRip(planet: Planet, centerW: WorldCoords, radiusW: number): void {}
- flush(): void {}
-}
-
-class QuasarRenderer implements QuasarRendererType {
- rendererType = RendererType.Quasar;
-
- queueQuasar(planet: Planet, centerW: WorldCoords, radiusW: number): void {}
- flush(): void {}
-}
-
-class RuinsRenderer implements RuinsRendererType {
- rendererType = RendererType.Ruins;
- queueRuins(planet: Planet, centerW: WorldCoords, radiusW: number): void {}
- flush(): void {}
-}
-class AsteroidRenderer implements AsteroidRendererType {
- rendererType = RendererType.Asteroid;
- queueAsteroid(planet: Planet, centerW: CanvasCoords, radiusW: number, color?: RGBVec): void {}
- flush(): void {}
-}
-
-class RingRenderer implements RingRendererType {
- rendererType = RendererType.Ring;
- queueRingAtIdx(
- planet: Planet,
- centerW: WorldCoords,
- radiusW: number,
- color?: RGBVec,
- beltIdx?: number,
- angle?: number
- ): void {}
- flush(): void {}
-}
-
-class SpriteRenderer implements SpriteRendererType {
- rendererType = RendererType.Sprite;
- //drawing artifacts around world
- queueArtifactWorld(
- artifact: RenderedArtifact,
- posW: CanvasCoords,
- widthW: number,
- alpha?: number,
- atFrame?: number | undefined,
- color?: RGBVec | undefined,
- theta?: number | undefined,
- viewport?: GameViewport
- ): void {}
- //drawing artifacts when traveling with voyagers
- queueArtifact(
- artifact: RenderedArtifact,
- pos: CanvasCoords,
- width?: number,
- alpha?: number,
- atFrame?: number | undefined,
- color?: RGBVec | undefined,
- theta?: number | undefined
- ): void {}
- flush(): void {}
-}
-
-class BlackDomainRenderer implements BlackDomainRendererType {
- rendererType = RendererType.BlackDomain;
- queueBlackDomain(planet: Planet, centerW: WorldCoords, radiusW: number): void {}
- flush(): void {}
-}
-
-class TextRenderer implements TextRendererType {
- rendererType = RendererType.Text;
- queueTextWorld(
- text: string,
- coords: WorldCoords,
- color?: RGBAVec,
- offY?: number, // measured in text units - constant screen-coord offset that it useful for drawing nice things
- align?: TextAlign,
- anchor?: TextAnchor,
- zIdx?: number
- ): void {}
- flush(): void {}
-}
-
-class VoyageRenderer implements VoyageRendererType {
- rendererType = RendererType.Voyager;
- queueVoyages(): void {}
- flush(): void {}
-}
-
-class WormholeRenderer implements WormholeRendererType {
- rendererType = RendererType.Wormhole;
- queueWormholes(): void {}
- flush(): void {}
-}
-
-class MineBodyRenderer implements MineBodyRendererType {
- rendererType = RendererType.MineBody;
- queueMineScreen(planet: Planet, center: WorldCoords, radius: number, z: number): void {}
- flush(): void {}
- setUniforms(): void {}
-}
-
-class BeltRenderer implements BeltRendererType {
- rendererType = RendererType.Belt;
- queueBeltAtIdx(
- planet: Planet,
- center: WorldCoords | CanvasCoords,
- radius?: number,
- color?: RGBVec,
- beltIdx?: number,
- angle?: number,
- screen?: boolean
- ): void {}
- flush(): void {}
- setUniforms(): void {}
-}
-
-class BackgroundRenderer implements BackgroundRendererType {
- rendererType = RendererType.Background;
- queueChunks(
- exploredChunks: Iterable,
- highPerfMode: boolean,
- drawChunkBorders: boolean,
- disableFancySpaceEffect: boolean,
- innerNebulaColor?: string,
- nebulaColor?: string,
- spaceColor?: string,
- deepSpaceColor?: string,
- deadSpaceColor?: string
- ): void {}
- flush(): void {}
-}
-
-class SpaceRenderer implements SpaceRendererType {
- rendererType = RendererType.Space;
- queueChunk(chunk: Chunk): void {}
- setColorConfiguration(
- innerNebulaColor: string,
- nebulaColor: string,
- spaceColor: string,
- deepSpaceColor: string,
- deadSpaceColor: string
- ): void {}
- flush(): void {}
-}
-
-class UnminedRenderer implements UnminedRendererType {
- rendererType = RendererType.Unmined;
- queueRect(
- { x, y }: CanvasCoords,
- width: number,
- height: number,
- color: RGBVec,
- zIdx: number
- ): void {}
- flush(): void {}
-}
-
-class PerlinRenderer implements PerlinRendererType {
- rendererType = RendererType.Perlin;
- queueChunk(chunk: Chunk): void {}
- flush(): void {}
-}
-
-class LineRenderer implements LineRendererType {
- rendererType = RendererType.Line;
- queueLineWorld(
- start: WorldCoords,
- end: WorldCoords,
- color?: RGBAVec,
- width?: number,
- zIdx?: number,
- dashed?: boolean
- ): void {}
- flush(): void {}
-}
-
-class RectRenderer implements RectRendererType {
- rendererType = RendererType.Rect;
- queueRectCenterWorld(
- center: WorldCoords,
- width: number,
- height: number,
- color?: RGBVec,
- stroke?: number,
- zIdx?: number
- ): void {}
- flush(): void {}
-}
-
-class CircleRenderer implements CircleRendererType {
- rendererType = RendererType.Circle;
- queueCircleWorld(
- center: CanvasCoords,
- radius: number,
- color?: RGBAVec,
- stroke?: number,
- angle?: number, // percent of arc to render
- dashed?: boolean
- ): void {}
- queueCircleWorldCenterOnly(
- center: WorldCoords,
- radius: number, // canvas coords
- color?: RGBAVec
- ): void {}
- flush(): void {}
-}
-
-class UIRenderer implements UIRendererType {
- rendererType = RendererType.UI;
- queueBorders(): void {}
- queueSelectedRangeRing(): void {}
- queueSelectedRect(): void {}
- queueHoveringRect(): void {}
- queueMousePath(): void {}
- drawMiner(): void {}
- flush(): void {}
-}
-
-class PlanetRenderManager implements PlanetRenderManagerType {
- rendererType = RendererType.PlanetManager;
- queueRangeRings(planet: LocatablePlanet): void {}
- queuePlanets(
- cachedPlanets: Map,
- now: number,
- highPerfMode: boolean,
- disableEmojis: boolean,
- disableHats: boolean
- ): void {}
- flush(): void {}
-}
-
-class QuasarBodyRenderer implements QuasarBodyRendererType {
- rendererType = RendererType.QuasarBody;
- queueQuasarBody(
- planet: Planet,
- centerW: WorldCoords,
- radiusW: number,
- z?: number,
- angle?: number
- ): void {}
- flush(): void {}
-}
-
-class QuasarRayRenderer implements QuasarRayRendererType {
- rendererType = RendererType.QuasarRay;
- queueQuasarRay(
- planet: Planet,
- centerW: WorldCoords,
- radiusW: number,
- z?: number,
- top?: boolean,
- angle?: number
- ): void {}
- flush(): void {}
-}
-
-class CaptureZoneRenderer implements CaptureZoneRendererType{
- rendererType = RendererType.CaptureZone;
-
- queueCaptureZones(): void {}
-
- flush(): void {}
-}
-
-// line 350 - 351
-// Circle Renderer Definitions using WebGl
-
-
-
-// Program Definition
-// A program is what we use to organizie the attributes and shaders of WebGl Programs
-
-const u = {
- matrix: 'u_matrix', // matrix to convert from world coords to clipspace
-};
-
-const a = {
- position: 'a_position', // as [posx, posy, rectposx, rectposy]
- color: 'a_color',
- props: 'a_props', // as [stroke, angle, dash]
- eps: 'a_eps',
- planetInfo: 'a_planetInfo', //as [planetlevel, radius]
- PlanetUpgrades: 'a_planetUpgrades', //as [defense:number , range: number, speed: number]
- PlanetResources: 'a_planetResources', //as [energy:number , energy cap: number, silver: number, silver cap: number]
-};
-
-const GENERIC_PLANET_PROGRAM_DEFINITION = {
- uniforms: {
- matrix: { name: u.matrix, type: UniformType.Mat4 },
- },
- attribs: {
- position: {
- dim: 4,
- type: AttribType.Float,
- normalize: false,
- name: a.position,
- },
- eps: {
- dim: 1,
- type: AttribType.Float,
- normalize: false,
- name: a.eps,
- },
- color: {
- dim: 4,
- type: AttribType.UByte,
- normalize: true,
- name: a.color,
- },
- props: {
- dim: 2,
- type: AttribType.Float,
- normalize: false,
- name: a.props,
- },
- planetInfo: {
- dim: 2,
- type: AttribType.UByte,
- normalize: false,
- name: a.planetInfo,
- },
- planetUpgrades: {
- dim: 3,
- type: AttribType.UByte,
- normalize: false,
- name: a.PlanetUpgrades,
- },
- planetResources: {
- dim: 4,
- type: AttribType.UByte,
- normalize: false,
- name: a.PlanetResources,
- },
- },
-
- vertexShader: glsl`
- in vec4 a_position;
- in vec4 a_color;
- in vec2 a_props;
- in float a_eps;
- in vec2 a_planetInfo;
- in vec4 a_planetResources;
-
- uniform mat4 u_matrix;
-
- out float v_planetLevel;
- out vec4 v_color;
- out vec2 v_rectPos;
- out float v_angle;
- out float v_dash;
- out float v_eps;
- out float energy;
- out float energy_cap;
-
- void main() {
- gl_Position = u_matrix * vec4(a_position.xy, 0.0, 1.0);
-
- v_rectPos = a_position.zw;
- v_color = a_color;
- v_angle = a_props.x;
- v_dash = a_props.y;
- v_eps = a_eps;
- v_planetLevel = a_planetInfo[0];
- energy = a_planetResources[0];
- energy_cap = a_planetResources[1];
- }
- `,
-
- fragmentShader: glsl`
- #define PI 3.1415926535
-
- precision highp float;
- out vec4 outColor;
-
- in vec4 v_color;
- in vec2 v_rectPos;
- in float v_angle;
- in float v_dash;
- in float v_eps;
- in float v_planetLevel;
- in float energy;
- in float energy_cap;
-
- void main() {
- vec4 color = v_color;
- float dist = length(v_rectPos);
-
- if (dist > 1.0) discard; // if it's outside the circle
-
- // anti-aliasing if barely in the circle
- float ratio = (1.0 - dist) / v_eps;
- if (ratio < 1.) {
- color.a *= ratio;
- }
-
-
- /* get angle for both angle + dash checks */
- float angle = atan(v_rectPos.y, v_rectPos.x);
-
- // add 5pi/2 to translate it to [-PI/2, 3PI / 2]
- float check = angle + (5.0 * PI / 2.0);
- check -= (check > 2.0 * PI ? 2.0 * PI : 0.0);
- float pct = check / (2.0 * PI);
-
- /* do angle check */
-
- if (v_angle != 1.0 && pct > v_angle) discard;
-
- /* do dash check */
- bool isDash = v_dash > 0.0;
- float interval = angle / v_dash;
- float modulo = interval - 2.0 * floor(interval / 2.0);
- bool isGap = modulo > 1.0;
- if (isDash && isGap) discard;
-
- /* now draw it */
- outColor = vec4(1,1.0/energy_cap*energy,0,1);
- }
- `,
-};
-class CirclePlanetRenderer extends GenericRenderer<
- typeof GENERIC_PLANET_PROGRAM_DEFINITION,
- GameGLManager
-> {
- quadBuffer: number[];
-
- viewport: GameViewport;
- rendererType: number;
-
- vertexShader: string;
- fragmentShader: string;
-
- manager: GameGLManager;
-
- constructor(glManager: GameGLManager, n: number) {
- super(glManager, GENERIC_PLANET_PROGRAM_DEFINITION);
- //@ts-ignore
- this.verts = 0; //found in generic renderer
-
- this.manager = glManager;
- const { vertexShader: vert, fragmentShader: frag } = GENERIC_PLANET_PROGRAM_DEFINITION;
- this.vertexShader = vert;
- this.fragmentShader = frag;
- this.rendererType = n;
- this.viewport = this.manager.renderer.getViewport();
- this.quadBuffer = EngineUtils.makeEmptyDoubleQuad();
- }
-
- public queuePlanet(
- center: CanvasCoords,
- radius: number,
- planet: Planet,
- angle = 1, // percent of arc to render
- dashed = false
- ): void {
- const color = [255, 255, 255, 255] as RGBAVec;
- const {
- position: posA,
- color: colorA,
- props: propsA,
- eps: epsA,
- planetInfo: planetInfoA,
- planetUpgrades: planetUpgradesA,
- planetResources: planetResourcesA,
- //@ts-ignore
- } = this.attribManagers;
- const { x, y } = center;
- // 1 on either side for antialiasing
- const r = radius + 1;
-
- const { x1, y1 } = { x1: x - r, y1: y - r };
- const { x2, y2 } = { x2: x + r, y2: y + r };
-
- // prettier-ignore
- EngineUtils.makeDoubleQuadBuffered(
- this.quadBuffer,
- x1, y1, x2, y2, -1, -1, 1, 1
- );
- //@ts-ignore
- posA.setVertex(this.quadBuffer, this.verts);
-
- // convert pixels to radians
- const interval = engineConsts.dashLength;
- const pixPerRad = radius;
-
- const dashRad = interval / pixPerRad;
- const dash = dashed ? dashRad : -1;
-
- const eps = 1 / radius;
- const resources = [planet.energy, planet.energyCap, planet.silver, planet.silverCap];
- for (let i = 0; i < 6; i++) {
- //@ts-ignore
- colorA.setVertex(color, this.verts + i);
- //@ts-ignore
- propsA.setVertex([angle, dash], this.verts + i);
- //@ts-ignore
- planetInfoA.setVertex([planet.planetLevel, radius], this.verts + i);
- //@ts-ignore
- planetUpgradesA.setVertex(planet.upgradeState, this.verts + i);
- //@ts-ignore
- planetResourcesA.setVertex(resources, this.verts + i);
- //@ts-ignore
- epsA.setVertex([eps], this.verts + i);
- }
- //@ts-ignore
- this.verts += 6;
- }
-
- public queueGenericPlanet(
- planet: Planet,
- center: WorldCoords,
- radius: number, // world coords
- stroke = -1,
- angle = 1,
- dashed = false
- ) {
- const centerCanvas = this.viewport.worldToCanvasCoords(center);
- const rCanvas = this.viewport.worldToCanvasDist(radius);
- this.queuePlanet(centerCanvas, rCanvas, planet, angle, dashed);
- }
-
- public setUniforms() {
- //@ts-ignore
- this.uniformSetters.matrix(this.manager.projectionMatrix);
- }
-
- public queuePlanetBody(planet: Planet, centerW: WorldCoords, radiusW: number): void {
- this.queueGenericPlanet(planet, centerW, radiusW);
- }
- public queueMine(planet: Planet, centerW: WorldCoords, radiusW: number): void {
- this.queueGenericPlanet(planet, centerW, radiusW);
- }
- public queueRip(planet: Planet, centerW: WorldCoords, radiusW: number): void {
- this.queueGenericPlanet(planet, centerW, radiusW);
- }
-
- public queueQuasar(planet: Planet, centerW: WorldCoords, radiusW: number): void {
- this.queueGenericPlanet(planet, centerW, radiusW);
- }
-
- public queueRuins(planet: Planet, centerW: WorldCoords, radiusW: number): void {
- this.queueGenericPlanet(planet, centerW, radiusW);
- }
-
- public queueAsteroid(planet: Planet, centerW: CanvasCoords, radiusW: number): void {
- this.queueGenericPlanet(planet, centerW, radiusW);
- }
-}
-
-/**
- * 626-END: Plugin
- */
-
-export default class EmbeddedRendererShowcase implements DFPlugin {
- CirclePlanetLibrary: { [key: string]: any };
- circleSelector: string;
- circleChecker: { [key: string]: boolean };
-
- constructor() {
- let glMan = ui.getGlManager();
- this.circleSelector = 'Planet';
- if (glMan) {
- this.CirclePlanetLibrary = {
- Planet: new CirclePlanetRenderer(glMan, RendererType.Planet),
- Mine: new CirclePlanetRenderer(glMan, RendererType.Mine),
- SpacetimeRip: new CirclePlanetRenderer(glMan, RendererType.SpacetimeRip),
- Quasar: new CirclePlanetRenderer(glMan, RendererType.Quasar),
- Ruins: new CirclePlanetRenderer(glMan, RendererType.Ruins),
- };
- }
- this.circleChecker = {};
- for (let key in this.CirclePlanetLibrary) {
- this.circleChecker[key] = false;
- }
- }
- async render(div: HTMLDivElement) {
- div.style.width = '500px';
- render(
- html`
- Disabling Renderers
-
- Whats actually happening here is that the current renderer is being replaced with a
- 'blank' renderer. A blank renderer is a renderer who's flush function has no
- functionality. So the behavior is similar to disabling the current renderer.
-
-
-
- {
- disable();
- }}
- >
- Disable
-
-
-
- Circle Planets
-
- This replaces the current planet renderer with a renderer that uses WebGL to create a
- circle where the color of the circle changes on the percentage of energy on the planet.
-
-
-
-
- {
- const btn = document.getElementById('CirclePlanetBtn');
- if (this.circleChecker[this.circleSelector] === false) {
- ui.setCustomRenderer(this.CirclePlanetLibrary[this.circleSelector]);
- this.circleChecker[this.circleSelector] = true;
- btn!.innerText = 'Disable';
- } else {
- ui.disableCustomRenderer(this.CirclePlanetLibrary[this.circleSelector]);
- this.circleChecker[this.circleSelector] = false;
- btn!.innerText = 'Enable';
- }
- }}
- >
- Enable
-
-
-
- Renderer Descriptions
-
-
- `,
- div
- );
- }
-
- destroy(): void {
- currentPlanet = 'Planet';
- for (let key in rendererLibrary) {
- ui.disableCustomRenderer(rendererLibrary[key]);
- }
- for (let key in this.CirclePlanetLibrary) {
- ui.disableCustomRenderer(this.CirclePlanetLibrary[key]);
- }
- }
-}
-
-let selectStyle = {
- outline: 'none',
- background: '#151515',
- color: '#838383',
- borderRadius: '4px',
- border: '1px solid #777',
- width: '100px',
- padding: '2px 6px',
- cursor: 'pointer',
- margin: '10px',
-};
-
-let inputStyle = {
- background: 'rgb(8,8,8)',
- width: '400px',
- padding: '3px 5px',
-};
-
-let buttonStyle = { height: '25px', padding: '3px 5px', margin: '10px', 'text-align': 'center' };
-
-let rendererLibrary: { [key: string]: any } = {
- Planet: new PlanetRenderer(),
- Mine: new MineRenderer(),
- SpacetimeRip: new SpacetimeRipRenderer(),
- Ruins: new RuinsRenderer(),
- Quasar: new QuasarRenderer(),
- Asteroid: new AsteroidRenderer(),
- MineBody: new MineBodyRenderer(),
- MineBelt: new BeltRenderer(),
- Background: new BackgroundRenderer(),
- UnminedBackground: new UnminedRenderer(),
- SpaceBackground: new SpaceRenderer(),
- Artifact: new SpriteRenderer(),
- AllPlanets: new PlanetRenderManager(),
- Text: new TextRenderer(),
- Voyager: new VoyageRenderer(),
- Perlin: new PerlinRenderer(),
- Wormhole: new WormholeRenderer(),
- BlackDomain: new BlackDomainRenderer(),
- Rectangles: new RectRenderer(),
- Line: new LineRenderer(),
- Circle: new CircleRenderer(),
- Ring: new RingRenderer(),
- UI: new UIRenderer(),
- QuasarBody: new QuasarBodyRenderer(),
- QuasarRay: new QuasarRayRenderer(),
- CaptureZone: new CaptureZoneRenderer(),
-};
-
-let disabled: { [key: string]: boolean } = {};
-for (let key in rendererLibrary) {
- disabled[key] = false;
-}
-
-let currentPlanet: string = 'Planet';
-
-function disable() {
- const btn = document.getElementById('RegPlanetBtn');
- if (disabled[currentPlanet] === false) {
- ui.setCustomRenderer(rendererLibrary[currentPlanet]);
- disabled[currentPlanet] = true;
- btn!.innerText = 'Enable';
- } else {
- ui.disableCustomRenderer(rendererLibrary[currentPlanet]);
- disabled[currentPlanet] = false;
- btn!.innerText = 'Disable';
- }
-}
-
-const cellStyle = {
- width: '25%',
- float: 'left',
-};
-
-const discriptionStyle = {
- TextAlign: 'justify',
-};
-
-// Used for discription of each type of renderer
-let rendererDescription: { [key: string]: any } = {
- Blank: '',
- Planet: 'basic planets',
- Mine: 'asteroid fields',
- SpacetimeRip: 'Spacetime Rips',
- Ruins: 'foundries',
- Quasar: 'quasars',
- Asteroid: 'asteroid that hover around different planets',
- MineBody: 'the body/asteroids of asteroid fields',
- MineBelt: 'the belts/rings around asteroid fields',
- Background: 'the background of the game',
- UnminedBackground: 'unmined space chunks (part of the background)',
- SpaceBackground: 'mined space chunks (part of the background)',
- Artifact: 'artifacts',
- AllPlanets: 'All planet types',
- Text: 'text that are displayed on the game canvas',
- Voyager: 'Voyages. The transfer of energy between planets.',
- Perlin:
- 'the game background. Perlin is the method in which we generate the location of space biomes.',
- Wormhole: 'visual effects of wormholes. Wormholes are generated by a special type of artifact.',
- BlackDomain:
- 'visual effects of black domains. Black Domains are created by a special type of artifact',
- Rectangles: 'all rectangles drawn in game: indicators for selection of planet, ',
- Line: ' all lines drawn in game: The line that connect planets during voyages and wormholes ',
- Circle:
- 'all circles drawn in the game: The voyager(circle) in voyages, Circles used to indicate the range a planets has, The boarder of the game world. ',
- Ring: 'rings that indicate the level of a planet',
- UI: 'in game user interface: game borders, range indicators, selection indicators, mouse path, miner',
- QuasarBody: 'the body of the Quasar',
- QuasarRay: 'the ray of the Quasar',
- CaptureZone: 'the capture zones'
-};
-/* eslint-enable */
diff --git a/client/embedded_plugins/Repeat-Attack.js b/client/embedded_plugins/Repeat-Attack.js
new file mode 100644
index 00000000..c2c4a709
--- /dev/null
+++ b/client/embedded_plugins/Repeat-Attack.js
@@ -0,0 +1,592 @@
+// Repeat Attack
+//
+// Auto-attack when source planet has enough energy!
+//
+// original author: TBC
+// enhancements in 2022: https://twitter.com/davidryan59
+
+//@ts-ignore
+import {
+ PlanetType,
+ SpaceType,
+ PlanetTypeNames,
+ //@ts-ignore
+} from 'https://cdn.skypack.dev/@darkforest_eth/types';
+//@ts-ignore
+import { isUnconfirmedMoveTx } from 'https://cdn.skypack.dev/@darkforest_eth/serde';
+//@ts-ignore
+import {
+ html,
+ render,
+ useEffect,
+ useState,
+ useLayoutEffect,
+ //@ts-ignore
+} from 'https://unpkg.com/htm/preact/standalone.module.js';
+
+import { getPlanetName } from 'https://cdn.skypack.dev/@darkforest_eth/procedural';
+
+
+// ----------------------------------------
+// User Configurable Options
+
+// Control how much energy gets sent, and when
+let DEFAULT_PERCENTAGE_TRIGGER = 75; // What percentage energy will trigger a send?
+let DEFAULT_PERCENTAGE_REMAIN = 25; // How much energy will remain after sending?
+
+// Stagger all the different attacks by this number of seconds, don't send all at once
+let STAGGER_S = 15; // Over what number of seconds will all repeat attacks happen once?
+
+// UI controls
+let MAX_CHARS = 15; // How many letters of planet name to display?
+let WIDTH_PX = 440; // What is the width of plugin window?
+let MIN_V = 10; // Set minimum values for sliders
+let MAX_V = 90; // Set maximum values for sliders
+let STEP_V = 5; // Set step size for sliders
+
+// Keyboard shortcuts
+const KEY_SET_SOURCE = 'v';
+const KEY_SET_TARGET = 'b';
+const KEY_START_FIRING = 'n';
+const KEY_TOGGLE_SILVER = 'm';
+const KEY_TOGGLE_OUTGOING_FIRING = ',';
+const KEY_TOGGLE_OUTGOING_FIRING_DISPLAY = '<'; // '<' displays better than ','
+const KEY_TOGGLE_INCOMING_FIRING = '.';
+const KEY_TOGGLE_INCOMING_FIRING_DISPLAY = '>'; // '>' displays better than '.'
+
+// Other controls
+let SILVER_SEND_PERCENT = 99; // Sends this proportion of silver from the source planet
+
+// Note - `let` was sometimes used by original author in this plugin to sidestep any weird execution env problems
+// ----------------------------------------
+
+
+const FIRING_NONE = 0;
+const FIRING_ACTIVE = 1;
+const FIRING_PAUSED = 2;
+
+const sendSilverStatuses = [
+ 'Do not send', // 0
+ 'Upgrade first', // 1
+ 'Send all' // 2
+];
+const sendSilverStatusesIcon = ['-', 'U', '$'];
+const UPGRADE_FIRST = 1;
+const SEND_ALL_SILVER = 2;
+const INITIAL_SILVER_STATUS = UPGRADE_FIRST;
+const toggleSilverStatus = val => (val + 1) % 3; // 3 way toggle
+
+const viewport = ui.getViewport();
+const PI_2 = 6.2831853; // 2 * pi, the number of radians in a complete circle
+const [DESYNC_X, DESYNC_Y] = [101, 103]; // Desynchronises pulsing of separate planets using prime numbers multiplied by canvas coord components
+
+const PLANET_UNKNOWN = '?????';
+const getPlanetString = locationId => {
+ const planet = df.getPlanetWithId(locationId);
+ if (!planet) return PLANET_UNKNOWN;
+ let type = 'P';
+ if( planet.planetType == PlanetType.SILVER_MINE) type = 'A'
+ else if (planet.planetType == PlanetType.RUINS) type = 'F'
+ else if (planet.planetType == PlanetType.TRADING_POST) type = 'STR'
+ else if (planet.planetType == PlanetType.SILVER_BANK) type = 'Q'
+ return `L${planet.planetLevel}-${type} ${getPlanetName(planet)}`;
+};
+const getPlanetMaxRank = (planet) => {
+ if (!planet) return 0;
+ if(planet.planetType != PlanetType.PLANET) return 0;
+ if (planet.spaceType === SpaceType.NEBULA) return 3;
+ else if (planet.spaceType === SpaceType.SPACE) return 4;
+ else return 5;
+};
+const isFullRank = (planet) => {
+ if (!planet) return true;
+ const maxRank = getPlanetMaxRank(planet);
+ const rank = planet.upgradeState.reduce(
+ (a, b) => a + b,
+ 0
+ );
+ return rank >= maxRank;
+};
+function unconfirmedDepartures(planet) {
+ return (
+ planet.transactions
+ ?.getTransactions(isUnconfirmedMoveTx)
+ //@ts-ignore
+ .reduce((acc, tx) => acc + tx.intent.forces, 0) || 0
+ );
+}
+function planetCurrentPercentEnergy(planet) {
+ const departures = unconfirmedDepartures(planet);
+ const estimatedEnergy = Math.floor(planet.energy - departures);
+ return Math.floor((estimatedEnergy / planet.energyCap) * 100);
+}
+class Repeater {
+ constructor() {
+ //@ts-ignore
+ if (typeof window.__CORELOOP__ == 'undefined') {
+ //setup append only interval id storage
+ //@ts-ignore
+ window.__CORELOOP__ = [];
+ } else {
+ //clear out old intervald
+ console.log('KILLING PREVIOUS INTERVALS');
+ //@ts-ignore
+ window.__CORELOOP__.forEach((id) => window.clearInterval(id));
+ }
+ this.currentPlanets = { // store relevant planets
+ selected: ui.getSelectedPlanet(),
+ source: null,
+ target: null
+ }
+ this.currentAttack = { // store attack being set up
+ sourceId: null,
+ targetId: null,
+ active: true,
+ pcTrigger: DEFAULT_PERCENTAGE_TRIGGER,
+ pcRemain: DEFAULT_PERCENTAGE_REMAIN,
+ sendSilverStatus: INITIAL_SILVER_STATUS
+ }
+ this.attacks = []; // attacks already set up
+ this.account = df.getAccount();
+ this.configHash = df.contractConstants.CONFIG_HASH;
+ this.contractAddress = df.getContractAddress();
+ this.loadAttacks();
+ this.intervalId = window.setInterval(this.coreLoop.bind(this), 1000);
+ //@ts-ignore
+ window.__CORELOOP__.push(this.intervalId);
+ }
+ saveAttacks() {
+ localStorage.setItem(`repeatAttacks-${this.account}-${this.configHash}`, JSON.stringify(this.attacks));
+ }
+ loadAttacks() {
+ const attacksJSON = localStorage.getItem(`repeatAttacks-${this.account}-${this.configHash}`);
+ // @ts-ignore
+ if (attacksJSON) this.attacks = JSON.parse(attacksJSON);
+ }
+ addAttack() {
+ const attack = { ...this.currentAttack };
+ // Make sure source and target set
+ if (!attack.sourceId || !attack.targetId) return;
+ // Make sure remaining energy is less than trigger energy
+ attack.pcRemain = (attack.pcTrigger <= attack.pcRemain) ? parseInt(attack.pcTrigger / 2) : attack.pcRemain;
+ // Filter out existing attacks from this source, then add new attack at top
+ let newAttacks = this.attacks.filter(a => a.sourceId !== attack.sourceId);
+ newAttacks = [attack, ...newAttacks];
+ this.attacks = newAttacks;
+ this.saveAttacks();
+ }
+ toggleActive(position) {
+ this.attacks[position].active = !this.attacks[position].active;
+ this.saveAttacks();
+ }
+ toggleSilver(position) {
+ this.attacks[position].sendSilverStatus = toggleSilverStatus(this.attacks[position].sendSilverStatus);
+ this.saveAttacks();
+ }
+ removeAttack(position) {
+ this.attacks.splice(position, 1);
+ this.saveAttacks();
+ }
+ removeAllAttacks() {
+ this.attacks = [];
+ this.saveAttacks();
+ }
+ getFiringStatus(item) {
+ const planetId = this.currentPlanets.selected?.locationId;
+ if (!planetId) return FIRING_NONE;
+ const attacks = this.attacks.filter(a => a[item] === planetId);
+ if (!attacks.length) return FIRING_NONE;
+ const pausedAttacks = attacks.filter(a => !a.active);
+ return (pausedAttacks.length < attacks.length) ? FIRING_ACTIVE : FIRING_PAUSED;
+ }
+ outgoingStatus() { return this.getFiringStatus('sourceId'); }
+ incomingStatus() { return this.getFiringStatus('targetId'); }
+ toggleOutgoingFiring() {
+ const planetId = this.currentPlanets.selected?.locationId;
+ if (!planetId) return;
+ const newActive = !(this.outgoingStatus() === FIRING_ACTIVE);
+ this.attacks = this.attacks.map(a => {
+ if (a.sourceId === planetId) a.active = newActive;
+ return a
+ })
+ this.saveAttacks();
+ }
+ toggleIncomingFiring() {
+ const planetId = this.currentPlanets.selected?.locationId;
+ if (!planetId) return;
+ const newActive = !(this.incomingStatus() === FIRING_ACTIVE);
+ this.attacks = this.attacks.map(a => {
+ if (a.targetId === planetId) a.active = newActive;
+ return a
+ })
+ this.saveAttacks();
+ }
+ coreLoop() {
+ if(!this || !this.attacks) return;
+ this.attacks.forEach( (attack, idx) => {
+ if(idx % STAGGER_S == Math.floor(Date.now() / 1000) % STAGGER_S) ExecuteAttack(attack);
+ });
+ }
+}
+const ExecuteAttack = ({sourceId, targetId, active, pcTrigger, pcRemain, sendSilverStatus}) => {
+ let srcPlanet = df.getPlanetWithId(sourceId);
+ if (!srcPlanet) return;
+ if (!active) return;
+ // Needs updated check getUnconfirmedDepartingForces
+ const departingForces = unconfirmedDepartures(srcPlanet);
+ const TRIGGER_AMOUNT = Math.floor((srcPlanet.energyCap * pcTrigger) / 100);
+ const FUZZY_ENERGY = Math.floor(srcPlanet.energy - departingForces); //Best estimate of how much energy is ready to send
+ if (FUZZY_ENERGY > TRIGGER_AMOUNT) {
+ const overflow_send =
+ planetCurrentPercentEnergy(srcPlanet) - pcRemain;
+ const FORCES = Math.floor((srcPlanet.energyCap * overflow_send) / 100);
+ let silver = 0;
+ if ( sendSilverStatus === SEND_ALL_SILVER || (sendSilverStatus === UPGRADE_FIRST && isFullRank(srcPlanet))) {
+ silver = Math.round(srcPlanet.silver * (SILVER_SEND_PERCENT / 100));
+ }
+ df.move(sourceId, targetId, FORCES, silver);
+ }
+};
+let Keyboard_Shortcut = {
+ fontSize: '85%',
+ color: 'rgba(220, 180, 128, 1)'
+};
+let Margin_3L_3R = {
+ marginLeft: '3px',
+ marginRight: '3px',
+};
+let Margin_12L_12R = {
+ marginLeft: '12px',
+ marginRight: '12px',
+};
+let Margin_12B = {
+ marginBottom: '12px',
+};
+let Margin_6B = {
+ marginBottom: '6px',
+};
+let Clickable = {
+ cursor: 'pointer',
+ textDecoration: 'underline',
+};
+let ActionEntry = {
+ marginBottom: '5px',
+ display: 'flex',
+ justifyContent: 'space-between',
+ color: '',
+};
+function centerPlanet(id) {
+ ui.centerLocationId(id);
+}
+function Attack({ attack, onToggleActive, onToggleSilver, onDelete }) {
+ const srcString = getPlanetString(attack.sourceId);
+ const targetString = getPlanetString(attack.targetId);
+ const finalSrc = srcString.length > MAX_CHARS ? srcString.slice(0, MAX_CHARS - 3).concat('...') : srcString;
+ const finalTarget = targetString.length > MAX_CHARS ? targetString.slice(0, MAX_CHARS - 3).concat('...') : targetString;
+ return html`
+