Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync develop w/ main #1780

Merged
merged 2 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
FROM ubuntu

# Install dependencies
RUN apt-get update
RUN apt-get install -y git \
openjdk-17-jdk \
openjdk-17-jre \
wget

# Create server directory
WORKDIR /testmcserver

# Build server
RUN wget -O BuildTools.jar https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar
RUN git config --global --unset core.autocrlf || :
RUN java -jar BuildTools.jar --rev 1.20.4
RUN echo "eula=true" > eula.txt
RUN mkdir plugins

# Build plugin
COPY . .
RUN ./gradlew build
RUN cp build/libs/*-all.jar plugins

# Run server
EXPOSE 25565
ENTRYPOINT java -jar spigot-1.20.4.jar
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ Alternatively, you can use the External API, the documentation for which can be
| [Deej](https://github.com/Mr-Deej) | Added checks to several commands |
| VoChiDanh | Refactored parts the PersistentData class in an attempt to resolve java compatibility issues |
| Kyrenic | Implemented contiguous claims config option |
| [Tems](https://github.com/Tems-py) | Fixed claim protection issues |
| MestreWilll | Contributed Brazilian Portueguese translation |

### Translators
| Name | Language(s) |
Expand All @@ -103,6 +105,7 @@ Alternatively, you can use the External API, the documentation for which can be
| JustGllenn | Dutch |
| TDL | Dutch |
| [n0virus](https://www.youtube.com/c/n0virus) | Dutch |
| MestreWilll | Brazilian Portuguese |

I created this plugin because I wanted to use the original [Factions](https://www.spigotmc.org/resources/factions.1900/) plugin for an upcoming server of mine, but it wasn't updated for the version of minecraft I was going to be using. I decided to take inspiration from the concept of factions - groups of players that can claim land - and create my own factions plugin.

Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ plugins {
}

group = "com.dansplugins"
version = "5.1.4"
version = "5.3.0"

def repoUsername = ""
def repoPassword = ""
Expand Down
7 changes: 7 additions & 0 deletions compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
services:
testmcserver:
build: .
image: mf-test-mc-server
container_name: mf-test-mc-server
ports:
- "25565:25565"
183 changes: 124 additions & 59 deletions src/main/kotlin/com/dansplugins/factionsystem/MedievalFactions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ import com.dansplugins.factionsystem.law.MfLawService
import com.dansplugins.factionsystem.legacy.MfLegacyDataMigrator
import com.dansplugins.factionsystem.listener.AreaEffectCloudApplyListener
import com.dansplugins.factionsystem.listener.AsyncPlayerChatListener
import com.dansplugins.factionsystem.listener.AsyncPlayerChatPreviewListener
import com.dansplugins.factionsystem.listener.AsyncPlayerPreLoginListener
import com.dansplugins.factionsystem.listener.BlockBreakListener
import com.dansplugins.factionsystem.listener.BlockExplodeListener
Expand All @@ -56,7 +55,9 @@ import com.dansplugins.factionsystem.listener.EntityDamageListener
import com.dansplugins.factionsystem.listener.EntityExplodeListener
import com.dansplugins.factionsystem.listener.InventoryMoveItemListener
import com.dansplugins.factionsystem.listener.LingeringPotionSplashListener
import com.dansplugins.factionsystem.listener.PlayerBucketListener
import com.dansplugins.factionsystem.listener.PlayerDeathListener
import com.dansplugins.factionsystem.listener.PlayerInteractEntityListener
import com.dansplugins.factionsystem.listener.PlayerInteractListener
import com.dansplugins.factionsystem.listener.PlayerJoinListener
import com.dansplugins.factionsystem.listener.PlayerMoveListener
Expand Down Expand Up @@ -95,7 +96,6 @@ import org.bstats.charts.SimplePie
import org.bukkit.NamespacedKey
import org.bukkit.boss.KeyedBossBar
import org.bukkit.entity.Player
import org.bukkit.event.player.AsyncPlayerChatEvent
import org.bukkit.plugin.java.JavaPlugin
import org.flywaydb.core.Flyway
import org.jooq.SQLDialect
Expand Down Expand Up @@ -141,12 +141,6 @@ class MedievalFactions : JavaPlugin() {
saveConfig()

language = Language(this, config.getString("language") ?: "en-US")
val metrics = Metrics(this, 8929)
metrics.addCustomChart(
SimplePie("language_used") {
config.getString("language")
}
)

Class.forName("org.h2.Driver")
val hikariConfig = HikariConfig()
Expand Down Expand Up @@ -189,6 +183,11 @@ class MedievalFactions : JavaPlugin() {

val gson = Gson()
val playerRepository: MfPlayerRepository = JooqMfPlayerRepository(this, dsl)
val dynmapService = if (server.pluginManager.getPlugin("dynmap") != null && config.getBoolean("dynmap.enableDynmapIntegration")) {
MfDynmapService(this)
} else {
null
}
val factionRepository: MfFactionRepository = JooqMfFactionRepository(this, dsl, gson)
val lawRepository: MfLawRepository = JooqMfLawRepository(dsl)
val factionRelationshipRepository: MfFactionRelationshipRepository = JooqMfFactionRelationshipRepository(dsl)
Expand All @@ -214,11 +213,6 @@ class MedievalFactions : JavaPlugin() {
val duelService = MfDuelService(this, duelRepository, duelInviteRepository)
val potionService = MfPotionService(this)
val teleportService = MfTeleportService(this)
val dynmapService = if (server.pluginManager.getPlugin("dynmap") != null) {
MfDynmapService(this)
} else {
null
}

services = Services(
playerService,
Expand All @@ -238,6 +232,64 @@ class MedievalFactions : JavaPlugin() {
)
setupRpkLockService()

val metrics = Metrics(this, 8929)
metrics.addCustomChart(
SimplePie("language_used") {
config.getString("language")
}
)
metrics.addCustomChart(
SimplePie("database_dialect") {
config.getString("database.dialect")
}
)
metrics.addCustomChart(
SimplePie("average_claims") {
factionService.factions
.map {
claimService.getClaims(it.id).size
}
.average().roundToInt().toString()
}
)
metrics.addCustomChart(
SimplePie("total_claims") {
factionService.factions.sumOf {
claimService.getClaims(it.id).size
}.toString()
}
)
metrics.addCustomChart(
SimplePie("initial_power") {
config.getDouble("players.initialPower").toString()
}
)
metrics.addCustomChart(
SimplePie("max_power") {
config.getDouble("players.maxPower").toString()
}
)
metrics.addCustomChart(
SimplePie("hours_to_reach_max_power") {
config.getDouble("players.hoursToReachMaxPower").toString()
}
)
metrics.addCustomChart(
SimplePie("hours_to_reach_min_power") {
config.getDouble("players.hoursToReachMinPower").toString()
}
)
metrics.addCustomChart(
SimplePie("limit_land") {
config.getBoolean("factions.limitLand").toString()
}
)
metrics.addCustomChart(
SimplePie("allow_neutrality") {
config.getBoolean("factions.allowNeutrality").toString()
}
)

if (config.getBoolean("migrateMf4")) {
migrator.migrate()
config.set("migrateMf4", null)
Expand All @@ -248,6 +300,10 @@ class MedievalFactions : JavaPlugin() {
MedievalFactionsPlaceholderExpansion(this).register()
}

if (config.getBoolean("dynmap.onlyRenderTerritoriesUponStartup")) {
logger.info(language["DynmapOnlyRenderTerritoriesUponStartupEnabled"])
}

if (dynmapService != null) {
factionService.factions.forEach { faction ->
dynmapService.scheduleUpdateClaims(faction)
Expand All @@ -269,17 +325,16 @@ class MedievalFactions : JavaPlugin() {
EntityExplodeListener(this),
InventoryMoveItemListener(this),
LingeringPotionSplashListener(this),
PlayerBucketListener(this),
PlayerDeathListener(this),
PlayerInteractListener(this),
PlayerJoinListener(this),
PlayerMoveListener(this),
PlayerQuitListener(this),
PlayerTeleportListener(this),
PotionSplashListener(this)
PotionSplashListener(this),
PlayerInteractEntityListener(this)
)
if (isChatPreviewEventAvailable()) {
registerListeners(AsyncPlayerChatPreviewListener(this))
}

getCommand("faction")?.setExecutor(MfFactionCommand(this))
getCommand("lock")?.setExecutor(MfLockCommand(this))
Expand All @@ -297,42 +352,12 @@ class MedievalFactions : JavaPlugin() {
server.scheduler.runTaskAsynchronously(
this,
Runnable {
val originalOnlinePlayerPower =
onlineMfPlayerIds.associateWith { playerService.getPlayer(it)?.power ?: initialPower }
playerService.updatePlayerPower(onlineMfPlayerIds).onFailure {
logger.log(SEVERE, "Failed to update player power: ${it.reason.message}", it.reason.cause)
return@Runnable
}
val newOnlinePlayerPower =
onlineMfPlayerIds.associateWith { playerService.getPlayer(it)?.power ?: initialPower }
server.scheduler.runTask(
this,
Runnable {
onlinePlayers.forEach { onlinePlayer ->
val playerId = MfPlayerId.fromBukkitPlayer(onlinePlayer)
val newPower = newOnlinePlayerPower[playerId] ?: initialPower
val originalPower = originalOnlinePlayerPower[playerId] ?: initialPower
val powerIncrease = floor(newPower).roundToInt() - floor(originalPower).roundToInt()
if (powerIncrease > 0) {
onlinePlayer.sendMessage("$GREEN${language["PowerIncreased", powerIncrease.toString()]}")
}
}
}
onPowerCycle(
onlineMfPlayerIds,
initialPower,
onlinePlayers,
disbandZeroPowerFactions
)
if (disbandZeroPowerFactions) {
factionService.factions.forEach { faction ->
if (faction.power <= 0.0) {
faction.sendMessage(
language["FactionDisbandedZeroPowerNotificationTitle"],
language["FactionDisbandedZeroPowerNotificationBody"]
)
factionService.delete(faction.id).onFailure {
logger.log(SEVERE, "Failed to delete faction: ${it.reason.message}", it.reason.cause)
return@Runnable
}
}
}
}
}
)
}, (15 - (LocalTime.now().minute % 15)) * 60 * 20L, 18000L)
Expand Down Expand Up @@ -442,6 +467,53 @@ class MedievalFactions : JavaPlugin() {
}
}

internal fun onPowerCycle(
onlineMfPlayerIds: List<MfPlayerId>,
initialPower: Double,
onlinePlayers: Collection<Player>,
disbandZeroPowerFactions: Boolean
) {
val playerService = services.playerService
val factionService = services.factionService

val originalOnlinePlayerPower =
onlineMfPlayerIds.associateWith { playerService.getPlayer(it)?.power ?: initialPower }
playerService.updatePlayerPower(onlineMfPlayerIds).onFailure {
logger.log(SEVERE, "Failed to update player power: ${it.reason.message}", it.reason.cause)
return
}
val newOnlinePlayerPower =
onlineMfPlayerIds.associateWith { playerService.getPlayer(it)?.power ?: initialPower }
server.scheduler.runTask(
this,
Runnable {
onlinePlayers.forEach { onlinePlayer ->
val playerId = MfPlayerId.fromBukkitPlayer(onlinePlayer)
val newPower = newOnlinePlayerPower[playerId] ?: initialPower
val originalPower = originalOnlinePlayerPower[playerId] ?: initialPower
val powerIncrease = floor(newPower).roundToInt() - floor(originalPower).roundToInt()
if (powerIncrease > 0) {
onlinePlayer.sendMessage("$GREEN${language["PowerIncreased", powerIncrease.toString()]}")
}
}
}
)
if (disbandZeroPowerFactions) {
factionService.factions.forEach { faction ->
if (faction.power <= 0.0) {
faction.sendMessage(
language["FactionDisbandedZeroPowerNotificationTitle"],
language["FactionDisbandedZeroPowerNotificationBody"]
)
factionService.delete(faction.id).onFailure {
logger.log(SEVERE, "Failed to delete faction: ${it.reason.message}", it.reason.cause)
return
}
}
}
}
}

private fun setupNotificationService(): MfNotificationService = when {
server.pluginManager.getPlugin("Mailboxes") != null -> MailboxesNotificationService(this)
server.pluginManager.getPlugin("rpk-notification-lib-bukkit") != null -> RpkNotificationService(this)
Expand All @@ -453,11 +525,4 @@ class MedievalFactions : JavaPlugin() {
MfRpkLockService(this)
}
}

private fun isChatPreviewEventAvailable() = try {
val previewClass = Class.forName("org.bukkit.event.player.AsyncPlayerChatPreviewEvent")
AsyncPlayerChatEvent::class.java.isAssignableFrom(previewClass)
} catch (exception: ClassNotFoundException) {
false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ class MfClaimService(private val plugin: MedievalFactions, private val repositor
if (claimFaction.flags[plugin.flags.liegeChainCanInteractWithLand] && lieges.contains(playerFaction.id)) return true
val allies = relationshipService.getRelationships(claim.factionId, MfFactionRelationshipType.ALLY).map { it.targetId }
if (claimFaction.flags[plugin.flags.alliesCanInteractWithLand] && allies.contains(playerFaction.id)) return true
val atWar = relationshipService.getRelationships(claim.factionId, MfFactionRelationshipType.AT_WAR).map { it.targetId }
if (plugin.config.getBoolean("pvp.enableWartimeBlockDestruction") && atWar.contains(playerFaction.id)) return true
return false
}

Expand Down Expand Up @@ -92,9 +94,16 @@ class MfClaimService(private val plugin: MedievalFactions, private val repositor
Runnable {
players.forEach { player ->
val title = "${ChatColor.of(faction.flags[plugin.flags.color])}${faction.name}"
val subtitle = "${ChatColor.of(faction.flags[plugin.flags.color])}${faction.description}"
if (plugin.config.getBoolean("factions.titleTerritoryIndicator")) {
player.resetTitle()
player.sendTitle(title, null, 10, 70, 20)
player.sendTitle(
title,
subtitle,
plugin.config.getInt("factions.titleTerritoryFadeInLength"),
plugin.config.getInt("factions.titleTerritoryDuration"),
plugin.config.getInt("factions.titleTerritoryFadeOutLength")
)
}
if (plugin.config.getBoolean("factions.actionBarTerritoryIndicator")) {
player.spigot().sendMessage(ACTION_BAR, *TextComponent.fromLegacyText(title))
Expand All @@ -107,7 +116,7 @@ class MfClaimService(private val plugin: MedievalFactions, private val repositor
}
)
val dynmapService = plugin.services.dynmapService
if (dynmapService != null) {
if (dynmapService != null && !plugin.config.getBoolean("dynmap.onlyRenderTerritoriesUponStartup")) {
plugin.server.scheduler.runTask(
plugin,
Runnable {
Expand Down Expand Up @@ -138,7 +147,13 @@ class MfClaimService(private val plugin: MedievalFactions, private val repositor
"${ChatColor.of(plugin.config.getString("wilderness.color"))}${plugin.language["Wilderness"]}"
if (plugin.config.getBoolean("factions.titleTerritoryIndicator")) {
player.resetTitle()
player.sendTitle(title, null, 10, 70, 20)
player.sendTitle(
title,
null,
plugin.config.getInt("factions.titleTerritoryFadeInLength"),
plugin.config.getInt("factions.titleTerritoryDuration"),
plugin.config.getInt("factions.titleTerritoryFadeOutLength")
)
}
if (plugin.config.getBoolean("factions.actionBarTerritoryIndicator")) {
player.spigot().sendMessage(ACTION_BAR, *TextComponent.fromLegacyText(title))
Expand All @@ -152,7 +167,7 @@ class MfClaimService(private val plugin: MedievalFactions, private val repositor
if (dynmapService != null) {
val factionService = plugin.services.factionService
val faction = factionService.getFaction(claim.factionId)
if (faction != null) {
if (faction != null && !plugin.config.getBoolean("dynmap.onlyRenderTerritoriesUponStartup")) {
plugin.server.scheduler.runTask(
plugin,
Runnable {
Expand Down
Loading