mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-11-19 02:46:35 -05:00
Merge branch 'master' into data-encoder-dat
This commit is contained in:
commit
b74bc3d0b6
@ -107,6 +107,10 @@ func (v *StreamReader) Size() uint64 {
|
|||||||
|
|
||||||
// ReadBytes reads multiple bytes
|
// ReadBytes reads multiple bytes
|
||||||
func (v *StreamReader) ReadBytes(count int) ([]byte, error) {
|
func (v *StreamReader) ReadBytes(count int) ([]byte, error) {
|
||||||
|
if count <= 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
size := v.Size()
|
size := v.Size()
|
||||||
if v.position >= size || v.position+uint64(count) > size {
|
if v.position >= size || v.position+uint64(count) > size {
|
||||||
return nil, io.EOF
|
return nil, io.EOF
|
||||||
|
@ -8,9 +8,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
unknownByteCount = 21
|
numUnknownHeaderBytes = 21
|
||||||
numHeaderBytes = 4 + unknownByteCount
|
numUnknownBodyBytes = 3
|
||||||
numLayerBytes = 9
|
numHeaderBytes = 4 + numUnknownHeaderBytes
|
||||||
|
numLayerBytes = 9
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -33,12 +34,41 @@ const (
|
|||||||
badCharacter = string(byte(0))
|
badCharacter = string(byte(0))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// New creates a new COF
|
||||||
|
func New() *COF {
|
||||||
|
return &COF{
|
||||||
|
unknownHeaderBytes: make([]byte, numUnknownHeaderBytes),
|
||||||
|
unknownBodyBytes: make([]byte, numUnknownBodyBytes),
|
||||||
|
NumberOfDirections: 0,
|
||||||
|
FramesPerDirection: 0,
|
||||||
|
NumberOfLayers: 0,
|
||||||
|
Speed: 0,
|
||||||
|
CofLayers: make([]CofLayer, 0),
|
||||||
|
CompositeLayers: make(map[d2enum.CompositeType]int),
|
||||||
|
AnimationFrames: make([]d2enum.AnimationFrame, 0),
|
||||||
|
Priority: make([][][]d2enum.CompositeType, 0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal a COF to a new byte slice
|
||||||
|
func Marshal(c *COF) []byte {
|
||||||
|
return c.Marshal()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal a byte slice to a new COF
|
||||||
|
func Unmarshal(data []byte) (*COF, error) {
|
||||||
|
c := New()
|
||||||
|
err := c.Unmarshal(data)
|
||||||
|
|
||||||
|
return c, err
|
||||||
|
}
|
||||||
|
|
||||||
// COF is a structure that represents a COF file.
|
// COF is a structure that represents a COF file.
|
||||||
type COF struct {
|
type COF struct {
|
||||||
// unknown bytes for header
|
// unknown bytes for header
|
||||||
unknownHeaderBytes []byte
|
unknownHeaderBytes []byte
|
||||||
// unknown bytes (first "body's" bytes)
|
// unknown bytes (first "body's" bytes)
|
||||||
unknown1 []byte
|
unknownBodyBytes []byte
|
||||||
NumberOfDirections int
|
NumberOfDirections int
|
||||||
FramesPerDirection int
|
FramesPerDirection int
|
||||||
NumberOfLayers int
|
NumberOfLayers int
|
||||||
@ -49,10 +79,9 @@ type COF struct {
|
|||||||
Priority [][][]d2enum.CompositeType
|
Priority [][][]d2enum.CompositeType
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load loads a COF file.
|
// Unmarshal a byte slice to this COF
|
||||||
// nolint:funlen // no need to change
|
// nolint:funlen // no need to change
|
||||||
func Load(fileData []byte) (*COF, error) {
|
func (c *COF) Unmarshal(fileData []byte) error {
|
||||||
result := &COF{}
|
|
||||||
streamReader := d2datautils.CreateStreamReader(fileData)
|
streamReader := d2datautils.CreateStreamReader(fileData)
|
||||||
|
|
||||||
var b []byte
|
var b []byte
|
||||||
@ -61,35 +90,29 @@ func Load(fileData []byte) (*COF, error) {
|
|||||||
|
|
||||||
b, err = streamReader.ReadBytes(numHeaderBytes)
|
b, err = streamReader.ReadBytes(numHeaderBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
result.NumberOfLayers = int(b[headerNumLayers])
|
c.NumberOfLayers = int(b[headerNumLayers])
|
||||||
result.FramesPerDirection = int(b[headerFramesPerDir])
|
c.FramesPerDirection = int(b[headerFramesPerDir])
|
||||||
result.NumberOfDirections = int(b[headerNumDirs])
|
c.NumberOfDirections = int(b[headerNumDirs])
|
||||||
result.unknownHeaderBytes = b[headerNumDirs+1 : headerSpeed]
|
c.unknownHeaderBytes = b[headerNumDirs+1 : headerSpeed]
|
||||||
result.Speed = int(b[headerSpeed])
|
c.Speed = int(b[headerSpeed])
|
||||||
|
|
||||||
// read unknown bytes
|
c.unknownBodyBytes, err = streamReader.ReadBytes(numUnknownBodyBytes)
|
||||||
// previous streamReader.SkipBytes(3)
|
if err != nil {
|
||||||
for i := 0; i < 3; i++ {
|
return err
|
||||||
b, errSR := streamReader.ReadByte()
|
|
||||||
if errSR != nil {
|
|
||||||
return nil, errSR
|
|
||||||
}
|
|
||||||
|
|
||||||
result.unknown1 = append(result.unknown1, b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result.CofLayers = make([]CofLayer, result.NumberOfLayers)
|
c.CofLayers = make([]CofLayer, c.NumberOfLayers)
|
||||||
result.CompositeLayers = make(map[d2enum.CompositeType]int)
|
c.CompositeLayers = make(map[d2enum.CompositeType]int)
|
||||||
|
|
||||||
for i := 0; i < result.NumberOfLayers; i++ {
|
for i := 0; i < c.NumberOfLayers; i++ {
|
||||||
layer := CofLayer{}
|
layer := CofLayer{}
|
||||||
|
|
||||||
b, err = streamReader.ReadBytes(numLayerBytes)
|
b, err = streamReader.ReadBytes(numLayerBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
layer.Type = d2enum.CompositeType(b[layerType])
|
layer.Type = d2enum.CompositeType(b[layerType])
|
||||||
@ -102,46 +125,46 @@ func Load(fileData []byte) (*COF, error) {
|
|||||||
layer.WeaponClass = d2enum.WeaponClassFromString(strings.TrimSpace(strings.ReplaceAll(
|
layer.WeaponClass = d2enum.WeaponClassFromString(strings.TrimSpace(strings.ReplaceAll(
|
||||||
string(b[layerWeaponClass:]), badCharacter, "")))
|
string(b[layerWeaponClass:]), badCharacter, "")))
|
||||||
|
|
||||||
result.CofLayers[i] = layer
|
c.CofLayers[i] = layer
|
||||||
result.CompositeLayers[layer.Type] = i
|
c.CompositeLayers[layer.Type] = i
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err = streamReader.ReadBytes(result.FramesPerDirection)
|
b, err = streamReader.ReadBytes(c.FramesPerDirection)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
result.AnimationFrames = make([]d2enum.AnimationFrame, result.FramesPerDirection)
|
c.AnimationFrames = make([]d2enum.AnimationFrame, c.FramesPerDirection)
|
||||||
|
|
||||||
for i := range b {
|
for i := range b {
|
||||||
result.AnimationFrames[i] = d2enum.AnimationFrame(b[i])
|
c.AnimationFrames[i] = d2enum.AnimationFrame(b[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
priorityLen := result.FramesPerDirection * result.NumberOfDirections * result.NumberOfLayers
|
priorityLen := c.FramesPerDirection * c.NumberOfDirections * c.NumberOfLayers
|
||||||
result.Priority = make([][][]d2enum.CompositeType, result.NumberOfDirections)
|
c.Priority = make([][][]d2enum.CompositeType, c.NumberOfDirections)
|
||||||
|
|
||||||
priorityBytes, err := streamReader.ReadBytes(priorityLen)
|
priorityBytes, err := streamReader.ReadBytes(priorityLen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
priorityIndex := 0
|
priorityIndex := 0
|
||||||
|
|
||||||
for direction := 0; direction < result.NumberOfDirections; direction++ {
|
for direction := 0; direction < c.NumberOfDirections; direction++ {
|
||||||
result.Priority[direction] = make([][]d2enum.CompositeType, result.FramesPerDirection)
|
c.Priority[direction] = make([][]d2enum.CompositeType, c.FramesPerDirection)
|
||||||
for frame := 0; frame < result.FramesPerDirection; frame++ {
|
for frame := 0; frame < c.FramesPerDirection; frame++ {
|
||||||
result.Priority[direction][frame] = make([]d2enum.CompositeType, result.NumberOfLayers)
|
c.Priority[direction][frame] = make([]d2enum.CompositeType, c.NumberOfLayers)
|
||||||
for i := 0; i < result.NumberOfLayers; i++ {
|
for i := 0; i < c.NumberOfLayers; i++ {
|
||||||
result.Priority[direction][frame][i] = d2enum.CompositeType(priorityBytes[priorityIndex])
|
c.Priority[direction][frame][i] = d2enum.CompositeType(priorityBytes[priorityIndex])
|
||||||
priorityIndex++
|
priorityIndex++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Marshal encodes COF back into byte slince
|
// Marshal this COF to a byte slice
|
||||||
func (c *COF) Marshal() []byte {
|
func (c *COF) Marshal() []byte {
|
||||||
sw := d2datautils.CreateStreamWriter()
|
sw := d2datautils.CreateStreamWriter()
|
||||||
|
|
||||||
@ -150,7 +173,7 @@ func (c *COF) Marshal() []byte {
|
|||||||
sw.PushBytes(byte(c.NumberOfDirections))
|
sw.PushBytes(byte(c.NumberOfDirections))
|
||||||
sw.PushBytes(c.unknownHeaderBytes...)
|
sw.PushBytes(c.unknownHeaderBytes...)
|
||||||
sw.PushBytes(byte(c.Speed))
|
sw.PushBytes(byte(c.Speed))
|
||||||
sw.PushBytes(c.unknown1...)
|
sw.PushBytes(c.unknownBodyBytes...)
|
||||||
|
|
||||||
for i := range c.CofLayers {
|
for i := range c.CofLayers {
|
||||||
sw.PushBytes(byte(c.CofLayers[i].Type.Int()))
|
sw.PushBytes(byte(c.CofLayers[i].Type.Int()))
|
||||||
|
35
d2common/d2fileformats/d2cof/cof_test.go
Normal file
35
d2common/d2fileformats/d2cof/cof_test.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package d2cof
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestCOF_New(t *testing.T) {
|
||||||
|
c := New()
|
||||||
|
|
||||||
|
if c == nil {
|
||||||
|
t.Error("method New created nil instance")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCOF_Marshal_Unmarshal(t *testing.T) {
|
||||||
|
cof1 := New()
|
||||||
|
cof2 := New()
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
err = cof1.Unmarshal(make([]byte, 1000))
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cof1.Speed = 255
|
||||||
|
data1 := cof1.Marshal()
|
||||||
|
|
||||||
|
err = cof2.Unmarshal(data1)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cof2.Speed != cof1.Speed {
|
||||||
|
t.Error("marshaled data does not match unmarshaled data")
|
||||||
|
}
|
||||||
|
}
|
@ -543,7 +543,7 @@ func (am *AssetManager) LoadCOF(cofPath string) (*d2cof.COF, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cof, err := d2cof.Load(fileData)
|
cof, err := d2cof.Unmarshal(fileData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user