mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-05 08:07:51 -05:00
lint fixes for the d2common package (#558)
This commit is contained in:
parent
db5e844aac
commit
d1f499fb79
@ -1,10 +1,12 @@
|
||||
package d2common
|
||||
|
||||
// Point represents a point
|
||||
type Point struct {
|
||||
X int
|
||||
Y int
|
||||
}
|
||||
|
||||
// Pointf represents a point with float coordinates
|
||||
type Pointf struct {
|
||||
X float64
|
||||
Y float64
|
||||
|
@ -18,6 +18,7 @@ func CreateBitStream(newData []byte) *BitStream {
|
||||
current: 0,
|
||||
bitCount: 0,
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@ -26,11 +27,14 @@ func (v *BitStream) ReadBits(bitCount int) int {
|
||||
if bitCount > 16 {
|
||||
log.Panic("Maximum BitCount is 16")
|
||||
}
|
||||
|
||||
if !v.EnsureBits(bitCount) {
|
||||
return -1
|
||||
}
|
||||
|
||||
result := v.current & (0xffff >> uint(16-bitCount))
|
||||
v.WasteBits(bitCount)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@ -39,6 +43,7 @@ func (v *BitStream) PeekByte() int {
|
||||
if !v.EnsureBits(8) {
|
||||
return -1
|
||||
}
|
||||
|
||||
return v.current & 0xff
|
||||
}
|
||||
|
||||
@ -47,19 +52,22 @@ func (v *BitStream) EnsureBits(bitCount int) bool {
|
||||
if bitCount <= v.bitCount {
|
||||
return true
|
||||
}
|
||||
|
||||
if v.dataPosition >= len(v.data) {
|
||||
return false
|
||||
}
|
||||
|
||||
nextValue := v.data[v.dataPosition]
|
||||
v.dataPosition++
|
||||
v.current |= int(nextValue) << uint(v.bitCount)
|
||||
v.bitCount += 8
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// WasteBits dry-reads the specified number of bits
|
||||
func (v *BitStream) WasteBits(bitCount int) {
|
||||
//noinspection GoRedundantConversion
|
||||
// noinspection GoRedundantConversion
|
||||
v.current >>= uint(bitCount)
|
||||
v.bitCount -= bitCount
|
||||
}
|
||||
|
@ -8,11 +8,13 @@ func TestBitStreamBits(t *testing.T) {
|
||||
data := []byte{0xAA}
|
||||
bitStream := CreateBitStream(data)
|
||||
shouldBeOne := 0
|
||||
|
||||
for i := 0; i < 8; i++ {
|
||||
bit := bitStream.ReadBits(1)
|
||||
if bit != shouldBeOne {
|
||||
t.Fatalf("Expected %d but got %d on iteration %d", shouldBeOne, bit, i)
|
||||
}
|
||||
|
||||
if shouldBeOne == 1 {
|
||||
shouldBeOne = 0
|
||||
} else {
|
||||
@ -24,6 +26,7 @@ func TestBitStreamBits(t *testing.T) {
|
||||
func TestBitStreamBytes(t *testing.T) {
|
||||
data := []byte{0xAA, 0xBB, 0xCC, 0xDD, 0x12, 0x34, 0x56, 0x78}
|
||||
bitStream := CreateBitStream(data)
|
||||
|
||||
for i := 0; i < 8; i++ {
|
||||
b := byte(bitStream.ReadBits(8))
|
||||
if b != data[i] {
|
||||
|
@ -2,9 +2,10 @@ package d2common
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
)
|
||||
|
||||
type cacheNode struct {
|
||||
@ -109,6 +110,7 @@ func (c *Cache) Retrieve(key string) (interface{}, bool) {
|
||||
if node.next != nil {
|
||||
node.next.prev = node.prev
|
||||
}
|
||||
|
||||
if node.prev != nil {
|
||||
node.prev.next = node.next
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
package d2common
|
||||
|
||||
// a calcstring is a type of string often used in datafiles to specify
|
||||
// CalcString is a type of string often used in datafiles to specify
|
||||
// a value that is calculated dynamically based on the stats of the relevant
|
||||
// source, for instance a missile might have a movement speed of lvl*2
|
||||
|
||||
type CalcString string
|
||||
|
||||
// todo: the logic for parsing these should exist here
|
||||
|
@ -27,7 +27,7 @@ func LoadAnimationData(rawData []byte) {
|
||||
AnimationData = make(map[string][]*AnimationDataRecord)
|
||||
streamReader := d2common.CreateStreamReader(rawData)
|
||||
|
||||
for !streamReader.Eof() {
|
||||
for !streamReader.EOF() {
|
||||
dataCount := int(streamReader.GetInt32())
|
||||
for i := 0; i < dataCount; i++ {
|
||||
cofNameBytes := streamReader.ReadBytes(8)
|
||||
|
@ -41,10 +41,11 @@ func LoadDataDictionary(buf []byte) *DataDictionary {
|
||||
}
|
||||
|
||||
// Next reads the next row, skips Expansion lines or
|
||||
// returns false when the end of a file is reached or an error occured
|
||||
// returns false when the end of a file is reached or an error occurred
|
||||
func (d *DataDictionary) Next() bool {
|
||||
var err error
|
||||
d.record, err = d.r.Read()
|
||||
|
||||
if err == io.EOF {
|
||||
return false
|
||||
} else if err != nil {
|
||||
@ -55,6 +56,7 @@ func (d *DataDictionary) Next() bool {
|
||||
if d.record[0] == "Expansion" {
|
||||
return d.Next()
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@ -69,6 +71,7 @@ func (d *DataDictionary) Number(field string) int {
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
@ -84,5 +87,6 @@ func (d *DataDictionary) Bool(field string) bool {
|
||||
if n > 1 {
|
||||
log.Panic("Bool on non-bool field")
|
||||
}
|
||||
|
||||
return n == 1
|
||||
}
|
||||
|
@ -4,17 +4,21 @@ import (
|
||||
"math"
|
||||
)
|
||||
|
||||
// MinInt returns the minimum of the given values
|
||||
func MinInt(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
// MaxInt returns the maximum of the given values
|
||||
func MaxInt(a, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
@ -23,6 +27,7 @@ func Min(a, b uint32) uint32 {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
@ -31,6 +36,7 @@ func Max(a, b uint32) uint32 {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
@ -39,13 +45,16 @@ func MaxInt32(a, b int32) int32 {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
// AbsInt32 returns the absolute of the given int32
|
||||
func AbsInt32(a int32) int32 {
|
||||
if a < 0 {
|
||||
return -a
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
@ -54,6 +63,7 @@ func MinInt32(a, b int32) int32 {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
@ -70,12 +80,15 @@ func GetAngleBetween(p1X, p1Y, p2X, p2Y float64) int {
|
||||
|
||||
result := math.Atan2(deltaY, deltaX) * (180 / math.Pi)
|
||||
iResult := int(result)
|
||||
|
||||
for iResult < 0 {
|
||||
iResult += 360
|
||||
}
|
||||
|
||||
for iResult >= 360 {
|
||||
iResult -= 360
|
||||
}
|
||||
|
||||
return iResult
|
||||
}
|
||||
|
||||
@ -92,17 +105,18 @@ func AlmostEqual(a, b, threshold float64) bool {
|
||||
return math.Abs(a-b) <= threshold
|
||||
}
|
||||
|
||||
// Return the new adjusted value, as well as any remaining amount after the max
|
||||
// AdjustWithRemainder returns the new adjusted value, as well as any remaining amount after the max
|
||||
func AdjustWithRemainder(sourceValue, adjustment, targetvalue float64) (newValue, remainder float64) {
|
||||
if adjustment == 0 || math.Abs(adjustment) < 0.000001 {
|
||||
return sourceValue, 0
|
||||
}
|
||||
|
||||
adjustNegative := adjustment < 0.0
|
||||
maxNegative := targetvalue-sourceValue < 0.0
|
||||
|
||||
if adjustNegative != maxNegative {
|
||||
// FIXME: This shouldn't happen but it happens all the time..
|
||||
return sourceValue, 0
|
||||
//panic("Cannot move towards the opposite direction...")
|
||||
}
|
||||
|
||||
finalValue := sourceValue + adjustment
|
||||
@ -111,11 +125,13 @@ func AdjustWithRemainder(sourceValue, adjustment, targetvalue float64) (newValue
|
||||
diff := finalValue - targetvalue
|
||||
return targetvalue, diff
|
||||
}
|
||||
|
||||
return finalValue, 0
|
||||
}
|
||||
|
||||
if finalValue < targetvalue {
|
||||
return targetvalue, finalValue - targetvalue
|
||||
}
|
||||
|
||||
return finalValue, 0
|
||||
}
|
||||
|
@ -2,51 +2,56 @@ package d2common
|
||||
|
||||
import "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
|
||||
// MusicDef stores the music definitions of a region
|
||||
type MusicDef struct {
|
||||
Region d2enum.RegionIdType
|
||||
InTown bool
|
||||
MusicFile string
|
||||
}
|
||||
|
||||
var musicDefs = [...]MusicDef{
|
||||
{d2enum.RegionAct1Town, false, "/data/global/music/Act1/town1.wav"},
|
||||
{d2enum.RegionAct1Wilderness, false, "/data/global/music/Act1/wild.wav"},
|
||||
{d2enum.RegionAct1Cave, false, "/data/global/music/Act1/caves.wav"},
|
||||
{d2enum.RegionAct1Crypt, false, "/data/global/music/Act1/crypt.wav"},
|
||||
{d2enum.RegionAct1Monestary, false, "/data/global/music/Act1/monastery.wav"},
|
||||
{d2enum.RegionAct1Courtyard, false, "/data/global/music/Act1/wild.wav"}, // ?
|
||||
{d2enum.RegionAct1Barracks, false, "/data/global/music/Act1/wild.wav"}, // ?
|
||||
{d2enum.RegionAct1Jail, false, "/data/global/music/Act1/wild.wav"}, // ?
|
||||
{d2enum.RegionAct1Cathedral, false, "/data/global/music/Act1/monastery.wav"}, // ?
|
||||
{d2enum.RegionAct1Catacombs, false, "/data/global/music/Act1/crypt.wav"}, // ?
|
||||
{d2enum.RegionAct1Tristram, false, "/data/global/music/Act1/tristram.wav"}, // ?
|
||||
{d2enum.RegionAct2Town, false, "/data/global/music/Act2/town2.wav"},
|
||||
{d2enum.RegionAct2Sewer, false, "/data/global/music/Act2/sewer.wav"},
|
||||
{d2enum.RegionAct2Harem, false, "/data/global/music/Act2/harem.wav"},
|
||||
{d2enum.RegionAct2Basement, false, "/data/global/music/Act2/lair.wav"}, // ?
|
||||
{d2enum.RegionAct2Desert, false, "/data/global/music/Act2/desrt.wav"},
|
||||
{d2enum.RegionAct2Tomb, false, "/data/global/music/Act2/tombs.wav"},
|
||||
{d2enum.RegionAct2Lair, false, "/data/global/music/Act2/lair.wav"},
|
||||
{d2enum.RegionAct2Arcane, false, "/data/global/music/Act2/sanctuary.wav"}, // ?
|
||||
{d2enum.RegionAct3Town, false, "/data/global/music/Act3/town3.wav"},
|
||||
{d2enum.RegionAct3Jungle, false, "/data/global/music/Act3/jungle.wav"},
|
||||
{d2enum.RegionAct3Kurast, false, "/data/global/music/Act3/kurast.wav"},
|
||||
{d2enum.RegionAct3Spider, false, "/data/global/music/Act3/spider.wav"},
|
||||
{d2enum.RegionAct3Dungeon, false, "/data/global/music/Act3/kurastsewer.wav"}, // ?
|
||||
{d2enum.RegionAct3Sewer, false, "/data/global/music/Act3/kurastsewer.wav"},
|
||||
{d2enum.RegionAct4Town, false, "/data/global/music/Act4/town4.wav"},
|
||||
{d2enum.RegionAct4Mesa, false, "/data/global/music/Act4/mesa.wav"},
|
||||
{d2enum.RegionAct4Lava, false, "/data/global/music/Act4/diablo.wav"}, // ?
|
||||
{d2enum.RegonAct5Town, false, "/data/global/music/Act5/xtown.wav"},
|
||||
{d2enum.RegionAct5Siege, false, "/data/global/music/Act5/siege.wav"},
|
||||
{d2enum.RegionAct5Barricade, false, "/data/global/music/Act5/shenkmusic.wav"}, // ?
|
||||
{d2enum.RegionAct5Temple, false, "/data/global/music/Act5/xtemple.wav"},
|
||||
{d2enum.RegionAct5IceCaves, false, "/data/global/music/Act5/icecaves.wav"},
|
||||
{d2enum.RegionAct5Baal, false, "/data/global/music/Act5/baal.wav"},
|
||||
{d2enum.RegionAct5Lava, false, "/data/global/music/Act5/nihlathakmusic.wav"}, // ?
|
||||
func getMusicDefs() []MusicDef {
|
||||
return []MusicDef{
|
||||
{d2enum.RegionAct1Town, false, "/data/global/music/Act1/town1.wav"},
|
||||
{d2enum.RegionAct1Wilderness, false, "/data/global/music/Act1/wild.wav"},
|
||||
{d2enum.RegionAct1Cave, false, "/data/global/music/Act1/caves.wav"},
|
||||
{d2enum.RegionAct1Crypt, false, "/data/global/music/Act1/crypt.wav"},
|
||||
{d2enum.RegionAct1Monestary, false, "/data/global/music/Act1/monastery.wav"},
|
||||
{d2enum.RegionAct1Courtyard, false, "/data/global/music/Act1/wild.wav"}, // ?
|
||||
{d2enum.RegionAct1Barracks, false, "/data/global/music/Act1/wild.wav"}, // ?
|
||||
{d2enum.RegionAct1Jail, false, "/data/global/music/Act1/wild.wav"}, // ?
|
||||
{d2enum.RegionAct1Cathedral, false, "/data/global/music/Act1/monastery.wav"}, // ?
|
||||
{d2enum.RegionAct1Catacombs, false, "/data/global/music/Act1/crypt.wav"}, // ?
|
||||
{d2enum.RegionAct1Tristram, false, "/data/global/music/Act1/tristram.wav"}, // ?
|
||||
{d2enum.RegionAct2Town, false, "/data/global/music/Act2/town2.wav"},
|
||||
{d2enum.RegionAct2Sewer, false, "/data/global/music/Act2/sewer.wav"},
|
||||
{d2enum.RegionAct2Harem, false, "/data/global/music/Act2/harem.wav"},
|
||||
{d2enum.RegionAct2Basement, false, "/data/global/music/Act2/lair.wav"}, // ?
|
||||
{d2enum.RegionAct2Desert, false, "/data/global/music/Act2/desrt.wav"},
|
||||
{d2enum.RegionAct2Tomb, false, "/data/global/music/Act2/tombs.wav"},
|
||||
{d2enum.RegionAct2Lair, false, "/data/global/music/Act2/lair.wav"},
|
||||
{d2enum.RegionAct2Arcane, false, "/data/global/music/Act2/sanctuary.wav"}, // ?
|
||||
{d2enum.RegionAct3Town, false, "/data/global/music/Act3/town3.wav"},
|
||||
{d2enum.RegionAct3Jungle, false, "/data/global/music/Act3/jungle.wav"},
|
||||
{d2enum.RegionAct3Kurast, false, "/data/global/music/Act3/kurast.wav"},
|
||||
{d2enum.RegionAct3Spider, false, "/data/global/music/Act3/spider.wav"},
|
||||
{d2enum.RegionAct3Dungeon, false, "/data/global/music/Act3/kurastsewer.wav"}, // ?
|
||||
{d2enum.RegionAct3Sewer, false, "/data/global/music/Act3/kurastsewer.wav"},
|
||||
{d2enum.RegionAct4Town, false, "/data/global/music/Act4/town4.wav"},
|
||||
{d2enum.RegionAct4Mesa, false, "/data/global/music/Act4/mesa.wav"},
|
||||
{d2enum.RegionAct4Lava, false, "/data/global/music/Act4/diablo.wav"}, // ?
|
||||
{d2enum.RegonAct5Town, false, "/data/global/music/Act5/xtown.wav"},
|
||||
{d2enum.RegionAct5Siege, false, "/data/global/music/Act5/siege.wav"},
|
||||
{d2enum.RegionAct5Barricade, false, "/data/global/music/Act5/shenkmusic.wav"}, // ?
|
||||
{d2enum.RegionAct5Temple, false, "/data/global/music/Act5/xtemple.wav"},
|
||||
{d2enum.RegionAct5IceCaves, false, "/data/global/music/Act5/icecaves.wav"},
|
||||
{d2enum.RegionAct5Baal, false, "/data/global/music/Act5/baal.wav"},
|
||||
{d2enum.RegionAct5Lava, false, "/data/global/music/Act5/nihlathakmusic.wav"}, // ?
|
||||
}
|
||||
}
|
||||
|
||||
// GetMusicDef returns the MusicDef of the given region
|
||||
func GetMusicDef(regionType d2enum.RegionIdType) *MusicDef {
|
||||
musicDefs := getMusicDefs()
|
||||
for idx := range musicDefs {
|
||||
if musicDefs[idx].Region != regionType {
|
||||
continue
|
||||
|
@ -1,5 +1,6 @@
|
||||
package d2common
|
||||
|
||||
// Path represents a path
|
||||
type Path struct {
|
||||
X int
|
||||
Y int
|
||||
|
@ -2,35 +2,44 @@ package d2common
|
||||
|
||||
import "github.com/OpenDiablo2/OpenDiablo2/d2common/d2astar"
|
||||
|
||||
// PathTile represents a node in path finding
|
||||
type PathTile struct {
|
||||
Walkable bool
|
||||
Up, Down, Left, Right, UpLeft, UpRight, DownLeft, DownRight *PathTile
|
||||
X, Y float64
|
||||
}
|
||||
|
||||
// PathNeighbors returns the direct neighboring nodes of this node which can be pathed to
|
||||
func (t *PathTile) PathNeighbors() []d2astar.Pather {
|
||||
result := make([]d2astar.Pather, 0, 8)
|
||||
if t.Up != nil {
|
||||
result = append(result, t.Up)
|
||||
}
|
||||
|
||||
if t.Right != nil {
|
||||
result = append(result, t.Right)
|
||||
}
|
||||
|
||||
if t.Down != nil {
|
||||
result = append(result, t.Down)
|
||||
}
|
||||
|
||||
if t.Left != nil {
|
||||
result = append(result, t.Left)
|
||||
}
|
||||
|
||||
if t.UpLeft != nil {
|
||||
result = append(result, t.UpLeft)
|
||||
}
|
||||
|
||||
if t.UpRight != nil {
|
||||
result = append(result, t.UpRight)
|
||||
}
|
||||
|
||||
if t.DownLeft != nil {
|
||||
result = append(result, t.DownLeft)
|
||||
}
|
||||
|
||||
if t.DownRight != nil {
|
||||
result = append(result, t.DownRight)
|
||||
}
|
||||
@ -38,20 +47,26 @@ func (t *PathTile) PathNeighbors() []d2astar.Pather {
|
||||
return result
|
||||
}
|
||||
|
||||
// PathNeighborCost calculates the exact movement cost to neighbor nodes
|
||||
func (t *PathTile) PathNeighborCost(to d2astar.Pather) float64 {
|
||||
return 1 // No cost specifics currently...
|
||||
}
|
||||
|
||||
// PathEstimatedCost is a heuristic method for estimating movement costs between non-adjacent nodes
|
||||
func (t *PathTile) PathEstimatedCost(to d2astar.Pather) float64 {
|
||||
toT := to.(*PathTile)
|
||||
absX := toT.X - t.X
|
||||
|
||||
if absX < 0 {
|
||||
absX = -absX
|
||||
}
|
||||
|
||||
absY := toT.Y - t.Y
|
||||
|
||||
if absY < 0 {
|
||||
absY = -absY
|
||||
}
|
||||
|
||||
r := absX + absY
|
||||
|
||||
return r
|
||||
|
@ -1,5 +1,6 @@
|
||||
package d2common
|
||||
|
||||
// Rectangle represents a rectangle
|
||||
type Rectangle struct {
|
||||
Left int
|
||||
Top int
|
||||
@ -7,14 +8,17 @@ type Rectangle struct {
|
||||
Height int
|
||||
}
|
||||
|
||||
// Bottom returns y of the bottom point of the rectangle
|
||||
func (v *Rectangle) Bottom() int {
|
||||
return v.Top + v.Height
|
||||
}
|
||||
|
||||
// Right returns x of the right point of the rectangle
|
||||
func (v *Rectangle) Right() int {
|
||||
return v.Left + v.Width
|
||||
}
|
||||
|
||||
// IsInRect returns if the given position is in the rectangle or not
|
||||
func (v *Rectangle) IsInRect(x, y int) bool {
|
||||
return x >= v.Left && x < v.Left+v.Width && y >= v.Top && y < v.Top+v.Height
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package d2common
|
||||
|
||||
// Size represents a size
|
||||
type Size struct {
|
||||
Width, Height int
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ func CreateStreamReader(source []byte) *StreamReader {
|
||||
data: source,
|
||||
position: 0,
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@ -33,6 +34,7 @@ func (v *StreamReader) GetSize() uint64 {
|
||||
func (v *StreamReader) GetByte() byte {
|
||||
result := v.data[v.position]
|
||||
v.position++
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@ -41,6 +43,7 @@ func (v *StreamReader) GetUInt16() uint16 {
|
||||
result := uint16(v.data[v.position])
|
||||
result += uint16(v.data[v.position+1]) << 8
|
||||
v.position += 2
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@ -48,24 +51,34 @@ func (v *StreamReader) GetUInt16() uint16 {
|
||||
func (v *StreamReader) GetInt16() int16 {
|
||||
result := (int16(v.data[v.position+1]) << uint(8)) + int16(v.data[v.position])
|
||||
v.position += 2
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// SetPosition sets the stream position with the given position
|
||||
func (v *StreamReader) SetPosition(newPosition uint64) {
|
||||
v.position = newPosition
|
||||
}
|
||||
|
||||
// GetUInt32 returns a uint32 dword from the stream
|
||||
func (v *StreamReader) GetUInt32() uint32 {
|
||||
result := (uint32(v.data[v.position+3]) << uint(24)) + (uint32(v.data[v.position+2]) << uint(16)) + (uint32(v.data[v.position+1]) << uint(8)) + uint32(v.data[v.position])
|
||||
result := (uint32(v.data[v.position+3]) << uint(24)) +
|
||||
(uint32(v.data[v.position+2]) << uint(16)) +
|
||||
(uint32(v.data[v.position+1]) << uint(8)) +
|
||||
uint32(v.data[v.position])
|
||||
v.position += 4
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// GetInt32 returns an int32 dword from the stream
|
||||
func (v *StreamReader) GetInt32() int32 {
|
||||
result := (int32(v.data[v.position+3]) << uint(24)) + (int32(v.data[v.position+2]) << uint(16)) + (int32(v.data[v.position+1]) << uint(8)) + int32(v.data[v.position])
|
||||
result := (int32(v.data[v.position+3]) << uint(24)) +
|
||||
(int32(v.data[v.position+2]) << uint(16)) +
|
||||
(int32(v.data[v.position+1]) << uint(8)) +
|
||||
int32(v.data[v.position])
|
||||
v.position += 4
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@ -80,21 +93,13 @@ func (v *StreamReader) GetUint64() uint64 {
|
||||
(uint64(v.data[v.position+1]) << uint(8)) +
|
||||
uint64(v.data[v.position])
|
||||
v.position += 8
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// GetInt64 returns a uint64 qword from the stream
|
||||
func (v *StreamReader) GetInt64() int64 {
|
||||
result := (uint64(v.data[v.position+7]) << uint(56)) +
|
||||
(uint64(v.data[v.position+6]) << uint(48)) +
|
||||
(uint64(v.data[v.position+5]) << uint(40)) +
|
||||
(uint64(v.data[v.position+4]) << uint(32)) +
|
||||
(uint64(v.data[v.position+3]) << uint(24)) +
|
||||
(uint64(v.data[v.position+2]) << uint(16)) +
|
||||
(uint64(v.data[v.position+1]) << uint(8)) +
|
||||
uint64(v.data[v.position])
|
||||
v.position += 8
|
||||
return int64(result)
|
||||
return int64(v.GetUint64())
|
||||
}
|
||||
|
||||
// ReadByte implements io.ByteReader
|
||||
@ -106,9 +111,11 @@ func (v *StreamReader) ReadByte() (byte, error) {
|
||||
func (v *StreamReader) ReadBytes(count int) []byte {
|
||||
result := v.data[v.position : v.position+uint64(count)]
|
||||
v.position += uint64(count)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// SkipBytes moves the stream position forward by the given amount
|
||||
func (v *StreamReader) SkipBytes(count int) {
|
||||
v.position += uint64(count)
|
||||
}
|
||||
@ -116,17 +123,21 @@ func (v *StreamReader) SkipBytes(count int) {
|
||||
// Read implements io.Reader
|
||||
func (v *StreamReader) Read(p []byte) (n int, err error) {
|
||||
streamLength := v.GetSize()
|
||||
|
||||
for i := 0; ; i++ {
|
||||
if v.GetPosition() >= streamLength {
|
||||
return i, io.EOF
|
||||
}
|
||||
|
||||
if i >= len(p) {
|
||||
return i, nil
|
||||
}
|
||||
|
||||
p[i] = v.GetByte()
|
||||
}
|
||||
}
|
||||
|
||||
func (v *StreamReader) Eof() bool {
|
||||
// EOF returns if the stream position is reached to the end of the data, or not
|
||||
func (v *StreamReader) EOF() bool {
|
||||
return v.position >= uint64(len(v.data))
|
||||
}
|
||||
|
@ -7,17 +7,21 @@ import (
|
||||
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)
|
||||
}
|
||||
@ -28,16 +32,20 @@ func TestStreamReaderWord(t *testing.T) {
|
||||
data := []byte{0x78, 0x56, 0x34, 0x12}
|
||||
sr := CreateStreamReader(data)
|
||||
ret := sr.GetUInt16()
|
||||
|
||||
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.GetUInt16()
|
||||
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)
|
||||
}
|
||||
@ -47,9 +55,11 @@ func TestStreamReaderDword(t *testing.T) {
|
||||
data := []byte{0x78, 0x56, 0x34, 0x12}
|
||||
sr := CreateStreamReader(data)
|
||||
ret := sr.GetUInt32()
|
||||
|
||||
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)
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ func CreateStreamWriter() *StreamWriter {
|
||||
result := &StreamWriter{
|
||||
data: new(bytes.Buffer),
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
@ -7,9 +7,11 @@ import (
|
||||
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 {
|
||||
@ -21,8 +23,10 @@ func TestStreamWriterByte(t *testing.T) {
|
||||
func TestStreamWriterWord(t *testing.T) {
|
||||
sr := CreateStreamWriter()
|
||||
data := []byte{0x12, 0x34, 0x56, 0x78}
|
||||
|
||||
sr.PushUint16(0x3412)
|
||||
sr.PushUint16(0x7856)
|
||||
|
||||
output := sr.GetBytes()
|
||||
for i, d := range data {
|
||||
if output[i] != d {
|
||||
@ -34,7 +38,9 @@ func TestStreamWriterWord(t *testing.T) {
|
||||
func TestStreamWriterDword(t *testing.T) {
|
||||
sr := CreateStreamWriter()
|
||||
data := []byte{0x12, 0x34, 0x56, 0x78}
|
||||
|
||||
sr.PushUint32(0x78563412)
|
||||
|
||||
output := sr.GetBytes()
|
||||
for i, d := range data {
|
||||
if output[i] != d {
|
||||
|
@ -15,14 +15,17 @@ func AsterToEmpty(text string) string {
|
||||
if strings.HasPrefix(text, "*") {
|
||||
return ""
|
||||
}
|
||||
|
||||
return text
|
||||
}
|
||||
|
||||
// EmptyToZero converts empty strings to "0" and leaves non-empty strings as is, for use before converting numerical data which equates empty to zero
|
||||
// EmptyToZero converts empty strings to "0" and leaves non-empty strings as is,
|
||||
// for use before converting numerical data which equates empty to zero
|
||||
func EmptyToZero(text string) string {
|
||||
if text == "" || text == " " {
|
||||
return "0"
|
||||
}
|
||||
|
||||
return text
|
||||
}
|
||||
|
||||
@ -32,6 +35,7 @@ func StringToInt(text string) int {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@ -43,6 +47,7 @@ func StringToUint(text string) uint {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return uint(result)
|
||||
}
|
||||
|
||||
@ -52,9 +57,11 @@ func StringToUint8(text string) uint8 {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if result < 0 || result > 255 {
|
||||
panic(fmt.Sprintf("value %d out of range of byte", result))
|
||||
}
|
||||
|
||||
return uint8(result)
|
||||
}
|
||||
|
||||
@ -64,16 +71,16 @@ func StringToInt8(text string) int8 {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if result < -128 || result > 122 {
|
||||
panic(fmt.Sprintf("value %d out of range of a signed byte", result))
|
||||
}
|
||||
|
||||
return int8(result)
|
||||
}
|
||||
|
||||
// StringToFloat64 converts a string to a float64
|
||||
|
||||
// Utf16BytesToString converts a utf16 byte array to string
|
||||
func Utf16BytesToString(b []byte) (string, error) {
|
||||
|
||||
if len(b)%2 != 0 {
|
||||
return "", fmt.Errorf("must have even length byte slice")
|
||||
}
|
||||
@ -95,40 +102,43 @@ func Utf16BytesToString(b []byte) (string, error) {
|
||||
return ret.String(), nil
|
||||
}
|
||||
|
||||
func CombineStrings(input []string) string {
|
||||
return strings.Join(input, "\n")
|
||||
}
|
||||
|
||||
// SplitIntoLinesWithMaxWidth splits the given string into lines considering the given maxChars
|
||||
func SplitIntoLinesWithMaxWidth(fullSentence string, maxChars int) []string {
|
||||
lines := make([]string, 0)
|
||||
line := ""
|
||||
totalLength := 0
|
||||
words := strings.Split(fullSentence, " ")
|
||||
|
||||
if len(words[0]) > maxChars {
|
||||
// mostly happened within CJK characters (no whitespace)
|
||||
return splitCjkIntoChunks(fullSentence, maxChars)
|
||||
}
|
||||
|
||||
for _, word := range words {
|
||||
totalLength += 1 + len(word)
|
||||
if totalLength > maxChars {
|
||||
totalLength = len(word)
|
||||
|
||||
lines = append(lines, line)
|
||||
line = ""
|
||||
} else {
|
||||
line += " "
|
||||
}
|
||||
|
||||
line += word
|
||||
}
|
||||
|
||||
if len(line) > 0 {
|
||||
lines = append(lines, line)
|
||||
}
|
||||
|
||||
return lines
|
||||
}
|
||||
|
||||
func splitCjkIntoChunks(str string, chars int) []string {
|
||||
chunks := make([]string, chars/len(str))
|
||||
i, count := 0, 0
|
||||
|
||||
for j, ch := range str {
|
||||
if ch < unicode.MaxLatin1 {
|
||||
count++
|
||||
@ -136,10 +146,12 @@ func splitCjkIntoChunks(str string, chars int) []string {
|
||||
// assume we're truncating CJK characters
|
||||
count += 2
|
||||
}
|
||||
|
||||
if count >= chars {
|
||||
chunks = append(chunks, str[i:j])
|
||||
i, count = j, 0
|
||||
}
|
||||
}
|
||||
|
||||
return append(chunks, str[i:])
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ type textDictionaryHashEntry struct {
|
||||
|
||||
var lookupTable map[string]string
|
||||
|
||||
// TranslateString returns the translation of the given string
|
||||
func TranslateString(key string) string {
|
||||
result, ok := lookupTable[key]
|
||||
if !ok {
|
||||
@ -23,24 +24,16 @@ func TranslateString(key string) string {
|
||||
// log.Panicf("Could not find a string for the key '%s'", key)
|
||||
return key
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func GetDictionaryEntryCount() int {
|
||||
if lookupTable == nil {
|
||||
return 0
|
||||
}
|
||||
return len(lookupTable)
|
||||
}
|
||||
|
||||
func GetTranslationMap() map[string]string {
|
||||
return lookupTable
|
||||
}
|
||||
|
||||
// LoadTextDictionary loads the text dictionary from the given data
|
||||
func LoadTextDictionary(dictionaryData []byte) {
|
||||
if lookupTable == nil {
|
||||
lookupTable = make(map[string]string)
|
||||
}
|
||||
|
||||
br := CreateStreamReader(dictionaryData)
|
||||
// CRC
|
||||
br.ReadBytes(2)
|
||||
@ -50,6 +43,7 @@ func LoadTextDictionary(dictionaryData []byte) {
|
||||
if _, err := br.ReadByte(); err != nil {
|
||||
log.Fatal("Error reading Version record")
|
||||
}
|
||||
|
||||
br.GetUInt32() // StringOffset
|
||||
br.GetUInt32() // When the number of times you have missed a match with a hash key equals this value, you give up because it is not there.
|
||||
br.GetUInt32() // FileSize
|
||||
@ -75,37 +69,31 @@ func LoadTextDictionary(dictionaryData []byte) {
|
||||
if !hashEntry.IsActive {
|
||||
continue
|
||||
}
|
||||
|
||||
br.SetPosition(uint64(hashEntry.NameString))
|
||||
nameVal := br.ReadBytes(int(hashEntry.NameLength - 1))
|
||||
value := string(nameVal)
|
||||
|
||||
br.SetPosition(uint64(hashEntry.IndexString))
|
||||
|
||||
key := ""
|
||||
|
||||
for {
|
||||
b := br.GetByte()
|
||||
if b == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
key += string(b)
|
||||
}
|
||||
|
||||
if key == "x" || key == "X" {
|
||||
key = "#" + strconv.Itoa(idx)
|
||||
}
|
||||
|
||||
_, exists := lookupTable[key]
|
||||
if !exists {
|
||||
lookupTable[key] = value
|
||||
|
||||
}
|
||||
// Use the following code to write out the values
|
||||
/*=
|
||||
f, err := os.OpenFile(`C:\Users\lunat\Desktop\D2\langdict.txt`,
|
||||
os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
defer f.Close()
|
||||
if _, err := f.WriteString("\n[" + key + "] " + value); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user