Черновой вариант

This commit is contained in:
justuser-31 2025-11-22 19:22:35 +03:00
commit ad7e50738d
5 changed files with 477 additions and 0 deletions

113
.gitignore vendored Normal file
View File

@ -0,0 +1,113 @@
# User-specific stuff
.idea/
*.iml
*.ipr
*.iws
# IntelliJ
out/
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
.mvn/wrapper/maven-wrapper.jar
.flattened-pom.xml
# Common working directory
run/

146
pom.xml Normal file
View File

@ -0,0 +1,146 @@
<?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>main</groupId>
<artifactId>vp_server_integration</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<name>vp_server_integration</name>
<properties>
<java.version>17</java.version>
<kotlin.version>2.3.0-RC</kotlin.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<defaultGoal>clean package</defaultGoal>
<sourceDirectory>${project.basedir}/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>
</execution>
</executions>
<configuration>
<jvmTarget>${java.version}</jvmTarget>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<repositories>
<repository>
<id>spigotmc-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.12.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
<!-- Deployment profile for FTPS and HTTP actions -->
<profiles>
<profile>
<id>myDeploy</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>3.1.0</version>
<dependencies>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.9.0</version>
</dependency>
</dependencies>
<executions>
<!-- FTPS file transfer execution -->
<execution>
<id>ftps-upload</id>
<phase>install</phase>
<configuration>
<target>
<echo message="UPLOADING file to ${ftps.username}@${ftps.host} ${srv.ftps.remote.directory}"/>
<echo message="curl -k --ssl-reqd --ftp-create-dirs -T target/vpSecure-1.0.jar -u ${ftps.username}:${ftps.password} ftp://${ftps.host}:${ftps.port}/${srv.ftps.remote.directory}"/>
<exec executable="sh">
<arg value="-c"/>
<arg value="curl -k --ssl-reqd --ftp-create-dirs -T target/vpSecure-1.0.jar -u ${ftps.username}:${ftps.password} ftp://${ftps.host}:${ftps.port}/${srv.ftps.remote.directory}"/>
</exec>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
<!-- HTTP POST request execution -->
<execution>
<id>http-notification</id>
<phase>install</phase>
<configuration>
<target>
<echo message="SENDING restart request to ${srv.restart.endpoint}"/>
<echo message="curl -k -X POST -H 'Authorization: Bearer ${minihost.token}' ${srv.restart.endpoint}"/>
<exec executable="sh">
<arg value="-c"/>
<arg value="curl -k -X POST -H 'Authorization: Bearer ${minihost.token}' ${srv.restart.endpoint}"/>
</exec>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,35 @@
package main.vp_server_integration
import org.bukkit.plugin.java.JavaPlugin
import org.bukkit.Bukkit
import java.util.logging.Logger
class Vp_server_integration : JavaPlugin() {
companion object {
lateinit var LOGGER: Logger
lateinit var SERVER: org.bukkit.Server
var PLUGIN_API_PORT: Int = 8010
lateinit var USERNAME: String
lateinit var TOKEN: String
lateinit var USER_API_URL: String
const val DEFAULT_USER_API_URL: String = "http://127.0.0.1:8010/api/"
const val DEFAULT_TOKEN: String = "test"
const val COLOR_CHAR: Char = '&'
}
override fun onEnable() {
// Initialize logger
LOGGER = this.logger
// Get server instance
SERVER = Bukkit.getServer()
// Plugin startup logic
LOGGER.info("VP Server Integration plugin enabled!")
}
override fun onDisable() {
// Plugin shutdown logic
LOGGER.info("VP Server Integration plugin disabled!")
}
}

View File

@ -0,0 +1,176 @@
package main.vp_server_integration
import com.google.gson.Gson
import com.google.gson.JsonElement
import com.google.gson.JsonParser
import com.google.gson.JsonSyntaxException
import org.bukkit.ChatColor
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
import java.io.BufferedReader
import java.io.InputStreamReader
import java.io.OutputStream
import java.net.HttpURLConnection
import java.net.URI
import java.net.URISyntaxException
import java.util.*
class VpcApi {
companion object {
// Using Gson for JSON serialization - much cleaner than manual string building
fun jsonify(args: List<String>): String {
val map = mutableMapOf<String, String>()
for (i in args.indices step 2) {
if (i + 1 < args.size) {
map[args[i]] = args[i + 1]
}
}
return Gson().toJson(map)
}
// Response wrapper class that supports both dot notation and bracket access
data class ApiResponse(
val status: Int,
val data: Map<String, Any>?,
val rawResponse: String
) {
operator fun get(key: String): Any? = data?.get(key)
}
fun sendPost(urlPoint: String, json: String, customUrl: Boolean = false, baseurl: String = ""): ApiResponse {
var uri: URI
try {
uri = if (customUrl) {
URI.create(baseurl + urlPoint)
} else {
URI.create(Vp_server_integration.DEFAULT_USER_API_URL + urlPoint)
}
} catch (e: URISyntaxException) {
return ApiResponse(-1, null, "Error: Invalid URL syntax")
}
var connection: HttpURLConnection? = null
try {
connection = uri.toURL().openConnection() as HttpURLConnection
connection.requestMethod = "POST"
connection.setRequestProperty("Content-Type", "application/json; utf-8")
connection.doOutput = true
// Using proper OutputStream handling
val os: OutputStream = connection.outputStream
os.write(json.toByteArray(Charsets.UTF_8))
os.close()
val responseCode = connection.responseCode
var rawResponse = ""
var responseData: Map<String, Any>? = null
// Handle both success (2xx) and error (4xx, 5xx) responses
val inputStream = if (responseCode in 200..299) {
connection.inputStream
} else {
connection.errorStream
}
// Read response if available
if (inputStream != null) {
rawResponse = BufferedReader(InputStreamReader(inputStream, "utf-8")).readText()
try {
// Try to parse response as JSON
// For Java 8 / Gson < 2.8.6, use JsonParser() constructor and parse() method
val jsonElement: JsonElement = JsonParser().parse(rawResponse)
if (jsonElement.isJsonObject) {
// If it's a JSON object, parse it as before
val jsonObject = jsonElement.asJsonObject
responseData = jsonObject.entrySet().associate { it.key to it.value.toString().trim('"') }
} else {
// If it's not a JSON object (e.g., raw string like "OK"), keep raw response
responseData = null
}
} catch (e: JsonSyntaxException) {
// If not valid JSON at all, keep raw response
responseData = null
}
}
rawResponse = rawResponse.replace("\"", "")
return ApiResponse(responseCode, responseData, rawResponse)
} catch (e: Exception) {
// Handle network errors and other exceptions
return ApiResponse(-1, null, "Error: ${e.message}")
} finally {
connection?.disconnect()
}
}
fun send(source: CommandSender, message: String, prefix: String = "&9[&bVPC&9] &3") {
// Translate color codes for Spigot
val coloredMessage = ChatColor.translateAlternateColorCodes('&', prefix + message)
source.sendMessage(coloredMessage)
}
fun get_super_UUID(source: CommandSender): String {
if (source is Player) {
val uuid = source.uniqueId
val username = source.name
val address = source.address?.hostString ?: "unknown"
// Note: Some properties don't exist in 1.12.2, using available alternatives
val merged = "$uuid$username$address"
return hash(merged)
} else {
return "None"
}
}
fun user_in_db(source: CommandSender? = null, username: String? = null): Map<String, Any>? {
var mine_uuid: String? = null
// Determine which parameter to use
val userParam = when {
username != null -> "username" to username
source is Player -> "username" to source.name
else -> throw IllegalArgumentException("Either source or username must be provided")
}
val response = sendPost(
"user_in_db/", jsonify(
listOf(
"token", Vp_server_integration.DEFAULT_TOKEN,
userParam.first, userParam.second
)
)
)
// response["someKey"] (map-like access)
return if (response.status == 200) {
response.data
} else {
null
}
}
fun transfer_coins(src_username: String, dst_username: String, amount: Float): Any? {
val response = sendPost(
"transfer_coins/", jsonify(
listOf(
"token", Vp_server_integration.DEFAULT_TOKEN,
"src_username", src_username,
"dst_username", dst_username,
"amount", amount.toString()
)
)
)
return if (response.status == 200) {
response.rawResponse
} else {
response.data?.get("detail")
}
}
// Simple hash function (you might want to replace this with a proper hashing algorithm)
private fun hash(input: String): String {
return UUID.nameUUIDFromBytes(input.toByteArray()).toString()
}
}
}

View File

@ -0,0 +1,7 @@
name: vp_server_integration
version: '1.0'
main: main.vp_server_integration.Vp_server_integration
load: STARTUP
authors: [ _SAN5_SkeLet0n_ ]
description: Integrate VPC into your server
website: voidproject.del.pw