Initialize Infstar Paper-based server core

This commit is contained in:
Coldsmiles
2026-09-13 18:08:00 +08:00
commit 5c27681d1d
22 changed files with 1502 additions and 0 deletions
+10
View File
@@ -0,0 +1,10 @@
.gradle/
build/
paper-api/
paper-server/
paper/
run/
# 本地测试服务器的世界、日志、配置和 JAR 均不上传。
test-server/
.idea/
*.iml
+47
View File
@@ -0,0 +1,47 @@
# Infstar
Infstar 是一个基于 Paper 的 Minecraft 服务端核心,优先保证原版机制、
技术服和客户端 Mod 的协议兼容性,再逐步加入可控的性能优化。
Paper 是 Infstar 唯一的代码上游。Leaves、Leaf、Purpur 和其他项目只作为
独立补丁的参考来源,不会成为 Infstar 的固定继承链或构建依赖。
## 当前基线
- Minecraft:`26.2`
- Paper commit:`e5fe71723e2ffde7cc9fafc085ac3bb73e63175e`
- Java:`25`
- 品牌标识:`infstarmc:infstar`
- Maven Group:`org.infstarmc.infstar`
- 开发版本:`<Minecraft 版本>-dev-<Git 短提交>`
Paper commit 有意固定在 `gradle.properties` 中。更新基线时应更新 commit、
重新应用补丁、运行兼容性测试,并审查生成的补丁变化后再合并。
## 构建
```bash
./gradlew applyAllPatches
./gradlew createPaperclipJar
```
Paperweight 会创建多层 Git 工作仓库,Linux 下应将项目放在 ext4、btrfs 等
原生 Linux 文件系统中。NTFS、exFAT 或部分 FUSE 挂载可能无法可靠处理 Git
锁文件,不建议直接在这些文件系统中构建。
需要使用 Paper 本地镜像或单独的上游工作目录时,可通过 Gradle 属性覆盖:
```bash
./gradlew applyAllPatches \
-PpaperRepository=/path/to/Paper \
-PpaperweightUpstreamWorkDir=/path/to/infstar-upstreams
```
在发布流程建立前,生成的服务端均视为开发版本。仓库还没有提交时,Git
短提交会临时显示为 `unknown`;首次提交后会自动使用七位短提交值。
## 上游策略
Infstar 直接跟进 Paper。其他下游项目不会作为 Git 子模块或构建必需依赖。
从其他项目移植的补丁必须经过审查、注明来源、完成测试,并在移植后由
Infstar 自行维护。
+68
View File
@@ -0,0 +1,68 @@
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent
plugins {
`maven-publish`
id("io.papermc.paperweight.patcher") version "2.0.0-beta.21"
}
val paperRepository = "https://repo.papermc.io/repository/maven-public/"
subprojects {
apply(plugin = "java-library")
apply(plugin = "maven-publish")
extensions.configure<JavaPluginExtension> {
toolchain.languageVersion = JavaLanguageVersion.of(25)
}
repositories {
mavenCentral()
maven(paperRepository)
}
tasks.withType<JavaCompile>().configureEach {
options.encoding = Charsets.UTF_8.name()
options.release = 25
options.isFork = true
options.compilerArgs.addAll(listOf("-Xlint:-deprecation", "-Xlint:-removal"))
}
tasks.withType<Javadoc>().configureEach {
options.encoding = Charsets.UTF_8.name()
}
tasks.withType<ProcessResources>().configureEach {
filteringCharset = Charsets.UTF_8.name()
}
tasks.withType<Test>().configureEach {
testLogging {
showStackTraces = true
exceptionFormat = TestExceptionFormat.FULL
events(TestLogEvent.STANDARD_OUT)
}
}
}
paperweight {
upstreams.paper {
repo = providers.gradleProperty("paperRepository")
.orElse("https://github.com/PaperMC/Paper.git")
ref = providers.gradleProperty("paperCommit")
patchFile {
path = "paper-api/build.gradle.kts"
outputFile = file("infstar-api/build.gradle.kts")
patchFile = file("infstar-api/build.gradle.kts.patch")
}
patchFile {
path = "paper-server/build.gradle.kts"
outputFile = file("infstar-server/build.gradle.kts")
patchFile = file("infstar-server/build.gradle.kts.patch")
}
patchDir("paperApi") {
upstreamPath = "paper-api"
excludes = setOf("build.gradle.kts")
patchesDir = file("infstar-api/paper-patches")
outputDir = file("paper-api")
}
}
}
+11
View File
@@ -0,0 +1,11 @@
group=org.infstarmc.infstar
mcVersion=26.2
apiVersion=26.2
channel=ALPHA
# Paper 是唯一代码上游。跟进 Paper 时应经过审查后再更新此 commit。
paperCommit=e5fe71723e2ffde7cc9fafc085ac3bb73e63175e
org.gradle.configuration-cache=true
org.gradle.caching=true
org.gradle.parallel=true
Binary file not shown.
+7
View File
@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored
+248
View File
@@ -0,0 +1,248 @@
#!/bin/sh
#
# Copyright © 2015 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
# gradlew start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh gradlew
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
Vendored
+82
View File
@@ -0,0 +1,82 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem gradlew startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables, and ensure extensions are enabled
setlocal EnableExtensions
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
"%COMSPEC%" /c exit 1
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
"%COMSPEC%" /c exit 1
:execute
@rem Setup the command line
@rem Execute gradlew
@rem endlocal doesn't take effect until after the line is parsed and variables are expanded
@rem which allows us to clear the local environment before executing the java command
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel
:exitWithErrorLevel
@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
"%COMSPEC%" /c exit %ERRORLEVEL%
+279
View File
@@ -0,0 +1,279 @@
import io.papermc.paperweight.checkstyle.JavadocTag
import paper.libs.com.google.gson.Gson
plugins {
`java-library`
`maven-publish`
// Infstar:API 模块基于 Paper API 源码生成。
idea
// Paper Checkstyle 依赖上游复合构建中的 paper-checkstyle 模块,衍生核心暂不启用。
// id("io.papermc.paperweight.paper-checkstyle")
}
java {
withSourcesJar()
withJavadocJar()
}
val projectCustomJavadocTags = setOf(
JavadocTag("apiNote", "a", "API Note:"),
)
/*
paperCheckstyle {
customJavadocTags = projectCustomJavadocTags
directoriesToSkipFile = layout.projectDirectory.file(".checkstyle/ignored_directories.txt")
}
*/
val annotationsVersion = "26.0.2"
val adventureVersion = "5.2.0"
val bungeeCordChatVersion = "1.21-R0.2-deprecated+build.21"
val slf4jVersion = "2.0.17"
val log4jVersion = "2.26.0"
val apiAndDocs: Configuration by configurations.creating
configurations.api {
extendsFrom(apiAndDocs)
}
val javadocSourcepath: Configuration by configurations.creating {
attributes {
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.DOCUMENTATION))
attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.EXTERNAL))
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType.SOURCES))
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
}
}
// Configure mockito agent that is needed in newer Java versions
val mockitoAgent = configurations.register("mockitoAgent")
abstract class MockitoAgentProvider : CommandLineArgumentProvider {
@get:CompileClasspath
abstract val fileCollection: ConfigurableFileCollection
override fun asArguments(): Iterable<String> {
return listOf("-javaagent:" + fileCollection.files.single().absolutePath)
}
}
dependencies {
// api dependencies are listed transitively to API consumers
api("com.google.guava:guava:33.6.0-jre")
api("com.google.code.gson:gson:2.14.0")
api("org.yaml:snakeyaml:2.2")
api("org.joml:joml:1.10.8") {
isTransitive = false // https://github.com/JOML-CI/JOML/issues/352
}
api("it.unimi.dsi:fastutil:8.5.18")
api("org.apache.logging.log4j:log4j-api:$log4jVersion")
api("org.slf4j:slf4j-api:$slf4jVersion")
api("com.mojang:brigadier:1.3.10")
// Deprecate bungeecord-chat in favor of adventure
api("net.md-5:bungeecord-chat:$bungeeCordChatVersion") {
exclude("com.google.guava", "guava")
}
apiAndDocs(platform("net.kyori:adventure-bom:$adventureVersion"))
apiAndDocs("net.kyori:adventure-api")
apiAndDocs("net.kyori:adventure-key")
apiAndDocs("net.kyori:adventure-text-minimessage")
apiAndDocs("net.kyori:adventure-text-serializer-gson")
apiAndDocs("net.kyori:adventure-text-serializer-legacy")
apiAndDocs("net.kyori:adventure-text-serializer-plain")
apiAndDocs("net.kyori:adventure-text-logger-slf4j")
api("org.apache.maven:maven-resolver-provider:3.9.6") // make API dependency for Paper Plugins
implementation("org.apache.maven.resolver:maven-resolver-connector-basic:1.9.18")
implementation("org.apache.maven.resolver:maven-resolver-transport-http:1.9.18")
// Annotations - Slowly migrate to jspecify
val annotations = "org.jetbrains:annotations:$annotationsVersion"
compileOnly(annotations)
testCompileOnly(annotations)
javadocSourcepath(annotations) // For adventure-api module requirements
val checkerQual = "org.checkerframework:checker-qual:3.49.2"
compileOnlyApi(checkerQual)
testCompileOnly(checkerQual)
apiAndDocs("org.jspecify:jspecify:1.0.0")
// Test dependencies
testImplementation("org.apache.commons:commons-lang3:3.20.0")
testImplementation("org.junit.jupiter:junit-jupiter:6.0.3")
testImplementation("org.hamcrest:hamcrest:2.2")
testImplementation("org.mockito:mockito-core:5.22.0")
testImplementation("org.ow2.asm:asm-tree:9.9.1")
mockitoAgent("org.mockito:mockito-core:5.22.0") { isTransitive = false } // configure mockito agent that is needed in newer java versions
testRuntimeOnly("org.junit.platform:junit-platform-launcher:6.0.3")
// checkstyle
// checkstyle(project(":paper-checkstyle"))
}
val generatedDir: java.nio.file.Path = rootProject.layout.projectDirectory.dir("paper-api/src/generated/java").asFile.toPath()
idea {
module {
generatedSourceDirs.add(generatedDir.toFile())
}
}
sourceSets {
main {
java {
srcDir(generatedDir)
srcDir(file("../paper-api/src/main/java"))
}
resources {
srcDir(file("../paper-api/src/main/resources"))
}
}
test {
java {
srcDir(file("../paper-api/src/test/java"))
}
resources {
srcDir(file("../paper-api/src/test/resources"))
}
}
}
val outgoingVariants = arrayOf("runtimeElements", "apiElements", "sourcesElements", "javadocElements")
val mainCapability = "${project.group}:${project.name}:${project.version}"
configurations {
val outgoing = outgoingVariants.map { named(it) }
for (config in outgoing) {
config {
attributes {
attribute(io.papermc.paperweight.util.mainCapabilityAttribute, mainCapability)
}
outgoing {
capability(mainCapability)
// Paper-MojangAPI has been merged into Paper-API
capability("io.papermc.paper:paper-mojangapi:${project.version}")
capability("com.destroystokyo.paper:paper-mojangapi:${project.version}")
// Conflict with old coordinates
capability("com.destroystokyo.paper:paper-api:${project.version}")
capability("org.spigotmc:spigot-api:${project.version}")
capability("org.bukkit:bukkit:${project.version}")
}
}
}
}
configure<PublishingExtension> {
publications.create<MavenPublication>("maven") {
// For Brigadier API
outgoingVariants.forEach {
suppressPomMetadataWarningsFor(it)
}
from(components["java"])
}
}
abstract class GenerateApiVersioningFile : DefaultTask() {
@get:OutputFile
abstract val outputFile: RegularFileProperty
@get:Input
abstract val projectVersion: Property<String>
@get:Input
abstract val apiVersion: Property<String>
@TaskAction
fun generate() {
val file = outputFile.get().asFile
file.parentFile.mkdirs()
val map = mapOf(
"version" to projectVersion.get(),
"currentApiVersion" to apiVersion.get()
)
file.writeText(Gson().toJson(map))
}
}
val generateApiVersioningFile = tasks.register<GenerateApiVersioningFile>("generateApiVersioningFile") {
outputFile.set(layout.buildDirectory.file("apiVersioning.json"))
projectVersion.set(project.version.toString())
apiVersion.set(rootProject.providers.gradleProperty("apiVersion"))
}
tasks.jar {
from(generateApiVersioningFile.flatMap { it.outputFile })
manifest {
attributes(
"Automatic-Module-Name" to "org.bukkit"
)
}
}
abstract class Services {
@get:Inject
abstract val fileSystemOperations: FileSystemOperations
}
val services = objects.newInstance<Services>()
tasks.withType<Javadoc>().configureEach {
val options = options as StandardJavadocDocletOptions
options.overview = "src/main/javadoc/overview.html"
options.use()
options.isDocFilesSubDirs = true
options.links(
"https://guava.dev/releases/33.6.0-jre/api/docs/",
"https://www.javadocs.dev/org.yaml/snakeyaml/2.2/",
"https://www.javadocs.dev/org.jetbrains/annotations/$annotationsVersion/",
"https://www.javadocs.dev/org.joml/joml/1.10.8/",
"https://www.javadocs.dev/com.google.code.gson/gson/2.14.0",
"https://jspecify.dev/docs/api/",
"https://jd.papermc.io/adventure/$adventureVersion/",
"https://www.javadocs.dev/org.slf4j/slf4j-api/$slf4jVersion/",
"https://logging.apache.org/log4j/2.x/javadoc/log4j-api/",
"https://www.javadocs.dev/org.apache.maven.resolver/maven-resolver-api/1.7.3",
)
options.tags(projectCustomJavadocTags.map { it.toOptionString() })
inputs.files(javadocSourcepath).ignoreEmptyDirectories().withPropertyName(javadocSourcepath.name + "-configuration")
val javadocSourcepathElements = javadocSourcepath.elements
doFirst {
options.addStringOption(
"sourcepath",
javadocSourcepathElements.get().map { it.asFile }.joinToString(separator = File.pathSeparator, transform = File::getPath)
)
}
// workaround for https://github.com/gradle/gradle/issues/4046
inputs.dir("src/main/javadoc").withPropertyName("javadoc-sourceset")
val fsOps = services.fileSystemOperations
doLast {
fsOps.copy {
from("src/main/javadoc") {
include("**/doc-files/**")
}
into("build/docs/javadoc")
}
}
}
tasks.test {
useJUnitPlatform()
// configure mockito agent that is needed in newer java versions
val provider = objects.newInstance<MockitoAgentProvider>()
provider.fileCollection.from(mockitoAgent)
jvmArgumentProviders.add(provider)
}
// Compile tests with -parameters for better junit parameterized test names
tasks.compileTestJava {
options.compilerArgs.add("-parameters")
}
val scanJarForBadCalls by tasks.registering(io.papermc.paperweight.tasks.ScanJarForBadCalls::class) {
badAnnotations.add("Lio/papermc/paper/annotation/DoNotUse;")
jarToScan.set(tasks.jar.flatMap { it.archiveFile })
classpath.from(configurations.compileClasspath)
}
tasks.check {
dependsOn(scanJarForBadCalls)
}
+59
View File
@@ -0,0 +1,59 @@
--- a/paper-api/build.gradle.kts
+++ b/paper-api/build.gradle.kts
@@ -4,8 +_,10 @@
plugins {
`java-library`
`maven-publish`
+ // Infstar:API 模块基于 Paper API 源码生成。
idea
- id("io.papermc.paperweight.paper-checkstyle")
+ // Paper Checkstyle 依赖上游复合构建中的 paper-checkstyle 模块,衍生核心暂不启用。
+ // id("io.papermc.paperweight.paper-checkstyle")
}
java {
@@ -17,10 +_,12 @@
JavadocTag("apiNote", "a", "API Note:"),
)
+/*
paperCheckstyle {
customJavadocTags = projectCustomJavadocTags
directoriesToSkipFile = layout.projectDirectory.file(".checkstyle/ignored_directories.txt")
}
+*/
val annotationsVersion = "26.0.2"
val adventureVersion = "5.2.0"
@@ -105,10 +_,10 @@
testRuntimeOnly("org.junit.platform:junit-platform-launcher:6.0.3")
// checkstyle
- checkstyle(project(":paper-checkstyle"))
+ // checkstyle(project(":paper-checkstyle"))
}
-val generatedDir: java.nio.file.Path = layout.projectDirectory.dir("src/generated/java").asFile.toPath()
+val generatedDir: java.nio.file.Path = rootProject.layout.projectDirectory.dir("paper-api/src/generated/java").asFile.toPath()
idea {
module {
generatedSourceDirs.add(generatedDir.toFile())
@@ -118,6 +_,18 @@
main {
java {
srcDir(generatedDir)
+ srcDir(file("../paper-api/src/main/java"))
+ }
+ resources {
+ srcDir(file("../paper-api/src/main/resources"))
+ }
+ }
+ test {
+ java {
+ srcDir(file("../paper-api/src/test/java"))
+ }
+ resources {
+ srcDir(file("../paper-api/src/test/resources"))
}
}
}
View File
@@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Coldsmiles <coldsmiles@outlook.com>
Date: Sun, 6 Sep 2026 11:33:34 +0800
Subject: [PATCH] Add Infstar brand identity
diff --git a/src/main/java/io/papermc/paper/ServerBuildInfo.java b/src/main/java/io/papermc/paper/ServerBuildInfo.java
index 4e099b584c3435ba1ebce492011d35ae1ac0cdf8..9e4fea24e65b43c0b7698adbb2d2e17f76336628 100644
--- a/src/main/java/io/papermc/paper/ServerBuildInfo.java
+++ b/src/main/java/io/papermc/paper/ServerBuildInfo.java
@@ -12,10 +12,12 @@ import org.jetbrains.annotations.ApiStatus;
*/
@ApiStatus.NonExtendable
public interface ServerBuildInfo {
- /**
- * The brand id for Paper.
- */
- Key BRAND_PAPER_ID = Key.key("papermc", "paper");
+ /** Infstar 的稳定品牌标识。 */
+ Key BRAND_INFSTAR_ID = Key.key("infstarmc", "infstar");
+
+ /** @deprecated 请使用 {@link #BRAND_INFSTAR_ID}。 */
+ @Deprecated(forRemoval = false)
+ Key BRAND_PAPER_ID = BRAND_INFSTAR_ID;
/**
* Gets the {@code ServerBuildInfo}.
+370
View File
@@ -0,0 +1,370 @@
import io.papermc.fill.model.BuildChannel
import io.papermc.paperweight.attribute.DevBundleOutput
import io.papermc.paperweight.util.*
import java.time.Instant
plugins {
`java-library`
`maven-publish`
idea
id("io.papermc.paperweight.core")
id("io.papermc.fill.gradle") version "1.0.12"
}
val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/"
dependencies {
mache("io.papermc:mache:26.2+build.1")
paperclip("io.papermc:paperclip:3.0.4")
}
paperweight {
minecraftVersion = providers.gradleProperty("mcVersion")
gitFilePatches = false
// Infstar:在 Paper 的服务端源码上应用自有补丁。
val infstar = forks.register("infstar") {
upstream.patchDir("paperServer") {
upstreamPath = "paper-server"
excludes = setOf("src/minecraft", "patches", "build.gradle.kts")
patchesDir = rootDirectory.dir("infstar-server/paper-patches")
outputDir = rootDirectory.dir("paper-server")
}
}
activeFork = infstar
updatingMinecraft {
// oldPaperCommit = "d4fe85375af18bfa88f44d7c1e6a61904ae550cc"
}
}
tasks.generateDevelopmentBundle {
libraryRepositories.addAll(
"https://repo.maven.apache.org/maven2/",
paperMavenPublicUrl,
)
}
abstract class Services {
@get:Inject
abstract val archiveOperations: ArchiveOperations
}
val services = objects.newInstance<Services>()
if (project.providers.gradleProperty("publishDevBundle").isPresent) {
val devBundleComponent = publishing.softwareComponentFactory.adhoc("devBundle")
components.add(devBundleComponent)
val devBundle = configurations.consumable("devBundle") {
attributes.attribute(DevBundleOutput.ATTRIBUTE, objects.named(DevBundleOutput.ZIP))
outgoing.artifact(tasks.generateDevelopmentBundle.flatMap { it.devBundleFile })
}
devBundleComponent.addVariantsFromConfiguration(devBundle) {}
val runtime = configurations.consumable("serverRuntimeClasspath") {
attributes.attribute(DevBundleOutput.ATTRIBUTE, objects.named(DevBundleOutput.SERVER_DEPENDENCIES))
attributes.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
extendsFrom(configurations.runtimeClasspath.get())
}
devBundleComponent.addVariantsFromConfiguration(runtime) {
mapToMavenScope("runtime")
}
val compile = configurations.consumable("serverCompileClasspath") {
attributes.attribute(DevBundleOutput.ATTRIBUTE, objects.named(DevBundleOutput.SERVER_DEPENDENCIES))
attributes.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_API))
extendsFrom(configurations.compileClasspath.get())
}
devBundleComponent.addVariantsFromConfiguration(compile) {
mapToMavenScope("compile")
}
tasks.withType(GenerateMavenPom::class).configureEach {
doLast {
val text = destination.readText()
// Remove dependencies from pom, dev bundle is designed for gradle module metadata consumers
destination.writeText(
text.substringBefore("<dependencies>") + text.substringAfter("</dependencies>")
)
}
}
publishing {
publications.create<MavenPublication>("devBundle") {
artifactId = "dev-bundle"
from(devBundleComponent)
}
}
}
// Infstar:编译生成后的 Paper 源码,而不是空的模块目录。
sourceSets {
main {
java {
srcDir("../paper-server/src/main/java")
srcDir("../paper-server/src/generated/java")
}
resources { srcDir("../paper-server/src/main/resources") }
}
test {
java { srcDir("../paper-server/src/test/java") }
resources { srcDir("../paper-server/src/test/resources") }
}
}
val log4jPlugins = sourceSets.create("log4jPlugins") {
java { srcDir("../paper-server/src/log4jPlugins/java") }
}
configurations.named(log4jPlugins.compileClasspathConfigurationName) {
extendsFrom(configurations.compileClasspath.get())
}
val alsoShade: Configuration by configurations.creating
val runtimeConfiguration by configurations.consumable("runtimeConfiguration") {
attributes.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
extendsFrom(configurations.getByName(sourceSets.main.get().runtimeElementsConfigurationName))
}
// Configure mockito agent that is needed in newer java versions
val mockitoAgent = configurations.register("mockitoAgent")
abstract class MockitoAgentProvider : CommandLineArgumentProvider {
@get:CompileClasspath
abstract val fileCollection: ConfigurableFileCollection
override fun asArguments(): Iterable<String> {
return listOf("-javaagent:" + fileCollection.files.single().absolutePath)
}
}
dependencies {
implementation(project(":infstar-api"))
implementation("ca.spottedleaf:leafpile:1.2.0")
implementation("org.jline:jline-terminal-ffm:3.27.1") // use ffm on java 22+
implementation("org.jline:jline-terminal-jni:3.27.1") // fall back to jni on java 21
implementation("net.minecrell:terminalconsoleappender:1.3.0")
implementation("net.kyori:adventure-text-serializer-ansi")
/*
Required to add the missing Log4j2Plugins.dat file from log4j-core
which has been removed by Mojang. Without it, log4j has to classload
all its classes to check if they are plugins.
Scanning takes about 1-2 seconds so adding this speeds up the server start.
*/
implementation("org.apache.logging.log4j:log4j-core:2.26.0")
log4jPlugins.annotationProcessorConfigurationName("org.apache.logging.log4j:log4j-core:2.26.0") // Needed to generate meta for our Log4j plugins
runtimeOnly(log4jPlugins.output)
alsoShade(log4jPlugins.output)
implementation("com.velocitypowered:velocity-native:4.1.0") {
isTransitive = false
}
implementation("io.netty:netty-codec-haproxy:4.2.15.Final") // Add support for proxy protocol
implementation("org.apache.logging.log4j:log4j-iostreams:2.26.0")
implementation("org.ow2.asm:asm-commons:9.9.1")
implementation("org.spongepowered:configurate-yaml:4.2.0")
// Deps that were previously in the API but have now been moved here for backwards compat, eventually to be removed
runtimeOnly("commons-lang:commons-lang:2.6")
runtimeOnly("org.xerial:sqlite-jdbc:3.49.1.0")
runtimeOnly("com.mysql:mysql-connector-j:9.2.0")
runtimeOnly("com.lmax:disruptor:3.4.4")
implementation("com.googlecode.json-simple:json-simple:1.1.1") { // change to runtimeOnly once Timings is removed
isTransitive = false // includes junit
}
testImplementation("io.github.classgraph:classgraph:4.8.184") // For mob goal test
testRuntimeOnly("org.junit.platform:junit-platform-launcher:6.0.3")
testImplementation("org.junit.jupiter:junit-jupiter:6.0.3")
testImplementation("org.junit.platform:junit-platform-suite-engine:6.0.3")
testImplementation("org.hamcrest:hamcrest:2.2")
testImplementation("org.mockito:mockito-core:5.22.0")
mockitoAgent("org.mockito:mockito-core:5.22.0") { isTransitive = false } // Configure mockito agent that is needed in newer java versions
testImplementation("org.ow2.asm:asm-tree:9.9.1")
testImplementation("org.junit-pioneer:junit-pioneer:2.3.0") // CartesianTest
// Spark
implementation("me.lucko:spark-api:0.1-20240720.200737-2")
implementation("me.lucko:spark-paper:1.10.180")
}
tasks.jar {
manifest {
val git = Git(rootProject.layout.projectDirectory.path)
val mcVersion = rootProject.providers.gradleProperty("mcVersion").get()
val buildTime = providers.environmentVariable("BUILD_STARTED_AT").map(Instant::parse).orElse(Instant.EPOCH).get()
val buildVersion = project.version.toString()
val gitHash = buildVersion.substringAfterLast('-')
val gitBranch = runCatching { git.exec(providers, "rev-parse", "--abbrev-ref", "HEAD").get().trim() }.getOrDefault("unknown")
attributes(
"Main-Class" to "org.bukkit.craftbukkit.Main",
"Implementation-Title" to "Infstar",
"Implementation-Version" to buildVersion,
"Implementation-Vendor" to "Infstar",
"Specification-Title" to "Infstar",
"Specification-Version" to project.version,
"Specification-Vendor" to "Infstar",
"Brand-Id" to "infstarmc:infstar",
"Brand-Name" to "Infstar",
"Build-Number" to "",
"Build-Time" to buildTime.toString(),
"Git-Branch" to gitBranch,
"Git-Commit" to gitHash,
)
for (tld in setOf("net", "com", "org")) {
attributes("$tld/bukkit", "Sealed" to true)
}
}
}
// Compile tests with -parameters for better junit parameterized test names
tasks.compileTestJava {
options.compilerArgs.add("-parameters")
}
tasks.named<JavaCompile>(log4jPlugins.compileJavaTaskName) {
options.compilerArgs.addAll(
listOf(
"-Alog4j.graalvm.groupId=${project.group}",
"-Alog4j.graalvm.artifactId=${project.name}"
)
)
}
// Bump compile tasks to 1GB memory to avoid OOMs
tasks.withType<JavaCompile>().configureEach {
options.forkOptions.memoryMaximumSize = "1G"
}
val scanJarForBadCalls by tasks.registering(io.papermc.paperweight.tasks.ScanJarForBadCalls::class) {
badAnnotations.add("Lio/papermc/paper/annotation/DoNotUse;")
jarToScan.set(tasks.jar.flatMap { it.archiveFile })
classpath.from(configurations.compileClasspath)
}
tasks.check {
dependsOn(scanJarForBadCalls)
}
// Use TCA for console improvements
tasks.jar {
val archiveOperations = services.archiveOperations
from(alsoShade.elements.map {
it.map { f ->
if (f.asFile.isFile) {
archiveOperations.zipTree(f.asFile)
} else {
f.asFile
}
}
})
}
tasks.test {
include("**/**TestSuite.class")
workingDir = temporaryDir
useJUnitPlatform {
forkEvery = 1
excludeTags("Slow")
}
// Configure mockito agent that is needed in newer java versions
val provider = objects.newInstance<MockitoAgentProvider>()
provider.fileCollection.from(mockitoAgent)
jvmArgumentProviders.add(provider)
}
val generatedDir: java.nio.file.Path = layout.projectDirectory.dir("src/generated/java").asFile.toPath()
idea {
module {
generatedSourceDirs.add(generatedDir.toFile())
}
}
sourceSets {
main {
java {
srcDir(generatedDir)
}
}
}
fun TaskContainer.registerRunTask(
name: String,
block: JavaExec.() -> Unit
): TaskProvider<JavaExec> = register<JavaExec>(name) {
group = "runs"
mainClass.set("org.bukkit.craftbukkit.Main")
standardInput = System.`in`
workingDir = rootProject.layout.projectDirectory
.dir(providers.gradleProperty("paper.runWorkDir").getOrElse("run"))
.asFile
javaLauncher.set(project.javaToolchains.launcherFor {
languageVersion.set(JavaLanguageVersion.of(25))
// TODO - JB runtime 25 has issues with spark rn
// vendor.set(JvmVendorSpec.JETBRAINS)
})
jvmArgs(/*"-XX:+AllowEnhancedClassRedefinition", */"--enable-native-access=ALL-UNNAMED")
if (rootProject.childProjects["test-plugin"] != null) {
val testPluginJar = rootProject.project(":test-plugin").tasks.jar.flatMap { it.archiveFile }
inputs.file(testPluginJar)
args("-add-plugin=${testPluginJar.get().asFile.absolutePath}")
}
args("--nogui")
systemProperty("net.kyori.adventure.text.warnWhenLegacyFormattingDetected", true)
if (providers.gradleProperty("paper.runDisableWatchdog").getOrElse("false") == "true") {
systemProperty("disable.watchdog", true)
}
systemProperty("io.papermc.paper.suppress.sout.nags", true)
systemProperty("paper.maxChatCommandInputSize", 32767)
systemProperty("paper.disableMigrationDelay", true)
systemProperty("paper.updatingMinecraft", providers.gradleProperty("updatingMinecraft").getOrElse("false").toBoolean())
val memoryGb = providers.gradleProperty("paper.runMemoryGb").getOrElse("2")
minHeapSize = "${memoryGb}G"
maxHeapSize = "${memoryGb}G"
doFirst {
workingDir.mkdirs()
}
block(this)
}
tasks.registerRunTask("runServer") {
description = "Spin up a test server from the Mojang mapped server jar"
classpath(tasks.jar)
classpath(configurations.runtimeClasspath)
}
tasks.registerRunTask("runDevServer") {
description = "Spin up a test server without assembling a jar"
classpath(sourceSets.main.map { it.runtimeClasspath })
}
tasks.registerRunTask("runBundler") {
description = "Spin up a test server from the Mojang mapped bundler jar"
classpath(tasks.createBundlerJar.flatMap { it.outputZip })
mainClass.set(null as String?)
}
tasks.registerRunTask("runPaperclip") {
description = "Spin up a test server from the Mojang mapped Paperclip jar"
classpath(tasks.createPaperclipJar.flatMap { it.outputZip })
mainClass.set(null as String?)
}
fill {
project("paper")
versionFamily(paperweight.minecraftVersion.map { it.split(".", "-").takeWhile { part -> part.toIntOrNull() != null }.take(2).joinToString(".") })
version(paperweight.minecraftVersion)
build {
channel = providers.gradleProperty("channel").map { BuildChannel.valueOf(it.uppercase()) }
downloads {
register("server:default") {
file = tasks.createPaperclipJar.flatMap { it.outputZip }
nameResolver.set { project, _, version, build -> "$project-$version-$build.jar" }
}
}
}
}
+90
View File
@@ -0,0 +1,90 @@
--- a/paper-server/build.gradle.kts
+++ b/paper-server/build.gradle.kts
@@ -22,6 +_,17 @@
minecraftVersion = providers.gradleProperty("mcVersion")
gitFilePatches = false
+ // Infstar:在 Paper 的服务端源码上应用自有补丁。
+ val infstar = forks.register("infstar") {
+ upstream.patchDir("paperServer") {
+ upstreamPath = "paper-server"
+ excludes = setOf("src/minecraft", "patches", "build.gradle.kts")
+ patchesDir = rootDirectory.dir("infstar-server/paper-patches")
+ outputDir = rootDirectory.dir("paper-server")
+ }
+ }
+ activeFork = infstar
+
updatingMinecraft {
// oldPaperCommit = "d4fe85375af18bfa88f44d7c1e6a61904ae550cc"
}
@@ -86,7 +_,24 @@
}
}
-val log4jPlugins = sourceSets.create("log4jPlugins")
+// Infstar:编译生成后的 Paper 源码,而不是空的模块目录。
+sourceSets {
+ main {
+ java {
+ srcDir("../paper-server/src/main/java")
+ srcDir("../paper-server/src/generated/java")
+ }
+ resources { srcDir("../paper-server/src/main/resources") }
+ }
+ test {
+ java { srcDir("../paper-server/src/test/java") }
+ resources { srcDir("../paper-server/src/test/resources") }
+ }
+}
+
+val log4jPlugins = sourceSets.create("log4jPlugins") {
+ java { srcDir("../paper-server/src/log4jPlugins/java") }
+}
configurations.named(log4jPlugins.compileClasspathConfigurationName) {
extendsFrom(configurations.compileClasspath.get())
}
@@ -109,7 +_,7 @@
}
dependencies {
- implementation(project(":paper-api"))
+ implementation(project(":infstar-api"))
implementation("ca.spottedleaf:leafpile:1.2.0")
implementation("org.jline:jline-terminal-ffm:3.27.1") // use ffm on java 22+
implementation("org.jline:jline-terminal-jni:3.27.1") // fall back to jni on java 21
@@ -163,23 +_,21 @@
manifest {
val git = Git(rootProject.layout.projectDirectory.path)
val mcVersion = rootProject.providers.gradleProperty("mcVersion").get()
- val build = System.getenv("BUILD_NUMBER") ?: null
val buildTime = providers.environmentVariable("BUILD_STARTED_AT").map(Instant::parse).orElse(Instant.EPOCH).get()
- val gitHash = git.exec(providers, "rev-parse", "--short=7", "HEAD").get().trim()
- val implementationVersion = "$mcVersion-${build ?: "DEV"}-$gitHash"
- val date = git.exec(providers, "show", "-s", "--format=%ci", gitHash).get().trim()
- val gitBranch = git.exec(providers, "rev-parse", "--abbrev-ref", "HEAD").get().trim()
+ val buildVersion = project.version.toString()
+ val gitHash = buildVersion.substringAfterLast('-')
+ val gitBranch = runCatching { git.exec(providers, "rev-parse", "--abbrev-ref", "HEAD").get().trim() }.getOrDefault("unknown")
attributes(
"Main-Class" to "org.bukkit.craftbukkit.Main",
- "Implementation-Title" to "Paper",
- "Implementation-Version" to implementationVersion,
- "Implementation-Vendor" to date,
- "Specification-Title" to "Paper",
+ "Implementation-Title" to "Infstar",
+ "Implementation-Version" to buildVersion,
+ "Implementation-Vendor" to "Infstar",
+ "Specification-Title" to "Infstar",
"Specification-Version" to project.version,
- "Specification-Vendor" to "Paper Team",
- "Brand-Id" to "papermc:paper",
- "Brand-Name" to "Paper",
- "Build-Number" to (build ?: ""),
+ "Specification-Vendor" to "Infstar",
+ "Brand-Id" to "infstarmc:infstar",
+ "Brand-Name" to "Infstar",
+ "Build-Number" to "",
"Build-Time" to buildTime.toString(),
"Git-Branch" to gitBranch,
"Git-Commit" to gitHash,
@@ -0,0 +1,34 @@
From e254ce543d684930c74959c5064f1498f17accce Mon Sep 17 00:00:00 2001
From: Coldsmiles <coldsmiles@outlook.com>
Date: Sun, 6 Sep 2026 12:05:28 +0800
Subject: [PATCH] Brand server runtime as Infstar
diff --git a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java
index 74ffdc823c06d33bd7c15fcce770b60bbad29c04..70f908474dfcf371a63c1cb8c4813db0e9580f20 100644
--- a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java
+++ b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java
@@ -30,9 +30,9 @@ public record ServerBuildInfoImpl(
private static final String ATTRIBUTE_GIT_BRANCH = "Git-Branch";
private static final String ATTRIBUTE_GIT_COMMIT = "Git-Commit";
- private static final String BRAND_PAPER_NAME = "Paper";
+ private static final String BRAND_INFSTAR_NAME = "Infstar";
- private static final String BUILD_DEV = "DEV";
+ private static final String BUILD_DEV = "dev";
public ServerBuildInfoImpl() {
this(JarManifests.manifest(CraftServer.class));
@@ -42,9 +42,9 @@ public record ServerBuildInfoImpl(
this(
getManifestAttribute(manifest, ATTRIBUTE_BRAND_ID)
.map(Key::key)
- .orElse(BRAND_PAPER_ID),
+ .orElse(BRAND_INFSTAR_ID),
getManifestAttribute(manifest, ATTRIBUTE_BRAND_NAME)
- .orElse(BRAND_PAPER_NAME),
+ .orElse(BRAND_INFSTAR_NAME),
SharedConstants.getCurrentVersion().id(),
SharedConstants.getCurrentVersion().name(),
getManifestAttribute(manifest, ATTRIBUTE_BUILD_NUMBER)
+38
View File
@@ -0,0 +1,38 @@
param(
[Parameter(Mandatory = $true)]
[ValidateScript({ Test-Path -LiteralPath $_ -PathType Leaf })]
[string] $JarPath,
[int] $Port = 25565
)
$projectRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
$runDirectory = Join-Path $projectRoot "run"
$targetJar = Join-Path $runDirectory "infstar.jar"
New-Item -ItemType Directory -Path $runDirectory -Force | Out-Null
Copy-Item -LiteralPath (Resolve-Path $JarPath).Path -Destination $targetJar -Force
@"
# Infstar 本地测试服务器配置
server-port=$Port
motd=Infstar Local Test Server
online-mode=false
enable-command-block=true
spawn-protection=0
view-distance=8
simulation-distance=6
enable-rcon=false
"@ | Set-Content -LiteralPath (Join-Path $runDirectory "server.properties") -Encoding utf8
"eula=true" | Set-Content -LiteralPath (Join-Path $runDirectory "eula.txt") -Encoding ascii
@"
这是 Infstar 的本地测试服务器目录,不应提交到 Git 仓库。
启动方式:
..\scripts\start-test-server.ps1
该目录包含世界、日志、配置和构建产物,已通过 .gitignore 排除。
"@ | Set-Content -LiteralPath (Join-Path $runDirectory "README.txt") -Encoding utf8
Write-Output "测试服务器已准备完成:$runDirectory"
+30
View File
@@ -0,0 +1,30 @@
#!/usr/bin/env bash
set -euo pipefail
if [[ $# -lt 1 || $# -gt 2 ]]; then
echo "用法:$0 <服务端 JAR 路径> [端口]" >&2
exit 2
fi
project_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
run_directory="$project_root/run"
jar_path="$(realpath "$1")"
port="${2:-25565}"
mkdir -p "$run_directory"
cp -f "$jar_path" "$run_directory/infstar.jar"
cat > "$run_directory/server.properties" <<EOF
# Infstar 本地测试服务器配置
server-port=$port
motd=Infstar Local Test Server
online-mode=false
enable-command-block=true
spawn-protection=0
view-distance=8
simulation-distance=6
enable-rcon=false
EOF
printf '%s\n' 'eula=true' > "$run_directory/eula.txt"
echo "测试服务器已准备完成:$run_directory"
+28
View File
@@ -0,0 +1,28 @@
param(
[int] $MemoryMinGb = 2,
[int] $MemoryMaxGb = 4
)
$projectRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
$runDirectory = Join-Path $projectRoot "run"
$serverJar = Join-Path $runDirectory "infstar.jar"
if (-not (Test-Path -LiteralPath $serverJar -PathType Leaf)) {
throw "未找到 $serverJar。请先运行 prepare-test-server.ps1。"
}
$java = Get-Command java -ErrorAction SilentlyContinue
if ($null -eq $java) {
throw "未找到 Java。Infstar 26.2 需要 Java 25。"
}
Push-Location $runDirectory
try {
& $java.Source "-Xms${MemoryMinGb}G" "-Xmx${MemoryMaxGb}G" "-jar" $serverJar "--nogui"
if ($LASTEXITCODE -ne 0) {
throw "测试服务器退出,代码:$LASTEXITCODE"
}
}
finally {
Pop-Location
}
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
set -euo pipefail
project_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
run_directory="$project_root/run"
server_jar="$run_directory/infstar.jar"
java_command="${JAVA_HOME:+$JAVA_HOME/bin/}java"
memory_min_gb="${INFSTAR_MEMORY_MIN_GB:-2}"
memory_max_gb="${INFSTAR_MEMORY_MAX_GB:-4}"
if [[ ! -f "$server_jar" ]]; then
echo "未找到 $server_jar,请先运行 prepare-test-server.sh。" >&2
exit 1
fi
if ! command -v "$java_command" >/dev/null 2>&1; then
echo "未找到 Java。Infstar 26.2 需要 Java 25。" >&2
exit 1
fi
cd "$run_directory"
exec "$java_command" \
"-Xms${memory_min_gb}G" \
"-Xmx${memory_max_gb}G" \
-jar "$server_jar" \
--nogui
+15
View File
@@ -0,0 +1,15 @@
param(
[Parameter(Mandatory = $true)]
[ValidatePattern('^[0-9a-fA-F]{40}$')]
[string] $PaperCommit
)
$propertiesPath = Join-Path $PSScriptRoot "..\gradle.properties"
$properties = Get-Content -LiteralPath $propertiesPath -Raw
$updated = [regex]::Replace($properties, '(?m)^paperCommit=.*$', "paperCommit=$PaperCommit")
if ($updated -eq $properties) {
throw "paperCommit was not found in $propertiesPath"
}
Set-Content -LiteralPath $propertiesPath -Value $updated -NoNewline
Write-Output "已将 Paper 固定到 $PaperCommit。合并前请运行 applyAllPatches 和兼容性测试。"
+33
View File
@@ -0,0 +1,33 @@
import java.util.Locale
pluginManagement {
repositories {
gradlePluginPortal()
maven("https://repo.papermc.io/repository/maven-public/")
}
}
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
}
if (!file(".git").exists()) {
error("Infstar 必须从 Git 仓库检出;Paperweight 需要 Git 元数据来应用补丁。")
}
rootProject.name = "infstar"
for (name in listOf("infstar-api", "infstar-server")) {
include(name.lowercase(Locale.ENGLISH))
}
gradle.lifecycle.beforeProject {
val minecraftVersion = providers.gradleProperty("mcVersion").get().trim()
val gitHash = providers.exec {
commandLine("git", "rev-parse", "--short=7", "HEAD")
isIgnoreExitValue = true
}.standardOutput.asText.map { output ->
output.trim().takeIf { it.matches(Regex("[0-9a-fA-F]{7,40}")) } ?: "unknown"
}.get()
version = "$minecraftVersion-dev-$gitHash"
}