Skip to content

Commit

Permalink
feat: Prepare for cross-platform porting
Browse files Browse the repository at this point in the history
  • Loading branch information
half-nothing committed Oct 11, 2024
1 parent c323891 commit 921ef86
Show file tree
Hide file tree
Showing 13 changed files with 136 additions and 77 deletions.
80 changes: 21 additions & 59 deletions src/main/kotlin/net/superricky/tpaplusplus/TpaPlusPlus.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
package net.superricky.tpaplusplus

import dev.architectury.event.events.common.CommandRegistrationEvent
import dev.architectury.event.events.common.EntityEvent
import dev.architectury.event.events.common.PlayerEvent
import dev.architectury.event.events.common.TickEvent
import dev.architectury.event.events.common.LifecycleEvent
import dev.architectury.platform.Platform
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import net.fabricmc.api.ModInitializer
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents
import net.fabricmc.loader.api.FabricLoader
import net.fabricmc.loader.api.Version
import net.minecraft.server.MinecraftServer
import net.superricky.tpaplusplus.GlobalConst.CONFIG_FILE_NAME
import net.superricky.tpaplusplus.GlobalConst.CONFIG_FILE_PATH
Expand All @@ -19,39 +14,40 @@ import net.superricky.tpaplusplus.GlobalConst.EXAMPLE_LANG_FILE_PATH
import net.superricky.tpaplusplus.GlobalConst.LANG_FOLDER_PATH
import net.superricky.tpaplusplus.GlobalConst.MOD_ID
import net.superricky.tpaplusplus.GlobalConst.logger
import net.superricky.tpaplusplus.async.AsyncCommandHelper
import net.superricky.tpaplusplus.command.CommandRegister
import net.superricky.tpaplusplus.config.config.AdvancedSpec
import net.superricky.tpaplusplus.config.config.CommonSpec
import net.superricky.tpaplusplus.config.config.Config
import net.superricky.tpaplusplus.config.config.Config.get
import net.superricky.tpaplusplus.config.language.LanguageConfig
import net.superricky.tpaplusplus.database.DataManager
import net.superricky.tpaplusplus.database.service.DataService
import net.superricky.tpaplusplus.event.ServerEvent
import java.nio.file.Files
import kotlin.coroutines.CoroutineContext
import net.superricky.tpaplusplus.utility.PlayerEvent as PlayerEventListener

object TpaPlusPlus : ModInitializer, CoroutineScope {
lateinit var server: MinecraftServer
override val coroutineContext: CoroutineContext = Dispatchers.IO
val version: Version = FabricLoader.getInstance().getModContainer(MOD_ID).get().metadata.version
val version: String = Platform.getMod(MOD_ID).version.toString()
lateinit var dataService: DataService

override fun onInitialize() {
logger.info("Initializing TPA++ ${version.friendlyString}")
init()
}

fun init() {
logger.info("Initializing TPA++ $version")

logger.info("Checking config...")
if (!Files.isDirectory(FabricLoader.getInstance().configDir.resolve(CONFIG_FOLDER_PATH))) {
if (!Files.isDirectory(Platform.getConfigFolder().resolve(CONFIG_FOLDER_PATH))) {
logger.info("Config folder not exist, Creating.")
Files.createDirectories(FabricLoader.getInstance().configDir.resolve(CONFIG_FOLDER_PATH))
Files.createDirectories(Platform.getConfigFolder().resolve(CONFIG_FOLDER_PATH))
}

if (!Files.exists(FabricLoader.getInstance().configDir.resolve(CONFIG_FILE_PATH))) {
if (!Files.exists(Platform.getConfigFolder().resolve(CONFIG_FILE_PATH))) {
logger.info("No config file, Creating")
Files.copy(
FabricLoader.getInstance().getModContainer(MOD_ID).get().findPath(CONFIG_FILE_NAME).get(),
FabricLoader.getInstance().configDir.resolve(CONFIG_FILE_PATH)
Platform.getMod(MOD_ID).findResource(CONFIG_FILE_NAME).get(),
Platform.getConfigFolder().resolve(CONFIG_FILE_PATH)
)
}

Expand All @@ -65,19 +61,19 @@ object TpaPlusPlus : ModInitializer, CoroutineScope {
}

logger.info("Checking lang file...")
if (!Files.exists(FabricLoader.getInstance().configDir.resolve(LANG_FOLDER_PATH))) {
if (!Files.exists(Platform.getConfigFolder().resolve(LANG_FOLDER_PATH))) {
logger.info("Lang folder not exist, Creating")
Files.createDirectories(FabricLoader.getInstance().configDir.resolve(LANG_FOLDER_PATH))
Files.createDirectories(Platform.getConfigFolder().resolve(LANG_FOLDER_PATH))
}

if (!Files.exists(
FabricLoader.getInstance().configDir.resolve(CONFIG_FOLDER_PATH).resolve(EXAMPLE_LANG_FILE_PATH)
Platform.getConfigFolder().resolve(CONFIG_FOLDER_PATH).resolve(EXAMPLE_LANG_FILE_PATH)
)
) {
logger.info("No example lang file, Creating")
Files.copy(
FabricLoader.getInstance().getModContainer(MOD_ID).get().findPath(EXAMPLE_LANG_FILE_PATH).get(),
FabricLoader.getInstance().configDir.resolve(CONFIG_FOLDER_PATH).resolve(EXAMPLE_LANG_FILE_PATH)
Platform.getMod(MOD_ID).findResource(EXAMPLE_LANG_FILE_PATH).get(),
Platform.getConfigFolder().resolve(CONFIG_FOLDER_PATH).resolve(EXAMPLE_LANG_FILE_PATH)
)
}

Expand All @@ -98,42 +94,8 @@ object TpaPlusPlus : ModInitializer, CoroutineScope {
}

logger.info("Add lifecycle event listener")
ServerLifecycleEvents.SERVER_STARTING.register(::serverStarting)
ServerLifecycleEvents.SERVER_STOPPED.register(::serverStopped)
LifecycleEvent.SERVER_BEFORE_START.register(ServerEvent::serverStartingEvent)
LifecycleEvent.SERVER_STOPPED.register(ServerEvent::serverStoppedEvent)
logger.info("Basic component initialization is complete")
}

private fun serverStarting(server: MinecraftServer) {
logger.info("Server starting...")
logger.info("Main logic initializing...")
this.server = server
this.dataService = DataManager

logger.info("Data service initializing...")
dataService.initDataService()

logger.info("Add player event listener...")
PlayerEvent.PLAYER_JOIN.register(PlayerEventListener::joinEvent)
EntityEvent.LIVING_DEATH.register(PlayerEventListener::deathEvent)

if (AdvancedSpec.unblockingTickLoop.get()) {
logger.info("Using non blocking tick loop")
logger.info(
"Initializing non blocking tick loop with rate of " +
"${AdvancedSpec.asyncLoopRate.get()} per second"
)
AsyncCommandHelper.startTickLoop(AdvancedSpec.asyncLoopRate.get())
} else {
logger.info("Using synchronous tick loop")
logger.info("Registering server post tick event")
TickEvent.SERVER_POST.register { AsyncCommandHelper.runTick() }
}
}

private fun serverStopped(ignored: MinecraftServer) {
logger.info("Shutting down TPA++")
AsyncCommandHelper.stopTickLoop()
coroutineContext.cancel()
dataService.saveData()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ object RootCommand : BuildableCommand {
source.sendFeedback(
{
SystemSpec.version.getMutableText(
TpaPlusPlus.version.friendlyString.literal().setStyle(TextColorPallet.secondaryVariant)
TpaPlusPlus.version.literal().setStyle(TextColorPallet.secondaryVariant)
).setStyle(TextColorPallet.primaryVariant)
},
false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ package net.superricky.tpaplusplus.config.config

import com.uchuhimo.konf.Config
import com.uchuhimo.konf.RequiredItem
import com.uchuhimo.konf.source.Source
import com.uchuhimo.konf.source.toml
import net.fabricmc.loader.api.FabricLoader
import dev.architectury.platform.Platform
import net.minecraft.util.WorldSavePath
import net.superricky.tpaplusplus.GlobalConst
import net.superricky.tpaplusplus.TpaPlusPlus
Expand All @@ -24,7 +25,7 @@ object Config {
addSpec(CommandLimitationsSpec)
}
.from.toml.resource(GlobalConst.CONFIG_FILE_NAME)
.from.toml.watchFile(FabricLoader.getInstance().configDir.resolve(GlobalConst.CONFIG_FILE_PATH).toFile())
.from.toml.watchFile(Platform.getConfigFolder().resolve(GlobalConst.CONFIG_FILE_PATH).toFile())
.from.env()

/**
Expand All @@ -38,6 +39,10 @@ object Config {
CommandNameSpec.items.forEach { replaceCommand(it as? RequiredItem<String> ?: return@forEach) }
}

fun addLoadListener(listener: Function1<Source, Unit>) {
config.beforeLoad { listener(it) }
}

/**
* Replace / before command
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ package net.superricky.tpaplusplus.config.language

import com.uchuhimo.konf.Config
import com.uchuhimo.konf.RequiredItem
import com.uchuhimo.konf.source.Source
import com.uchuhimo.konf.source.toml
import net.fabricmc.loader.api.FabricLoader
import dev.architectury.platform.Platform
import net.minecraft.text.MutableText
import net.minecraft.text.TranslatableTextContent
import net.superricky.tpaplusplus.GlobalConst.DEFAULT_LANG_FILE_NAME
Expand Down Expand Up @@ -44,23 +45,27 @@ object LanguageConfig {
}
.from.toml.resource(DEFAULT_LANG_FILE_SOURCE_PATH)
.from.toml.watchFile(
FabricLoader.getInstance().configDir.resolve(LANG_FOLDER_PATH).resolve(languageFileName).toFile()
Platform.getConfigFolder().resolve(LANG_FOLDER_PATH).resolve(languageFileName).toFile()
)
.from.env()
config.validateRequired()
}

fun addLoadListener(listener: Function1<Source, Unit>) {
config.beforeLoad { listener(it) }
}

private fun checkLanguageFile(language: String): Boolean {
val languageFilePath = Path(LANG_FOLDER_PATH).resolve(languageFileName)
val languageSourcePath = Path(LANG_FOLDER_NAME).resolve(languageFileName).toString()
if (!Files.exists(FabricLoader.getInstance().configDir.resolve(languageFilePath))) {
if (!Files.exists(Platform.getConfigFolder().resolve(languageFilePath))) {
// If language has been supported
if (supportedLanguage.contains(language)) {
logger.info("No $languageFileName file, Creating")
try {
Files.copy(
FabricLoader.getInstance().getModContainer(MOD_ID).get().findPath(languageSourcePath).get(),
FabricLoader.getInstance().configDir.resolve(languageFilePath)
Platform.getMod(MOD_ID).findResource(languageSourcePath).get(),
Platform.getConfigFolder().resolve(languageFilePath)
)
} catch (e: Exception) {
logger.error(e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ object SystemSpec : ConfigSpec("system") {
val courseforgeView by required<String>()
val reloadStart by required<String>()
val reloadFinish by required<String>()
val configChange by required<String>()
val languageChange by required<String>()
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package net.superricky.tpaplusplus.utility
package net.superricky.tpaplusplus.event

import dev.architectury.event.EventResult
import kotlinx.coroutines.launch
import net.minecraft.entity.LivingEntity
import net.minecraft.entity.damage.DamageSource
import net.minecraft.server.network.ServerPlayerEntity
import net.superricky.tpaplusplus.TpaPlusPlus
import net.superricky.tpaplusplus.utility.LevelBoundVec3
import net.superricky.tpaplusplus.utility.getDimension

object PlayerEvent {
fun joinEvent(player: ServerPlayerEntity) {
Expand Down
76 changes: 76 additions & 0 deletions src/main/kotlin/net/superricky/tpaplusplus/event/ServerEvent.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package net.superricky.tpaplusplus.event

import dev.architectury.event.events.common.EntityEvent
import dev.architectury.event.events.common.TickEvent
import kotlinx.coroutines.cancel
import net.minecraft.server.MinecraftServer
import net.minecraft.server.network.ServerPlayerEntity
import net.superricky.tpaplusplus.GlobalConst.PERMISSION_LEVEL
import net.superricky.tpaplusplus.GlobalConst.logger
import net.superricky.tpaplusplus.TpaPlusPlus
import net.superricky.tpaplusplus.TpaPlusPlus.coroutineContext
import net.superricky.tpaplusplus.TpaPlusPlus.dataService
import net.superricky.tpaplusplus.async.AsyncCommandHelper
import net.superricky.tpaplusplus.config.config.AdvancedSpec
import net.superricky.tpaplusplus.config.config.Config
import net.superricky.tpaplusplus.config.config.Config.get
import net.superricky.tpaplusplus.config.language.LanguageConfig
import net.superricky.tpaplusplus.config.language.LanguageConfig.getMutableText
import net.superricky.tpaplusplus.config.language.SystemSpec
import net.superricky.tpaplusplus.database.DataManager
import net.superricky.tpaplusplus.utility.TextColorPallet

object ServerEvent {
fun serverStartingEvent(server: MinecraftServer) {
fun getOps(server: MinecraftServer): List<ServerPlayerEntity> {
val ops = mutableListOf<ServerPlayerEntity>()
server.playerManager.playerList.filterTo(ops) {
it.hasPermissionLevel(PERMISSION_LEVEL)
}
return ops.toList()
}
logger.info("Server starting...")
logger.info("Main logic initializing...")
TpaPlusPlus.server = server
dataService = DataManager

logger.info("Data service initializing...")
dataService.initDataService()

logger.info("Add player event listener...")
dev.architectury.event.events.common.PlayerEvent.PLAYER_JOIN.register(PlayerEvent::joinEvent)
EntityEvent.LIVING_DEATH.register(PlayerEvent::deathEvent)

Config.addLoadListener {
getOps(server).forEach {
it.sendMessage(SystemSpec.configChange.getMutableText().setStyle(TextColorPallet.primary))
}
}

LanguageConfig.addLoadListener {
getOps(server).forEach {
it.sendMessage(SystemSpec.languageChange.getMutableText().setStyle(TextColorPallet.primary))
}
}

if (AdvancedSpec.unblockingTickLoop.get()) {
logger.info("Using non blocking tick loop")
logger.info(
"Initializing non blocking tick loop with rate of " +
"${AdvancedSpec.asyncLoopRate.get()} per second"
)
AsyncCommandHelper.startTickLoop(AdvancedSpec.asyncLoopRate.get())
} else {
logger.info("Using synchronous tick loop")
logger.info("Registering server post tick event")
TickEvent.SERVER_POST.register { AsyncCommandHelper.runTick() }
}
}

fun serverStoppedEvent(ignored: MinecraftServer) {
logger.info("Shutting down TPA++")
AsyncCommandHelper.stopTickLoop()
coroutineContext.cancel()
dataService.saveData()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,17 @@ object LimitationHelper {
) {
return 0.0
}
if (CommandLimitationsSpec.maxTpDistance.get() <= 0.0 ||
CommandLimitationsSpec.minTpDistance.get() <= 0.0
) {
return 0.0
}
val senderPos = LevelBoundVec3(sender.getDimension(), sender.pos)
val receiverPos = LevelBoundVec3(receiver.getDimension(), receiver.pos)
val distance = senderPos.distance(receiverPos)
if (distance > CommandLimitationsSpec.maxTpDistance.get()) {
if (CommandLimitationsSpec.maxTpDistance.get() > 0.0 &&
distance > CommandLimitationsSpec.maxTpDistance.get()
) {
return distance.absoluteValue
}
if (distance < CommandLimitationsSpec.minTpDistance.get()) {
if (CommandLimitationsSpec.minTpDistance.get() > 0.0 &&
distance < CommandLimitationsSpec.minTpDistance.get()
) {
return -distance.absoluteValue
}
return 0.0
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/lang/en_us.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ courseforgeBase = "CourseForge: %s"
courseforgeView = "View on CourseForge"
reloadStart = "Reloading language file..."
reloadFinish = "Language file reload complete"
configChange = "The config file is modified and is being overloaded"
languageChange = "The language file is modified and is being overloaded"

[error]
# A message sent when the sender player is not exist ( Only happened when command block run command )
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/lang/example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ courseforgeBase = "CourseForge: %s"
courseforgeView = "View on CourseForge"
reloadStart = "Reloading language file..."
reloadFinish = "Language file reload complete"
configChange = "The config file is modified and is being overloaded"
languageChange = "The language file is modified and is being overloaded"

[error]
# A message sent when the sender player is not exist ( Only happened when command block run command )
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/lang/zh_cn.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ courseforgeBase = "CourseForge: %s"
courseforgeView = "在 CourseForge 上查看"
reloadStart = "正在重载语言文件"
reloadFinish = "语言文件重载完成"
configChange = "配置文件被修改,正在重载"
languageChange = "语言文件被修改,正在重载"

[error]
# A message sent when the sender player is not exist ( Only happened when command block run command )
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/lang/zh_tw.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ courseforgeBase = "CourseForge: %s"
courseforgeView = "在 CourseForge 上查看"
reloadStart = "正在重載語言檔"
reloadFinish = "語言檔重載完成"
configChange = "配置檔被修改,正在重載"
languageChange = "語言檔被修改,正在重載"

[error]
# A message sent when the sender player is not exist ( Only happened when command block run command )
Expand Down
4 changes: 2 additions & 2 deletions src/main/resources/tpaplusplus.toml
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ tpaDistance = 0.0
# Modifying any of these commands can take effect without a restart.
# Whether to allow sending TPA requests if the player(s) are not in the same dimension
# Set this to false if you wish to disable this limitation
crossDimAllowed = true
crossDimAllowed = false

# How far away a player can be from another player in order to teleport
# This is measured in blocks.
Expand All @@ -200,4 +200,4 @@ minTpDistance = 0.0
# TPAPlusPlus will automatically account for the nether's coordinate system
# ( 1 block in the nether is 8 blocks in the overworld! )
# Set this to false if you wish to disable this limitation
ignoreDistanceCrossDim = true
ignoreDistanceCrossDim = false

0 comments on commit 921ef86

Please sign in to comment.