@@ -7,27 +7,28 @@ 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
29
tiles : Tile [ ] ;
30
30
objects : LandscapeObject [ ] ;
31
+ mapFile : MapFile ;
31
32
}
32
33
33
34
@@ -37,20 +38,54 @@ export interface MapRegion {
37
38
export class ChunkManager {
38
39
39
40
public readonly regionMap : Map < string , MapRegion > = new Map < string , MapRegion > ( ) ;
40
- public readonly tileMap : Map < string , Tile > = new Map < string , Tile > ( ) ;
41
41
private readonly chunkMap : Map < string , Chunk > ;
42
42
43
43
public constructor ( ) {
44
44
this . chunkMap = new Map < string , Chunk > ( ) ;
45
45
}
46
46
47
+ public getTile ( position : Position ) : Tile {
48
+ const chunkX = position . chunkX + 6 ;
49
+ const chunkY = position . chunkY + 6 ;
50
+ const mapRegionX = Math . floor ( chunkX / 8 ) ;
51
+ const mapRegionY = Math . floor ( chunkY / 8 ) ;
52
+ const mapWorldPositionX = ( mapRegionX & 0xff ) * 64 ;
53
+ const mapWorldPositionY = mapRegionY * 64 ;
54
+ const regionSettings = this . regionMap . get ( `${ mapRegionX } ,${ mapRegionY } ` ) ?. mapFile ?. tileSettings ;
55
+
56
+ this . registerMapRegion ( mapRegionX , mapRegionY ) ;
57
+
58
+ if ( ! regionSettings ) {
59
+ return new Tile ( position . x , position . y , position . level ) ;
60
+ }
61
+
62
+ const tileX = position . x - mapWorldPositionX ;
63
+ const tileY = position . y - mapWorldPositionY ;
64
+ const tileLevel = position . level ;
65
+ let tileSettings = regionSettings [ tileLevel ] [ tileX ] [ tileY ] ;
66
+
67
+ if ( tileLevel < 3 ) {
68
+ // Check for a bridge tile above the active tile
69
+ const tileAboveSettings = regionSettings [ tileLevel + 1 ] [ tileX ] [ tileY ] ;
70
+ if ( ( tileAboveSettings & 0x2 ) === 2 ) {
71
+ // Set this tile as walkable if the tile above is a bridge -
72
+ // This is because the maps are stored with bridges being one level
73
+ // above where their collision maps need to be
74
+ tileSettings = 0 ;
75
+ }
76
+ }
77
+
78
+ return new Tile ( position . x , position . y , tileLevel , tileSettings ) ;
79
+ }
80
+
47
81
public registerMapRegion ( mapRegionX : number , mapRegionY : number ) : void {
48
82
const key = `${ mapRegionX } ,${ mapRegionY } ` ;
49
83
50
84
if ( this . regionMap . has ( key ) ) {
51
85
// Map region already registered
52
86
return ;
53
87
}
88
+ this . regionMap . set ( key , null ) ;
54
89
55
90
let mapFile : MapFile ;
56
91
let landscapeFile : LandscapeFile ;
@@ -66,69 +101,25 @@ export class ChunkManager {
66
101
logger . error ( `Error decoding landscape file ${ mapRegionX } ,${ mapRegionY } ` ) ;
67
102
}
68
103
69
- const region : MapRegion = { tiles : [ ] ,
104
+ const region : MapRegion = { mapFile , tiles : [ ] ,
70
105
objects : landscapeFile ?. landscapeObjects || [ ] } ;
71
106
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
- }
81
-
82
107
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 ) ;
108
+ this . registerObjects ( region . objects , region . tiles || [ ] ) ;
88
109
}
89
110
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 {
111
+ public registerObjects ( objects : LandscapeObject [ ] , tiles : Tile [ ] ) : void {
115
112
if ( ! objects || objects . length === 0 ) {
116
113
return ;
117
114
}
118
115
119
116
for ( const object of objects ) {
120
117
const position = new Position ( object . x , object . y , object . level ) ;
121
118
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 ;
119
+ if ( tiles . some ( tile => ( tile ?. settings & 0x2 ) === 2 &&
120
+ tile ?. x === object . x && tile ?. y === object . y && tile ?. level >= object . level ) ) {
121
+ // Object is on or underneath a bridge tile and needs to move down one level
122
+ position . move ( object . x , object . y , object . level - 1 ) ;
132
123
}
133
124
134
125
this . getChunkForWorldPosition ( position ) . setFilestoreLandscapeObject ( object ) ;
@@ -175,6 +166,7 @@ export class ChunkManager {
175
166
} else {
176
167
const chunk = new Chunk ( pos ) ;
177
168
this . chunkMap . set ( pos . key , chunk ) ;
169
+ chunk . registerMapRegion ( ) ;
178
170
return chunk ;
179
171
}
180
172
}
0 commit comments