This commit is contained in:
disclearing 2020-02-02 22:02:20 +00:00
parent c32822dc39
commit 6ea4e9c056
47 changed files with 2088 additions and 0 deletions

17
hub/.idea/compiler.xml Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile default="true" name="Default" enabled="true" />
<profile name="Annotation profile for hub" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<processorPath useClasspath="false">
<entry name="$MAVEN_REPOSITORY$/org/projectlombok/lombok/1.16.16/lombok-1.16.16.jar" />
</processorPath>
<module name="hub" />
</profile>
</annotationProcessing>
</component>
</project>

4
hub/.idea/encodings.xml Normal file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with NO BOM" />
</project>

11
hub/.idea/hub.iml Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="AutoImportedSourceRoots">
<option name="directories">
<list>
<option value="src/main/kotlin" />
<option value="src/main/resources" />
</list>
</option>
</component>
</module>

14
hub/.idea/misc.xml Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8.0_171" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

180
hub/.idea/workspace.xml Normal file
View File

@ -0,0 +1,180 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="d4293081-4b97-4363-a700-275c352d661d" name="Default Changelist" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Kotlin Class" />
<option value="Class" />
<option value="Kotlin File" />
</list>
</option>
</component>
<component name="MavenImportPreferences">
<option name="importingSettings">
<MavenImportingSettings>
<option name="importAutomatically" value="true" />
</MavenImportingSettings>
</option>
</component>
<component name="ProjectId" id="1UfgW0mdpnS2hRBa8reEXk8GeJS" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showExcludedFiles" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
<property name="com.android.tools.idea.instantapp.provision.ProvisionBeforeRunTaskProvider.myTimeStamp" value="1567969864015" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/../practice" />
<property name="project.structure.last.edited" value="Libraries" />
<property name="project.structure.proportion" value="0.0" />
<property name="project.structure.side.proportion" value="0.2" />
<property name="settings.editor.selected.configurable" value="reference.projectsettings.compiler.annotationProcessors" />
</component>
<component name="RecentsManager">
<key name="MoveKotlinTopLevelDeclarationsDialog.RECENTS_KEY">
<recent name="cc.fyre.hub.cosmetic.categories.hidden" />
<recent name="cc.fyre.hub.cosmetic.cosmetics.emote" />
<recent name="cc.fyre.hub.cosmetic.categories.wearables" />
<recent name="cc.fyre.hub.cosmetic.categories.particles" />
<recent name="cc.fyre.hub.cosmetic.menu" />
</key>
<key name="CopyFile.RECENT_KEYS">
<recent name="C:\Users\joele\Desktop\My Projects\Kihar\hub\src\main\kotlin\cc\fyre\hub" />
</key>
<key name="MoveFile.RECENT_KEYS">
<recent name="C:\Users\skruf\Documents\Projects\Fyre\hub\src\main\kotlin\cc\fyre\hub" />
</key>
</component>
<component name="RunManager">
<configuration default="true" type="Applet">
<option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration default="true" type="Application" factoryName="Application">
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration default="true" type="JUnit" factoryName="JUnit">
<option name="TEST_OBJECT" value="class" />
<option name="WORKING_DIRECTORY" value="$MODULE_DIR$" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration name="hub [clean,install]" type="MavenRunConfiguration" factoryName="Maven" nameIsGenerated="true">
<MavenSettings>
<option name="myGeneralSettings" />
<option name="myRunnerSettings" />
<option name="myRunnerParameters">
<MavenRunnerParameters>
<option name="profiles">
<set />
</option>
<option name="goals">
<list>
<option value="clean" />
<option value="install" />
</list>
</option>
<option name="pomFileName" />
<option name="profilesMap">
<map />
</option>
<option name="resolveToWorkspace" value="false" />
<option name="workingDirPath" value="$PROJECT_DIR$" />
</MavenRunnerParameters>
</option>
</MavenSettings>
<method v="2" />
</configuration>
<configuration default="true" type="TestNG">
<option name="TEST_OBJECT" value="CLASS" />
<option name="WORKING_DIRECTORY" value="$MODULE_DIR$" />
<properties />
<listeners />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration default="true" type="#org.jetbrains.idea.devkit.run.PluginConfigurationType">
<module name="" />
<option name="VM_PARAMETERS" value="-Xmx512m -Xms256m -XX:MaxPermSize=250m -ea" />
<option name="PROGRAM_PARAMETERS" />
<predefined_log_file enabled="true" id="idea.log" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
<component name="ServiceViewManager">
<option name="viewStates">
<list>
<serviceView>
<treeState>
<expand />
<select />
</treeState>
</serviceView>
</list>
</option>
</component>
<component name="SvnConfiguration">
<configuration />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="d4293081-4b97-4363-a700-275c352d661d" name="Default Changelist" comment="" />
<created>1565448624260</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1565448624260</updated>
</task>
<servers />
</component>
<component name="WindowStateProjectService">
<state x="740" y="274" key="FileChooserDialogImpl" timestamp="1576321406927">
<screen x="0" y="0" width="1920" height="1040" />
</state>
<state x="740" y="274" key="FileChooserDialogImpl/0.0.1920.1040@0.0.1920.1040" timestamp="1576321406927" />
<state width="1877" height="280" key="GridCell.Tab.0.bottom" timestamp="1576338384230">
<screen x="0" y="0" width="1920" height="1040" />
</state>
<state width="1877" height="280" key="GridCell.Tab.0.bottom/0.0.1920.1040@0.0.1920.1040" timestamp="1576338384230" />
<state width="1877" height="280" key="GridCell.Tab.0.center" timestamp="1576338384230">
<screen x="0" y="0" width="1920" height="1040" />
</state>
<state width="1877" height="280" key="GridCell.Tab.0.center/0.0.1920.1040@0.0.1920.1040" timestamp="1576338384230" />
<state width="1877" height="280" key="GridCell.Tab.0.left" timestamp="1576338384230">
<screen x="0" y="0" width="1920" height="1040" />
</state>
<state width="1877" height="280" key="GridCell.Tab.0.left/0.0.1920.1040@0.0.1920.1040" timestamp="1576338384230" />
<state width="1877" height="280" key="GridCell.Tab.0.right" timestamp="1576338384230">
<screen x="0" y="0" width="1920" height="1040" />
</state>
<state width="1877" height="280" key="GridCell.Tab.0.right/0.0.1920.1040@0.0.1920.1040" timestamp="1576338384230" />
<state x="440" y="94" key="SettingsEditor" timestamp="1576322424278">
<screen x="0" y="0" width="1920" height="1040" />
</state>
<state x="440" y="94" key="SettingsEditor/0.0.1920.1040@0.0.1920.1040" timestamp="1576322424278" />
<state x="656" y="343" key="com.intellij.ide.util.TipDialog" timestamp="1576501427746">
<screen x="0" y="0" width="1920" height="1040" />
</state>
<state x="656" y="343" key="com.intellij.ide.util.TipDialog/0.0.1920.1040@0.0.1920.1040" timestamp="1576501427746" />
<state x="656" y="257" width="607" height="526" key="find.popup" timestamp="1578942490592">
<screen x="0" y="0" width="1920" height="1040" />
</state>
<state x="656" y="257" width="607" height="526" key="find.popup/0.0.1920.1040/1920.69.1920.1040@0.0.1920.1040" timestamp="1578942490592" />
</component>
</project>

13
hub/hub.iml Normal file
View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="AutoImportedSourceRoots">
<option name="directories">
<list>
<option value="C:\Users\skruf\Documents\Projects\Zuiy\hub/src/main/kotlin" />
<option value="C:\Users\skruf\Documents\Projects\Zuiy\hub/src/test/java" />
<option value="C:\Users\skruf\Documents\Projects\Zuiy\hub/src/test/kotlin" />
<option value="src/main/kotlin" />
</list>
</option>
</component>
</module>

135
hub/pom.xml Normal file
View File

@ -0,0 +1,135 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cc.fyre</groupId>
<artifactId>hub</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>1.3.41</kotlin.version>
</properties>
<build>
<sourceDirectory>src/main/kotlin</sourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<sourceDirs>
<source>src/main/kotlin</source>
<source>src/main/resources</source>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<configuration>
<jvmTarget>1.8</jvmTarget>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<executions>
<!-- Replacing default-compile as it is treated specially by maven -->
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<!-- Replacing default-testCompile as it is treated specially by maven -->
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
<execution>
<id>java-compile</id>
<phase>compile</phase>
<goals> <goal>compile</goal> </goals>
</execution>
<execution>
<id>java-test-compile</id>
<phase>test-compile</phase>
<goals> <goal>testCompile</goal> </goals>
</execution>
</executions>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.16</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals> <goal>single</goal> </goals>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Hylist Spigot -->
<dependency>
<groupId>net.hylist</groupId>
<artifactId>spigot-server</artifactId>
<version>1.7.10-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- Stark -->
<dependency>
<groupId>cc.fyre.stark</groupId>
<artifactId>bukkit</artifactId>
<version>1.3-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<version>1.3.41</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.10.2</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,88 @@
package cc.fyre.hub
import cc.fyre.hub.cosmetic.CosmeticListeners
import cc.fyre.hub.cosmetic.Cosmetics
import cc.fyre.hub.cosmetic.CosmeticsTickRunnable
import cc.fyre.hub.listener.HubListeners
import cc.fyre.hub.listener.PreventionListeners
import cc.fyre.hub.mongo.Mongo
import cc.fyre.hub.mongo.MongoCredentials
import cc.fyre.hub.scoreboard.HubScoreGetter
import org.bukkit.entity.ExperienceOrb
import org.bukkit.entity.Item
import org.bukkit.entity.LivingEntity
import org.bukkit.entity.Player
import org.bukkit.plugin.java.JavaPlugin
class Hub : JavaPlugin() {
lateinit var mongo: Mongo
lateinit var cosmetics: Cosmetics
override fun onEnable() {
instance = this
saveDefaultConfig()
loadDatabase()
loadEngineAdapters()
registerListeners()
cosmetics = Cosmetics()
server.scheduler.runTaskTimerAsynchronously(this, CosmeticsTickRunnable(), 1L, 1L)
cleanupWorld()
}
private fun loadDatabase() {
val builder = MongoCredentials.Builder()
.host(config.getString("Mongo.Host"))
.port(config.getInt("Mongo.Port"))
if (config.contains("Mongo.Authentication.Username")) {
builder.username(config.getString("Mongo.Authentication.Username"))
}
if (config.contains("Mongo.Authentication.Password")) {
builder.password(config.getString("Mongo.Authentication.Password"))
}
mongo = Mongo("hub")
mongo.load(builder.build())
}
private fun loadEngineAdapters() {
Stark.instance.tabEngine.layoutProvider = null
Stark.instance.scoreboardEngine.configuration = ScoreboardConfiguration(
TitleGetter.forStaticString("&6&lKihar &f&lNetwork"),
HubScoreGetter()
)
}
private fun registerListeners() {
val pluginManager = server.pluginManager
pluginManager.registerEvents(HubListeners(), this)
pluginManager.registerEvents(CosmeticListeners(), this)
pluginManager.registerEvents(PreventionListeners(), this)
}
private fun cleanupWorld() {
server.worlds[0].time = 4000
for (entity in server.worlds[0].entities) {
if (entity is Player) {
continue
}
if (entity is LivingEntity || entity is Item || entity is ExperienceOrb) {
entity.remove()
}
}
}
companion object {
lateinit var instance: Hub
}
}

View File

@ -0,0 +1,25 @@
package cc.fyre.hub
import cc.fyre.stark.util.ItemBuilder
import org.bukkit.ChatColor
import org.bukkit.Material
object HubItems {
val SELECTOR = ItemBuilder.of(Material.WATCH)
.name("${ChatColor.YELLOW}${ChatColor.BOLD}Server Selector")
.build()
val COSMETICS = ItemBuilder.of(Material.FEATHER)
.name("${ChatColor.LIGHT_PURPLE}${ChatColor.BOLD}Cosmetics")
.build()
val ENDER_BUTT = ItemBuilder.of(Material.ENDER_PEARL)
.name("${ChatColor.YELLOW}${ChatColor.BOLD}Enderbutt")
.build()
val EMOTE_BOX = ItemBuilder.of(Material.CHEST)
.name("${ChatColor.GREEN}${ChatColor.BOLD}Emote Box")
.build()
}

View File

@ -0,0 +1,33 @@
package cc.fyre.hub
import org.apache.commons.lang.StringUtils
import org.bukkit.ChatColor
object HubLang {
/**
* `&7&l» ` - Arrow used on the left side of item display names
* Named left arrow due to its usage on the left side of items, despite the fact
* the arrow is actually pointing to the right.
*/
val LEFT_ARROW = ChatColor.BLUE.toString() + "» "
val LEFT_ARROW_NAKED = "»"
/**
* ` &7&l«` - Arrow used on the right side of item display names
* Named right arrow due to its usage on the right side of items, despite the fact
* the arrow is actually pointing to the left.
*/
val RIGHT_ARROW = ChatColor.BLUE.toString() + " «"
val RIGHT_ARROW_NAKED = "«"
/**
* Solid line which almost entirely spans the (default) Minecraft
* chat box. 53 is chosen for no reason other than its width being
* almost equal to that of the chat box.
*/
val LONG_LINE = ChatColor.STRIKETHROUGH.toString() + StringUtils.repeat("-", 53)
}

View File

@ -0,0 +1,35 @@
package cc.fyre.hub.cosmetic
import org.bukkit.entity.Player
import org.bukkit.event.Listener
import org.bukkit.inventory.ItemStack
interface Cosmetic : Listener {
fun getIcon(): ItemStack
fun getName(): String
fun getDescription(): List<String>
fun getPermission(): String
fun hiddenIfNotPermitted(): Boolean {
return false
}
fun canBeToggled(): Boolean {
return true
}
fun onEnable(player: Player) {}
fun onDisable(player: Player) {}
fun onTick(player: Player) {}
fun getSerializedName(): String {
return getName().replace(" ", "_")
}
}

View File

@ -0,0 +1,20 @@
package cc.fyre.hub.cosmetic
import org.bukkit.entity.Player
import org.bukkit.material.MaterialData
interface CosmeticCategory {
fun getIcon(): MaterialData
fun getName(): String
fun getCosmetics(): List<Cosmetic>
fun getAccessableCosmetics(player: Player): List<Cosmetic> {
return getCosmetics()
.filter { cosmetic -> player.hasPermission(cosmetic.getPermission()) }
.toList()
}
}

View File

@ -0,0 +1,25 @@
package cc.fyre.hub.cosmetic
import cc.fyre.hub.Hub
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.player.PlayerJoinEvent
class CosmeticListeners : Listener {
@EventHandler
fun onPlayerJoinEvent(event: PlayerJoinEvent) {
Hub.instance.server.scheduler.runTaskAsynchronously(Hub.instance) {
val profile = Hub.instance.cosmetics.loadProfile(event.player.uniqueId)
Hub.instance.cosmetics.categories.forEach { category ->
category.getAccessableCosmetics(event.player).forEach { cosmetic ->
if (profile.isCosmeticEnabled(cosmetic) || !cosmetic.canBeToggled()) {
cosmetic.onEnable(event.player)
}
}
}
}
}
}

View File

@ -0,0 +1,108 @@
package cc.fyre.hub.cosmetic
import cc.fyre.hub.Hub
import cc.fyre.hub.cosmetic.categories.HiddenCosmeticCategory
import cc.fyre.hub.cosmetic.categories.ParticlesCosmeticCategory
import cc.fyre.hub.cosmetic.categories.WearablesCosmeticCategory
import cc.fyre.hub.cosmetic.menu.CosmeticCategoriesMenu
import com.mongodb.client.MongoCollection
import com.mongodb.client.model.ReplaceOptions
import org.bson.Document
import org.bukkit.ChatColor
import org.bukkit.entity.Player
import java.util.*
class Cosmetics {
private val collection: MongoCollection<Document> = Hub.instance.mongo.database.getCollection("profiles")
val categories: List<CosmeticCategory> = arrayListOf(
WearablesCosmeticCategory(),
ParticlesCosmeticCategory(),
HiddenCosmeticCategory()
)
val profiles: MutableMap<UUID, CosmeticsProfile> = hashMapOf()
init {
categories.forEach { category ->
category.getCosmetics().forEach { cosmetic ->
Hub.instance.server.pluginManager.registerEvents(cosmetic, Hub.instance)
}
}
}
fun openMenu(player: Player) {
if (player.hasPermission("hub.cosmetics")) {
CosmeticCategoriesMenu().openMenu(player)
} else {
player.sendMessage("${ChatColor.RED}You don't own any cosmetics. Purchase a rank on our store ${ChatColor.BOLD}store.kihar.net ${ChatColor.RED}to get access to cosmetics.")
}
}
fun isCosmeticEnabled(player: Player, cosmetic: Cosmetic): Boolean {
val profile = profiles[player.uniqueId]
return profile?.isCosmeticEnabled(cosmetic) ?: false
}
fun toggleCosmetic(player: Player, cosmetic: Cosmetic) {
val profile = profiles[player.uniqueId]
if (profile != null) {
profile.toggleCosmetic(cosmetic)
if (profile.isCosmeticEnabled(cosmetic)) {
cosmetic.onEnable(player)
} else {
cosmetic.onDisable(player)
}
// disable other cosmetics in the same category
for (category in Hub.instance.cosmetics.categories) {
if (!category.getCosmetics().contains(cosmetic)) {
continue
}
for (enabledCheck in category.getCosmetics()) {
if (enabledCheck != cosmetic && profile.isCosmeticEnabled(enabledCheck)) {
profile.toggleCosmetic(enabledCheck)
}
}
}
Hub.instance.server.scheduler.runTaskAsynchronously(Hub.instance) {
saveProfile(player.uniqueId, profile)
}
}
}
fun loadProfile(uuid: UUID): CosmeticsProfile {
val profile = CosmeticsProfile()
val document = collection.find(Document("uuid", uuid.toString())).first()
if (document != null) {
categories.forEach { category ->
category.getCosmetics().forEach { cosmetic ->
if (document.containsKey(cosmetic.getSerializedName())) {
profile.map[cosmetic.getSerializedName()] = document.getBoolean(cosmetic.getSerializedName())
}
}
}
}
profiles[uuid] = profile
return profile
}
private fun saveProfile(uuid: UUID, profile: CosmeticsProfile) {
val document = Document("uuid", uuid.toString())
profile.map.forEach { (t, u) ->
document[t] = u
}
collection.replaceOne(Document("uuid", uuid.toString()), document, ReplaceOptions().upsert(true))
}
}

View File

@ -0,0 +1,23 @@
package cc.fyre.hub.cosmetic
class CosmeticsProfile {
val map: MutableMap<String, Boolean> = hashMapOf()
fun isCosmeticEnabled(cosmetic: Cosmetic): Boolean {
if (map.containsKey(cosmetic.getSerializedName())) {
return map[cosmetic.getSerializedName()]!!
}
return false
}
fun toggleCosmetic(cosmetic: Cosmetic) {
if (map.containsKey(cosmetic.getSerializedName())) {
map[cosmetic.getSerializedName()] = !map[cosmetic.getSerializedName()]!!
} else {
map[cosmetic.getSerializedName()] = true
}
}
}

View File

@ -0,0 +1,23 @@
package cc.fyre.hub.cosmetic
import cc.fyre.hub.Hub
/**
* Every cosmetic should calculate their tick executions
* based on the tick interval of this runnable.
*/
class CosmeticsTickRunnable : Runnable {
override fun run() {
Hub.instance.server.onlinePlayers.forEach { player ->
Hub.instance.cosmetics.categories.forEach { category ->
category.getCosmetics().forEach { cosmetic ->
if (Hub.instance.cosmetics.isCosmeticEnabled(player, cosmetic)) {
cosmetic.onTick(player)
}
}
}
}
}
}

View File

@ -0,0 +1,27 @@
package cc.fyre.hub.cosmetic.categories
import cc.fyre.hub.cosmetic.Cosmetic
import cc.fyre.hub.cosmetic.CosmeticCategory
import cc.fyre.hub.cosmetic.categories.hidden.EmotesBoxCosmetic
import org.bukkit.Material
import org.bukkit.material.MaterialData
class HiddenCosmeticCategory : CosmeticCategory {
private val cosmetics = arrayListOf<Cosmetic>(
EmotesBoxCosmetic()
)
override fun getIcon(): MaterialData {
return MaterialData(Material.AIR)
}
override fun getName(): String {
return "Hidden"
}
override fun getCosmetics(): List<Cosmetic> {
return ArrayList(cosmetics)
}
}

View File

@ -0,0 +1,31 @@
package cc.fyre.hub.cosmetic.categories
import cc.fyre.hub.cosmetic.Cosmetic
import cc.fyre.hub.cosmetic.CosmeticCategory
import cc.fyre.hub.cosmetic.categories.particles.WaterRings
import cc.fyre.hub.cosmetic.categories.particles.GodModeCosmetic
import cc.fyre.hub.cosmetic.categories.particles.LavaRings
import org.bukkit.Material
import org.bukkit.material.MaterialData
class ParticlesCosmeticCategory : CosmeticCategory {
private val cosmetics = arrayListOf(
GodModeCosmetic(),
LavaRings(),
WaterRings()
)
override fun getIcon(): MaterialData {
return MaterialData(Material.RECORD_4)
}
override fun getName(): String {
return "Particles"
}
override fun getCosmetics(): List<Cosmetic> {
return ArrayList(cosmetics)
}
}

View File

@ -0,0 +1,36 @@
package cc.fyre.hub.cosmetic.categories
import cc.fyre.hub.cosmetic.Cosmetic
import cc.fyre.hub.cosmetic.CosmeticCategory
import cc.fyre.hub.cosmetic.categories.wearables.RankArmourCosmetic
import org.bukkit.Color
import org.bukkit.Material
import org.bukkit.material.MaterialData
class WearablesCosmeticCategory : CosmeticCategory {
private val cosmetics = arrayListOf(
RankArmourCosmetic("Owner", "rank.owner", true, Color.fromRGB(156, 10, 8)),
RankArmourCosmetic("Manager", "rank.manager", true, Color.fromRGB(196, 14, 47)),
RankArmourCosmetic("Admin", "rank.admin", true, Color.fromRGB(209, 35, 29)),
RankArmourCosmetic("Mod", "rank.moderator", true, Color.PURPLE),
RankArmourCosmetic("T-Mod", "rank.trial-mod", true, Color.fromRGB(15, 214, 214)),
RankArmourCosmetic("Kihar", "rank.kihar", false, Color.fromRGB(0,170,170)),
RankArmourCosmetic("Platinum", "rank.platinum", false, Color.fromRGB(252, 144, 3)),
RankArmourCosmetic("Premium", "rank.premium", false, Color.fromRGB(85,85,255)),
RankArmourCosmetic("Basic", "rank.basic", false, Color.fromRGB(23, 227, 77))
)
override fun getIcon(): MaterialData {
return MaterialData(Material.PUMPKIN)
}
override fun getName(): String {
return "Wearables"
}
override fun getCosmetics(): List<Cosmetic> {
return ArrayList(cosmetics)
}
}

View File

@ -0,0 +1,39 @@
package cc.fyre.hub.cosmetic.categories.hidden
import cc.fyre.hub.HubItems
import cc.fyre.hub.cosmetic.Cosmetic
import org.bukkit.Material
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
/**
* Gives a player the [cc.fyre.hub.HubItems.EMOTE_BOX] item,
* which opens a menu that allows players to display emotes.
*/
class EmotesBoxCosmetic : Cosmetic {
override fun getIcon(): ItemStack {
return ItemStack(Material.CHEST)
}
override fun getName(): String {
return "Emotes Box"
}
override fun getDescription(): List<String> {
return emptyList()
}
override fun getPermission(): String {
return "hub.cosmetics.emote-box"
}
override fun canBeToggled(): Boolean {
return false
}
override fun onEnable(player: Player) {
player.inventory.setItem(7, HubItems.EMOTE_BOX)
}
}

View File

@ -0,0 +1,16 @@
package cc.fyre.hub.cosmetic.categories.hidden.emote
import org.bukkit.Location
import org.bukkit.material.MaterialData
interface Emote {
fun getDisplayName(): String
fun getDescription(): List<String>
fun getIcon(): MaterialData
fun playEffect(location: Location)
}

View File

@ -0,0 +1,11 @@
package cc.fyre.hub.cosmetic.categories.hidden.emote
import cc.fyre.hub.cosmetic.categories.hidden.emote.impl.HeartEmote
object Emotes {
val emotes = arrayListOf<Emote>(
HeartEmote()
)
}

View File

@ -0,0 +1,29 @@
package cc.fyre.hub.cosmetic.categories.hidden.emote.impl
import cc.fyre.hub.cosmetic.categories.hidden.emote.Emote
import cc.fyre.hub.util.ParticleMeta
import cc.fyre.hub.util.ParticleUtil
import org.bukkit.Effect
import org.bukkit.Location
import org.bukkit.Material
import org.bukkit.material.MaterialData
class HeartEmote : Emote {
override fun getDisplayName(): String {
return "Heart"
}
override fun getDescription(): List<String> {
return arrayListOf("&6Perform a &c❤ &6emote.")
}
override fun getIcon(): MaterialData {
return MaterialData(Material.RED_ROSE)
}
override fun playEffect(location: Location) {
ParticleUtil.sendsParticleToAll(ParticleMeta(location, Effect.HEART))
}
}

View File

@ -0,0 +1,32 @@
package cc.fyre.hub.cosmetic.categories.particles
import cc.fyre.hub.cosmetic.Cosmetic
import org.bukkit.Material
import org.bukkit.inventory.ItemStack
/**
* Displays particles under the player's feet that makes
* it seem like the player is flying.
*/
class GodModeCosmetic : Cosmetic {
override fun getIcon(): ItemStack {
return ItemStack(Material.FEATHER)
}
override fun getName(): String {
return "God Mode"
}
override fun getDescription(): List<String> {
return arrayListOf(
"&6Appear as if you're floating",
"&6on a cloud. (Look down)"
)
}
override fun getPermission(): String {
return "hub.cosmetics.god-mode"
}
}

View File

@ -0,0 +1,65 @@
package cc.fyre.hub.cosmetic.categories.particles
import cc.fyre.hub.cosmetic.Cosmetic
import cc.fyre.hub.util.ParticleMeta
import cc.fyre.hub.util.ParticleUtil
import org.bukkit.Effect
import org.bukkit.Material
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.player.PlayerQuitEvent
import org.bukkit.inventory.ItemStack
import java.util.*
class LavaRings : Cosmetic {
private val ticks = hashMapOf<UUID, Int>()
override fun getIcon(): ItemStack {
return ItemStack(Material.RECORD_4)
}
override fun getName(): String {
return "Lava Rings"
}
override fun getDescription(): List<String> {
return arrayListOf(
"&6Surround yourself with",
"&6rings made of lava."
)
}
override fun getPermission(): String {
return "rank.platinum"
}
override fun onTick(player: Player) {
var ticks = this.ticks.putIfAbsent(player.uniqueId, 0) ?: 0
if (ticks >= 32) {
ticks = -1
}
this.ticks[player.uniqueId] = ticks + 1
val location = player.location.clone().add(0.1, 0.0, 0.1)
val angle = ticks * ((2 * Math.PI) / 32)
val cos = Math.cos(angle)
val sin = Math.sin(angle)
val bottomRingLocation = location.clone().add(0.8 * cos, 0.6, 0.8 * sin)
val topRingLocation = location.clone().add(0.8 * cos, 1.4, 0.8 * sin)
for (i in 0 until 5) {
ParticleUtil.sendsParticleToAll(ParticleMeta(bottomRingLocation, Effect.LAVADRIP))
ParticleUtil.sendsParticleToAll(ParticleMeta(topRingLocation, Effect.LAVADRIP))
}
}
@EventHandler
fun onPlayerQuitEvent(event: PlayerQuitEvent) {
ticks.remove(event.player.uniqueId)
}
}

View File

@ -0,0 +1,84 @@
package cc.fyre.hub.cosmetic.categories.particles
import cc.fyre.hub.cosmetic.Cosmetic
import cc.fyre.hub.util.ParticleMeta
import cc.fyre.hub.util.ParticleUtil
import org.bukkit.Effect
import org.bukkit.Material
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.player.PlayerQuitEvent
import org.bukkit.inventory.ItemStack
import java.util.*
class WaterRings : Cosmetic {
private val ticks = hashMapOf<UUID, Int>()
override fun getIcon(): ItemStack {
return ItemStack(Material.RECORD_12)
}
override fun getName(): String {
return "Water Rings"
}
override fun getDescription(): List<String> {
return arrayListOf(
"&6Surround yourself with",
"&6rings made of water."
)
}
override fun getPermission(): String {
return "rank.premium"
}
override fun onTick(player: Player) {
var ticks = this.ticks.putIfAbsent(player.uniqueId, 0) ?: 0
if (ticks >= 40) {
ticks = -1
}
this.ticks[player.uniqueId] = ticks + 1
val location = player.location.clone().add(0.1, 0.0, 0.1)
val angle = ticks * ((2 * Math.PI) / 40)
val cos = Math.cos(angle)
val sin = Math.sin(angle)
val particleMetaList = arrayListOf<ParticleMeta>()
particleMetaList.add(ParticleMeta(
location.clone().add(1.0 * cos, 0.5 + (1.0 * cos), 1.0 * sin),
Effect.WATERDRIP
))
particleMetaList.add(ParticleMeta(
location.clone().add(1.0 * cos, 1.0 + (1.0 * cos), 1.0 * sin),
Effect.WATERDRIP
))
particleMetaList.add(ParticleMeta(
location.clone().add(1.0 * cos, 1.5 + (1.0 * cos), 1.0 * sin),
Effect.WATERDRIP
))
ParticleUtil.sendsParticleToAll(*particleMetaList.toTypedArray())
// val xSlantedRingLocation = location.clone().add(1.1 * cos, 0.9 + (0.55 * cos), 1.1 * sin)
// val zSlantedRingLocation = location.clone().add(1.1 * cos, 0.9 + (1.1 * sin), 1.1 * sin)
// ParticleUtil.sendsParticleToAll(ParticleMeta(verticalRingLocation, Effect.COLOURED_DUST, 255.0F, 0.0F, 0.0F, 1.0F, 0))
// ParticleUtil.sendsParticleToAll(ParticleMeta(horizontalRingLocation, Effect.COLOURED_DUST, 255.0F, 0.0F, 0.0F, 1.0F, 0))
// ParticleUtil.sendsParticleToAll(ParticleMeta(xSlantedRingLocation, Effect.COLOURED_DUST, 255.0F, 0.0F, 0.0F, 1.0F, 0))
// ParticleUtil.sendsParticleToAll(ParticleMeta(zSlantedRingLocation, Effect.COLOURED_DUST, 255.0F, 0.0F, 0.0F, 1.0F, 0))
}
@EventHandler
fun onPlayerQuitEvent(event: PlayerQuitEvent) {
ticks.remove(event.player.uniqueId)
}
}

View File

@ -0,0 +1 @@
package cc.fyre.hub.cosmetic.categories.wearables import cc.fyre.hub.cosmetic.Cosmetic import org.bukkit.Color import org.bukkit.Material import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack import org.bukkit.inventory.meta.LeatherArmorMeta /** * Equips the player with colored armour based on their rank. */ class RankArmourCosmetic(private val rankName: String, private val permission: String, private val hidden: Boolean, val color: Color) : Cosmetic { override fun getIcon(): ItemStack { val itemStack = ItemStack(Material.LEATHER_HELMET) val itemMeta = itemStack.itemMeta as LeatherArmorMeta itemMeta.color = color itemStack.itemMeta = itemMeta return itemStack } override fun getName(): String { return "$rankName Rank Armour" } override fun getDescription(): List<String> { return arrayListOf( "&6Get a set of armour matching", "&6your rank's color." ) } override fun getPermission(): String { return permission } override fun hiddenIfNotPermitted(): Boolean { return hidden } override fun onEnable(player: Player) { val armour = arrayOf( ItemStack(Material.LEATHER_HELMET), ItemStack(Material.LEATHER_CHESTPLATE), ItemStack(Material.LEATHER_LEGGINGS), ItemStack(Material.LEATHER_BOOTS) ) for (armourPiece in armour) { val meta = armourPiece.itemMeta as LeatherArmorMeta meta.color = color armourPiece.itemMeta = meta } player.inventory.armorContents = armour player.updateInventory() player.closeInventory() } override fun onDisable(player: Player) { player.inventory.armorContents = arrayOfNulls(4) player.updateInventory() player.closeInventory() } }

View File

@ -0,0 +1,73 @@
package cc.fyre.hub.cosmetic.menu
import cc.fyre.hub.Hub
import cc.fyre.hub.cosmetic.Cosmetic
import cc.fyre.hub.cosmetic.categories.wearables.RankArmourCosmetic
import cc.fyre.stark.engine.menu.Button
import org.bukkit.ChatColor
import org.bukkit.Material
import org.bukkit.entity.Player
import org.bukkit.event.inventory.ClickType
import org.bukkit.inventory.meta.ItemMeta
import org.bukkit.inventory.meta.LeatherArmorMeta
class CosmeticButton(private val cosmetic: Cosmetic) : Button() {
override fun getMaterial(player: Player): Material? {
return cosmetic.getIcon().type
}
override fun getDamageValue(player: Player): Byte {
return cosmetic.getIcon().data.data
}
override fun applyMetadata(player: Player, itemMeta: ItemMeta): ItemMeta? {
if (cosmetic is RankArmourCosmetic) {
(itemMeta as LeatherArmorMeta).color = cosmetic.color
}
return itemMeta
}
override fun getName(player: Player): String? {
return if (player.hasPermission(cosmetic.getPermission())) {
val color = if (Hub.instance.cosmetics.isCosmeticEnabled(player, cosmetic)) {
ChatColor.GREEN.toString()
} else {
ChatColor.RED.toString()
}
color + ChatColor.BOLD + cosmetic.getName()
} else {
"${ChatColor.RED}${ChatColor.BOLD}" + cosmetic.getName()
}
}
override fun getDescription(player: Player): List<String>? {
val description = arrayListOf<String>()
description.add("")
if (player.hasPermission(cosmetic.getPermission())) {
for (line in cosmetic.getDescription()) {
description.add(line)
}
description.add("")
description.add("${ChatColor.YELLOW}Click to toggle this cosmetic.")
} else {
description.add("${ChatColor.RED}${ChatColor.BOLD}COSMETIC LOCKED")
description.add("${ChatColor.RED}You don't have access to")
description.add("${ChatColor.RED}this cosmetic. To get access")
description.add("${ChatColor.RED}purchase a rank on our store.")
}
return description
}
override fun clicked(player: Player, slot: Int, clickType: ClickType) {
if (player.hasPermission(cosmetic.getPermission())) {
Hub.instance.cosmetics.toggleCosmetic(player, cosmetic)
}
}
}

View File

@ -0,0 +1,31 @@
package cc.fyre.hub.cosmetic.menu
import cc.fyre.hub.Hub
import cc.fyre.stark.engine.menu.Button
import cc.fyre.stark.engine.menu.Menu
import org.bukkit.Material
import org.bukkit.entity.Player
class CosmeticCategoriesMenu : Menu() {
init {
placeholder = true
updateAfterClick = true
}
override fun getTitle(player: Player): String {
return "Cosmetics Menu"
}
override fun getButtons(player: Player): Map<Int, Button> {
val buttons = hashMapOf<Int, Button>()
buttons[11] = CosmeticCategoryButton(Hub.instance.cosmetics.categories[0])
buttons[15] = CosmeticCategoryButton(Hub.instance.cosmetics.categories[1])
buttons[26] = Button.placeholder(Material.STAINED_GLASS_PANE, 15.toByte(), " ")
return buttons
}
}

View File

@ -0,0 +1,48 @@
package cc.fyre.hub.cosmetic.menu
import cc.fyre.hub.cosmetic.CosmeticCategory
import cc.fyre.stark.engine.menu.Button
import org.bukkit.ChatColor
import org.bukkit.Material
import org.bukkit.entity.Player
import org.bukkit.event.inventory.ClickType
class CosmeticCategoryButton(private val category: CosmeticCategory) : Button() {
override fun getMaterial(player: Player): Material? {
return category.getIcon().itemType
}
override fun getDamageValue(player: Player): Byte {
return category.getIcon().data
}
override fun getName(player: Player): String? {
return "${ChatColor.YELLOW}${ChatColor.BOLD}${category.getName()}"
}
override fun getDescription(player: Player): List<String>? {
val description = arrayListOf<String>()
description.add("")
val cosmetics = category.getCosmetics()
cosmetics.forEach {
if (player.hasPermission(it.getPermission())) {
description.add("${ChatColor.GRAY}* ${ChatColor.GREEN}${it.getName()}")
} else {
description.add("${ChatColor.GRAY}* ${ChatColor.RED}${it.getName()}")
}
}
description.add("")
description.add("${ChatColor.YELLOW}Click to browse this category.")
return description
}
override fun clicked(player: Player, slot: Int, clickType: ClickType) {
CosmeticsMenu(category).openMenu(player)
}
}

View File

@ -0,0 +1,59 @@
package cc.fyre.hub.cosmetic.menu
import cc.fyre.hub.cosmetic.CosmeticCategory
import cc.fyre.stark.engine.menu.Button
import cc.fyre.stark.engine.menu.Menu
import org.bukkit.Material
import org.bukkit.entity.Player
class CosmeticsMenu(private val category: CosmeticCategory) : Menu() {
init {
placeholder = true
updateAfterClick = true
}
override fun getTitle(player: Player): String {
return "Cosmetics : ${category.getName()}"
}
override fun getButtons(player: Player): Map<Int, Button> {
val buttons = hashMapOf<Int, Button>()
var slotIndex = 0
category.getCosmetics().forEach { cosmetic ->
if (cosmetic.canBeToggled()) {
buttons[slots[slotIndex++]] = CosmeticButton(cosmetic)
}
}
slotIndex--
// fill remaining row slots
for (i in 1 .. 8) {
if (!slots.contains(slots[slotIndex] + i)) {
break
}
buttons[slots[slotIndex] + i] = Button.placeholder(Material.AIR)
}
// make bottom glass border row
buttons[getSlot(9, Math.ceil((slotIndex + 2) / 9.0).toInt())] = Button.placeholder(Material.STAINED_GLASS_PANE, 15, " ")
return buttons
}
companion object {
private val slots = arrayListOf<Int>()
init {
slots.addAll(10 .. 16)
slots.addAll(19 .. 25)
slots.addAll(28 .. 34)
slots.addAll(37 .. 43)
}
}
}

View File

@ -0,0 +1,25 @@
package cc.fyre.hub.cosmetic.menu
import cc.fyre.hub.cosmetic.categories.hidden.emote.Emotes
import cc.fyre.stark.engine.menu.Button
import cc.fyre.stark.engine.menu.Menu
import org.bukkit.entity.Player
class EmoteBoxMenu : Menu() {
override fun getTitle(player: Player): String {
return "Emote Box"
}
override fun getButtons(player: Player): Map<Int, Button> {
val buttons = hashMapOf<Int, Button>()
var i = 0
for (emote in Emotes.emotes) {
buttons[i++] = EmoteButton(emote)
}
return buttons
}
}

View File

@ -0,0 +1,43 @@
package cc.fyre.hub.cosmetic.menu
import cc.fyre.hub.cosmetic.categories.hidden.emote.Emote
import cc.fyre.stark.engine.menu.Button
import org.bukkit.ChatColor
import org.bukkit.Material
import org.bukkit.entity.Player
import org.bukkit.event.inventory.ClickType
class EmoteButton(private val emote: Emote) : Button() {
override fun getMaterial(player: Player): Material? {
return emote.getIcon().itemType
}
override fun getDamageValue(player: Player): Byte {
return emote.getIcon().data
}
override fun getName(player: Player): String? {
return "${ChatColor.YELLOW}${emote.getDisplayName()}"
}
override fun getDescription(player: Player): List<String>? {
val description = arrayListOf<String>()
description.add("")
for (line in emote.getDescription()) {
description.add(line)
}
description.add("")
description.add("${ChatColor.YELLOW}Click to perform this emote.")
return description
}
override fun clicked(player: Player, slot: Int, clickType: ClickType) {
player.closeInventory()
emote.playEffect(player.eyeLocation.clone().add(player.location.direction))
}
}

View File

@ -0,0 +1,136 @@
package cc.fyre.hub.listener
import cc.fyre.hub.Hub
import cc.fyre.hub.HubItems
import cc.fyre.hub.cosmetic.menu.EmoteBoxMenu
import cc.fyre.hub.menu.ServerSelectorMenu
import mkremins.fanciful.FancyMessage
import org.bukkit.ChatColor
import org.bukkit.Sound
import org.bukkit.entity.EnderPearl
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.block.Action
import org.bukkit.event.entity.ProjectileLaunchEvent
import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.event.player.PlayerJoinEvent
import org.spigotmc.event.entity.EntityDismountEvent
class HubListeners : Listener {
companion object {
private val PREFIX = FancyMessage("* ").color(ChatColor.GRAY).style(ChatColor.BOLD)
}
@EventHandler
fun onPlayerJoinEvent(event: PlayerJoinEvent) {
val player = event.player
PREFIX.clone()
.then("Welcome to the ").color(ChatColor.YELLOW).style(ChatColor.BOLD)
.then("Kihar Network").color(ChatColor.GOLD).style(ChatColor.BOLD).then("!").color(ChatColor.YELLOW).style(ChatColor.BOLD)
.send(player)
PREFIX.clone()
.then("Website: ").color(ChatColor.YELLOW).style(ChatColor.BOLD)
.then("https://www.kihar.net").color(ChatColor.LIGHT_PURPLE).style(ChatColor.BOLD).link("https://www.kihar.net")
.send(player)
PREFIX.clone()
.then("Discord: ").color(ChatColor.YELLOW).style(ChatColor.BOLD)
.then("https://discord.gg/4V7phmq").color(ChatColor.LIGHT_PURPLE).style(ChatColor.BOLD).link("https://discord.gg/4V7phmq")
.send(player)
PREFIX.clone()
.then("Teamspeak: ").color(ChatColor.YELLOW).style(ChatColor.BOLD)
.then("ts.kihar.net").color(ChatColor.LIGHT_PURPLE).style(ChatColor.BOLD).link("ts.kihar.net")
.send(player)
PREFIX.clone()
.then("Twitter: ").color(ChatColor.YELLOW).style(ChatColor.BOLD)
.then("@KiharMC").color(ChatColor.LIGHT_PURPLE).style(ChatColor.BOLD).link("https://www.twitter.com/@KiharMC")
.send(player)
player.inventory.armorContents = arrayOfNulls(4)
player.inventory.contents = arrayOfNulls(36)
player.inventory.heldItemSlot = 0
player.health = 20.0
player.foodLevel = 20
player.exp = 0.0F
player.inventory.setItem(0, HubItems.SELECTOR)
player.inventory.setItem(4, HubItems.COSMETICS)
player.inventory.setItem(8, HubItems.ENDER_BUTT)
player.updateInventory()
player.teleport(Hub.instance.server.worlds[0].spawnLocation)
}
@EventHandler
fun onPlayerInteractEvent(event: PlayerInteractEvent) {
if (event.action == Action.RIGHT_CLICK_AIR || event.action == Action.RIGHT_CLICK_BLOCK) {
val itemInHand = event.player.itemInHand
if (itemInHand != null) {
when (itemInHand) {
HubItems.SELECTOR -> {
ServerSelectorMenu().openMenu(event.player)
}
HubItems.COSMETICS -> {
Hub.instance.cosmetics.openMenu(event.player)
}
HubItems.ENDER_BUTT -> {
if (event.action == Action.RIGHT_CLICK_BLOCK) {
event.isCancelled = true
}
}
HubItems.EMOTE_BOX -> {
EmoteBoxMenu().openMenu(event.player)
}
}
}
}
}
@EventHandler
fun onProjectileLaunchEvent(event: ProjectileLaunchEvent) {
if (event.entity is EnderPearl && event.entity.shooter is Player) {
val player = event.entity.shooter as Player
if (player.vehicle != null) {
val vehicle = player.vehicle
player.eject()
vehicle.remove()
}
event.entity.velocity = player.location.direction.normalize().multiply(1.5F)
event.entity.passenger = player
player.world.playSound(player.location, Sound.ENDERMAN_TELEPORT, 1.0F, 1.0F)
// wait 1 tick before giving item back
Hub.instance.server.scheduler.runTaskLater(Hub.instance, {
player.inventory.setItem(8, HubItems.ENDER_BUTT)
player.updateInventory()
}, 1L)
}
}
@EventHandler
fun onEntityDismountEvent(event: EntityDismountEvent) {
if (event.entity is Player && event.entity.vehicle is EnderPearl) {
val vehicle = event.entity.vehicle
event.entity.eject()
// wait 1 tick before removing entity
Hub.instance.server.scheduler.runTaskLater(Hub.instance, {
if (!vehicle.isDead) {
vehicle.remove()
}
}, 1L)
}
}
}

View File

@ -0,0 +1,188 @@
package cc.fyre.hub.listener
import org.bukkit.GameMode
import org.bukkit.Material
import org.bukkit.entity.EntityType
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.block.*
import org.bukkit.event.entity.*
import org.bukkit.event.inventory.CraftItemEvent
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.inventory.PrepareItemCraftEvent
import org.bukkit.event.player.*
import org.bukkit.event.weather.ThunderChangeEvent
import org.bukkit.event.weather.WeatherChangeEvent
class PreventionListeners : Listener {
@EventHandler
fun onPlayerJoin(event: PlayerJoinEvent) {
event.joinMessage = null
}
@EventHandler
fun onPlayerKick(event: PlayerKickEvent) {
event.leaveMessage = null
}
@EventHandler
fun onPlayerQuit(event: PlayerQuitEvent) {
event.quitMessage = null
}
@EventHandler
fun onProjectileHit(event: ProjectileHitEvent) {
if (event.entityType == EntityType.ARROW) {
event.entity.remove()
}
}
@EventHandler
fun onEntityDamageEvent(event: EntityDamageEvent) {
if (event.entity is Player) {
event.isCancelled = true
if (event.cause == EntityDamageEvent.DamageCause.VOID || event.entity.location.y < 0) {
event.entity.teleport(event.entity.world.spawnLocation)
}
}
}
@EventHandler
fun onFoodLevelChangeEvent(event: FoodLevelChangeEvent) {
event.isCancelled = true
}
@EventHandler
fun onPlayerExpChangedEvent(event: PlayerExpChangeEvent) {
event.player.exp = 0.0F
}
@EventHandler
fun onThunderChange(event: ThunderChangeEvent) {
event.isCancelled = true
}
@EventHandler
fun onWeatherChange(event: WeatherChangeEvent) {
event.isCancelled = true
}
@EventHandler
fun onCreatureSpawn(event: CreatureSpawnEvent) {
if (!(event.spawnReason == CreatureSpawnEvent.SpawnReason.SPAWNER_EGG ||
event.spawnReason == CreatureSpawnEvent.SpawnReason.CUSTOM)) {
event.isCancelled = true
}
}
@EventHandler
fun onPlayerDeath(event: PlayerDeathEvent) {
event.deathMessage = null
event.droppedExp = 0
}
@EventHandler
fun onBlockSpread(event: BlockSpreadEvent) {
event.isCancelled = true
}
@EventHandler
fun onLeavesDecay(event: LeavesDecayEvent) {
event.isCancelled = true
}
@EventHandler
fun onBlockFade(event: BlockFadeEvent) {
event.isCancelled = true
}
@EventHandler
fun onBlockForm(event: BlockFormEvent) {
event.isCancelled = true
}
@EventHandler
fun onPlayerPortal(event: PlayerPortalEvent) {
event.isCancelled = true
}
@EventHandler
fun onBlockBreakEvent(event: BlockBreakEvent) {
if (!canPerformAction(event.player)) {
event.isCancelled = true
}
}
@EventHandler
fun onBlockPlaceEvent(event: BlockPlaceEvent) {
if (!canPerformAction(event.player)) {
event.isCancelled = true
}
}
@EventHandler
fun onPlayerBucketFillEvent(event: PlayerBucketFillEvent) {
if (!canPerformAction(event.player)) {
event.isCancelled = true
}
}
@EventHandler
fun onPlayerBucketEmptyEvent(event: PlayerBucketEmptyEvent) {
if (!canPerformAction(event.player)) {
event.isCancelled = true
}
}
@EventHandler
fun onPlayerDropItemEvent(event: PlayerDropItemEvent) {
if (!canPerformAction(event.player)) {
event.isCancelled = true
}
}
@EventHandler
fun onPlayerPickupItemEvent(event: PlayerPickupItemEvent) {
if (!canPerformAction(event.player)) {
event.isCancelled = true
}
}
@EventHandler
fun onInventoryClickEvent(event: InventoryClickEvent) {
if (!canPerformAction(event.whoClicked as Player)) {
if (event.clickedInventory == event.whoClicked.inventory) {
event.isCancelled = true
}
}
}
@EventHandler
fun onPlayerInteract(event: PlayerInteractEvent) {
if (event.action == Action.PHYSICAL) {
event.isCancelled = true
}
}
@EventHandler
fun onPrepareCraft(event: PrepareItemCraftEvent) {
event.inventory.result = null
}
@EventHandler
fun onCraft(event: CraftItemEvent) {
event.isCancelled = true
}
private fun canPerformAction(player: Player): Boolean {
if (!player.isOp || !player.hasMetadata("Build") || player.gameMode != GameMode.CREATIVE) {
return false
}
return true
}
}

View File

@ -0,0 +1,67 @@
package cc.fyre.hub.menu
import cc.fyre.stark.Stark
import cc.fyre.stark.engine.menu.Button
import cc.fyre.stark.engine.menu.Menu
import org.bukkit.Material
import org.bukkit.entity.Player
class ServerSelectorMenu : Menu() {
init {
autoUpdate = true
updateAfterClick = true
}
override fun getTitle(player: Player): String {
return "Select a server to join"
}
override fun getButtons(player: Player): Map<Int, Button> {
val buttons = hashMapOf<Int, Button>()
buttons[11] = ServerTypeButton(
Stark.instance.core.servers.getServerByName("Practice-NA"),
ServerTypeMeta(
Material.DIAMOND_SWORD,
"Practice-NA",
arrayListOf(
"&7* &61v1s, 2v2s, Team Fights!",
"&7* &6Leaderboards, Clan Wars!",
"&7* &6Hosted Events, Party Events!"
)
)
)
buttons[13] = ServerTypeButton(
Stark.instance.core.servers.getServerByName("KitMap"),
ServerTypeMeta(
Material.ENDER_PEARL,
"KitMap",
arrayListOf(
"&7* &65 Minute KOTHs!",
"&7* &624/7 PvP, Killstreaks!",
"&7* &6Bases, Obstacles!"
)
)
)
buttons[15] = ServerTypeButton(
Stark.instance.core.servers.getServerByName("MineSG"),
ServerTypeMeta(
Material.CHEST,
"MineSG",
arrayListOf(
"&7* &6Solo and Duo Queues!",
"&7* &650 Players Per Game!",
"&7* &6Last Man Standing Wins!"
)
)
)
buttons[26] = Button.placeholder(Material.AIR)
return buttons
}
}

View File

@ -0,0 +1,88 @@
package cc.fyre.hub.menu
import cc.fyre.hub.HubLang
import cc.fyre.stark.core.server.Server
import cc.fyre.stark.engine.menu.Button
import cc.fyre.stark.util.BungeeUtil
import org.bukkit.ChatColor
import org.bukkit.Material
import org.bukkit.entity.Player
import org.bukkit.event.inventory.ClickType
import java.util.*
class ServerTypeButton(private val optionalServer: Optional<Server>, private val meta: ServerTypeMeta) : Button() {
override fun getMaterial(player: Player): Material? {
return if (optionalServer.isPresent) {
val server = optionalServer.get()
if (server.isOnline()) {
meta.material
} else {
Material.REDSTONE_BLOCK
}
} else {
Material.REDSTONE_BLOCK
}
}
override fun getName(player: Player): String? {
return if (optionalServer.isPresent) {
val server = optionalServer.get()
if (server.isOnline()) {
"${ChatColor.GREEN}${ChatColor.BOLD}${server.serverName}"
} else {
"${ChatColor.RED}${ChatColor.BOLD}${server.serverName}"
}
} else {
"${ChatColor.RED}${ChatColor.BOLD}${meta.fallbackName}"
}
}
override fun getDescription(player: Player): List<String>? {
val description = arrayListOf<String>()
description.add("")
for (line in meta.description) {
description.add(line)
}
description.add("")
if (optionalServer.isPresent) {
val server = optionalServer.get()
if (server.isOnline()) {
description.add(0, "${ChatColor.YELLOW}Players: ${ChatColor.WHITE}(${server.playerCount}/${server.maxSlots})")
if (server.whitelisted) {
description.add("${ChatColor.YELLOW}This server is whitelisted.")
} else {
description.add("${ChatColor.GRAY}${HubLang.LEFT_ARROW_NAKED} ${ChatColor.YELLOW}Click to join the queue! ${ChatColor.GRAY}${HubLang.RIGHT_ARROW_NAKED}")
}
} else {
description.add("${ChatColor.YELLOW}This server is offline.")
}
} else {
description.add("${ChatColor.YELLOW}This server is offline.")
}
return description
}
override fun clicked(player: Player, slot: Int, clickType: ClickType) {
if (!optionalServer.isPresent || !optionalServer.get().isOnline()) {
player.sendMessage("${ChatColor.YELLOW}That server is offline.")
} else {
val server = optionalServer.get()
if (server.whitelisted) {
player.sendMessage("${ChatColor.YELLOW}That server is whitelisted.")
} else {
BungeeUtil.sendToServer(player, server.serverName)
}
}
}
}

View File

@ -0,0 +1,5 @@
package cc.fyre.hub.menu
import org.bukkit.Material
data class ServerTypeMeta(val material: Material, val fallbackName: String, val description: List<String>)

View File

@ -0,0 +1,31 @@
package cc.fyre.hub.mongo
import com.mongodb.MongoClient
import com.mongodb.MongoClientOptions
import com.mongodb.MongoCredential
import com.mongodb.ServerAddress
import java.io.Closeable
class Mongo(private val dbName: String) : Closeable {
lateinit var client: MongoClient
lateinit var database: com.mongodb.client.MongoDatabase
fun load(credentials: MongoCredentials) {
client = if (credentials.shouldAuthenticate()) {
val serverAddress = ServerAddress(credentials.host, credentials.port)
val credential = MongoCredential.createCredential(credentials.username!!, "admin", credentials.password!!.toCharArray())
MongoClient(serverAddress, credential, MongoClientOptions.builder().build())
} else {
MongoClient(credentials.host, credentials.port)
}
database = client.getDatabase(dbName)
}
override fun close() {
client.close()
}
}

View File

@ -0,0 +1,41 @@
package cc.fyre.hub.mongo
data class MongoCredentials(
var host: String = "localhost",
var port: Int = 27017,
var username: String? = null,
var password: String? = null) {
fun shouldAuthenticate(): Boolean {
return username != null && (password != null && password!!.isNotEmpty() && password!!.isNotBlank())
}
class Builder {
val credentials: MongoCredentials = MongoCredentials()
fun host(host: String): Builder {
credentials.host = host
return this
}
fun port(port: Int): Builder {
credentials.port = port
return this
}
fun username(username: String): Builder {
credentials.username = username
return this
}
fun password(password: String): Builder {
credentials.password = password
return this
}
fun build(): MongoCredentials {
return credentials
}
}
}

View File

@ -0,0 +1,32 @@
package cc.fyre.hub.scoreboard
import cc.fyre.stark.Stark
import cc.fyre.stark.engine.scoreboard.ScoreGetter
import org.bukkit.ChatColor
import org.bukkit.entity.Player
import java.util.*
class HubScoreGetter : ScoreGetter {
override fun getScores(scores: LinkedList<String>, player: Player) {
val profile = Stark.instance.core.getProfileHandler().getByUUID(player.uniqueId)!!
val rank = profile.getRank()
scores.add("&a&7&m--------------------")
scores.add("&fYour Rank:")
if (rank.default) {
scores.add("${ChatColor.GREEN}${rank.displayName}")
} else {
scores.add("${rank.gameColor}${rank.displayName}")
}
scores.add("")
scores.add("&fOnline:")
scores.add("&6${Stark.instance.core.servers.globalCount}&r")
scores.add("")
scores.add("&6kihar.net")
scores.add("&b&7&m--------------------")
}
}

View File

@ -0,0 +1,28 @@
package cc.fyre.hub.util
import org.bukkit.Effect
import org.bukkit.Location
data class ParticleMeta(val location: Location, val effect: Effect) {
constructor(location: Location,
effect: Effect,
offsetX: Float,
offsetY: Float,
offsetZ: Float,
speed: Float,
amount: Int) : this(location, effect) {
this.offsetX = offsetX
this.offsetY = offsetY
this.offsetZ = offsetZ
this.speed = speed
this.amount = amount
}
var offsetX = 0.0F
var offsetY = 0.0F
var offsetZ = 0.0F
var speed = 1.0F
var amount = 1
}

View File

@ -0,0 +1,40 @@
package cc.fyre.hub.util
import net.minecraft.server.v1_7_R4.PacketPlayOutWorldParticles
import org.bukkit.Location
import org.bukkit.craftbukkit.v1_7_R4.CraftWorld
/**
* A class to simplify sending particles to players.
*
* Also created to fix the issue of bukkit sometimes
* not sending the particle or sending the particle
* in varying speeds / sizes.
*/
object ParticleUtil {
// name x y z offX offY offZ speed count
fun sendsParticleToAll(vararg particleMetas: ParticleMeta) {
val packets = arrayListOf<Pair<Location, PacketPlayOutWorldParticles>>()
for (meta in particleMetas) {
packets.add(meta.location to PacketPlayOutWorldParticles(
meta.effect.getName(),
meta.location.x.toFloat(),
meta.location.y.toFloat(),
meta.location.z.toFloat(),
meta.offsetX,
meta.offsetY,
meta.offsetZ,
meta.speed,
meta.amount))
}
packets.forEach { pair ->
(pair.first.world as CraftWorld).handle.playerMap.forEachNearby(pair.first.x, pair.first.y, pair.first.z, 64.0, true) { player ->
player.playerConnection.sendPacket(pair.second)
}
}
}
}

View File

@ -0,0 +1,8 @@
Mongo:
Host: "127.0.0.1"
Port: 27017
DbName: "hub"
Authentication:
Enabled: false
Username: "admin"
Password: ""

View File

@ -0,0 +1,6 @@
name: Hub
version: ${project.version}
description: Hub plugin
author: joeleoli
main: cc.fyre.hub.Hub
depend: [Stark]

View File

@ -0,0 +1,8 @@
Mongo:
Host: "127.0.0.1"
Port: 27017
DbName: "hub"
Authentication:
Enabled: false
Username: "admin"
Password: ""

View File

@ -0,0 +1,6 @@
name: Hub
version: ${project.version}
description: Hub plugin
author: joeleoli
main: cc.fyre.hub.Hub
depend: [Stark]