mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-11-16 17:35:57 -05:00
Added stream writer and reader. Updated readme.
This commit is contained in:
parent
cb5c068279
commit
89a72c6f33
51
Common/StreamReader.go
Normal file
51
Common/StreamReader.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package Common
|
||||||
|
|
||||||
|
// StreamReader allows you to read data from a byte array in various formats
|
||||||
|
type StreamReader struct {
|
||||||
|
data []byte
|
||||||
|
position uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateStreamReader creates an instance of the stream reader
|
||||||
|
func CreateStreamReader(source []byte) *StreamReader {
|
||||||
|
result := &StreamReader{
|
||||||
|
data: source,
|
||||||
|
position: 0,
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPosition returns the current stream position
|
||||||
|
func (v *StreamReader) GetPosition() uint64 {
|
||||||
|
return v.position
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSize returns the total size of the stream in bytes
|
||||||
|
func (v *StreamReader) GetSize() uint64 {
|
||||||
|
return uint64(len(v.data))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByte returns a byte from the stream
|
||||||
|
func (v *StreamReader) GetByte() byte {
|
||||||
|
result := v.data[v.position]
|
||||||
|
v.position++
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWord returns a uint16 word from the stream
|
||||||
|
func (v *StreamReader) GetWord() uint16 {
|
||||||
|
result := uint16(v.data[v.position])
|
||||||
|
result += (uint16(v.data[v.position+1]) << 8)
|
||||||
|
v.position += 2
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDword returns a uint32 dword from the stream
|
||||||
|
func (v *StreamReader) GetDword() uint32 {
|
||||||
|
result := uint32(v.data[v.position])
|
||||||
|
result += (uint32(v.data[v.position+1]) << 8)
|
||||||
|
result += (uint32(v.data[v.position+2]) << 16)
|
||||||
|
result += (uint32(v.data[v.position+3]) << 24)
|
||||||
|
v.position += 4
|
||||||
|
return result
|
||||||
|
}
|
56
Common/StreamReader_test.go
Normal file
56
Common/StreamReader_test.go
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package Common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStreamReaderByte(t *testing.T) {
|
||||||
|
data := []byte{0x78, 0x56, 0x34, 0x12}
|
||||||
|
sr := CreateStreamReader(data)
|
||||||
|
if sr.GetPosition() != 0 {
|
||||||
|
t.Fatal("StreamReader.GetPosition() did not start at 0")
|
||||||
|
}
|
||||||
|
if ss := sr.GetSize(); ss != 4 {
|
||||||
|
t.Fatalf("StreamREader.GetSize() was expected to return %d, but returned %d instead", 4, ss)
|
||||||
|
}
|
||||||
|
for i := 0; i < len(data); i++ {
|
||||||
|
ret := sr.GetByte()
|
||||||
|
if ret != data[i] {
|
||||||
|
t.Fatalf("StreamReader.GetDword() was expected to return %X, but returned %X instead", data[i], ret)
|
||||||
|
}
|
||||||
|
if pos := sr.GetPosition(); pos != uint64(i+1) {
|
||||||
|
t.Fatalf("StreamReader.GetPosition() should be at %d, but was at %d instead", i, pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStreamReaderWord(t *testing.T) {
|
||||||
|
data := []byte{0x78, 0x56, 0x34, 0x12}
|
||||||
|
sr := CreateStreamReader(data)
|
||||||
|
ret := sr.GetWord()
|
||||||
|
if ret != 0x5678 {
|
||||||
|
t.Fatalf("StreamReader.GetDword() was expected to return %X, but returned %X instead", 0x5678, ret)
|
||||||
|
}
|
||||||
|
if pos := sr.GetPosition(); pos != 2 {
|
||||||
|
t.Fatalf("StreamReader.GetPosition() should be at %d, but was at %d instead", 2, pos)
|
||||||
|
}
|
||||||
|
ret = sr.GetWord()
|
||||||
|
if ret != 0x1234 {
|
||||||
|
t.Fatalf("StreamReader.GetDword() was expected to return %X, but returned %X instead", 0x1234, ret)
|
||||||
|
}
|
||||||
|
if pos := sr.GetPosition(); pos != 4 {
|
||||||
|
t.Fatalf("StreamReader.GetPosition() should be at %d, but was at %d instead", 4, pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStreamReaderDword(t *testing.T) {
|
||||||
|
data := []byte{0x78, 0x56, 0x34, 0x12}
|
||||||
|
sr := CreateStreamReader(data)
|
||||||
|
ret := sr.GetDword()
|
||||||
|
if ret != 0x12345678 {
|
||||||
|
t.Fatalf("StreamReader.GetDword() was expected to return %X, but returned %X instead", 0x12345678, ret)
|
||||||
|
}
|
||||||
|
if pos := sr.GetPosition(); pos != 4 {
|
||||||
|
t.Fatalf("StreamReader.GetPosition() should be at %d, but was at %d instead", 4, pos)
|
||||||
|
}
|
||||||
|
}
|
37
Common/StreamWriter.go
Normal file
37
Common/StreamWriter.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package Common
|
||||||
|
|
||||||
|
// StreamWriter allows you to create a byte array by streaming in writes of various sizes
|
||||||
|
type StreamWriter struct {
|
||||||
|
data []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateStreamWriter creates a new StreamWriter instance
|
||||||
|
func CreateStreamWriter() *StreamWriter {
|
||||||
|
result := &StreamWriter{
|
||||||
|
data: make([]byte, 0),
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// PushByte writes a byte to the stream
|
||||||
|
func (v *StreamWriter) PushByte(val byte) {
|
||||||
|
v.data = append(v.data, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PushWord writes an uint16 word to the stream
|
||||||
|
func (v *StreamWriter) PushWord(val uint16) {
|
||||||
|
v.data = append(v.data, byte(val&0xFF))
|
||||||
|
v.data = append(v.data, byte((val>>8)&0xFF))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PushDword writes a uint32 dword to the stream
|
||||||
|
func (v *StreamWriter) PushDword(val uint32) {
|
||||||
|
v.data = append(v.data, byte(val&0xFF))
|
||||||
|
v.data = append(v.data, byte((val>>8)&0xFF))
|
||||||
|
v.data = append(v.data, byte((val>>16)&0xFF))
|
||||||
|
v.data = append(v.data, byte((val>>24)&0xFF))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *StreamWriter) GetBytes() []byte {
|
||||||
|
return v.data
|
||||||
|
}
|
44
Common/StreamWriter_test.go
Normal file
44
Common/StreamWriter_test.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package Common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStreamWriterByte(t *testing.T) {
|
||||||
|
sr := CreateStreamWriter()
|
||||||
|
data := []byte{0x12, 0x34, 0x56, 0x78}
|
||||||
|
for _, d := range data {
|
||||||
|
sr.PushByte(d)
|
||||||
|
}
|
||||||
|
output := sr.GetBytes()
|
||||||
|
for i, d := range data {
|
||||||
|
if output[i] != d {
|
||||||
|
t.Fatalf("sr.PushByte() pushed %X, but wrote %X instead", d, output[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStreamWriterWord(t *testing.T) {
|
||||||
|
sr := CreateStreamWriter()
|
||||||
|
data := []byte{0x12, 0x34, 0x56, 0x78}
|
||||||
|
sr.PushWord(0x3412)
|
||||||
|
sr.PushWord(0x7856)
|
||||||
|
output := sr.GetBytes()
|
||||||
|
for i, d := range data {
|
||||||
|
if output[i] != d {
|
||||||
|
t.Fatalf("sr.PushWord() pushed byte %X to %d, but %X was expected instead", output[i], i, d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStreamWriterDword(t *testing.T) {
|
||||||
|
sr := CreateStreamWriter()
|
||||||
|
data := []byte{0x12, 0x34, 0x56, 0x78}
|
||||||
|
sr.PushDword(0x78563412)
|
||||||
|
output := sr.GetBytes()
|
||||||
|
for i, d := range data {
|
||||||
|
if output[i] != d {
|
||||||
|
t.Fatalf("sr.PushDword() pushed byte %X to %d, but %X was expected instead", output[i], i, d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
README.md
32
README.md
@ -29,9 +29,39 @@ To run the project, run `go run ./cmd/Client` from the root folder.
|
|||||||
|
|
||||||
You can also open the root folder in VSCode. Make sure you have the `ms-vscode.go` plugin installed.
|
You can also open the root folder in VSCode. Make sure you have the `ms-vscode.go` plugin installed.
|
||||||
|
|
||||||
|
## VS Code Extensions
|
||||||
|
|
||||||
|
The following extensions are recommended for working with this project:
|
||||||
|
* ms-vscode.go
|
||||||
|
* defaltd.go-coverage-viewer
|
||||||
|
|
||||||
|
For the Go extension, it is recommended you add the following to settings.json:
|
||||||
|
```json
|
||||||
|
"go.languageServerExperimentalFeatures": {
|
||||||
|
"format": true,
|
||||||
|
"autoComplete": true,
|
||||||
|
"rename": true,
|
||||||
|
"goToDefinition": true,
|
||||||
|
"hover": true,
|
||||||
|
"signatureHelp": true,
|
||||||
|
"goToTypeDefinition": true,
|
||||||
|
"goToImplementation": true,
|
||||||
|
"documentSymbols": true,
|
||||||
|
"workspaceSymbols": true,
|
||||||
|
"findReferences": true,
|
||||||
|
"diagnostics": true,
|
||||||
|
"documentLink": true
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
You can get to it by going to settings <kbd>Ctrl+,</kbd>, expanding `Extensions` and selecting `Go configuration`,
|
||||||
|
then clicking on `Edit in settings.json`. Just paste that section where appropriate.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
The engine is configured via the `config.json` file.
|
The engine is configured via the `config.json` file. By default, the configuration assumes that you have installed Diablo 2 and the
|
||||||
|
expansion via the official Blizzard Diablo2 installers using the default file paths. If you are not on Windows, or have installed
|
||||||
|
the game in a different location, the base path may have to be adjusted.
|
||||||
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
Loading…
Reference in New Issue
Block a user