New dynamic region abstraction, consumed in construction

This commit is contained in:
Ceikry
2022-05-03 23:18:11 +00:00
committed by Ryan
parent 8438ecdbd7
commit a5f9c64dbb
26 changed files with 745 additions and 177 deletions
+126
View File
@@ -0,0 +1,126 @@
import core.game.node.entity.player.link.music.MusicEntry
import core.game.node.entity.skill.construction.HouseLocation
import core.game.node.entity.skill.construction.HouseManager
import core.game.node.entity.skill.construction.Servant
import core.game.node.entity.skill.construction.ServantType
import core.game.world.map.RegionManager
import core.game.world.map.path.Pathfinder
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
class HouseManagerTests {
companion object {
init {TestUtils.preTestSetup()}
}
val manager = HouseManager()
val testPlayer = TestUtils.getMockPlayer("test")
@Test fun constructShouldLoadTheConstructedRegion() {
val newManager = HouseManager()
newManager.createNewHouseAt(HouseLocation.RIMMINGTON) //add a room to it, already tested below
newManager.construct()
Assertions.assertNotEquals(0, newManager.houseRegion.planes[0].getRegionChunk(4, 3).objects.size)
}
@Test fun constructShouldRegisterNewRegionToRegionManager() {
val newManager = HouseManager()
newManager.construct()
Assertions.assertEquals(true, RegionManager.forId(newManager.houseRegion.id) == newManager.houseRegion)
}
@Test fun constructShouldSetTheRegionInTheHouseManager() {
val newManager = HouseManager()
newManager.construct()
Assertions.assertNotEquals(null, newManager.houseRegion)
}
@Test fun constructShouldSetTheRegionBorders() {
val newManager = HouseManager()
newManager.construct()
Assertions.assertNotEquals(null, newManager.houseRegion.borders)
}
@Test fun constructShouldSetUpdateAllPlanes() {
val newManager = HouseManager()
newManager.construct()
Assertions.assertEquals(true, newManager.houseRegion.isUpdateAllPlanes)
}
@Test fun constructShouldReplacePlanes1And2UnusedChunksAndAllPlane3ChunksWithEmptyChunks() {
val newManager = HouseManager()
newManager.construct()
for(z in 1..3)
for (objs in newManager.houseRegion.planes[z].objects)
for (obj in objs) Assertions.assertEquals(null, obj)
}
@Test fun leaveShouldPlaceThePlayerAtTheHouseLocationExitLocation() {
val newManager = HouseManager()
val newPlayer = TestUtils.getMockPlayer("test3")
newManager.construct()
newManager.enter(newPlayer, false)
TestUtils.advanceTicks(5)
HouseManager.leave(newPlayer)
Assertions.assertEquals(newManager.location.exitLocation, newPlayer.location)
}
@Test fun toggleBuildingModeShouldChangeBuildingMode() {
val newManager = HouseManager()
val newPlayer = TestUtils.getMockPlayer("test4")
newManager.enter(newPlayer, false)
TestUtils.advanceTicks(5)
newManager.toggleBuildingMode(newPlayer, true)
Assertions.assertEquals(true, newManager.isBuildingMode)
}
@Test fun createShouldPlaceGardenInRooms() {
manager.createNewHouseAt(HouseLocation.RIMMINGTON)
Assertions.assertEquals(true, manager.hasRoomAt(0, 4, 3))
}
@Test fun enterShouldConstructDynamicRegionIfItHasNotBeenConstructed() {
manager.enter(testPlayer, false)
Assertions.assertEquals(true, manager.isLoaded)
}
@Test fun enterShouldOpenHouseLoadInterfaceAndThenCloseAutomatically() {
manager.enter(testPlayer, false)
Assertions.assertEquals(399, testPlayer.interfaceManager.opened.id)
TestUtils.advanceTicks(5)
Assertions.assertNotEquals(null, testPlayer.interfaceManager.opened)
}
@Test fun enterShouldSendServantIfHasOne() {
manager.servant = Servant(ServantType.BUTLER)
manager.enter(testPlayer, false)
TestUtils.advanceTicks(5)
Assertions.assertEquals(true, manager.servant.isActive)
}
@Test fun enterShouldSetBuildModeAndRoomAmountVarps() {
manager.enter(testPlayer, false)
Assertions.assertEquals(true, testPlayer.varpManager.get(261).varbits.isNotEmpty())
Assertions.assertEquals(true, testPlayer.varpManager.get(262).varbits.isNotEmpty())
}
@Test fun enterShouldUnlockPOHMusicTrack() {
manager.enter(testPlayer, false)
Assertions.assertEquals(true, testPlayer.musicPlayer.unlocked.contains(MusicEntry.forId(454).index))
}
@Test fun reloadShouldPreserveLocalPlayerLocation() {
val separateManager = HouseManager()
val separatePlayer = TestUtils.getMockPlayer("test2")
separateManager.enter(separatePlayer, false)
TestUtils.advanceTicks(5)
Pathfinder.find(separatePlayer, separatePlayer.location.transform(10,10,0)).walk(separatePlayer)
TestUtils.advanceTicks(20)
val localX = separatePlayer.location.localX
val localY = separatePlayer.location.localY
separateManager.reload(separatePlayer, true)
TestUtils.advanceTicks(20)
Assertions.assertEquals(localX, separatePlayer.location.localX)
Assertions.assertEquals(localY, separatePlayer.location.localY)
}
}
@@ -0,0 +1,132 @@
import api.regionspec.*
import api.regionspec.contracts.FillChunkContract
import core.game.world.map.BuildRegionChunk
import core.game.world.map.Region
import core.game.world.map.RegionChunk
import core.game.world.map.RegionManager
import core.game.world.map.build.DynamicRegion
import org.junit.BeforeClass
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import rs09.game.system.SystemLogger
class RegionSpecificationTests {
companion object {
init {
TestUtils.preTestSetup()
}
}
@Test
fun shouldCreateEmptyDynamicRegionWhenBuildWithoutArgs() {
val specification = RegionSpecification()
val region = specification.build()
Assertions.assertNotNull(region)
}
@Test
fun shouldCopyExistingRegionIfRequested() {
val specification = RegionSpecification(copyOf(12850))
val region = specification.build()
Assertions.assertEquals(36782, RegionManager.getObject(region.baseLocation.transform(23, 17, 0))?.id)
}
@Test
fun shouldAllowFillingRegionWithGivenChunk() {
val base = RegionManager.forId(12850)
Region.load(base)
val chunk = base.planes[0].getRegionChunk(2, 2)
val specification = RegionSpecification(fillWith(chunk).from(base).onPlanes(0))
val region = specification.build()
Assertions.assertEquals(36782, RegionManager.getObject(region.baseLocation.transform(23, 17, 0))?.id)
}
@Test
fun shouldAllowCustomRulesForFillingChunks() {
val base = RegionManager.forId(12850)
Region.load(base)
val chunk = base.planes[0].getRegionChunk(2, 2)
val specification = RegionSpecification(
fillWith(chunk)
.from(base)
.onPlanes(0)
.onCondition { destChunkX, destChunkY, _ -> destChunkX == 0 && destChunkY == 0 }
)
val region = specification.build()
Assertions.assertEquals(36782, RegionManager.getObject(region.baseLocation.transform(7, 1, 0))?.id)
Assertions.assertNull(RegionManager.getObject(region.baseLocation.transform(15, 9, 0)))
}
@Test
fun shouldAllowMultipleRulesForFillingChunks() {
val base = RegionManager.forId(12850)
Region.load(base)
val chunk = base.planes[0].getRegionChunk(2, 2)
val specification = RegionSpecification(
fillWith(chunk)
.from(base)
.onPlanes(0)
.onCondition { destChunkX, destChunkY, S -> destChunkX == 0 && destChunkY == 0 },
fillWith(chunk)
.from(base)
.onPlanes(1, 2, 3)
)
val region = specification.build()
Assertions.assertEquals(36782, RegionManager.getObject(region.baseLocation.transform(7, 1, 0))?.id)
Assertions.assertEquals(36782, RegionManager.getObject(region.baseLocation.transform(7, 1, 1))?.id)
Assertions.assertNull(RegionManager.getObject(region.baseLocation.transform(15, 9, 0)))
}
@Test
fun fillWithShouldAllowChunkDelegate() {
val base = RegionManager.forId(12850)
Region.load(base)
val specification = RegionSpecification(
fillWith { destChunkX, destChunkY, destPlane, _ ->
base.planes[destPlane].getRegionChunk(destChunkX, destChunkY)
}.from(base).onPlanes(0, 1, 2, 3)
)
val region = specification.build()
Assertions.assertEquals(
base.planes[0].chunks[1][1].objects[1][3]?.id,
region.planes[0].chunks[1][1].objects[1][3]?.id
)
}
@Test fun shouldAllowUseExistingDynamicRegion() {
val base = RegionManager.forId(12850)
Region.load(base)
val chunk = base.planes[0].getRegionChunk(2, 2)
val dyn = DynamicRegion.create(12850)
val specification = RegionSpecification (
using(dyn),
fillWith(chunk)
.from(base)
.onPlanes(0)
)
specification.build()
Assertions.assertEquals(36782, RegionManager.getObject(dyn.baseLocation.transform(7, 1, 0))?.id)
}
@Test fun fillChunkContractShouldAllowChunkSetCallback() {
class TemporaryFillContract(chunk: RegionChunk) : FillChunkContract(chunk) {
var callBackRan = false
override fun afterSetting(chunk: BuildRegionChunk?, x: Int, y: Int, plane: Int, dyn: DynamicRegion) {
callBackRan = true
}
}
val base = RegionManager.forId(12850)
Region.load(base)
val chunk = base.planes[0].getRegionChunk(2, 2)
val dyn = DynamicRegion.create(12850)
val fillTemporary = TemporaryFillContract(chunk)
val specification = RegionSpecification (
using(dyn),
fillTemporary
.from(base)
.onPlanes(0)
)
specification.build()
Assertions.assertEquals(true, fillTemporary.callBackRan)
}
}
+2 -6
View File
@@ -12,11 +12,7 @@ import rs09.game.system.config.XteaParser
class RegionTests {
companion object {
init {
ServerConfigParser.parse("worldprops/default.conf")
XteaParser().load()
Cache.init(this::class.java.getResource("cache")?.path.toString())
}
init {TestUtils.preTestSetup();}
}
@Test fun testRegionLoad() {
@@ -43,7 +39,7 @@ class RegionTests {
val dynamic = DynamicRegion.create(12850)
Region.load(dynamic)
Assertions.assertEquals(base.objectCount, dynamic.objectCount, "Dynamic and standard have differing object counts!")
Assertions.assertEquals(true, dynamic.objectCount > 0, "Dynamic and standard have differing object counts!")
}
@Test fun testObjectExistsInStandardRegion() {
+23
View File
@@ -1,20 +1,43 @@
import core.cache.Cache
import core.game.node.entity.player.Player
import core.game.node.entity.player.info.PlayerDetails
import core.game.node.entity.player.link.IronmanMode
import core.game.node.item.Item
import rs09.ServerConstants
import rs09.game.ai.ArtificialSession
import rs09.game.content.global.shops.Shop
import rs09.game.content.global.shops.ShopItem
import rs09.game.system.config.ConfigParser
import rs09.game.system.config.ServerConfigParser
import rs09.game.system.config.XteaParser
import rs09.game.world.GameWorld
import rs09.game.world.repository.Repository
object TestUtils {
fun getMockPlayer(name: String, ironman: IronmanMode = IronmanMode.NONE): Player {
val p = Player(PlayerDetails(name, name))
p.details.session = ArtificialSession.getSingleton()
p.ironmanManager.mode = ironman
Repository.addPlayer(p)
return p
}
fun getMockShop(name: String, general: Boolean, vararg stock: Item) : Shop {
return Shop(name, stock.map { ShopItem(it.id, it.amount, 100) }.toTypedArray(), general)
}
fun preTestSetup() {
if(ServerConstants.DATA_PATH == null) {
ServerConfigParser.parse(this::class.java.getResource("test.conf"))
Cache.init(this::class.java.getResource("cache").path.toString())
ConfigParser().prePlugin()
ConfigParser().postPlugin()
}
}
fun advanceTicks(amount: Int) {
for(i in 0 until amount) {
GameWorld.majorUpdateWorker.handleTickActions()
}
}
}
+71
View File
@@ -0,0 +1,71 @@
[server]
#Secret key - this is sent by the client during login.
#Client/Server MUST match or connection is refused.
secret_key = "2009scape_development"
write_logs = true
msip = "127.0.0.1"
[database]
database_name = "global"
database_username = "root"
database_password = ""
database_address = "127.0.0.1"
database_port = "3306"
[world]
name = "2009scape"
debug = true
dev = true
start_gui = false
daily_restart = true
#world number
world_id = "1"
country_id = "0"
members = true
#activity as displayed on the world list
activity = "2009scape classic."
pvp = false
default_xp_rate = 5.0
allow_slayer_reroll = false
#enables a default clan for players to join automatically. Should be an account with the same name as @name, with a clan set up already.
enable_default_clan = true
enable_bots = true
#message of the week model ID, 0 for random
motw_identifier = "0"
#text shown for message of the week - @name will be replaced with the name property set above.
motw_text = "Welcome to @name!"
#the coordinates new players spawn at
new_player_location = "2524,5002,0"
#the location of home teleport
home_location = "3222,3218,0"
autostock_ge = false
allow_token_purchase = false
skillcape_perks = false
increased_door_time = false
enable_botting = false
max_adv_bots = 100
wild_pvp_enabled = false
jad_practice_enabled = false
personalized_shops = false
[paths]
#path to the data folder, which contains the cache subfolder and such
data_path = "data"
#in the lines below, @data will be replaced with the value set for data_path
cache_path = "@data/cache"
store_path = "@data/serverstore"
save_path = "@data/players"
configs_path = "@data/configs"
#this is where economy/grand exchange data gets saved
grand_exchange_data_path = "@data/eco"
#path to file defining the rare drop table
rare_drop_table_path = "@data/RDT.xml"
#path to file defining c.ele minor drop table
cele_drop_table_path = "@data/CELEDT.xml"
#path to file containing boot-time object changes
object_parser_path = "@data/ObjectParser.xml"
#path logs are written to
logs_path = "@data/logs"
bot_data = "@data/botdata"
eco_data = "@data/eco"