KMXBQVJSTSU46WB6IYGNWNMXKIVAMIHILKCDQVD3E76YDR2TCZNAC 7HBFOC5MXDEVFOALYURNJZPXCGJRR5AW6ISGAGEGLTISIOURT4RAC RB4XTDEUFAEAB4QNC6XXZUHDKVN77N3EG2NSCTQLRTQICLSEHDMAC WNMPJOSW3767SR2TZ6I55IH5WBJD2OS2HDP3YDWCVIDMUQDRIRRQC L4VMIGM6D5WUEBYOCXBIF6V66NRJAKOJO4FHALHIUIAGAUQUKDPAC PZNEDCRDS5IBR7QDPHTW5HZRMQAZFIF7VB3IKWPZDC7IALHZKHWAC 33W6NM7THHPV4WL6WI2UOLGCOTFAITF2OZ3JN2SMYY2MHCGB27IQC 3UFL673QX2JG7KHTAM7DFH4BBYVHDNMXBS2RW45G3JBNFZFLSRRQC GZRMSSTEWT3T2JERC7WCVT727X237UA6MXWVT6OSV5D5BRD4UOGQC L72HFM6IYLNHEFEIFOQQQUAGMY2RN4POCV3Q3SMQERSQBMEZ5J3QC RWQMSAGYY7OTRP6HVYYJUY3IOII6P5IBQEHE5NJN2V6DGIYER5OAC FPECYSD5K4I23LPBSJW2AOILTFLJE55HQ34FMK6CKTBUOFBUL6XAC U665HW6MTIDB6FVOODL24BOMJMOJ6ZSP664NU4T442QFLYD5CGHQC 2OZGXOFLTXALS34QEIQ2F6VT7AUWYK7FVXUUDX66GZT5I7FUNPVAC CWCOGTXQXEQPK6O4TQFCIPDVMZD7WHOBGMIG2DTSO6BEBFEADZIQC GIDOI5BK3WYIDEQL7SZTJPR3Q5TDQ34YHDPDCUFFH6PX4POEDSQQC 6ZGB7JZJ4EWDELXAENEHRNNJZB2EK7E7BEKNPK34MJL75DOPJNPAC NKWFGTCM6HM35MAJAREANFQS76ALYOD7K6FT77X5HQPBCRAPXVRAC ZDAABIZI6MPCP5DPGUN24XLSWIKQQ6LYMKIH67ORLUSFUVS5AJ5AC AF2QOVSSTCKR26APL4PQSNUGZPPJY3IIUUHN4LJ5URL5THW2NSDQC AZRGEBFL5YFY6PVBYGVAEUOEP5UUHVP4LLYRVMC3TAKQV6XUHXLQC SACCO45GNBBHHTWCVMKJ64ZLGW32DM4DIKSOJF3N6U47WP4JY5HAC HOHGBK6XI5VIWIC42IKHRO6OUNMUFUI2TXHDHMDCIPLAT7COB5TAC GO6HOZRQC3PVIH6REZM4MYH3PGAQD5YSW3VCFJZ6ZENJLC5KDDMAC 3J7QNHQ4F2VBYCK6SWKPO3AW3YYAJZNWOW6XNSURSRDZOE2ZIGQAC CZPLX4O4R7K3TF3NSAL5PT7NO3CUOLDY3OR332GBIYYNKMZTW24AC DV3KM46EQREZL5Y47SDAFJQZFLEAOIBYGYZOKGLJXW2AI4MWLFGAC HPOKB2TCHK3MTYYKXL3DE476BF3JXVSX6MSGI5NF4PSLALTS3PHQC 4CQWVYQVUFXWUZBVLT7X7YW6TVIUHAGABPLXZTC66WNQQP5BOREAC QYHOJMYCWRCAMP6YPVGTBWSOOIDZI7Z2IMGODEA5UUJFMMYZCFCQC MFKZYXV3EZAQCPNCFKCK5DM3O66CEGWYEUM6HZ2I2PMGVE73EYZAC Z5I5KK7NX6RS23QAB7ISLQCM5Z6TMVZK532NPSE7CO4MNXNKVKMAC GJGKS2YPL6XOT4CLQ2NVHUU2W7MDHYE2XC77WWRGPBCPSTWZ5GIAC QTTO6EU2UCXVVPN724D2FUMGKJSEWTG7FXLOFNUB3IL3RVV3AVUAC 5NOOFT552GDEBDUACQZXG4TOLQSILGZEPGEJRS5BQD34TIJQ6T2QC PSY4Y3X4ZWLXR2FEDR2W5E4SW2ASS4BPBOT4W5TDLNU2NCFZISNAC 7KT5VCNGU24M5NPW2YME3BAE3HASNPJ7Y6VEKCFEJDQKNXCP4MYAC HGV5HTLAKXK2AEBXAAASX5AC6SDBNGT253O3NY4MYNZN3TN4S3BQC export class PointNodeComponent {public container: Pixi.Container;staleProps: Props;public state: State;public sprite: Pixi.Spritepublic halfwayCenterSprite: Pixi.Sprite;public centerSprite: Pixi.Sprite;public hitArea: Pixi.IHitArea;public tooltippableArea?: TooltippableAreaComponentpublic tooltippableAreaPropsFactory: (p: Props, s: State) => TooltippableAreaComponentPropspublic _children: {childClass :any, instance: any, propsFactory: Function}[] = []public forceUpdates: {childClass :any, instance: any, propsFactory: Function}[] = []constructor(props: Props) {this.staleProps = props;this.state = {justTriedToAllocate: false,justSpentSp: false,justFailedToAllocate: false,numClicks: 0};this.container = new Pixi.Container();this.container.sortableChildren = true;this.sprite = new Pixi.Sprite(props.args.pointNodeTexture);this.sprite.anchor.x = 0.5;this.sprite.anchor.y = 0.5;this.sprite.zIndex = -1;this.container.addChild(this.sprite);this.centerSprite = new Pixi.Sprite(props.args.pointNodeTexture);this.centerSprite.anchor.x = 0.5;this.centerSprite.anchor.y = 0.5;this.centerSprite.scale = PixiPointFrom(new Vector2(0.5, 0.5));this.centerSprite.zIndex = 1;this.centerSprite.alpha = 0; // TESTING// this.container.addChild(this.centerSprite);this.halfwayCenterSprite = new Pixi.Sprite(props.args.pointNodeTexture);this.halfwayCenterSprite.anchor.x = 0.5;this.halfwayCenterSprite.anchor.y = 0.5;this.halfwayCenterSprite.scale = PixiPointFrom(new Vector2(0.75, 0.75));this.halfwayCenterSprite.zIndex = 0;// disable this sprite for now - causes a fairly significant fps hit, until we get around to holding less nodes on the page at oncethis.halfwayCenterSprite.alpha = 0;// this.container.addChild(this.halfwayCenterSprite);this.container.interactive = true;// NOTE(bowei): ive tested, the following 2 settings don't significantly affect FPSthis.container.buttonMode = true;this.hitArea = new Pixi.Rectangle(- RenderedChunkConstants.NODE_HITAREA_PX / 2,- RenderedChunkConstants.NODE_HITAREA_PX / 2,RenderedChunkConstants.NODE_HITAREA_PX,RenderedChunkConstants.NODE_HITAREA_PX,);// note: hitarea breaks child onhover: https://github.com/pixijs/pixi.js/issues/5837// this.container.hitArea = this.hitArea;this.tooltippableAreaPropsFactory = (p: Props, s: State) => {return {args: {markForceUpdate: this.markForceUpdate,},hitArea: this.hitArea,}}this.tooltippableArea = new TooltippableAreaComponent(this.tooltippableAreaPropsFactory(props, this.state));this.container.addChild(this.tooltippableArea.container);this._children.push({childClass: TooltippableAreaComponent,instance: this.tooltippableArea,propsFactory: this.tooltippableAreaPropsFactory,});this.renderSelf(props);this.didMount();}renderSelf(props: Props) {this.container.position = PixiPointFrom(props.position);let tint: number;let centerTint: number;if (props.isSelected) {tint = 0xBBBBFF;centerTint = 0xBBBBFF;} else {tint = 0xFFFFFF;centerTint = 0xFFFFFF;}if (props.isAllocated) {tint = 0x444444;} else {}let baseColor: number = 0;if (props.pointNodeGen.resourceType === ResourceType.Nothing) {baseColor = 0x99bbff; // blue that mixes in with bg} else if (props.pointNodeGen.resourceType === ResourceType.Mana0) {if (props.pointNodeGen.resourceModifier === ResourceModifier.Flat) {baseColor = 0xeeaaaa; // pink} else if (props.pointNodeGen.resourceModifier === ResourceModifier.Increased0) {baseColor = 0xcc88ee; // lavender?}}// switch (props.pointNodeGen.resourceType) {// case ResourceType.Nothing:// baseColor = 0x99bbff; // blue that mixes in with bg// break;// case ResourceType.Mana0:// baseColor = 0xeeaaaa; // red// break;// case ResourceType.Mana1:// baseColor = 0xbb7733; // brown?// break;// case ResourceType.Mana2:// baseColor = 0x44aa44; // green// break;// }this.sprite.tint = multiplyColor(baseColor, tint);this.centerSprite.tint = multiplyColor(baseColor, centerTint);
if (props.selfPointNodeRef.pointNodeCoord.equals(Vector2.Zero)) {this.container.scale = PixiPointFrom(new Vector2(1.25, 1.25));}}updateSelf(props: Props) { }shouldUpdate(prevProps: Props, props: Props): boolean {for (let key of (Object.keys(prevProps) as (keyof Props)[])) {if (key === 'delta' || key === 'args' || key === 'updaters') { continue; }if (prevProps[key] !== props[key]) {return true;}if (key === 'position') {if (!prevProps[key].equals(props[key])) {console.log(`chunk shouldUpdate differed in ${key}, returning true`);return true;} else {continue;}}if (key === 'selfPointNodeRef') {if (prevProps[key]?.hash() !== props[key]?.hash()) {console.log(`chunk shouldUpdate differed in ${key}, returning true`);return true;} else {continue;}}}return false;}/** callback passed to child - since child is not a pure component, it needs to inform us of updates if otherwise we wouldnt update */markForceUpdate = (childInstance: any) => {this.staleProps.args.markForceUpdate(this); // mark us for update in OUR parentfor (let childInfo of this._children) {if (childInfo.instance === childInstance) { // we found the instance in our _children array, now ensure it is in force updates array then returnif (this.forceUpdates.indexOf(childInfo) === -1) {this.forceUpdates.push(childInfo);}return;}}throw new Error(`Error, child ${childInstance} not found in ${this}`);}public didForceUpdateChild(instance: any) { }public update(props: Props) {// let staleState = { ...this.state };this.updateSelf(props)if (!this.shouldUpdate(this.staleProps, props)) {// we think we don't need to update; however, we still need to// update the chidlren that asked us to forcefully update themlet forceUpdates = [...this.forceUpdates];this.forceUpdates = [];for (let { instance, propsFactory } of forceUpdates) {instance._update(propsFactory(props, this.state)); // why are we even calling props factory here?? theres no point... we should just tell the child to use their own stale props, like this:// instance._forceUpdate();// note that children can add themselves into forceupdate next tick as well, if they need to ensure they're continuously in therethis.didForceUpdateChild(instance);}// no need to do anything else -- stale props has not changedreturn;}this.tooltippableArea?._update(this.tooltippableAreaPropsFactory(props, this.state));this.renderSelf(props);this.staleProps = props;new Promise((resolve) => resolve(this.didUpdate()));}didMount() {const { updaters } = this.staleProps; // we assume this will never change// this.container.addListener('pointerover', (event: Pixi.InteractionEvent) => {// this.state.pointerover = event;// })// this.container.addListener('pointerout', () => {// this.state.pointerover = undefined;// })//this.container.addListener("pointerdown", (event: Pixi.InteractionEvent) => {this.state.numClicks++;// event.stopPropagation();// update selected to ourselvesupdaters.playerUI.selectedPointNode.enqueueUpdate((prev, gameState) => {if (prev?.pointNodeId === this.staleProps.selfPointNodeRef.pointNodeId) {this.state.justTriedToAllocate = true;}return this.staleProps.selfPointNodeRef;});// if we tried to allocate ourselves, see if we canupdaters.playerSave.enqueueUpdate((prev, prevGameState) => {if (this.state.justTriedToAllocate) {this.state.justTriedToAllocate = false;let [next, succeeded] = doTryAllocate(prev, prevGameState, this.staleProps.selfPointNodeRef);if (succeeded) {this.state.justSpentSp = true;return next;} else {this.state.justFailedToAllocate = true;return prev;}}return prev;});// TODO(bowei): if we spent sp, remember to update quest status!!updaters.enqueueUpdate((prev, prevGameState) => {if (this.state.justSpentSp) {this.state.justSpentSp = false;return {...prev,playerSave: afterMaybeSpendingSp(prev.playerSave, prevGameState),computed: {...computePlayerResourceAmounts(prevGameState)}};}return prev;})// if we failed to allocate, shift the active tab so the player can see whyupdaters.playerUI.activeTab.enqueueUpdate((prev, prevGameState) => {if (this.state.justFailedToAllocate) {console.log('just failed to allocate: ', this);this.state.justFailedToAllocate = false;return 1;}return prev;});});}public willUnmount() { }public didUpdate() {// console.log(`point node component ${this.staleProps.selfPointNodeRef.toString()} was updated`);}// bridge while we migrate to lifecycle handlerpublic _update(props: Props) { this.update(props); }}
// const wrapped = engageLifecycle(PointNodeComponent2);// // eslint-disable-next-line// type wrapped = PointNodeComponent2;// export { wrapped as PointNodeComponent };// export type { Props as PointNodeComponentProps };
const wrapped = engageLifecycle(PointNodeComponent2);// eslint-disable-next-linetype wrapped = PointNodeComponent2;export { wrapped as PointNodeComponent };export type { Props as PointNodeComponentProps };