Ds1 refactor: removed npcIndexes field+fixed SetNumberOfWalls bug (#7)

* ds1 refactor: removed npcIndexes field
it was unnecessary, because described a number of objects with paths to use in encoder, but we can calculate manually

* ds1 refactor: fixed set number of (layers) bug

* ds1 refactor: SetNumberOf...Layers now returns error if incorrect number given

* ds1 refactor: lintfix

* ds1 refactor: rename: setupStreamLayerTypes -> GetStreamLayerTypes

Co-authored-by: M. Sz <mszeptuch@protonmail.com>
This commit is contained in:
gucio321 2021-02-23 21:35:06 +01:00 committed by GitHub
parent 5e62b12bc4
commit 4e7ec3e843
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 109 additions and 54 deletions

View File

@ -2,6 +2,7 @@ package d2ds1
import (
"fmt"
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2datautils"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
@ -56,10 +57,9 @@ type DS1 struct {
numberOfSubstitutionLayers int32 // SubstitutionNum number of substitution layer used
// substitutionGroupsNum int32 // SubstitutionGroupsNum number of substitution groups, datas between objects & NPC paths
dirty bool // when modifying tiles, need to perform upkeep on ds1 state
unknown1 []byte
unknown2 uint32
npcIndexes []int
dirty bool // when modifying tiles, need to perform upkeep on ds1 state
unknown1 []byte
unknown2 uint32
}
// Files returns a list of file path strings.
@ -323,35 +323,42 @@ func (ds1 *DS1) NumberOfWallLayers() int {
}
// SetNumberOfWallLayers sets new number of tiles' walls
func (ds1 *DS1) SetNumberOfWallLayers(n int32) {
for y := range ds1.tiles {
for x := range ds1.tiles[y] {
for v := int32(0); v < n-int32(len(ds1.tiles[y][x].Walls)); v++ {
ds1.tiles[y][x].Walls = append(ds1.tiles[y][x].Walls, Wall{})
}
}
func (ds1 *DS1) SetNumberOfWallLayers(n int32) error {
if n > d2enum.MaxNumberOfWalls {
return fmt.Errorf("cannot set number of walls to %d: number of walls is greater than %d", n, d2enum.MaxNumberOfWalls)
}
// if n = number of walls, do nothing
if n == ds1.numberOfWallLayers {
return
}
ds1.dirty = true
defer ds1.update()
for y := range ds1.tiles {
for x := range ds1.tiles[y] {
newWalls := make([]Wall, n)
for v := int32(0); v < n; v++ {
newWalls[v] = ds1.tiles[y][x].Walls[v]
// ugh, I don't know, WHY do I nned to use
// helper variable, but other way
// simply doesn't work
newWalls := ds1.tiles[y][x].Walls
for v := int32(0); v < (n - int32(len(ds1.tiles[y][x].Walls))); v++ {
newWalls = append(newWalls, Wall{0, 0, 0, 0, 0, 0, 0, 0, 0, 0})
}
ds1.tiles[y][x].Walls = newWalls
}
}
// if n = number of walls, do nothing
if n == ds1.numberOfWallLayers {
return nil
}
for y := range ds1.tiles {
for x := range ds1.tiles[y] {
ds1.tiles[y][x].Walls = ds1.tiles[y][x].Walls[:n]
}
}
ds1.numberOfWallLayers = n
ds1.dirty = true
ds1.update()
return nil
}
// NumberOfFloorLayers returns the number of floor layers per tile
@ -364,21 +371,25 @@ func (ds1 *DS1) NumberOfFloorLayers() int {
}
// SetNumberOfFloorLayers sets new number of tiles' floors
func (ds1 *DS1) SetNumberOfFloorLayers(n int32) {
// calculate, how much walls is missing
missingFloors := n - ds1.numberOfFloorLayers
func (ds1 *DS1) SetNumberOfFloorLayers(n int32) error {
if n > d2enum.MaxNumberOfFloors {
return fmt.Errorf("cannot set number of floors to %d: number is greater than %d", n, d2enum.MaxNumberOfFloors)
}
for y := range ds1.tiles {
for x := range ds1.tiles[y] {
for v := int32(0); v < missingFloors; v++ {
ds1.tiles[y][x].Floors = append(ds1.tiles[y][x].Floors, Floor{})
newFloors := ds1.tiles[y][x].Floors
for v := int32(0); v < (n - int32(len(ds1.tiles[y][x].Floors))); v++ {
newFloors = append(newFloors, Floor{})
}
ds1.tiles[y][x].Floors = newFloors
}
}
// if n = number of walls, do nothing
if n == ds1.numberOfFloorLayers {
return
return nil
}
ds1.dirty = true
@ -396,6 +407,8 @@ func (ds1 *DS1) SetNumberOfFloorLayers(n int32) {
}
ds1.numberOfFloorLayers = n
return nil
}
// NumberOfShadowLayers returns the number of shadow layers per tile
@ -434,6 +447,7 @@ func (ds1 *DS1) update() {
ds1.SetSize(len(ds1.tiles[0]), len(ds1.tiles))
maxWalls := ds1.numberOfWallLayers
for y := range ds1.tiles {
for x := range ds1.tiles[y] {
if len(ds1.tiles[y][x].Walls) > int(maxWalls) {
@ -442,7 +456,25 @@ func (ds1 *DS1) update() {
}
}
ds1.SetNumberOfWallLayers(maxWalls)
err := ds1.SetNumberOfWallLayers(maxWalls)
if err != nil {
log.Print(err)
}
maxFloors := ds1.numberOfFloorLayers
for y := range ds1.tiles {
for x := range ds1.tiles[y] {
if len(ds1.tiles[y][x].Floors) > int(maxFloors) {
maxFloors = int32(len(ds1.tiles[y][x].Floors))
}
}
}
err = ds1.SetNumberOfFloorLayers(maxFloors)
if err != nil {
log.Print(err)
}
ds1.dirty = false
}
@ -733,7 +765,8 @@ func (ds1 *DS1) loadSubstitutions(br *d2datautils.StreamReader) error {
return err
}
func (ds1 *DS1) setupStreamLayerTypes() []d2enum.LayerStreamType {
// GetStreamLayerTypes returns layers used in ds1
func (ds1 *DS1) GetStreamLayerTypes() []d2enum.LayerStreamType {
var layerStream []d2enum.LayerStreamType
if ds1.version < v4 {
@ -804,7 +837,6 @@ 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
}
@ -869,7 +901,7 @@ func (ds1 *DS1) loadLayerStreams(br *d2datautils.StreamReader) error {
0x0F, 0x10, 0x11, 0x12, 0x14,
}
layerStreamTypes := ds1.setupStreamLayerTypes()
layerStreamTypes := ds1.GetStreamLayerTypes()
for _, layerStreamType := range layerStreamTypes {
for y := 0; y < int(ds1.height); y++ {
@ -990,7 +1022,7 @@ func (ds1 *DS1) Marshal() []byte {
}
func (ds1 *DS1) encodeLayers(sw *d2datautils.StreamWriter) {
layerStreamTypes := ds1.setupStreamLayerTypes()
layerStreamTypes := ds1.GetStreamLayerTypes()
for _, layerStreamType := range layerStreamTypes {
for y := 0; y < int(ds1.height); y++ {
@ -1022,21 +1054,29 @@ func (ds1 *DS1) encodeLayers(sw *d2datautils.StreamWriter) {
}
func (ds1 *DS1) encodeNPCs(sw *d2datautils.StreamWriter) {
objectsWithPaths := make([]int, 0)
for n, obj := range ds1.objects {
if len(obj.Paths) != 0 {
objectsWithPaths = append(objectsWithPaths, n)
}
}
// Step 5.1 - encode npc's
sw.PushUint32(uint32(len(ds1.npcIndexes)))
sw.PushUint32(uint32(len(objectsWithPaths)))
// 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 objectIdx := range objectsWithPaths {
sw.PushUint32(uint32(len(ds1.objects[objectIdx].Paths)))
sw.PushUint32(uint32(ds1.objects[objectIdx].X))
sw.PushUint32(uint32(ds1.objects[objectIdx].Y))
for _, j := range ds1.objects[i].Paths {
sw.PushUint32(uint32(j.Position.X()))
sw.PushUint32(uint32(j.Position.Y()))
for _, path := range ds1.objects[objectIdx].Paths {
sw.PushUint32(uint32(path.Position.X()))
sw.PushUint32(uint32(path.Position.Y()))
if ds1.version >= v15 {
sw.PushUint32(uint32(j.Action))
sw.PushUint32(uint32(path.Action))
}
}
}

View File

@ -56,7 +56,6 @@ func exampleDS1() *DS1 {
numberOfFloorLayers: 1,
numberOfShadowLayers: 1,
numberOfSubstitutionLayers: 1,
npcIndexes: []int{},
}
}
@ -490,11 +489,16 @@ func TestDS1_NumberOfWalls(t *testing.T) {
}
func TestDS1_SetNumberOfWalls(t *testing.T) {
var err error
ds1 := exampleDS1()
newNumber := int32(2)
newNumber := int32(4)
ds1.SetNumberOfWallLayers(newNumber)
err = ds1.SetNumberOfWallLayers(newNumber)
if err != nil {
t.Errorf("error setting number of walls: %v", err)
}
test := func(ds1 *DS1) {
if len(ds1.tiles[0][0].Walls) != int(newNumber) {
@ -506,13 +510,16 @@ func TestDS1_SetNumberOfWalls(t *testing.T) {
}
}
if err := testIfRestorable(ds1, test); err != nil {
if err = testIfRestorable(ds1, test); err != nil {
t.Errorf("unable to restore: %v", err)
}
newNumber = 1
ds1.SetNumberOfWallLayers(newNumber)
err = ds1.SetNumberOfWallLayers(newNumber)
if err != nil {
t.Errorf("error setting number of walls: %v", err)
}
test = func(ds1 *DS1) {
if len(ds1.tiles[0][0].Walls) != int(newNumber) {
@ -524,7 +531,7 @@ func TestDS1_SetNumberOfWalls(t *testing.T) {
}
}
if err := testIfRestorable(ds1, test); err != nil {
if err = testIfRestorable(ds1, test); err != nil {
t.Errorf("unable to restore: %v", err)
}
}
@ -538,11 +545,16 @@ func TestDS1_NumberOfFloors(t *testing.T) {
}
func TestDS1_SetNumberOfFloors(t *testing.T) {
var err error
ds1 := exampleDS1()
newNumber := int32(2)
ds1.SetNumberOfFloorLayers(newNumber)
err = ds1.SetNumberOfFloorLayers(newNumber)
if err != nil {
t.Errorf("error setting number of floors: %v", err)
}
test := func(ds1 *DS1) {
if len(ds1.tiles[0][0].Floors) != int(newNumber) {
@ -554,13 +566,16 @@ func TestDS1_SetNumberOfFloors(t *testing.T) {
}
}
if err := testIfRestorable(ds1, test); err != nil {
if err = testIfRestorable(ds1, test); err != nil {
t.Errorf("unable to restore: %v", err)
}
newNumber = 1
ds1.SetNumberOfFloorLayers(newNumber)
err = ds1.SetNumberOfFloorLayers(newNumber)
if err != nil {
t.Errorf("error setting number of floors: %v", err)
}
test = func(ds1 *DS1) {
if len(ds1.tiles[0][0].Floors) != int(newNumber) {
@ -572,7 +587,7 @@ func TestDS1_SetNumberOfFloors(t *testing.T) {
}
}
if err := testIfRestorable(ds1, test); err != nil {
if err = testIfRestorable(ds1, test); err != nil {
t.Errorf("unable to restore: %v", err)
}
}
@ -625,7 +640,7 @@ func TestDS1_SetSubstitutionGroups(t *testing.T) {
}
}
func TestDS1_setupStreamLayerTypes(t *testing.T) {
func TestDS1_GetStreamLayerTypes(t *testing.T) {
ds1 := exampleDS1()
lst := []d2enum.LayerStreamType{
@ -636,7 +651,7 @@ func TestDS1_setupStreamLayerTypes(t *testing.T) {
d2enum.LayerStreamSubstitute,
}
layerStreamTypes := ds1.setupStreamLayerTypes()
layerStreamTypes := ds1.GetStreamLayerTypes()
if len(lst) != len(layerStreamTypes) {
t.Fatal("unexpected length")