@@ -7,27 +7,27 @@ import { LandscapeFile, LandscapeObject, MapFile } from '@runejs/filestore';
7
7
8
8
export class Tile {
9
9
10
- public settings : number ;
11
- public nonWalkable : boolean ;
12
- public bridge : boolean ;
10
+ public settings : number = 0 ;
11
+ public blocked : boolean = false ;
12
+ public bridge : boolean = false ;
13
13
14
14
public constructor ( public x : number , public y : number , public level : number , settings ?: number ) {
15
- if ( settings !== undefined ) {
15
+ if ( settings ) {
16
16
this . setSettings ( settings ) ;
17
17
}
18
18
}
19
19
20
20
public setSettings ( settings : number ) : void {
21
21
this . settings = settings ;
22
- this . nonWalkable = ( this . settings & 0x1 ) == 0x1 ;
23
- this . bridge = ( this . settings & 0x2 ) == 0x2 ;
22
+ this . blocked = ( this . settings & 0x1 ) === 1 ;
23
+ this . bridge = ( this . settings & 0x2 ) === 2 ;
24
24
}
25
25
26
26
}
27
27
28
28
export interface MapRegion {
29
- tiles : Tile [ ] ;
30
29
objects : LandscapeObject [ ] ;
30
+ mapFile : MapFile ;
31
31
}
32
32
33
33
@@ -37,20 +37,54 @@ export interface MapRegion {
37
37
export class ChunkManager {
38
38
39
39
public readonly regionMap : Map < string , MapRegion > = new Map < string , MapRegion > ( ) ;
40
- public readonly tileMap : Map < string , Tile > = new Map < string , Tile > ( ) ;
41
40
private readonly chunkMap : Map < string , Chunk > ;
42
41
43
42
public constructor ( ) {
44
43
this . chunkMap = new Map < string , Chunk > ( ) ;
45
44
}
46
45
46
+ public getTile ( position : Position ) : Tile {
47
+ const chunkX = position . chunkX + 6 ;
48
+ const chunkY = position . chunkY + 6 ;
49
+ const mapRegionX = Math . floor ( chunkX / 8 ) ;
50
+ const mapRegionY = Math . floor ( chunkY / 8 ) ;
51
+ const mapWorldPositionX = ( mapRegionX & 0xff ) * 64 ;
52
+ const mapWorldPositionY = mapRegionY * 64 ;
53
+ const regionSettings = this . regionMap . get ( `${ mapRegionX } ,${ mapRegionY } ` ) ?. mapFile ?. tileSettings ;
54
+
55
+ this . registerMapRegion ( mapRegionX , mapRegionY ) ;
56
+
57
+ if ( ! regionSettings ) {
58
+ return new Tile ( position . x , position . y , position . level ) ;
59
+ }
60
+
61
+ const tileX = position . x - mapWorldPositionX ;
62
+ const tileY = position . y - mapWorldPositionY ;
63
+ const tileLevel = position . level ;
64
+ let tileSettings = regionSettings [ tileLevel ] [ tileX ] [ tileY ] ;
65
+
66
+ if ( tileLevel < 3 ) {
67
+ // Check for a bridge tile above the active tile
68
+ const tileAboveSettings = regionSettings [ tileLevel + 1 ] [ tileX ] [ tileY ] ;
69
+ if ( ( tileAboveSettings & 0x2 ) === 2 ) {
70
+ // Set this tile as walkable if the tile above is a bridge -
71
+ // This is because the maps are stored with bridges being one level
72
+ // above where their collision maps need to be
73
+ tileSettings = 0 ;
74
+ }
75
+ }
76
+
77
+ return new Tile ( position . x , position . y , tileLevel , tileSettings ) ;
78
+ }
79
+
47
80
public registerMapRegion ( mapRegionX : number , mapRegionY : number ) : void {
48
81
const key = `${ mapRegionX } ,${ mapRegionY } ` ;
49
82
50
83
if ( this . regionMap . has ( key ) ) {
51
84
// Map region already registered
52
85
return ;
53
86
}
87
+ this . regionMap . set ( key , null ) ;
54
88
55
89
let mapFile : MapFile ;
56
90
let landscapeFile : LandscapeFile ;
@@ -66,69 +100,30 @@ export class ChunkManager {
66
100
logger . error ( `Error decoding landscape file ${ mapRegionX } ,${ mapRegionY } ` ) ;
67
101
}
68
102
69
- const region : MapRegion = { tiles : [ ] ,
70
- objects : landscapeFile ?. landscapeObjects || [ ] } ;
71
-
72
- // Parse map tiles for game engine use
73
- for ( let level = 0 ; level < 4 ; level ++ ) {
74
- for ( let x = 0 ; x < 64 ; x ++ ) {
75
- for ( let y = 0 ; y < 64 ; y ++ ) {
76
- const tileSettings = mapFile ?. tileSettings [ level ] [ x ] [ y ] || 0 ;
77
- region . tiles . push ( new Tile ( x , y , level , tileSettings ) ) ;
78
- }
79
- }
80
- }
103
+ const region : MapRegion = { mapFile, objects : landscapeFile ?. landscapeObjects || [ ] } ;
81
104
82
105
this . regionMap . set ( key , region ) ;
83
- this . registerTiles ( region . tiles ) ;
84
-
85
- const worldX = ( mapRegionX & 0xff ) * 64 ;
86
- const worldY = mapRegionY * 64 ;
87
- this . registerObjects ( region . objects , worldX , worldY ) ;
106
+ this . registerObjects ( region . objects , mapFile ) ;
88
107
}
89
108
90
- public registerTiles ( tiles : Tile [ ] ) : void {
91
- if ( ! tiles || tiles . length === 0 ) {
92
- return ;
93
- }
94
-
95
- for ( const tile of tiles ) {
96
- const key = `${ tile . x } ,${ tile . y } ,${ tile . level } ` ;
97
-
98
- if ( tile . bridge ) {
99
- // Move this tile down one level if it's a bridge tile
100
- const newTile = new Tile ( tile . x , tile . y , tile . level - 1 , 0 ) ;
101
- this . tileMap . set ( `${ newTile . x } ,${ newTile . y } ,${ newTile . level } ` , newTile ) ;
102
-
103
- // And also add the bridge tile itself, so that game objects know about it
104
- this . tileMap . set ( key , tile ) ;
105
- } else if ( tile . nonWalkable ) { // No need to know about walkable tiles for collision maps, only nonwalkable
106
- if ( ! this . tileMap . has ( key ) ) {
107
- // Otherwise add a new tile if it hasn't already been set (IE by a bridge tile above)
108
- this . tileMap . set ( key , tile ) ;
109
- }
110
- }
111
- }
112
- }
113
-
114
- public registerObjects ( objects : LandscapeObject [ ] , mapRegionStartX : number , mapRegionStartY : number ) : void {
109
+ public registerObjects ( objects : LandscapeObject [ ] , mapFile : MapFile ) : void {
115
110
if ( ! objects || objects . length === 0 ) {
116
111
return ;
117
112
}
118
113
114
+ const mapWorldPositionX = ( mapFile . regionX & 0xff ) * 64 ;
115
+ const mapWorldPositionY = mapFile . regionY * 64 ;
116
+
119
117
for ( const object of objects ) {
120
118
const position = new Position ( object . x , object . y , object . level ) ;
119
+ const localX = object . x - mapWorldPositionX ;
120
+ const localY = object . y - mapWorldPositionY ;
121
121
122
- const tile = this . tileMap . get ( position . key ) ;
123
- if ( tile ?. bridge ) {
124
- // Object is on a bridge tile, move it down a level to create proper collision maps
125
- position . level -= 1 ;
126
- }
127
-
128
- const tileAbove = this . tileMap . get ( `${ object . x } ,${ object . y } ,${ object . level + 1 } ` ) ;
129
- if ( tileAbove ?. bridge ) {
130
- // Object is below a bridge tile, move it down a level to create proper collision maps
131
- position . level -= 1 ;
122
+ for ( let level = 3 ; level >= 0 ; level -- ) {
123
+ if ( ( mapFile . tileSettings [ level ] [ localX ] [ localY ] & 0x2 ) === 2 ) {
124
+ // Object is on or underneath a bridge tile and needs to move down one level
125
+ position . move ( object . x , object . y , object . level - 1 ) ;
126
+ }
132
127
}
133
128
134
129
this . getChunkForWorldPosition ( position ) . setFilestoreLandscapeObject ( object ) ;
@@ -175,6 +170,7 @@ export class ChunkManager {
175
170
} else {
176
171
const chunk = new Chunk ( pos ) ;
177
172
this . chunkMap . set ( pos . key , chunk ) ;
173
+ chunk . registerMapRegion ( ) ;
178
174
return chunk ;
179
175
}
180
176
}
0 commit comments