Merge pull request #2077 from thecodingmachine/use-tiled-objects
Read properties from Tiled objects
This commit is contained in:
@@ -7,4 +7,4 @@ export const isChangeZoneEvent = z.object({
|
||||
/**
|
||||
* A message sent from the game to the iFrame when a user enters or leaves a zone.
|
||||
*/
|
||||
export type ChangeZoneEvent = z.infer<typeof isChangeZoneEvent>;
|
||||
export type ChangeAreaEvent = z.infer<typeof isChangeZoneEvent>;
|
||||
@@ -29,7 +29,7 @@ import { isMenuRegisterEvent, isUnregisterMenuEvent } from "./ui/MenuRegisterEve
|
||||
import type { ChangeLayerEvent } from "./ChangeLayerEvent";
|
||||
import { isPlayerPosition } from "./PlayerPosition";
|
||||
import type { WasCameraUpdatedEvent } from "./WasCameraUpdatedEvent";
|
||||
import type { ChangeZoneEvent } from "./ChangeZoneEvent";
|
||||
import type { ChangeAreaEvent } from "./ChangeAreaEvent";
|
||||
import { isCameraSetEvent } from "./CameraSetEvent";
|
||||
import { isCameraFollowPlayerEvent } from "./CameraFollowPlayerEvent";
|
||||
import { isColorEvent } from "./ColorEvent";
|
||||
@@ -162,8 +162,8 @@ export interface IframeResponseEventMap {
|
||||
leaveEvent: EnterLeaveEvent;
|
||||
enterLayerEvent: ChangeLayerEvent;
|
||||
leaveLayerEvent: ChangeLayerEvent;
|
||||
enterZoneEvent: ChangeZoneEvent;
|
||||
leaveZoneEvent: ChangeZoneEvent;
|
||||
enterAreaEvent: ChangeAreaEvent;
|
||||
leaveAreaEvent: ChangeAreaEvent;
|
||||
buttonClickedEvent: ButtonClickedEvent;
|
||||
remotePlayerClickedEvent: RemotePlayerClickedEvent;
|
||||
actionsMenuActionClickedEvent: ActionsMenuActionClickedEvent;
|
||||
|
||||
@@ -28,7 +28,7 @@ import { ModifyEmbeddedWebsiteEvent } from "./Events/EmbeddedWebsiteEvent";
|
||||
import { handleMenuRegistrationEvent, handleMenuUnregisterEvent } from "../Stores/MenuStore";
|
||||
import type { ChangeLayerEvent } from "./Events/ChangeLayerEvent";
|
||||
import type { WasCameraUpdatedEvent } from "./Events/WasCameraUpdatedEvent";
|
||||
import type { ChangeZoneEvent } from "./Events/ChangeZoneEvent";
|
||||
import type { ChangeAreaEvent } from "./Events/ChangeAreaEvent";
|
||||
import { CameraSetEvent } from "./Events/CameraSetEvent";
|
||||
import { CameraFollowPlayerEvent } from "./Events/CameraFollowPlayerEvent";
|
||||
import type { RemotePlayerClickedEvent } from "./Events/RemotePlayerClickedEvent";
|
||||
@@ -445,21 +445,21 @@ class IframeListener {
|
||||
});
|
||||
}
|
||||
|
||||
sendEnterZoneEvent(zoneName: string) {
|
||||
sendEnterAreaEvent(areaName: string) {
|
||||
this.postMessage({
|
||||
type: "enterZoneEvent",
|
||||
type: "enterAreaEvent",
|
||||
data: {
|
||||
name: zoneName,
|
||||
} as ChangeZoneEvent,
|
||||
name: areaName,
|
||||
} as ChangeAreaEvent,
|
||||
});
|
||||
}
|
||||
|
||||
sendLeaveZoneEvent(zoneName: string) {
|
||||
sendLeaveAreaEvent(areaName: string) {
|
||||
this.postMessage({
|
||||
type: "leaveZoneEvent",
|
||||
type: "leaveAreaEvent",
|
||||
data: {
|
||||
name: zoneName,
|
||||
} as ChangeZoneEvent,
|
||||
name: areaName,
|
||||
} as ChangeAreaEvent,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -22,9 +22,9 @@ export type layerChangeCallback = (
|
||||
allLayersOnNewPosition: Array<ITiledMapLayer>
|
||||
) => void;
|
||||
|
||||
export type zoneChangeCallback = (
|
||||
zonesChangedByAction: Array<ITiledMapObject>,
|
||||
allZonesOnNewPosition: Array<ITiledMapObject>
|
||||
export type areaChangeCallback = (
|
||||
areasChangedByAction: Array<ITiledMapObject>,
|
||||
allAreasOnNewPosition: Array<ITiledMapObject>
|
||||
) => void;
|
||||
|
||||
/**
|
||||
@@ -54,8 +54,8 @@ export class GameMap {
|
||||
|
||||
private enterLayerCallbacks = Array<layerChangeCallback>();
|
||||
private leaveLayerCallbacks = Array<layerChangeCallback>();
|
||||
private enterZoneCallbacks = Array<zoneChangeCallback>();
|
||||
private leaveZoneCallbacks = Array<zoneChangeCallback>();
|
||||
private enterAreaCallbacks = Array<areaChangeCallback>();
|
||||
private leaveAreaCallbacks = Array<areaChangeCallback>();
|
||||
|
||||
private tileNameMap = new Map<string, number>();
|
||||
|
||||
@@ -63,7 +63,9 @@ export class GameMap {
|
||||
public readonly flatLayers: ITiledMapLayer[];
|
||||
public readonly tiledObjects: ITiledMapObject[];
|
||||
public readonly phaserLayers: TilemapLayer[] = [];
|
||||
public readonly zones: ITiledMapObject[] = [];
|
||||
public readonly areas: ITiledMapObject[] = [];
|
||||
|
||||
private readonly areasPositionOffsetY: number = 16;
|
||||
|
||||
public exitUrls: Array<string> = [];
|
||||
|
||||
@@ -76,7 +78,8 @@ export class GameMap {
|
||||
) {
|
||||
this.flatLayers = flattenGroupLayersMap(map);
|
||||
this.tiledObjects = this.getObjectsFromLayers(this.flatLayers);
|
||||
this.zones = this.tiledObjects.filter((object) => object.type === "zone");
|
||||
// NOTE: We leave "zone" for legacy reasons
|
||||
this.areas = this.tiledObjects.filter((object) => ["zone", "area"].includes(object.type));
|
||||
|
||||
let depth = -2;
|
||||
for (const layer of this.flatLayers) {
|
||||
@@ -148,7 +151,10 @@ export class GameMap {
|
||||
public setPosition(x: number, y: number) {
|
||||
this.oldPosition = this.position;
|
||||
this.position = { x, y };
|
||||
this.triggerZonesChange();
|
||||
const areasChanged = this.triggerAreasChange();
|
||||
if (areasChanged) {
|
||||
this.triggerAllProperties();
|
||||
}
|
||||
|
||||
this.oldKey = this.key;
|
||||
|
||||
@@ -201,21 +207,17 @@ export class GameMap {
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback called when the user moves inside another zone.
|
||||
*
|
||||
* @deprecated
|
||||
* Registers a callback called when the user moves inside another area.
|
||||
*/
|
||||
public onEnterZone(callback: zoneChangeCallback) {
|
||||
this.enterZoneCallbacks.push(callback);
|
||||
public onEnterArea(callback: areaChangeCallback) {
|
||||
this.enterAreaCallbacks.push(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback called when the user moves outside another zone.
|
||||
*
|
||||
* @deprecated
|
||||
* Registers a callback called when the user moves outside another area.
|
||||
*/
|
||||
public onLeaveZone(callback: zoneChangeCallback) {
|
||||
this.leaveZoneCallbacks.push(callback);
|
||||
public onLeaveArea(callback: areaChangeCallback) {
|
||||
this.leaveAreaCallbacks.push(callback);
|
||||
}
|
||||
|
||||
public findLayer(layerName: string): ITiledMapLayer | undefined {
|
||||
@@ -424,55 +426,56 @@ export class GameMap {
|
||||
}
|
||||
|
||||
/**
|
||||
* We use Tiled Objects with type "zone" as zones with defined x, y, width and height for easier event triggering.
|
||||
* We use Tiled Objects with type "area" as areas with defined x, y, width and height for easier event triggering.
|
||||
* @returns If there were any areas changes
|
||||
*/
|
||||
private triggerZonesChange(): void {
|
||||
const zonesByOldPosition = this.oldPosition
|
||||
? this.zones.filter((zone) => {
|
||||
if (!this.oldPosition) {
|
||||
return false;
|
||||
}
|
||||
return MathUtils.isOverlappingWithRectangle(this.oldPosition, zone);
|
||||
})
|
||||
: [];
|
||||
private triggerAreasChange(): boolean {
|
||||
const areasByOldPosition = this.getAreasOnPosition(this.oldPosition, this.areasPositionOffsetY);
|
||||
const areasByNewPosition = this.getAreasOnPosition(this.position, this.areasPositionOffsetY);
|
||||
|
||||
const zonesByNewPosition = this.position
|
||||
? this.zones.filter((zone) => {
|
||||
if (!this.position) {
|
||||
return false;
|
||||
}
|
||||
return MathUtils.isOverlappingWithRectangle(this.position, zone);
|
||||
})
|
||||
: [];
|
||||
const enterAreas = new Set(areasByNewPosition);
|
||||
const leaveAreas = new Set(areasByOldPosition);
|
||||
|
||||
const enterZones = new Set(zonesByNewPosition);
|
||||
const leaveZones = new Set(zonesByOldPosition);
|
||||
|
||||
enterZones.forEach((zone) => {
|
||||
if (leaveZones.has(zone)) {
|
||||
leaveZones.delete(zone);
|
||||
enterZones.delete(zone);
|
||||
enterAreas.forEach((area) => {
|
||||
if (leaveAreas.has(area)) {
|
||||
leaveAreas.delete(area);
|
||||
enterAreas.delete(area);
|
||||
}
|
||||
});
|
||||
|
||||
if (enterZones.size > 0) {
|
||||
const zonesArray = Array.from(enterZones);
|
||||
for (const callback of this.enterZoneCallbacks) {
|
||||
callback(zonesArray, zonesByNewPosition);
|
||||
let areasChange = false;
|
||||
if (enterAreas.size > 0) {
|
||||
const areasArray = Array.from(enterAreas);
|
||||
for (const callback of this.enterAreaCallbacks) {
|
||||
callback(areasArray, areasByNewPosition);
|
||||
}
|
||||
areasChange = true;
|
||||
}
|
||||
|
||||
if (leaveZones.size > 0) {
|
||||
const zonesArray = Array.from(leaveZones);
|
||||
for (const callback of this.leaveZoneCallbacks) {
|
||||
callback(zonesArray, zonesByNewPosition);
|
||||
if (leaveAreas.size > 0) {
|
||||
const areasArray = Array.from(leaveAreas);
|
||||
for (const callback of this.leaveAreaCallbacks) {
|
||||
callback(areasArray, areasByNewPosition);
|
||||
}
|
||||
areasChange = true;
|
||||
}
|
||||
return areasChange;
|
||||
}
|
||||
|
||||
private getProperties(key: number): Map<string, string | boolean | number> {
|
||||
const properties = new Map<string, string | boolean | number>();
|
||||
|
||||
for (const area of this.getAreasOnPosition(this.position, this.areasPositionOffsetY)) {
|
||||
if (area.properties !== undefined) {
|
||||
for (const property of area.properties) {
|
||||
if (property.value === undefined) {
|
||||
continue;
|
||||
}
|
||||
properties.set(property.name, property.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const layer of this.flatLayers) {
|
||||
if (layer.type !== "tilelayer") {
|
||||
continue;
|
||||
@@ -511,6 +514,17 @@ export class GameMap {
|
||||
return properties;
|
||||
}
|
||||
|
||||
private getAreasOnPosition(position?: { x: number; y: number }, offsetY: number = 0): ITiledMapObject[] {
|
||||
return position
|
||||
? this.areas.filter((area) => {
|
||||
if (!position) {
|
||||
return false;
|
||||
}
|
||||
return MathUtils.isOverlappingWithRectangle({ x: position.x, y: position.y + offsetY }, area);
|
||||
})
|
||||
: [];
|
||||
}
|
||||
|
||||
private getTileProperty(index: number): Array<ITiledMapProperty> {
|
||||
if (this.tileSetPropertyMap[index]) {
|
||||
return this.tileSetPropertyMap[index];
|
||||
|
||||
@@ -7,6 +7,7 @@ export enum GameMapProperties {
|
||||
EXIT_URL = "exitUrl",
|
||||
EXIT_SCENE_URL = "exitSceneUrl",
|
||||
FONT_FAMILY = "font-family",
|
||||
FOCUSABLE = "focusable",
|
||||
JITSI_ADMIN_ROOM_TAG = "jitsiRoomAdminTag",
|
||||
JITSI_CONFIG = "jitsiConfig",
|
||||
JITSI_INTERFACE_CONFIG = "jitsiInterfaceConfig",
|
||||
@@ -36,4 +37,5 @@ export enum GameMapProperties {
|
||||
URL = "url",
|
||||
WRITABLE_BY = "writableBy",
|
||||
ZONE = "zone",
|
||||
ZOOM_MARGIN = "zoom_margin",
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { layoutManagerActionStore } from "../../Stores/LayoutManagerStore";
|
||||
import { localUserStore } from "../../Connexion/LocalUserStore";
|
||||
import { get } from "svelte/store";
|
||||
import { ON_ACTION_TRIGGER_BUTTON, ON_ICON_TRIGGER_BUTTON } from "../../WebRtc/LayoutManager";
|
||||
import type { ITiledMapLayer } from "../Map/ITiledMap";
|
||||
import type { ITiledMapProperty } from "../Map/ITiledMap";
|
||||
import { GameMapProperties } from "./GameMapProperties";
|
||||
import type { CoWebsite } from "../../WebRtc/CoWebsite/CoWesbite";
|
||||
import { SimpleCoWebsite } from "../../WebRtc/CoWebsite/SimpleCoWebsite";
|
||||
@@ -23,9 +23,21 @@ interface OpenCoWebsite {
|
||||
coWebsite?: CoWebsite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Either Layer or Object within Objects Layer in Tiled
|
||||
*/
|
||||
export interface ITiledPlace {
|
||||
name: string;
|
||||
properties?: ITiledMapProperty[];
|
||||
x?: number;
|
||||
y?: number;
|
||||
width?: number;
|
||||
height?: number;
|
||||
}
|
||||
|
||||
export class GameMapPropertiesListener {
|
||||
private coWebsitesOpenByLayer = new Map<ITiledMapLayer, OpenCoWebsite>();
|
||||
private coWebsitesActionTriggerByLayer = new Map<ITiledMapLayer, string>();
|
||||
private coWebsitesOpenByPlace = new Map<ITiledPlace, OpenCoWebsite>();
|
||||
private coWebsitesActionTriggerByPlace = new Map<ITiledPlace, string>();
|
||||
|
||||
constructor(private scene: GameScene, private gameMap: GameMap) {}
|
||||
|
||||
@@ -183,193 +195,241 @@ export class GameMapPropertiesListener {
|
||||
}
|
||||
});
|
||||
|
||||
// Open a new co-website by the property.
|
||||
this.gameMap.onEnterLayer((newLayers) => {
|
||||
const handler = () => {
|
||||
newLayers.forEach((layer) => {
|
||||
if (!layer.properties) {
|
||||
return;
|
||||
}
|
||||
|
||||
let openWebsiteProperty: string | undefined;
|
||||
let allowApiProperty: boolean | undefined;
|
||||
let websitePolicyProperty: string | undefined;
|
||||
let websiteWidthProperty: number | undefined;
|
||||
let websitePositionProperty: number | undefined;
|
||||
let websiteTriggerProperty: string | undefined;
|
||||
let websiteTriggerMessageProperty: string | undefined;
|
||||
|
||||
layer.properties.forEach((property) => {
|
||||
switch (property.name) {
|
||||
case GameMapProperties.OPEN_WEBSITE:
|
||||
openWebsiteProperty = property.value as string | undefined;
|
||||
break;
|
||||
case GameMapProperties.OPEN_WEBSITE_ALLOW_API:
|
||||
allowApiProperty = property.value as boolean | undefined;
|
||||
break;
|
||||
case GameMapProperties.OPEN_WEBSITE_POLICY:
|
||||
websitePolicyProperty = property.value as string | undefined;
|
||||
break;
|
||||
case GameMapProperties.OPEN_WEBSITE_WIDTH:
|
||||
websiteWidthProperty = property.value as number | undefined;
|
||||
break;
|
||||
case GameMapProperties.OPEN_WEBSITE_POSITION:
|
||||
websitePositionProperty = property.value as number | undefined;
|
||||
break;
|
||||
case GameMapProperties.OPEN_WEBSITE_TRIGGER:
|
||||
websiteTriggerProperty = property.value as string | undefined;
|
||||
break;
|
||||
case GameMapProperties.OPEN_WEBSITE_TRIGGER_MESSAGE:
|
||||
websiteTriggerMessageProperty = property.value as string | undefined;
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
if (!openWebsiteProperty) {
|
||||
return;
|
||||
}
|
||||
|
||||
const actionId = "openWebsite-" + (Math.random() + 1).toString(36).substring(7);
|
||||
|
||||
if (this.coWebsitesOpenByLayer.has(layer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const coWebsiteOpen: OpenCoWebsite = {
|
||||
actionId: actionId,
|
||||
};
|
||||
|
||||
this.coWebsitesOpenByLayer.set(layer, coWebsiteOpen);
|
||||
|
||||
const loadCoWebsiteFunction = (coWebsite: CoWebsite) => {
|
||||
coWebsiteManager.loadCoWebsite(coWebsite).catch(() => {
|
||||
console.error("Error during loading a co-website: " + coWebsite.getUrl());
|
||||
});
|
||||
|
||||
layoutManagerActionStore.removeAction(actionId);
|
||||
};
|
||||
|
||||
const openCoWebsiteFunction = () => {
|
||||
const coWebsite = new SimpleCoWebsite(
|
||||
new URL(openWebsiteProperty ?? "", this.scene.MapUrlFile),
|
||||
allowApiProperty,
|
||||
websitePolicyProperty,
|
||||
websiteWidthProperty,
|
||||
false
|
||||
);
|
||||
|
||||
coWebsiteOpen.coWebsite = coWebsite;
|
||||
|
||||
coWebsiteManager.addCoWebsiteToStore(coWebsite, websitePositionProperty);
|
||||
|
||||
loadCoWebsiteFunction(coWebsite);
|
||||
};
|
||||
|
||||
if (
|
||||
localUserStore.getForceCowebsiteTrigger() ||
|
||||
websiteTriggerProperty === ON_ACTION_TRIGGER_BUTTON
|
||||
) {
|
||||
if (!websiteTriggerMessageProperty) {
|
||||
websiteTriggerMessageProperty = get(LL).trigger.cowebsite();
|
||||
}
|
||||
|
||||
this.coWebsitesActionTriggerByLayer.set(layer, actionId);
|
||||
|
||||
layoutManagerActionStore.addAction({
|
||||
uuid: actionId,
|
||||
type: "message",
|
||||
message: websiteTriggerMessageProperty,
|
||||
callback: () => openCoWebsiteFunction(),
|
||||
userInputManager: this.scene.userInputManager,
|
||||
});
|
||||
} else if (websiteTriggerProperty === ON_ICON_TRIGGER_BUTTON) {
|
||||
const coWebsite = new SimpleCoWebsite(
|
||||
new URL(openWebsiteProperty ?? "", this.scene.MapUrlFile),
|
||||
allowApiProperty,
|
||||
websitePolicyProperty,
|
||||
websiteWidthProperty,
|
||||
false
|
||||
);
|
||||
|
||||
coWebsiteOpen.coWebsite = coWebsite;
|
||||
|
||||
coWebsiteManager.addCoWebsiteToStore(coWebsite, websitePositionProperty);
|
||||
}
|
||||
|
||||
if (!websiteTriggerProperty) {
|
||||
openCoWebsiteFunction();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
handler();
|
||||
this.onEnterPlaceHandler(newLayers);
|
||||
});
|
||||
|
||||
// Close opened co-websites on leave the layer who contain the property.
|
||||
this.gameMap.onLeaveLayer((oldLayers) => {
|
||||
const handler = () => {
|
||||
oldLayers.forEach((layer) => {
|
||||
if (!layer.properties) {
|
||||
return;
|
||||
}
|
||||
this.onLeavePlaceHandler(oldLayers);
|
||||
});
|
||||
|
||||
let openWebsiteProperty: string | undefined;
|
||||
let websiteTriggerProperty: string | undefined;
|
||||
this.gameMap.onEnterArea((newAreas) => {
|
||||
this.onEnterPlaceHandler(newAreas);
|
||||
});
|
||||
|
||||
layer.properties.forEach((property) => {
|
||||
switch (property.name) {
|
||||
case GameMapProperties.OPEN_WEBSITE:
|
||||
openWebsiteProperty = property.value as string | undefined;
|
||||
break;
|
||||
case GameMapProperties.OPEN_WEBSITE_TRIGGER:
|
||||
websiteTriggerProperty = property.value as string | undefined;
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
if (!openWebsiteProperty) {
|
||||
return;
|
||||
}
|
||||
|
||||
const coWebsiteOpen = this.coWebsitesOpenByLayer.get(layer);
|
||||
|
||||
if (!coWebsiteOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
const coWebsite = coWebsiteOpen.coWebsite;
|
||||
|
||||
if (coWebsite) {
|
||||
coWebsiteManager.closeCoWebsite(coWebsite);
|
||||
}
|
||||
|
||||
this.coWebsitesOpenByLayer.delete(layer);
|
||||
|
||||
if (!websiteTriggerProperty) {
|
||||
return;
|
||||
}
|
||||
|
||||
const actionStore = get(layoutManagerActionStore);
|
||||
const actionTriggerUuid = this.coWebsitesActionTriggerByLayer.get(layer);
|
||||
|
||||
if (!actionTriggerUuid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const action =
|
||||
actionStore && actionStore.length > 0
|
||||
? actionStore.find((action) => action.uuid === actionTriggerUuid)
|
||||
: undefined;
|
||||
|
||||
if (action) {
|
||||
layoutManagerActionStore.removeAction(actionTriggerUuid);
|
||||
}
|
||||
|
||||
this.coWebsitesActionTriggerByLayer.delete(layer);
|
||||
});
|
||||
};
|
||||
|
||||
handler();
|
||||
this.gameMap.onLeaveArea((oldAreas) => {
|
||||
this.onLeavePlaceHandler(oldAreas);
|
||||
});
|
||||
}
|
||||
|
||||
private onEnterPlaceHandler(places: ITiledPlace[]): void {
|
||||
places.forEach((place) => {
|
||||
this.handleOpenWebsitePropertiesOnEnter(place);
|
||||
this.handleFocusablePropertiesOnEnter(place);
|
||||
});
|
||||
}
|
||||
|
||||
private onLeavePlaceHandler(places: ITiledPlace[]): void {
|
||||
places.forEach((place) => {
|
||||
if (!place.properties) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.handleOpenWebsitePropertiesOnLeave(place);
|
||||
this.handleFocusablePropertiesOnLeave(place);
|
||||
});
|
||||
}
|
||||
|
||||
private handleOpenWebsitePropertiesOnEnter(place: ITiledPlace): void {
|
||||
if (!place.properties) {
|
||||
return;
|
||||
}
|
||||
let openWebsiteProperty: string | undefined;
|
||||
let allowApiProperty: boolean | undefined;
|
||||
let websitePolicyProperty: string | undefined;
|
||||
let websiteWidthProperty: number | undefined;
|
||||
let websitePositionProperty: number | undefined;
|
||||
let websiteTriggerProperty: string | undefined;
|
||||
let websiteTriggerMessageProperty: string | undefined;
|
||||
|
||||
place.properties.forEach((property) => {
|
||||
switch (property.name) {
|
||||
case GameMapProperties.OPEN_WEBSITE:
|
||||
openWebsiteProperty = property.value as string | undefined;
|
||||
break;
|
||||
case GameMapProperties.OPEN_WEBSITE_ALLOW_API:
|
||||
allowApiProperty = property.value as boolean | undefined;
|
||||
break;
|
||||
case GameMapProperties.OPEN_WEBSITE_POLICY:
|
||||
websitePolicyProperty = property.value as string | undefined;
|
||||
break;
|
||||
case GameMapProperties.OPEN_WEBSITE_WIDTH:
|
||||
websiteWidthProperty = property.value as number | undefined;
|
||||
break;
|
||||
case GameMapProperties.OPEN_WEBSITE_POSITION:
|
||||
websitePositionProperty = property.value as number | undefined;
|
||||
break;
|
||||
case GameMapProperties.OPEN_WEBSITE_TRIGGER:
|
||||
websiteTriggerProperty = property.value as string | undefined;
|
||||
break;
|
||||
case GameMapProperties.OPEN_WEBSITE_TRIGGER_MESSAGE:
|
||||
websiteTriggerMessageProperty = property.value as string | undefined;
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
if (!openWebsiteProperty) {
|
||||
return;
|
||||
}
|
||||
|
||||
const actionId = "openWebsite-" + (Math.random() + 1).toString(36).substring(7);
|
||||
|
||||
if (this.coWebsitesOpenByPlace.has(place)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const coWebsiteOpen: OpenCoWebsite = {
|
||||
actionId: actionId,
|
||||
};
|
||||
|
||||
this.coWebsitesOpenByPlace.set(place, coWebsiteOpen);
|
||||
|
||||
const loadCoWebsiteFunction = (coWebsite: CoWebsite) => {
|
||||
coWebsiteManager.loadCoWebsite(coWebsite).catch(() => {
|
||||
console.error("Error during loading a co-website: " + coWebsite.getUrl());
|
||||
});
|
||||
|
||||
layoutManagerActionStore.removeAction(actionId);
|
||||
};
|
||||
|
||||
const openCoWebsiteFunction = () => {
|
||||
const coWebsite = new SimpleCoWebsite(
|
||||
new URL(openWebsiteProperty ?? "", this.scene.MapUrlFile),
|
||||
allowApiProperty,
|
||||
websitePolicyProperty,
|
||||
websiteWidthProperty,
|
||||
false
|
||||
);
|
||||
|
||||
coWebsiteOpen.coWebsite = coWebsite;
|
||||
|
||||
coWebsiteManager.addCoWebsiteToStore(coWebsite, websitePositionProperty);
|
||||
|
||||
loadCoWebsiteFunction(coWebsite);
|
||||
};
|
||||
|
||||
if (localUserStore.getForceCowebsiteTrigger() || websiteTriggerProperty === ON_ACTION_TRIGGER_BUTTON) {
|
||||
if (!websiteTriggerMessageProperty) {
|
||||
websiteTriggerMessageProperty = get(LL).trigger.cowebsite();
|
||||
}
|
||||
|
||||
this.coWebsitesActionTriggerByPlace.set(place, actionId);
|
||||
|
||||
layoutManagerActionStore.addAction({
|
||||
uuid: actionId,
|
||||
type: "message",
|
||||
message: websiteTriggerMessageProperty,
|
||||
callback: () => openCoWebsiteFunction(),
|
||||
userInputManager: this.scene.userInputManager,
|
||||
});
|
||||
} else if (websiteTriggerProperty === ON_ICON_TRIGGER_BUTTON) {
|
||||
const coWebsite = new SimpleCoWebsite(
|
||||
new URL(openWebsiteProperty ?? "", this.scene.MapUrlFile),
|
||||
allowApiProperty,
|
||||
websitePolicyProperty,
|
||||
websiteWidthProperty,
|
||||
false
|
||||
);
|
||||
|
||||
coWebsiteOpen.coWebsite = coWebsite;
|
||||
|
||||
coWebsiteManager.addCoWebsiteToStore(coWebsite, websitePositionProperty);
|
||||
}
|
||||
|
||||
if (!websiteTriggerProperty) {
|
||||
openCoWebsiteFunction();
|
||||
}
|
||||
}
|
||||
|
||||
private handleFocusablePropertiesOnEnter(place: ITiledPlace): void {
|
||||
if (!place.properties) {
|
||||
return;
|
||||
}
|
||||
if (place.x === undefined || place.y === undefined || !place.height || !place.width) {
|
||||
return;
|
||||
}
|
||||
const focusable = place.properties.find((property) => property.name === GameMapProperties.FOCUSABLE);
|
||||
if (focusable && focusable.value === true) {
|
||||
const zoomMargin = place.properties.find((property) => property.name === GameMapProperties.ZOOM_MARGIN);
|
||||
this.scene.getCameraManager().enterFocusMode(
|
||||
{
|
||||
x: place.x + place.width * 0.5,
|
||||
y: place.y + place.height * 0.5,
|
||||
width: place.width,
|
||||
height: place.height,
|
||||
},
|
||||
zoomMargin ? Math.max(0, Number(zoomMargin.value)) : undefined
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private handleOpenWebsitePropertiesOnLeave(place: ITiledPlace): void {
|
||||
if (!place.properties) {
|
||||
return;
|
||||
}
|
||||
|
||||
let openWebsiteProperty: string | undefined;
|
||||
let websiteTriggerProperty: string | undefined;
|
||||
|
||||
place.properties.forEach((property) => {
|
||||
switch (property.name) {
|
||||
case GameMapProperties.OPEN_WEBSITE:
|
||||
openWebsiteProperty = property.value as string | undefined;
|
||||
break;
|
||||
case GameMapProperties.OPEN_WEBSITE_TRIGGER:
|
||||
websiteTriggerProperty = property.value as string | undefined;
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
if (!openWebsiteProperty) {
|
||||
return;
|
||||
}
|
||||
|
||||
const coWebsiteOpen = this.coWebsitesOpenByPlace.get(place);
|
||||
|
||||
if (!coWebsiteOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
const coWebsite = coWebsiteOpen.coWebsite;
|
||||
|
||||
if (coWebsite) {
|
||||
coWebsiteManager.closeCoWebsite(coWebsite);
|
||||
}
|
||||
|
||||
this.coWebsitesOpenByPlace.delete(place);
|
||||
|
||||
if (!websiteTriggerProperty) {
|
||||
return;
|
||||
}
|
||||
|
||||
const actionStore = get(layoutManagerActionStore);
|
||||
const actionTriggerUuid = this.coWebsitesActionTriggerByPlace.get(place);
|
||||
|
||||
if (!actionTriggerUuid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const action =
|
||||
actionStore && actionStore.length > 0
|
||||
? actionStore.find((action) => action.uuid === actionTriggerUuid)
|
||||
: undefined;
|
||||
|
||||
if (action) {
|
||||
layoutManagerActionStore.removeAction(actionTriggerUuid);
|
||||
}
|
||||
|
||||
this.coWebsitesActionTriggerByPlace.delete(place);
|
||||
}
|
||||
|
||||
private handleFocusablePropertiesOnLeave(place: ITiledPlace): void {
|
||||
if (!place.properties) {
|
||||
return;
|
||||
}
|
||||
const focusable = place.properties.find((property) => property.name === GameMapProperties.FOCUSABLE);
|
||||
if (focusable && focusable.value === true) {
|
||||
this.scene.getCameraManager().leaveFocusMode(this.scene.CurrentPlayer, 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -907,38 +907,15 @@ export class GameScene extends DirtyScene {
|
||||
});
|
||||
});
|
||||
|
||||
this.gameMap.onEnterZone((zones) => {
|
||||
for (const zone of zones) {
|
||||
const focusable = zone.properties?.find((property) => property.name === "focusable");
|
||||
if (focusable && focusable.value === true) {
|
||||
const zoomMargin = zone.properties?.find((property) => property.name === "zoom_margin");
|
||||
this.cameraManager.enterFocusMode(
|
||||
{
|
||||
x: zone.x + zone.width * 0.5,
|
||||
y: zone.y + zone.height * 0.5,
|
||||
width: zone.width,
|
||||
height: zone.height,
|
||||
},
|
||||
zoomMargin ? Math.max(0, Number(zoomMargin.value)) : undefined
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
zones.forEach((zone) => {
|
||||
iframeListener.sendEnterZoneEvent(zone.name);
|
||||
this.gameMap.onEnterArea((areas) => {
|
||||
areas.forEach((area) => {
|
||||
iframeListener.sendEnterAreaEvent(area.name);
|
||||
});
|
||||
});
|
||||
|
||||
this.gameMap.onLeaveZone((zones) => {
|
||||
for (const zone of zones) {
|
||||
const focusable = zone.properties?.find((property) => property.name === "focusable");
|
||||
if (focusable && focusable.value === true) {
|
||||
this.cameraManager.leaveFocusMode(this.CurrentPlayer, 1000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
zones.forEach((zone) => {
|
||||
iframeListener.sendLeaveZoneEvent(zone.name);
|
||||
this.gameMap.onLeaveArea((areas) => {
|
||||
areas.forEach((area) => {
|
||||
iframeListener.sendLeaveAreaEvent(area.name);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user