mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-03 07:07:25 -05:00
data encoder: ds1
This commit is contained in:
parent
a89042c1f2
commit
9f56574066
@ -43,6 +43,10 @@ type DS1 struct {
|
||||
NumberOfShadowLayers int32 // ShadowNum number of shadow layer used
|
||||
NumberOfSubstitutionLayers int32 // SubstitutionNum number of substitution layer used
|
||||
SubstitutionGroupsNum int32 // SubstitutionGroupsNum number of substitution groups, datas between objects & NPC paths
|
||||
unknown1 []byte
|
||||
layerStreamTypes []d2enum.LayerStreamType
|
||||
unknown2 uint32
|
||||
npcIndexes []int
|
||||
}
|
||||
|
||||
// LoadDS1 loads the specified DS1 file
|
||||
@ -127,7 +131,10 @@ func LoadDS1(fileData []byte) (*DS1, error) {
|
||||
|
||||
if ds1.Version >= v9 && ds1.Version <= v13 {
|
||||
// Skipping two dwords because they are "meaningless"?
|
||||
br.SkipBytes(8) //nolint:gomnd // We don't know what's here
|
||||
ds1.unknown1, err = br.ReadBytes(8) //nolint:gomnd // We don't know what's here
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if ds1.Version >= v4 {
|
||||
@ -146,7 +153,7 @@ func LoadDS1(fileData []byte) (*DS1, error) {
|
||||
}
|
||||
}
|
||||
|
||||
layerStream := ds1.setupStreamLayerTypes()
|
||||
ds1.layerStreamTypes = ds1.setupStreamLayerTypes()
|
||||
|
||||
ds1.Tiles = make([][]TileRecord, ds1.Height)
|
||||
|
||||
@ -160,7 +167,7 @@ func LoadDS1(fileData []byte) (*DS1, error) {
|
||||
}
|
||||
}
|
||||
|
||||
err = ds1.loadLayerStreams(br, layerStream)
|
||||
err = ds1.loadLayerStreams(br)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -245,7 +252,10 @@ func (ds1 *DS1) loadSubstitutions(br *d2datautils.StreamReader) error {
|
||||
}
|
||||
|
||||
if ds1.Version >= v18 {
|
||||
_, _ = br.ReadUInt32()
|
||||
ds1.unknown2, err = br.ReadUInt32()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
numberOfSubGroups, err := br.ReadInt32()
|
||||
@ -360,6 +370,8 @@ func (ds1 *DS1) loadNPCs(br *d2datautils.StreamReader) error {
|
||||
for idx, ds1Obj := range ds1.Objects {
|
||||
if ds1Obj.X == int(npcX) && ds1Obj.Y == int(npcY) {
|
||||
objIdx = idx
|
||||
ds1.npcIndexes = append(ds1.npcIndexes, idx)
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -418,7 +430,7 @@ func (ds1 *DS1) loadNpcPaths(br *d2datautils.StreamReader, objIdx, numPaths int)
|
||||
return err
|
||||
}
|
||||
|
||||
func (ds1 *DS1) loadLayerStreams(br *d2datautils.StreamReader, layerStream []d2enum.LayerStreamType) error {
|
||||
func (ds1 *DS1) loadLayerStreams(br *d2datautils.StreamReader) error {
|
||||
var err error
|
||||
|
||||
var dirLookup = []int32{
|
||||
@ -427,8 +439,8 @@ func (ds1 *DS1) loadLayerStreams(br *d2datautils.StreamReader, layerStream []d2e
|
||||
0x0F, 0x10, 0x11, 0x12, 0x14,
|
||||
}
|
||||
|
||||
for lIdx := range layerStream {
|
||||
layerStreamType := layerStream[lIdx]
|
||||
for lIdx := range ds1.layerStreamTypes {
|
||||
layerStreamType := ds1.layerStreamTypes[lIdx]
|
||||
|
||||
for y := 0; y < int(ds1.Height); y++ {
|
||||
for x := 0; x < int(ds1.Width); x++ {
|
||||
@ -445,7 +457,7 @@ func (ds1 *DS1) loadLayerStreams(br *d2datautils.StreamReader, layerStream []d2e
|
||||
ds1.Tiles[y][x].Walls[wallIndex].Unknown1 = byte((dw & 0x000FC000) >> 14) //nolint:gomnd // Bitmask
|
||||
ds1.Tiles[y][x].Walls[wallIndex].Style = byte((dw & 0x03F00000) >> 20) //nolint:gomnd // Bitmask
|
||||
ds1.Tiles[y][x].Walls[wallIndex].Unknown2 = byte((dw & 0x7C000000) >> 26) //nolint:gomnd // Bitmask
|
||||
ds1.Tiles[y][x].Walls[wallIndex].Hidden = byte((dw&0x80000000)>>31) > 0 //nolint:gomnd // Bitmask
|
||||
ds1.Tiles[y][x].Walls[wallIndex].hidden = byte((dw & 0x80000000) >> 31) //nolint:gomnd // Bitmask
|
||||
case d2enum.LayerStreamOrientation1, d2enum.LayerStreamOrientation2,
|
||||
d2enum.LayerStreamOrientation3, d2enum.LayerStreamOrientation4:
|
||||
wallIndex := int(layerStreamType) - int(d2enum.LayerStreamOrientation1)
|
||||
@ -466,14 +478,14 @@ func (ds1 *DS1) loadLayerStreams(br *d2datautils.StreamReader, layerStream []d2e
|
||||
ds1.Tiles[y][x].Floors[floorIndex].Unknown1 = byte((dw & 0x000FC000) >> 14) //nolint:gomnd // Bitmask
|
||||
ds1.Tiles[y][x].Floors[floorIndex].Style = byte((dw & 0x03F00000) >> 20) //nolint:gomnd // Bitmask
|
||||
ds1.Tiles[y][x].Floors[floorIndex].Unknown2 = byte((dw & 0x7C000000) >> 26) //nolint:gomnd // Bitmask
|
||||
ds1.Tiles[y][x].Floors[floorIndex].Hidden = byte((dw&0x80000000)>>31) > 0 //nolint:gomnd // Bitmask
|
||||
ds1.Tiles[y][x].Floors[floorIndex].hidden = byte((dw & 0x80000000) >> 31) //nolint:gomnd // Bitmask
|
||||
case d2enum.LayerStreamShadow:
|
||||
ds1.Tiles[y][x].Shadows[0].Prop1 = byte(dw & 0x000000FF) //nolint:gomnd // Bitmask
|
||||
ds1.Tiles[y][x].Shadows[0].Sequence = byte((dw & 0x00003F00) >> 8) //nolint:gomnd // Bitmask
|
||||
ds1.Tiles[y][x].Shadows[0].Unknown1 = byte((dw & 0x000FC000) >> 14) //nolint:gomnd // Bitmask
|
||||
ds1.Tiles[y][x].Shadows[0].Style = byte((dw & 0x03F00000) >> 20) //nolint:gomnd // Bitmask
|
||||
ds1.Tiles[y][x].Shadows[0].Unknown2 = byte((dw & 0x7C000000) >> 26) //nolint:gomnd // Bitmask
|
||||
ds1.Tiles[y][x].Shadows[0].Hidden = byte((dw&0x80000000)>>31) > 0 //nolint:gomnd // Bitmask
|
||||
ds1.Tiles[y][x].Shadows[0].hidden = byte((dw & 0x80000000) >> 31) //nolint:gomnd // Bitmask
|
||||
case d2enum.LayerStreamSubstitute:
|
||||
ds1.Tiles[y][x].Substitutions[0].Unknown = dw
|
||||
}
|
||||
@ -483,3 +495,142 @@ func (ds1 *DS1) loadLayerStreams(br *d2datautils.StreamReader, layerStream []d2e
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Marshal encodes ds1 back to byte slice
|
||||
// nolint:funlen,gocognit // no need to change
|
||||
func (ds1 *DS1) Marshal() []byte {
|
||||
// create stream writer
|
||||
sw := d2datautils.CreateStreamWriter()
|
||||
|
||||
// Step 1 - encode header
|
||||
sw.PushInt32(ds1.Version)
|
||||
sw.PushInt32(ds1.Width - 1)
|
||||
sw.PushInt32(ds1.Height - 1)
|
||||
|
||||
if ds1.Version >= v8 {
|
||||
sw.PushInt32(ds1.Act - 1)
|
||||
}
|
||||
|
||||
if ds1.Version >= v10 {
|
||||
sw.PushInt32(ds1.SubstitutionType)
|
||||
}
|
||||
|
||||
if ds1.Version >= v3 {
|
||||
sw.PushInt32(int32(len(ds1.Files)))
|
||||
|
||||
for _, i := range ds1.Files {
|
||||
sw.PushBytes([]byte(i)...)
|
||||
|
||||
// separator
|
||||
sw.PushBytes(0)
|
||||
}
|
||||
}
|
||||
|
||||
if ds1.Version >= v9 && ds1.Version <= v13 {
|
||||
sw.PushBytes(ds1.unknown1...)
|
||||
}
|
||||
|
||||
if ds1.Version >= v4 {
|
||||
sw.PushInt32(ds1.NumberOfWalls)
|
||||
|
||||
if ds1.Version >= v16 {
|
||||
sw.PushInt32(ds1.NumberOfFloors)
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2 - encode layers
|
||||
for lIdx := range ds1.layerStreamTypes {
|
||||
layerStreamType := ds1.layerStreamTypes[lIdx]
|
||||
|
||||
for y := 0; y < int(ds1.Height); y++ {
|
||||
for x := 0; x < int(ds1.Width); x++ {
|
||||
dw := uint32(0)
|
||||
|
||||
switch layerStreamType {
|
||||
case d2enum.LayerStreamWall1, d2enum.LayerStreamWall2, d2enum.LayerStreamWall3, d2enum.LayerStreamWall4:
|
||||
wallIndex := int(layerStreamType) - int(d2enum.LayerStreamWall1)
|
||||
dw |= uint32(ds1.Tiles[y][x].Walls[wallIndex].Prop1) & 0xFF //nolint:gomnd // Bitmask
|
||||
dw |= (uint32(ds1.Tiles[y][x].Walls[wallIndex].Sequence) & 0x3F) << 8 //nolint:gomnd // Bitmask
|
||||
dw |= (uint32(ds1.Tiles[y][x].Walls[wallIndex].Unknown1) & 0xFC) << 14 //nolint:gomnd // Bitmask
|
||||
dw |= (uint32(ds1.Tiles[y][x].Walls[wallIndex].Style) & 0x3F) << 20 //nolint:gomnd // Bitmask
|
||||
dw |= (uint32(ds1.Tiles[y][x].Walls[wallIndex].Unknown2) & 0x7C) << 26 //nolint:gomnd // Bitmask
|
||||
dw |= (uint32(ds1.Tiles[y][x].Walls[wallIndex].hidden) & 0x01) << 31 //nolint:gomnd // Bitmask
|
||||
case d2enum.LayerStreamOrientation1, d2enum.LayerStreamOrientation2,
|
||||
d2enum.LayerStreamOrientation3, d2enum.LayerStreamOrientation4:
|
||||
wallIndex := int(layerStreamType) - int(d2enum.LayerStreamOrientation1)
|
||||
dw |= uint32(ds1.Tiles[y][x].Walls[wallIndex].Type)
|
||||
dw |= (uint32(ds1.Tiles[y][x].Walls[wallIndex].Zero) & 0xFFFFFF00) << 8 //nolint:gomnd // Bitmask
|
||||
|
||||
case d2enum.LayerStreamFloor1, d2enum.LayerStreamFloor2:
|
||||
floorIndex := int(layerStreamType) - int(d2enum.LayerStreamFloor1)
|
||||
dw |= uint32(ds1.Tiles[y][x].Floors[floorIndex].Prop1) & 0xFF //nolint:gomnd // Bitmask
|
||||
dw |= (uint32(ds1.Tiles[y][x].Floors[floorIndex].Sequence) & 0x3F) << 8 //nolint:gomnd // Bitmask
|
||||
dw |= (uint32(ds1.Tiles[y][x].Floors[floorIndex].Unknown1) & 0xFC) << 14 //nolint:gomnd // Bitmask
|
||||
dw |= (uint32(ds1.Tiles[y][x].Floors[floorIndex].Style) & 0x3F) << 20 //nolint:gomnd // Bitmask
|
||||
dw |= (uint32(ds1.Tiles[y][x].Floors[floorIndex].Unknown2) & 0x7C) << 26 //nolint:gomnd // Bitmask
|
||||
dw |= (uint32(ds1.Tiles[y][x].Floors[floorIndex].hidden) & 0x01) << 31 //nolint:gomnd // Bitmask
|
||||
case d2enum.LayerStreamShadow:
|
||||
dw |= uint32(ds1.Tiles[y][x].Shadows[0].Prop1) & 0xFF //nolint:gomnd // Bitmask
|
||||
dw |= (uint32(ds1.Tiles[y][x].Shadows[0].Sequence) & 0x3F) << 8 //nolint:gomnd // Bitmask
|
||||
dw |= (uint32(ds1.Tiles[y][x].Shadows[0].Unknown1) & 0xFC) << 14 //nolint:gomnd // Bitmask
|
||||
dw |= (uint32(ds1.Tiles[y][x].Shadows[0].Style) & 0x3F) << 20 //nolint:gomnd // Bitmask
|
||||
dw |= (uint32(ds1.Tiles[y][x].Shadows[0].Unknown2) & 0x7C) << 26 //nolint:gomnd // Bitmask
|
||||
dw |= (uint32(ds1.Tiles[y][x].Shadows[0].hidden) & 0x01) << 31 //nolint:gomnd // Bitmask
|
||||
case d2enum.LayerStreamSubstitute:
|
||||
dw = ds1.Tiles[y][x].Substitutions[0].Unknown
|
||||
}
|
||||
|
||||
sw.PushUint32(dw)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3 - encode objects
|
||||
if !(ds1.Version < v2) {
|
||||
sw.PushInt32(int32(len(ds1.Objects)))
|
||||
|
||||
for _, i := range ds1.Objects {
|
||||
sw.PushUint32(uint32(i.Type))
|
||||
sw.PushUint32(uint32(i.ID))
|
||||
sw.PushUint32(uint32(i.X))
|
||||
sw.PushUint32(uint32(i.Y))
|
||||
sw.PushUint32(uint32(i.Flags))
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4 - encode substitutions
|
||||
if ds1.Version >= v12 && (ds1.SubstitutionType == subType1 || ds1.SubstitutionType == subType2) {
|
||||
sw.PushUint32(ds1.unknown2)
|
||||
|
||||
sw.PushUint32(uint32(len(ds1.SubstitutionGroups)))
|
||||
|
||||
for _, i := range ds1.SubstitutionGroups {
|
||||
sw.PushInt32(i.TileX)
|
||||
sw.PushInt32(i.TileY)
|
||||
sw.PushInt32(i.WidthInTiles)
|
||||
sw.PushInt32(i.HeightInTiles)
|
||||
sw.PushInt32(i.Unknown)
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5.1 - encode npc's
|
||||
sw.PushUint32(uint32(len(ds1.npcIndexes)))
|
||||
|
||||
// Step 5.2 - enoce npcs' paths
|
||||
for _, i := range ds1.npcIndexes {
|
||||
sw.PushUint32(uint32(len(ds1.Objects[i].Paths)))
|
||||
sw.PushUint32(uint32(ds1.Objects[i].X))
|
||||
sw.PushUint32(uint32(ds1.Objects[i].Y))
|
||||
|
||||
for _, j := range ds1.Objects[i].Paths {
|
||||
sw.PushUint32(uint32(j.Position.X()))
|
||||
sw.PushUint32(uint32(j.Position.Y()))
|
||||
|
||||
if ds1.Version >= v15 {
|
||||
sw.PushUint32(uint32(j.Action))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sw.GetBytes()
|
||||
}
|
||||
|
@ -7,8 +7,13 @@ type FloorShadowRecord struct {
|
||||
Unknown1 byte
|
||||
Style byte
|
||||
Unknown2 byte
|
||||
Hidden bool
|
||||
hidden byte
|
||||
RandomIndex byte
|
||||
Animated bool
|
||||
YAdjust int
|
||||
}
|
||||
|
||||
// Hidden returns if floor/shadow is hidden
|
||||
func (f *FloorShadowRecord) Hidden() bool {
|
||||
return f.hidden > 0
|
||||
}
|
||||
|
@ -11,7 +11,12 @@ type WallRecord struct {
|
||||
Unknown1 byte
|
||||
Style byte
|
||||
Unknown2 byte
|
||||
Hidden bool
|
||||
hidden byte
|
||||
RandomIndex byte
|
||||
YAdjust int
|
||||
}
|
||||
|
||||
// Hidden returns if wall is hidden
|
||||
func (w *WallRecord) Hidden() bool {
|
||||
return w.hidden > 0
|
||||
}
|
||||
|
@ -359,19 +359,19 @@ func (mr *MapRenderer) renderPass4(target d2interface.Surface, startX, startY, e
|
||||
|
||||
func (mr *MapRenderer) renderTilePass1(tile *d2mapengine.MapTile, target d2interface.Surface) {
|
||||
for _, wall := range tile.Components.Walls {
|
||||
if !wall.Hidden && wall.Prop1 != 0 && wall.Type.LowerWall() {
|
||||
if !wall.Hidden() && wall.Prop1 != 0 && wall.Type.LowerWall() {
|
||||
mr.renderWall(wall, mr.viewport, target)
|
||||
}
|
||||
}
|
||||
|
||||
for _, floor := range tile.Components.Floors {
|
||||
if !floor.Hidden && floor.Prop1 != 0 {
|
||||
if !floor.Hidden() && floor.Prop1 != 0 {
|
||||
mr.renderFloor(floor, target)
|
||||
}
|
||||
}
|
||||
|
||||
for _, shadow := range tile.Components.Shadows {
|
||||
if !shadow.Hidden && shadow.Prop1 != 0 {
|
||||
if !shadow.Hidden() && shadow.Prop1 != 0 {
|
||||
mr.renderShadow(shadow, target)
|
||||
}
|
||||
}
|
||||
@ -379,7 +379,7 @@ func (mr *MapRenderer) renderTilePass1(tile *d2mapengine.MapTile, target d2inter
|
||||
|
||||
func (mr *MapRenderer) renderTilePass2(tile *d2mapengine.MapTile, target d2interface.Surface) {
|
||||
for _, wall := range tile.Components.Walls {
|
||||
if !wall.Hidden && wall.Type.UpperWall() {
|
||||
if !wall.Hidden() && wall.Type.UpperWall() {
|
||||
mr.renderWall(wall, mr.viewport, target)
|
||||
}
|
||||
}
|
||||
|
@ -34,19 +34,19 @@ func (mr *MapRenderer) generateTileCache() {
|
||||
tile := &tiles[idx]
|
||||
|
||||
for i := range tile.Components.Floors {
|
||||
if !tile.Components.Floors[i].Hidden && tile.Components.Floors[i].Prop1 != 0 {
|
||||
if !tile.Components.Floors[i].Hidden() && tile.Components.Floors[i].Prop1 != 0 {
|
||||
mr.generateFloorCache(&tile.Components.Floors[i])
|
||||
}
|
||||
}
|
||||
|
||||
for i := range tile.Components.Shadows {
|
||||
if !tile.Components.Shadows[i].Hidden && tile.Components.Shadows[i].Prop1 != 0 {
|
||||
if !tile.Components.Shadows[i].Hidden() && tile.Components.Shadows[i].Prop1 != 0 {
|
||||
mr.generateShadowCache(&tile.Components.Shadows[i])
|
||||
}
|
||||
}
|
||||
|
||||
for i := range tile.Components.Walls {
|
||||
if !tile.Components.Walls[i].Hidden && tile.Components.Walls[i].Prop1 != 0 {
|
||||
if !tile.Components.Walls[i].Hidden() && tile.Components.Walls[i].Prop1 != 0 {
|
||||
mr.generateWallCache(&tile.Components.Walls[i])
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user