1230 lines
31 KiB
Go
1230 lines
31 KiB
Go
package object
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// Test Object creation and basic properties
|
|
func TestNewObject(t *testing.T) {
|
|
obj := NewObject()
|
|
if obj == nil {
|
|
t.Fatal("NewObject returned nil")
|
|
}
|
|
|
|
// Test default values
|
|
if obj.IsClickable() {
|
|
t.Error("New object should not be clickable by default")
|
|
}
|
|
|
|
if obj.GetDeviceID() != DeviceIDNone {
|
|
t.Errorf("Expected device ID %d, got %d", DeviceIDNone, obj.GetDeviceID())
|
|
}
|
|
|
|
if obj.GetZoneName() != "" {
|
|
t.Errorf("Expected empty zone name, got '%s'", obj.GetZoneName())
|
|
}
|
|
|
|
if !obj.IsObject() {
|
|
t.Error("Object should return true for IsObject()")
|
|
}
|
|
}
|
|
|
|
func TestObjectBasicProperties(t *testing.T) {
|
|
obj := NewObject()
|
|
|
|
// Test clickable
|
|
obj.SetClickable(true)
|
|
if !obj.IsClickable() {
|
|
t.Error("Object should be clickable after setting to true")
|
|
}
|
|
|
|
obj.SetClickable(false)
|
|
if obj.IsClickable() {
|
|
t.Error("Object should not be clickable after setting to false")
|
|
}
|
|
|
|
// Test zone name
|
|
testZone := "commonlands"
|
|
obj.SetZone(testZone)
|
|
if obj.GetZoneName() != testZone {
|
|
t.Errorf("Expected zone name '%s', got '%s'", testZone, obj.GetZoneName())
|
|
}
|
|
|
|
// Test device ID
|
|
testDeviceID := int8(5)
|
|
obj.SetDeviceID(testDeviceID)
|
|
if obj.GetDeviceID() != testDeviceID {
|
|
t.Errorf("Expected device ID %d, got %d", testDeviceID, obj.GetDeviceID())
|
|
}
|
|
}
|
|
|
|
func TestObjectMerchantProperties(t *testing.T) {
|
|
obj := NewObject()
|
|
|
|
// Test merchant ID
|
|
testMerchantID := int32(12345)
|
|
obj.SetMerchantID(testMerchantID)
|
|
if obj.GetMerchantID() != testMerchantID {
|
|
t.Errorf("Expected merchant ID %d, got %d", testMerchantID, obj.GetMerchantID())
|
|
}
|
|
|
|
// Test merchant type
|
|
testMerchantType := int8(2)
|
|
obj.SetMerchantType(testMerchantType)
|
|
if obj.GetMerchantType() != testMerchantType {
|
|
t.Errorf("Expected merchant type %d, got %d", testMerchantType, obj.GetMerchantType())
|
|
}
|
|
|
|
// Test merchant level range
|
|
testMinLevel, testMaxLevel := int8(10), int8(50)
|
|
obj.SetMerchantLevelRange(testMinLevel, testMaxLevel)
|
|
if obj.GetMerchantMinLevel() != testMinLevel {
|
|
t.Errorf("Expected min level %d, got %d", testMinLevel, obj.GetMerchantMinLevel())
|
|
}
|
|
if obj.GetMerchantMaxLevel() != testMaxLevel {
|
|
t.Errorf("Expected max level %d, got %d", testMaxLevel, obj.GetMerchantMaxLevel())
|
|
}
|
|
|
|
// Test collector flag
|
|
obj.SetCollector(true)
|
|
if !obj.IsCollector() {
|
|
t.Error("Object should be a collector after setting to true")
|
|
}
|
|
|
|
obj.SetCollector(false)
|
|
if obj.IsCollector() {
|
|
t.Error("Object should not be a collector after setting to false")
|
|
}
|
|
}
|
|
|
|
func TestObjectSize(t *testing.T) {
|
|
obj := NewObject()
|
|
|
|
// Test size
|
|
testSize := int16(150)
|
|
obj.SetSize(testSize)
|
|
if obj.GetSize() != testSize {
|
|
t.Errorf("Expected size %d, got %d", testSize, obj.GetSize())
|
|
}
|
|
|
|
// Test size offset
|
|
testOffset := int8(10)
|
|
obj.SetSizeOffset(testOffset)
|
|
if obj.GetSizeOffset() != testOffset {
|
|
t.Errorf("Expected size offset %d, got %d", testOffset, obj.GetSizeOffset())
|
|
}
|
|
}
|
|
|
|
func TestObjectCommands(t *testing.T) {
|
|
obj := NewObject()
|
|
|
|
// Test primary commands
|
|
primaryCommands := []string{"use", "examine", "talk"}
|
|
obj.SetPrimaryCommands(primaryCommands)
|
|
retrievedPrimary := obj.GetPrimaryCommands()
|
|
if len(retrievedPrimary) != len(primaryCommands) {
|
|
t.Errorf("Expected %d primary commands, got %d", len(primaryCommands), len(retrievedPrimary))
|
|
}
|
|
for i, cmd := range primaryCommands {
|
|
if retrievedPrimary[i] != cmd {
|
|
t.Errorf("Primary command %d: expected '%s', got '%s'", i, cmd, retrievedPrimary[i])
|
|
}
|
|
}
|
|
|
|
// Test secondary commands
|
|
secondaryCommands := []string{"attack", "inspect"}
|
|
obj.SetSecondaryCommands(secondaryCommands)
|
|
retrievedSecondary := obj.GetSecondaryCommands()
|
|
if len(retrievedSecondary) != len(secondaryCommands) {
|
|
t.Errorf("Expected %d secondary commands, got %d", len(secondaryCommands), len(retrievedSecondary))
|
|
}
|
|
for i, cmd := range secondaryCommands {
|
|
if retrievedSecondary[i] != cmd {
|
|
t.Errorf("Secondary command %d: expected '%s', got '%s'", i, cmd, retrievedSecondary[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestObjectHP(t *testing.T) {
|
|
obj := NewObject()
|
|
|
|
// Test total HP
|
|
testTotalHP := int32(1000)
|
|
obj.SetTotalHP(testTotalHP)
|
|
if obj.GetTotalHP() != testTotalHP {
|
|
t.Errorf("Expected total HP %d, got %d", testTotalHP, obj.GetTotalHP())
|
|
}
|
|
|
|
// Test current HP
|
|
testCurrentHP := int32(750)
|
|
obj.SetHP(testCurrentHP)
|
|
if obj.GetHP() != testCurrentHP {
|
|
t.Errorf("Expected current HP %d, got %d", testCurrentHP, obj.GetHP())
|
|
}
|
|
}
|
|
|
|
func TestObjectPower(t *testing.T) {
|
|
obj := NewObject()
|
|
|
|
// Test total power
|
|
testTotalPower := int32(500)
|
|
obj.SetTotalPower(testTotalPower)
|
|
if obj.GetTotalPower() != testTotalPower {
|
|
t.Errorf("Expected total power %d, got %d", testTotalPower, obj.GetTotalPower())
|
|
}
|
|
|
|
// Test current power
|
|
testCurrentPower := int32(300)
|
|
obj.SetPower(testCurrentPower)
|
|
if obj.GetPower() != testCurrentPower {
|
|
t.Errorf("Expected current power %d, got %d", testCurrentPower, obj.GetPower())
|
|
}
|
|
}
|
|
|
|
func TestObjectTransporter(t *testing.T) {
|
|
obj := NewObject()
|
|
|
|
testTransporterID := int32(9876)
|
|
obj.SetTransporterID(testTransporterID)
|
|
if obj.GetTransporterID() != testTransporterID {
|
|
t.Errorf("Expected transporter ID %d, got %d", testTransporterID, obj.GetTransporterID())
|
|
}
|
|
}
|
|
|
|
func TestObjectFlags(t *testing.T) {
|
|
obj := NewObject()
|
|
|
|
// Test sounds disabled flag
|
|
obj.SetSoundsDisabled(true)
|
|
if !obj.IsSoundsDisabled() {
|
|
t.Error("Sounds should be disabled after setting to true")
|
|
}
|
|
|
|
obj.SetSoundsDisabled(false)
|
|
if obj.IsSoundsDisabled() {
|
|
t.Error("Sounds should not be disabled after setting to false")
|
|
}
|
|
|
|
// Test omitted by DB flag
|
|
obj.SetOmittedByDBFlag(true)
|
|
if !obj.IsOmittedByDBFlag() {
|
|
t.Error("Object should be omitted by DB after setting to true")
|
|
}
|
|
|
|
obj.SetOmittedByDBFlag(false)
|
|
if obj.IsOmittedByDBFlag() {
|
|
t.Error("Object should not be omitted by DB after setting to false")
|
|
}
|
|
}
|
|
|
|
func TestObjectLoot(t *testing.T) {
|
|
obj := NewObject()
|
|
|
|
// Test loot tier
|
|
testLootTier := int8(3)
|
|
obj.SetLootTier(testLootTier)
|
|
if obj.GetLootTier() != testLootTier {
|
|
t.Errorf("Expected loot tier %d, got %d", testLootTier, obj.GetLootTier())
|
|
}
|
|
|
|
// Test loot drop type
|
|
testDropType := int8(2)
|
|
obj.SetLootDropType(testDropType)
|
|
if obj.GetLootDropType() != testDropType {
|
|
t.Errorf("Expected loot drop type %d, got %d", testDropType, obj.GetLootDropType())
|
|
}
|
|
}
|
|
|
|
func TestObjectSpawnScript(t *testing.T) {
|
|
obj := NewObject()
|
|
|
|
testScript := "test_script.lua"
|
|
obj.SetSpawnScript(testScript)
|
|
if obj.GetSpawnScript() != testScript {
|
|
t.Errorf("Expected spawn script '%s', got '%s'", testScript, obj.GetSpawnScript())
|
|
}
|
|
|
|
if !obj.GetSpawnScriptSetDB() {
|
|
t.Error("Spawn script set DB flag should be true after setting script")
|
|
}
|
|
|
|
// Test empty script
|
|
obj.SetSpawnScript("")
|
|
if obj.GetSpawnScriptSetDB() {
|
|
t.Error("Spawn script set DB flag should be false after setting empty script")
|
|
}
|
|
}
|
|
|
|
func TestObjectCommandIcon(t *testing.T) {
|
|
obj := NewObject()
|
|
|
|
// Test show command icon
|
|
obj.SetShowCommandIcon(true)
|
|
if !obj.ShowsCommandIcon() {
|
|
t.Error("Object should show command icon after setting to true")
|
|
}
|
|
|
|
obj.SetShowCommandIcon(false)
|
|
if obj.ShowsCommandIcon() {
|
|
t.Error("Object should not show command icon after setting to false")
|
|
}
|
|
}
|
|
|
|
func TestObjectCopy(t *testing.T) {
|
|
// Create original object with various properties set
|
|
original := NewObject()
|
|
original.SetClickable(true)
|
|
original.SetZone("testzone")
|
|
original.SetDeviceID(5)
|
|
original.SetMerchantID(12345)
|
|
original.SetMerchantType(2)
|
|
original.SetCollector(true)
|
|
original.SetSize(100)
|
|
original.SetSizeOffset(10)
|
|
original.SetTransporterID(9876)
|
|
original.SetTotalHP(1000)
|
|
original.SetHP(750)
|
|
original.SetShowCommandIcon(true)
|
|
|
|
// Create copy
|
|
copied := original.Copy()
|
|
if copied == nil {
|
|
t.Fatal("Copy returned nil")
|
|
}
|
|
|
|
// Verify copy has same properties
|
|
if copied.IsClickable() != original.IsClickable() {
|
|
t.Error("Copied object clickable state doesn't match original")
|
|
}
|
|
|
|
if copied.GetZoneName() != original.GetZoneName() {
|
|
t.Error("Copied object zone name doesn't match original")
|
|
}
|
|
|
|
if copied.GetDeviceID() != original.GetDeviceID() {
|
|
t.Error("Copied object device ID doesn't match original")
|
|
}
|
|
|
|
if copied.GetMerchantID() != original.GetMerchantID() {
|
|
t.Error("Copied object merchant ID doesn't match original")
|
|
}
|
|
|
|
if copied.IsCollector() != original.IsCollector() {
|
|
t.Error("Copied object collector flag doesn't match original")
|
|
}
|
|
|
|
if copied.GetTransporterID() != original.GetTransporterID() {
|
|
t.Error("Copied object transporter ID doesn't match original")
|
|
}
|
|
|
|
// Test size randomization with offset
|
|
if original.GetSizeOffset() > 0 {
|
|
// Size should be different but within reasonable range
|
|
originalSize := original.GetSize()
|
|
copiedSize := copied.GetSize()
|
|
sizeDiff := copiedSize - originalSize
|
|
offsetInt16 := int16(original.GetSizeOffset())
|
|
if sizeDiff < -offsetInt16 || sizeDiff > offsetInt16 {
|
|
t.Errorf("Copied object size randomization out of range: original=%d, copied=%d, offset=%d",
|
|
originalSize, copiedSize, original.GetSizeOffset())
|
|
}
|
|
}
|
|
|
|
// Verify they are separate objects
|
|
copied.SetClickable(false)
|
|
if copied.IsClickable() == original.IsClickable() {
|
|
t.Error("Copied object should be independent from original")
|
|
}
|
|
}
|
|
|
|
func TestObjectHandleUse(t *testing.T) {
|
|
obj := NewObject()
|
|
clientID := int32(12345)
|
|
|
|
// Test non-interactive object
|
|
err := obj.HandleUse(clientID, "use")
|
|
if err == nil {
|
|
t.Error("Expected error for non-interactive object")
|
|
}
|
|
|
|
// Test with transporter ID
|
|
obj.SetTransporterID(100)
|
|
err = obj.HandleUse(clientID, "use")
|
|
if err == nil {
|
|
t.Error("Expected error for transport system not implemented")
|
|
}
|
|
if !strings.Contains(err.Error(), "transport system not yet implemented") {
|
|
t.Errorf("Expected transport error message, got: %v", err)
|
|
}
|
|
|
|
// Test with command icon
|
|
obj.SetTransporterID(0) // Remove transporter
|
|
obj.SetShowCommandIcon(true)
|
|
obj.SetPrimaryCommands([]string{"use", "examine"})
|
|
|
|
err = obj.HandleUse(clientID, "use")
|
|
if err != nil {
|
|
t.Errorf("Expected no error for valid command, got: %v", err)
|
|
}
|
|
|
|
err = obj.HandleUse(clientID, "invalid")
|
|
if err == nil {
|
|
t.Error("Expected error for invalid command")
|
|
}
|
|
if !strings.Contains(err.Error(), "command 'invalid' not found") {
|
|
t.Errorf("Expected command not found error, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestObjectInfo(t *testing.T) {
|
|
obj := NewObject()
|
|
obj.SetClickable(true)
|
|
obj.SetZone("testzone")
|
|
obj.SetDeviceID(5)
|
|
obj.SetMerchantID(12345)
|
|
obj.SetTransporterID(9876)
|
|
obj.SetCollector(true)
|
|
obj.SetSize(150)
|
|
obj.SetPrimaryCommands([]string{"use", "examine"})
|
|
obj.SetSecondaryCommands([]string{"attack"})
|
|
obj.SetShowCommandIcon(true)
|
|
|
|
info := obj.GetObjectInfo()
|
|
if info == nil {
|
|
t.Fatal("GetObjectInfo returned nil")
|
|
}
|
|
|
|
// Check various properties
|
|
if info["clickable"] != true {
|
|
t.Error("Info should show object as clickable")
|
|
}
|
|
|
|
if info["zone_name"] != "testzone" {
|
|
t.Error("Info should show correct zone name")
|
|
}
|
|
|
|
if info["device_id"] != int8(5) {
|
|
t.Error("Info should show correct device ID")
|
|
}
|
|
|
|
if info["merchant_id"] != int32(12345) {
|
|
t.Error("Info should show correct merchant ID")
|
|
}
|
|
|
|
if info["transporter_id"] != int32(9876) {
|
|
t.Error("Info should show correct transporter ID")
|
|
}
|
|
|
|
if info["is_collector"] != true {
|
|
t.Error("Info should show object as collector")
|
|
}
|
|
|
|
if info["primary_commands"] != 2 {
|
|
t.Error("Info should show correct primary command count")
|
|
}
|
|
|
|
if info["secondary_commands"] != 1 {
|
|
t.Error("Info should show correct secondary command count")
|
|
}
|
|
|
|
if info["shows_command_icon"] != true {
|
|
t.Error("Info should show command icon as visible")
|
|
}
|
|
}
|
|
|
|
// Test ObjectSpawn creation and integration
|
|
func TestNewObjectSpawn(t *testing.T) {
|
|
objectSpawn := NewObjectSpawn()
|
|
if objectSpawn == nil {
|
|
t.Fatal("NewObjectSpawn returned nil")
|
|
}
|
|
|
|
if objectSpawn.Spawn == nil {
|
|
t.Fatal("ObjectSpawn should have embedded Spawn")
|
|
}
|
|
|
|
// Test default spawn type
|
|
if objectSpawn.GetSpawnType() != ObjectSpawnType {
|
|
t.Errorf("Expected spawn type %d, got %d", ObjectSpawnType, objectSpawn.GetSpawnType())
|
|
}
|
|
|
|
// Test default appearance values
|
|
appearance := objectSpawn.GetAppearanceData()
|
|
if appearance.ActivityStatus != ObjectActivityStatus {
|
|
t.Errorf("Expected activity status %d, got %d", ObjectActivityStatus, appearance.ActivityStatus)
|
|
}
|
|
if appearance.Pos.State != ObjectPosState {
|
|
t.Errorf("Expected pos state %d, got %d", ObjectPosState, appearance.Pos.State)
|
|
}
|
|
if appearance.Difficulty != ObjectDifficulty {
|
|
t.Errorf("Expected difficulty %d, got %d", ObjectDifficulty, appearance.Difficulty)
|
|
}
|
|
|
|
if !objectSpawn.IsObject() {
|
|
t.Error("ObjectSpawn should return true for IsObject()")
|
|
}
|
|
}
|
|
|
|
func TestObjectSpawnMerchantProperties(t *testing.T) {
|
|
objectSpawn := NewObjectSpawn()
|
|
|
|
// Test merchant ID
|
|
testMerchantID := int32(54321)
|
|
objectSpawn.SetMerchantID(testMerchantID)
|
|
if objectSpawn.GetMerchantID() != testMerchantID {
|
|
t.Errorf("Expected merchant ID %d, got %d", testMerchantID, objectSpawn.GetMerchantID())
|
|
}
|
|
|
|
// Test merchant type
|
|
testMerchantType := int8(3)
|
|
objectSpawn.SetMerchantType(testMerchantType)
|
|
if objectSpawn.GetMerchantType() != testMerchantType {
|
|
t.Errorf("Expected merchant type %d, got %d", testMerchantType, objectSpawn.GetMerchantType())
|
|
}
|
|
|
|
// Test merchant level range
|
|
minLevel, maxLevel := int8(5), int8(25)
|
|
objectSpawn.SetMerchantLevelRange(minLevel, maxLevel)
|
|
if objectSpawn.GetMerchantMinLevel() != minLevel {
|
|
t.Errorf("Expected min level %d, got %d", minLevel, objectSpawn.GetMerchantMinLevel())
|
|
}
|
|
if objectSpawn.GetMerchantMaxLevel() != maxLevel {
|
|
t.Errorf("Expected max level %d, got %d", maxLevel, objectSpawn.GetMerchantMaxLevel())
|
|
}
|
|
|
|
// Test collector
|
|
objectSpawn.SetCollector(true)
|
|
if !objectSpawn.IsCollector() {
|
|
t.Error("ObjectSpawn should be a collector after setting to true")
|
|
}
|
|
}
|
|
|
|
func TestObjectSpawnTransporter(t *testing.T) {
|
|
objectSpawn := NewObjectSpawn()
|
|
|
|
testTransporterID := int32(11111)
|
|
objectSpawn.SetTransporterID(testTransporterID)
|
|
if objectSpawn.GetTransporterID() != testTransporterID {
|
|
t.Errorf("Expected transporter ID %d, got %d", testTransporterID, objectSpawn.GetTransporterID())
|
|
}
|
|
}
|
|
|
|
func TestObjectSpawnCommandIcon(t *testing.T) {
|
|
objectSpawn := NewObjectSpawn()
|
|
|
|
// Test setting command icon
|
|
objectSpawn.SetShowCommandIcon(true)
|
|
if !objectSpawn.ShowsCommandIcon() {
|
|
t.Error("ObjectSpawn should show command icon after setting to true")
|
|
}
|
|
|
|
objectSpawn.SetShowCommandIcon(false)
|
|
if objectSpawn.ShowsCommandIcon() {
|
|
t.Error("ObjectSpawn should not show command icon after setting to false")
|
|
}
|
|
}
|
|
|
|
func TestObjectSpawnCopy(t *testing.T) {
|
|
// Create original with properties
|
|
original := NewObjectSpawn()
|
|
original.SetClickable(true)
|
|
original.SetDeviceID(7)
|
|
original.SetMerchantID(98765)
|
|
original.SetMerchantType(4)
|
|
original.SetCollector(true)
|
|
original.SetTransporterID(55555)
|
|
original.SetDatabaseID(12345)
|
|
original.SetName("Test Object")
|
|
original.SetLevel(10)
|
|
|
|
// Create copy
|
|
copied := original.Copy()
|
|
if copied == nil {
|
|
t.Fatal("Copy returned nil")
|
|
}
|
|
|
|
// Verify properties were copied
|
|
if copied.IsClickable() != original.IsClickable() {
|
|
t.Error("Copied clickable state doesn't match")
|
|
}
|
|
|
|
if copied.GetDeviceID() != original.GetDeviceID() {
|
|
t.Error("Copied device ID doesn't match")
|
|
}
|
|
|
|
if copied.GetMerchantID() != original.GetMerchantID() {
|
|
t.Error("Copied merchant ID doesn't match")
|
|
}
|
|
|
|
if copied.IsCollector() != original.IsCollector() {
|
|
t.Error("Copied collector flag doesn't match")
|
|
}
|
|
|
|
if copied.GetTransporterID() != original.GetTransporterID() {
|
|
t.Error("Copied transporter ID doesn't match")
|
|
}
|
|
|
|
if copied.GetDatabaseID() != original.GetDatabaseID() {
|
|
t.Error("Copied database ID doesn't match")
|
|
}
|
|
|
|
if strings.TrimRight(copied.GetName(), "\x00") != strings.TrimRight(original.GetName(), "\x00") {
|
|
t.Error("Copied name doesn't match")
|
|
}
|
|
|
|
if copied.GetLevel() != original.GetLevel() {
|
|
t.Error("Copied level doesn't match")
|
|
}
|
|
|
|
// Verify independence
|
|
copied.SetClickable(false)
|
|
if copied.IsClickable() == original.IsClickable() {
|
|
t.Error("Copy should be independent from original")
|
|
}
|
|
}
|
|
|
|
func TestObjectSpawnInfo(t *testing.T) {
|
|
objectSpawn := NewObjectSpawn()
|
|
objectSpawn.SetClickable(true)
|
|
objectSpawn.SetDeviceID(8)
|
|
objectSpawn.SetMerchantID(77777)
|
|
objectSpawn.SetTransporterID(88888)
|
|
objectSpawn.SetCollector(true)
|
|
objectSpawn.SetShowCommandIcon(true)
|
|
objectSpawn.SetDatabaseID(99999)
|
|
|
|
info := objectSpawn.GetObjectInfo()
|
|
if info == nil {
|
|
t.Fatal("GetObjectInfo returned nil")
|
|
}
|
|
|
|
// Check spawn info
|
|
if info["database_id"] != int32(99999) {
|
|
t.Error("Info should show correct database ID")
|
|
}
|
|
|
|
// Check object info
|
|
if info["clickable"] != true {
|
|
t.Error("Info should show object as clickable")
|
|
}
|
|
|
|
if info["device_id"] != int8(8) {
|
|
t.Error("Info should show correct device ID")
|
|
}
|
|
|
|
if info["merchant_id"] != int32(77777) {
|
|
t.Error("Info should show correct merchant ID")
|
|
}
|
|
|
|
if info["transporter_id"] != int32(88888) {
|
|
t.Error("Info should show correct transporter ID")
|
|
}
|
|
|
|
if info["is_collector"] != true {
|
|
t.Error("Info should show object as collector")
|
|
}
|
|
|
|
if info["shows_command_icon"] != true {
|
|
t.Error("Info should show command icon as visible")
|
|
}
|
|
}
|
|
|
|
// Test ObjectManager functionality
|
|
func TestNewObjectManager(t *testing.T) {
|
|
manager := NewObjectManager()
|
|
if manager == nil {
|
|
t.Fatal("NewObjectManager returned nil")
|
|
}
|
|
|
|
if manager.GetObjectCount() != 0 {
|
|
t.Error("New manager should have 0 objects")
|
|
}
|
|
|
|
if manager.GetZoneCount() != 0 {
|
|
t.Error("New manager should have 0 zones")
|
|
}
|
|
}
|
|
|
|
func TestObjectManagerAddRemove(t *testing.T) {
|
|
manager := NewObjectManager()
|
|
|
|
// Test adding nil object
|
|
err := manager.AddObject(nil)
|
|
if err == nil {
|
|
t.Error("Expected error when adding nil object")
|
|
}
|
|
|
|
// Create test object
|
|
obj := NewObject()
|
|
obj.SetDatabaseID(12345)
|
|
obj.SetZone("testzone")
|
|
|
|
// Test adding object without database ID
|
|
objNoDB := NewObject()
|
|
err = manager.AddObject(objNoDB)
|
|
if err == nil {
|
|
t.Error("Expected error when adding object without database ID")
|
|
}
|
|
|
|
// Test adding valid object
|
|
err = manager.AddObject(obj)
|
|
if err != nil {
|
|
t.Errorf("Unexpected error adding object: %v", err)
|
|
}
|
|
|
|
if manager.GetObjectCount() != 1 {
|
|
t.Error("Manager should have 1 object after adding")
|
|
}
|
|
|
|
// Test adding duplicate
|
|
err = manager.AddObject(obj)
|
|
if err == nil {
|
|
t.Error("Expected error when adding duplicate object")
|
|
}
|
|
|
|
// Test retrieving object
|
|
retrieved := manager.GetObject(12345)
|
|
if retrieved == nil {
|
|
t.Error("Should be able to retrieve added object")
|
|
}
|
|
|
|
if retrieved.GetDatabaseID() != obj.GetDatabaseID() {
|
|
t.Error("Retrieved object should match added object")
|
|
}
|
|
|
|
// Test removing object
|
|
err = manager.RemoveObject(12345)
|
|
if err != nil {
|
|
t.Errorf("Unexpected error removing object: %v", err)
|
|
}
|
|
|
|
if manager.GetObjectCount() != 0 {
|
|
t.Error("Manager should have 0 objects after removing")
|
|
}
|
|
|
|
// Test removing non-existent object
|
|
err = manager.RemoveObject(99999)
|
|
if err == nil {
|
|
t.Error("Expected error when removing non-existent object")
|
|
}
|
|
}
|
|
|
|
func TestObjectManagerZoneOperations(t *testing.T) {
|
|
manager := NewObjectManager()
|
|
|
|
// Create objects in different zones
|
|
obj1 := NewObject()
|
|
obj1.SetDatabaseID(1)
|
|
obj1.SetZone("zone1")
|
|
|
|
obj2 := NewObject()
|
|
obj2.SetDatabaseID(2)
|
|
obj2.SetZone("zone1")
|
|
|
|
obj3 := NewObject()
|
|
obj3.SetDatabaseID(3)
|
|
obj3.SetZone("zone2")
|
|
|
|
// Add objects
|
|
manager.AddObject(obj1)
|
|
manager.AddObject(obj2)
|
|
manager.AddObject(obj3)
|
|
|
|
// Test zone count
|
|
if manager.GetZoneCount() != 2 {
|
|
t.Errorf("Expected 2 zones, got %d", manager.GetZoneCount())
|
|
}
|
|
|
|
// Test getting objects by zone
|
|
zone1Objects := manager.GetObjectsByZone("zone1")
|
|
if len(zone1Objects) != 2 {
|
|
t.Errorf("Expected 2 objects in zone1, got %d", len(zone1Objects))
|
|
}
|
|
|
|
zone2Objects := manager.GetObjectsByZone("zone2")
|
|
if len(zone2Objects) != 1 {
|
|
t.Errorf("Expected 1 object in zone2, got %d", len(zone2Objects))
|
|
}
|
|
|
|
emptyZoneObjects := manager.GetObjectsByZone("nonexistent")
|
|
if len(emptyZoneObjects) != 0 {
|
|
t.Errorf("Expected 0 objects in nonexistent zone, got %d", len(emptyZoneObjects))
|
|
}
|
|
|
|
// Test clearing zone
|
|
clearedCount := manager.ClearZone("zone1")
|
|
if clearedCount != 2 {
|
|
t.Errorf("Expected to clear 2 objects, cleared %d", clearedCount)
|
|
}
|
|
|
|
if manager.GetObjectCount() != 1 {
|
|
t.Errorf("Expected 1 object remaining, got %d", manager.GetObjectCount())
|
|
}
|
|
|
|
if manager.GetZoneCount() != 1 {
|
|
t.Errorf("Expected 1 zone remaining, got %d", manager.GetZoneCount())
|
|
}
|
|
}
|
|
|
|
func TestObjectManagerTypeFiltering(t *testing.T) {
|
|
manager := NewObjectManager()
|
|
|
|
// Create objects with different properties
|
|
interactive := NewObject()
|
|
interactive.SetDatabaseID(1)
|
|
interactive.SetZone("testzone")
|
|
interactive.SetClickable(true)
|
|
|
|
transport := NewObject()
|
|
transport.SetDatabaseID(2)
|
|
transport.SetZone("testzone")
|
|
transport.SetTransporterID(100)
|
|
|
|
merchant := NewObject()
|
|
merchant.SetDatabaseID(3)
|
|
merchant.SetZone("testzone")
|
|
merchant.SetMerchantID(200)
|
|
|
|
collector := NewObject()
|
|
collector.SetDatabaseID(4)
|
|
collector.SetZone("testzone")
|
|
collector.SetCollector(true)
|
|
|
|
// Add objects
|
|
manager.AddObject(interactive)
|
|
manager.AddObject(transport)
|
|
manager.AddObject(merchant)
|
|
manager.AddObject(collector)
|
|
|
|
// Test type filtering
|
|
interactiveObjects := manager.GetInteractiveObjects()
|
|
if len(interactiveObjects) != 1 {
|
|
t.Errorf("Expected 1 interactive object, got %d", len(interactiveObjects))
|
|
}
|
|
|
|
transportObjects := manager.GetTransportObjects()
|
|
if len(transportObjects) != 1 {
|
|
t.Errorf("Expected 1 transport object, got %d", len(transportObjects))
|
|
}
|
|
|
|
merchantObjects := manager.GetMerchantObjects()
|
|
if len(merchantObjects) != 1 {
|
|
t.Errorf("Expected 1 merchant object, got %d", len(merchantObjects))
|
|
}
|
|
|
|
collectorObjects := manager.GetCollectorObjects()
|
|
if len(collectorObjects) != 1 {
|
|
t.Errorf("Expected 1 collector object, got %d", len(collectorObjects))
|
|
}
|
|
|
|
// Test GetObjectsByType
|
|
if len(manager.GetObjectsByType("interactive")) != 1 {
|
|
t.Error("GetObjectsByType should return 1 interactive object")
|
|
}
|
|
|
|
if len(manager.GetObjectsByType("transport")) != 1 {
|
|
t.Error("GetObjectsByType should return 1 transport object")
|
|
}
|
|
|
|
if len(manager.GetObjectsByType("merchant")) != 1 {
|
|
t.Error("GetObjectsByType should return 1 merchant object")
|
|
}
|
|
|
|
if len(manager.GetObjectsByType("collector")) != 1 {
|
|
t.Error("GetObjectsByType should return 1 collector object")
|
|
}
|
|
|
|
if len(manager.GetObjectsByType("invalid")) != 0 {
|
|
t.Error("GetObjectsByType should return 0 objects for invalid type")
|
|
}
|
|
}
|
|
|
|
func TestObjectManagerUpdate(t *testing.T) {
|
|
manager := NewObjectManager()
|
|
|
|
obj := NewObject()
|
|
obj.SetDatabaseID(12345)
|
|
obj.SetZone("zone1")
|
|
obj.SetClickable(false)
|
|
|
|
manager.AddObject(obj)
|
|
|
|
// Test update
|
|
err := manager.UpdateObject(12345, func(o *Object) {
|
|
o.SetClickable(true)
|
|
o.SetZone("zone2")
|
|
})
|
|
|
|
if err != nil {
|
|
t.Errorf("Unexpected error updating object: %v", err)
|
|
}
|
|
|
|
// Verify update took effect
|
|
updated := manager.GetObject(12345)
|
|
if !updated.IsClickable() {
|
|
t.Error("Object should be clickable after update")
|
|
}
|
|
|
|
if updated.GetZoneName() != "zone2" {
|
|
t.Error("Object should be in zone2 after update")
|
|
}
|
|
|
|
// Verify zone indexing was updated
|
|
zone1Objects := manager.GetObjectsByZone("zone1")
|
|
zone2Objects := manager.GetObjectsByZone("zone2")
|
|
|
|
if len(zone1Objects) != 0 {
|
|
t.Error("zone1 should have 0 objects after update")
|
|
}
|
|
|
|
if len(zone2Objects) != 1 {
|
|
t.Error("zone2 should have 1 object after update")
|
|
}
|
|
|
|
// Test updating non-existent object
|
|
err = manager.UpdateObject(99999, func(o *Object) {})
|
|
if err == nil {
|
|
t.Error("Expected error when updating non-existent object")
|
|
}
|
|
}
|
|
|
|
func TestObjectManagerStatistics(t *testing.T) {
|
|
manager := NewObjectManager()
|
|
|
|
// Create test objects
|
|
obj1 := NewObject()
|
|
obj1.SetDatabaseID(1)
|
|
obj1.SetZone("zone1")
|
|
obj1.SetClickable(true)
|
|
|
|
obj2 := NewObject()
|
|
obj2.SetDatabaseID(2)
|
|
obj2.SetZone("zone2")
|
|
obj2.SetMerchantID(100)
|
|
|
|
manager.AddObject(obj1)
|
|
manager.AddObject(obj2)
|
|
|
|
stats := manager.GetStatistics()
|
|
if stats == nil {
|
|
t.Fatal("GetStatistics returned nil")
|
|
}
|
|
|
|
if stats["total_objects"] != 2 {
|
|
t.Error("Statistics should show 2 total objects")
|
|
}
|
|
|
|
if stats["zones_with_objects"] != 2 {
|
|
t.Error("Statistics should show 2 zones with objects")
|
|
}
|
|
|
|
if stats["interactive_objects"] != 1 {
|
|
t.Error("Statistics should show 1 interactive object")
|
|
}
|
|
|
|
if stats["merchant_objects"] != 1 {
|
|
t.Error("Statistics should show 1 merchant object")
|
|
}
|
|
|
|
zoneStats, ok := stats["objects_by_zone"].(map[string]int)
|
|
if !ok {
|
|
t.Fatal("Zone stats should be a map[string]int")
|
|
}
|
|
|
|
if zoneStats["zone1"] != 1 {
|
|
t.Error("zone1 should have 1 object in statistics")
|
|
}
|
|
|
|
if zoneStats["zone2"] != 1 {
|
|
t.Error("zone2 should have 1 object in statistics")
|
|
}
|
|
}
|
|
|
|
func TestObjectManagerShutdown(t *testing.T) {
|
|
manager := NewObjectManager()
|
|
|
|
// Add some objects
|
|
obj1 := NewObject()
|
|
obj1.SetDatabaseID(1)
|
|
obj1.SetZone("zone1")
|
|
|
|
manager.AddObject(obj1)
|
|
|
|
if manager.GetObjectCount() != 1 {
|
|
t.Error("Manager should have 1 object before shutdown")
|
|
}
|
|
|
|
// Test shutdown
|
|
manager.Shutdown()
|
|
|
|
if manager.GetObjectCount() != 0 {
|
|
t.Error("Manager should have 0 objects after shutdown")
|
|
}
|
|
|
|
if manager.GetZoneCount() != 0 {
|
|
t.Error("Manager should have 0 zones after shutdown")
|
|
}
|
|
}
|
|
|
|
// Test utility functions
|
|
func TestCreateSpecialObjectSpawns(t *testing.T) {
|
|
// Test creating merchant object spawn
|
|
merchant := CreateMerchantObjectSpawn(12345, 2)
|
|
if merchant == nil {
|
|
t.Fatal("CreateMerchantObjectSpawn returned nil")
|
|
}
|
|
|
|
if merchant.GetMerchantID() != 12345 {
|
|
t.Error("Merchant object should have correct merchant ID")
|
|
}
|
|
|
|
if merchant.GetMerchantType() != 2 {
|
|
t.Error("Merchant object should have correct merchant type")
|
|
}
|
|
|
|
if !merchant.IsClickable() {
|
|
t.Error("Merchant object should be clickable")
|
|
}
|
|
|
|
if !merchant.ShowsCommandIcon() {
|
|
t.Error("Merchant object should show command icon")
|
|
}
|
|
|
|
// Test creating transport object spawn
|
|
transport := CreateTransportObjectSpawn(54321)
|
|
if transport == nil {
|
|
t.Fatal("CreateTransportObjectSpawn returned nil")
|
|
}
|
|
|
|
if transport.GetTransporterID() != 54321 {
|
|
t.Error("Transport object should have correct transporter ID")
|
|
}
|
|
|
|
// Test creating device object spawn
|
|
device := CreateDeviceObjectSpawn(7)
|
|
if device == nil {
|
|
t.Fatal("CreateDeviceObjectSpawn returned nil")
|
|
}
|
|
|
|
if device.GetDeviceID() != 7 {
|
|
t.Error("Device object should have correct device ID")
|
|
}
|
|
|
|
// Test creating collector object spawn
|
|
collector := CreateCollectorObjectSpawn()
|
|
if collector == nil {
|
|
t.Fatal("CreateCollectorObjectSpawn returned nil")
|
|
}
|
|
|
|
if !collector.IsCollector() {
|
|
t.Error("Collector object should be a collector")
|
|
}
|
|
}
|
|
|
|
// Test ObjectSpawnManager
|
|
func TestObjectSpawnManager(t *testing.T) {
|
|
manager := NewObjectSpawnManager()
|
|
if manager == nil {
|
|
t.Fatal("NewObjectSpawnManager returned nil")
|
|
}
|
|
|
|
// Test adding object spawn
|
|
objectSpawn := NewObjectSpawn()
|
|
objectSpawn.SetDatabaseID(12345)
|
|
|
|
err := manager.AddObjectSpawn(objectSpawn)
|
|
if err != nil {
|
|
t.Errorf("Unexpected error adding object spawn: %v", err)
|
|
}
|
|
|
|
// Test retrieving object spawn
|
|
retrieved := manager.GetObjectSpawn(objectSpawn.GetID())
|
|
if retrieved == nil {
|
|
t.Error("Should be able to retrieve added object spawn")
|
|
}
|
|
|
|
// Test removing object spawn
|
|
err = manager.RemoveObjectSpawn(objectSpawn.GetID())
|
|
if err != nil {
|
|
t.Errorf("Unexpected error removing object spawn: %v", err)
|
|
}
|
|
|
|
// Test adding nil object spawn
|
|
err = manager.AddObjectSpawn(nil)
|
|
if err == nil {
|
|
t.Error("Expected error when adding nil object spawn")
|
|
}
|
|
}
|
|
|
|
// Test interface implementations
|
|
func TestObjectItem(t *testing.T) {
|
|
item := NewObjectItem(12345, "Test Item", 5)
|
|
if item == nil {
|
|
t.Fatal("NewObjectItem returned nil")
|
|
}
|
|
|
|
if item.GetID() != 12345 {
|
|
t.Error("Item should have correct ID")
|
|
}
|
|
|
|
if item.GetName() != "Test Item" {
|
|
t.Error("Item should have correct name")
|
|
}
|
|
|
|
if item.GetQuantity() != 5 {
|
|
t.Error("Item should have correct quantity")
|
|
}
|
|
|
|
// Test setting properties
|
|
item.SetQuantity(10)
|
|
if item.GetQuantity() != 10 {
|
|
t.Error("Item quantity should be updated")
|
|
}
|
|
|
|
item.SetNoTrade(true)
|
|
if !item.IsNoTrade() {
|
|
t.Error("Item should be no-trade after setting")
|
|
}
|
|
|
|
item.SetHeirloom(true)
|
|
if !item.IsHeirloom() {
|
|
t.Error("Item should be heirloom after setting")
|
|
}
|
|
|
|
item.SetAttuned(true)
|
|
if !item.IsAttuned() {
|
|
t.Error("Item should be attuned after setting")
|
|
}
|
|
|
|
// Test creation time
|
|
if item.GetCreationTime().IsZero() {
|
|
t.Error("Item should have a creation time")
|
|
}
|
|
|
|
// Test group character IDs
|
|
groupIDs := []int32{1, 2, 3}
|
|
item.SetGroupCharacterIDs(groupIDs)
|
|
retrievedIDs := item.GetGroupCharacterIDs()
|
|
if len(retrievedIDs) != len(groupIDs) {
|
|
t.Error("Group character IDs length should match")
|
|
}
|
|
for i, id := range groupIDs {
|
|
if retrievedIDs[i] != id {
|
|
t.Errorf("Group character ID %d should be %d, got %d", i, id, retrievedIDs[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestObjectSpawnAsEntity(t *testing.T) {
|
|
objectSpawn := NewObjectSpawn()
|
|
entity := NewObjectSpawnAsEntity(objectSpawn)
|
|
if entity == nil {
|
|
t.Fatal("NewObjectSpawnAsEntity returned nil")
|
|
}
|
|
|
|
// Test entity interface methods
|
|
if entity.GetID() != objectSpawn.GetID() {
|
|
t.Error("Entity should have same ID as object spawn")
|
|
}
|
|
|
|
if entity.IsPlayer() {
|
|
t.Error("Object entity should not be a player")
|
|
}
|
|
|
|
if entity.IsBot() {
|
|
t.Error("Object entity should not be a bot by default")
|
|
}
|
|
|
|
entity.SetBot(true)
|
|
if !entity.IsBot() {
|
|
t.Error("Object entity should be a bot after setting")
|
|
}
|
|
|
|
// Test coins
|
|
if entity.HasCoins(100) {
|
|
t.Error("Object entity should not have coins by default")
|
|
}
|
|
|
|
entity.SetCoins(500)
|
|
if !entity.HasCoins(100) {
|
|
t.Error("Object entity should have sufficient coins after setting")
|
|
}
|
|
|
|
if entity.HasCoins(1000) {
|
|
t.Error("Object entity should not have more coins than set")
|
|
}
|
|
|
|
// Test client version
|
|
if entity.GetClientVersion() != 1000 {
|
|
t.Error("Object entity should have default client version")
|
|
}
|
|
|
|
entity.SetClientVersion(2000)
|
|
if entity.GetClientVersion() != 2000 {
|
|
t.Error("Object entity should have updated client version")
|
|
}
|
|
|
|
// Test name
|
|
if entity.GetName() != "Object" {
|
|
t.Error("Object entity should have default name")
|
|
}
|
|
|
|
entity.SetName("Test Object")
|
|
if entity.GetName() != "Test Object" {
|
|
t.Error("Object entity should have updated name")
|
|
}
|
|
}
|
|
|
|
// Benchmark tests
|
|
func BenchmarkNewObject(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
NewObject()
|
|
}
|
|
}
|
|
|
|
func BenchmarkObjectCopy(b *testing.B) {
|
|
obj := NewObject()
|
|
obj.SetClickable(true)
|
|
obj.SetZone("testzone")
|
|
obj.SetMerchantID(12345)
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
obj.Copy()
|
|
}
|
|
}
|
|
|
|
func BenchmarkObjectManagerAdd(b *testing.B) {
|
|
manager := NewObjectManager()
|
|
objects := make([]*Object, b.N)
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
obj := NewObject()
|
|
obj.SetDatabaseID(int32(i + 1))
|
|
obj.SetZone("testzone")
|
|
objects[i] = obj
|
|
}
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
manager.AddObject(objects[i])
|
|
}
|
|
}
|
|
|
|
func BenchmarkObjectManagerGet(b *testing.B) {
|
|
manager := NewObjectManager()
|
|
|
|
// Pre-populate with objects
|
|
for i := 0; i < 1000; i++ {
|
|
obj := NewObject()
|
|
obj.SetDatabaseID(int32(i + 1))
|
|
obj.SetZone("testzone")
|
|
manager.AddObject(obj)
|
|
}
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
manager.GetObject(int32((i % 1000) + 1))
|
|
}
|
|
} |