add 1.20
This commit is contained in:
commit
7784fddd27
7
.gitattributes
vendored
Normal file
7
.gitattributes
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
/gradlew text eol=lf
|
||||
*.jar binary
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.class binary
|
||||
* text=auto eol=lf
|
||||
*.bat text eol=crlf
|
15
.gitignore
vendored
Normal file
15
.gitignore
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
# Ignore Gradle project-specific cache directory
|
||||
.gradle
|
||||
|
||||
# Ignore Gradle build output directory
|
||||
build
|
||||
|
||||
.idea
|
||||
mod_build
|
||||
node_modules
|
||||
|
||||
run
|
||||
|
||||
pnpm-lock.yaml
|
||||
|
||||
dist
|
35
.prettierrc
Normal file
35
.prettierrc
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/prettierrc",
|
||||
"printWidth": 120,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"singleQuote": true,
|
||||
"quoteProps": "as-needed",
|
||||
"trailingComma": "all",
|
||||
"bracketSpacing": true,
|
||||
"arrowParens": "always",
|
||||
"rangeStart": 0,
|
||||
"vueIndentScriptAndStyle": false,
|
||||
"endOfLine": "auto",
|
||||
"semi": true,
|
||||
"requirePragma": false,
|
||||
"bracketSameLine": true,
|
||||
"htmlWhitespaceSensitivity": "ignore",
|
||||
"plugins": [
|
||||
"prettier-plugin-java"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.json",
|
||||
"options": {
|
||||
"tabWidth": 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": "*.java",
|
||||
"options": {
|
||||
"tabWidth": 4
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
202
LICENSE
Normal file
202
LICENSE
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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
|
||||
|
||||
http://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.
|
64
build.gradle.kts
Normal file
64
build.gradle.kts
Normal file
@ -0,0 +1,64 @@
|
||||
|
||||
|
||||
subprojects {
|
||||
apply(plugin = "java")
|
||||
apply(plugin = "idea")
|
||||
tasks.withType<AbstractArchiveTask>().configureEach() {
|
||||
destinationDirectory.set(
|
||||
rootProject.projectDir.resolve("mod_build")
|
||||
)
|
||||
}
|
||||
tasks.named("jar") {
|
||||
enabled = false
|
||||
}
|
||||
tasks.withType<JavaCompile>().configureEach {
|
||||
options.release.set(17)
|
||||
}
|
||||
}
|
||||
tasks.withType<JavaExec> {
|
||||
jvmArgs = listOf(
|
||||
"-Dfile.encoding=UTF-8",
|
||||
"-Dsun.stdout.encoding=UTF-8",
|
||||
"-Dsun.stderr.encoding=UTF-8"
|
||||
)
|
||||
}
|
||||
tasks.withType<JavaCompile> {
|
||||
options.encoding = "UTF-8"
|
||||
}
|
||||
val loaders = listOf("Fabric", "Forge", "NeoForge")
|
||||
val mod_minecrat_versions: String by project
|
||||
|
||||
val modVersions = mod_minecrat_versions.split(",")
|
||||
|
||||
modVersions.forEach {
|
||||
tasks.register("build_$it") {
|
||||
group = "mod_${it}"
|
||||
dependsOn(":modsrc:${it}:shadowJar")
|
||||
}
|
||||
loaders.forEach { ti ->
|
||||
run {
|
||||
if (findProject(":modsrc:$it:$ti") != null) {
|
||||
println("$it:$ti")
|
||||
tasks.register("${ti}RunServer_$it") {
|
||||
group = "mod_$it"
|
||||
dependsOn(":modsrc:$it:$ti:runServer")
|
||||
}
|
||||
tasks.register("${ti}RunClient_$it") {
|
||||
group = "mod_$it"
|
||||
dependsOn(":modsrc:$it:$ti:runClient")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register("cleanAll", Delete::class) {
|
||||
subprojects.forEach{
|
||||
val task = it.tasks.findByName("clean")
|
||||
if (task != null){
|
||||
dependsOn(task)
|
||||
}
|
||||
}
|
||||
group = "build"
|
||||
delete("mod_build")
|
||||
}
|
37
common/build.gradle.kts
Normal file
37
common/build.gradle.kts
Normal file
@ -0,0 +1,37 @@
|
||||
plugins {
|
||||
id("java-library")
|
||||
id("java")
|
||||
|
||||
}
|
||||
|
||||
val java_version: String by project
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of(java_version))
|
||||
}
|
||||
}
|
||||
sourceSets {
|
||||
main {
|
||||
java { srcDirs("src") }
|
||||
resources { srcDirs("resources",rootProject.rootDir.resolve("dist")) }
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
maven {
|
||||
name = "mingliqiye repository"
|
||||
url = uri("https://gitee.com/minglipro/maven-repository-raw/raw/master")
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
implementation("io.javalin:javalin:6.7.0")
|
||||
implementation("com.fasterxml.jackson.core:jackson-databind:2.19.1")
|
||||
implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.19.1")
|
||||
implementation("com.mingliqiye:string-utils:1.0.4")
|
||||
|
||||
compileOnlyApi("org.slf4j:slf4j-api:2.0.7")
|
||||
}
|
||||
|
||||
tasks.jar {
|
||||
enabled = true
|
||||
}
|
1
common/gradle.properties
Normal file
1
common/gradle.properties
Normal file
@ -0,0 +1 @@
|
||||
java_version=17
|
@ -0,0 +1,27 @@
|
||||
{
|
||||
"enchantment.minecraft.damage": {
|
||||
"allow": true,
|
||||
"allowlist": [
|
||||
"enchantment.minecraft.sharpness",
|
||||
"enchantment.minecraft.smite",
|
||||
"enchantment.minecraft.bane_of_arthropods"
|
||||
]
|
||||
},
|
||||
"enchantment.minecraft.infinity": {
|
||||
"allow": true,
|
||||
"allowlist": ["enchantment.minecraft.infinity", "enchantment.minecraft.mending"]
|
||||
},
|
||||
"enchantment.minecraft.protection": {
|
||||
"allow": true,
|
||||
"allowlist": [
|
||||
"enchantment.minecraft.protection",
|
||||
"enchantment.minecraft.fire_protection",
|
||||
"enchantment.minecraft.blast_protection",
|
||||
"enchantment.minecraft.projectile_protection"
|
||||
]
|
||||
},
|
||||
"enchantment.minecraft.piercing": {
|
||||
"allow": true,
|
||||
"allowlist": ["enchantment.minecraft.piercing", "enchantment.minecraft.multishot"]
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
{
|
||||
"minecraft:damage": {
|
||||
"allow": true,
|
||||
"allowlist": [
|
||||
"minecraft:sharpness",
|
||||
"minecraft:smite",
|
||||
"minecraft:bane_of_arthropods",
|
||||
"minecraft:density",
|
||||
"minecraft:breach"
|
||||
]
|
||||
},
|
||||
"minecraft:infinity": {
|
||||
"allow": true,
|
||||
"allowlist": [
|
||||
"minecraft:infinity",
|
||||
"minecraft:mending"
|
||||
]
|
||||
},
|
||||
"minecraft:protection": {
|
||||
"allow": true,
|
||||
"allowlist": [
|
||||
"minecraft:protection",
|
||||
"minecraft:fire_protection",
|
||||
"minecraft:blast_protection",
|
||||
"minecraft:projectile_protection"
|
||||
]
|
||||
},
|
||||
"minecraft:piercing": {
|
||||
"allow": true,
|
||||
"allowlist": [
|
||||
"minecraft:piercing",
|
||||
"minecraft:multishot"
|
||||
]
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 67 KiB |
Binary file not shown.
After Width: | Height: | Size: 218 KiB |
@ -0,0 +1,113 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.common;
|
||||
|
||||
import static com.mingliqiye.minecraft.enchantment.conflict.common.DataFormat.JSONOBJECTMAPPER;
|
||||
import static com.mingliqiye.minecraft.enchantment.conflict.common.DataFormat.YALMOBJECTMAPPER;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.mingliqiye.utils.StringUtil;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public class ConfigManager {
|
||||
|
||||
private final String FILE_NAME = StringUtil.format("{}.yaml", MinecraftMod.MOD_ID);
|
||||
private final DefConfig defConfig;
|
||||
|
||||
public static final JavaType MODCONFIGTYPE = JSONOBJECTMAPPER.getTypeFactory().constructMapType(
|
||||
Map.class,
|
||||
String.class,
|
||||
ConfigPair.class
|
||||
);
|
||||
|
||||
public static Map<String, ConfigPair> fromyaml(String s) {
|
||||
try {
|
||||
return YALMOBJECTMAPPER.readValue(s, MODCONFIGTYPE);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String toyaml(Map<String, ConfigPair> c) {
|
||||
try {
|
||||
return YALMOBJECTMAPPER.writeValueAsString(c);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<String, ConfigPair> fromjson(String s) {
|
||||
try {
|
||||
return JSONOBJECTMAPPER.readValue(s, MODCONFIGTYPE);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String tojson(Map<String, ConfigPair> c) {
|
||||
try {
|
||||
return JSONOBJECTMAPPER.writeValueAsString(c);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, ConfigPair> getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public void setConfig(Map<String, ConfigPair> config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
private Map<String, ConfigPair> config;
|
||||
private final Path configPath;
|
||||
private final Logger log;
|
||||
private final Path configFile;
|
||||
private final VersionsEnum versions;
|
||||
|
||||
public ConfigManager(Path configPath, Logger log, VersionsEnum versions) {
|
||||
this.versions = versions;
|
||||
defConfig = new DefConfig(versions);
|
||||
this.log = log;
|
||||
configFile = configPath.resolve(FILE_NAME);
|
||||
this.configPath = configPath;
|
||||
config = load();
|
||||
}
|
||||
|
||||
public Map<String, ConfigPair> load() {
|
||||
try {
|
||||
if (Files.exists(configFile)) {
|
||||
log.info("{} 配置加载", MinecraftMod.MOD_ID);
|
||||
return YALMOBJECTMAPPER.readValue(Files.readString(configFile), MODCONFIGTYPE);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to load config", e);
|
||||
}
|
||||
return save(defConfig.getConfig());
|
||||
}
|
||||
|
||||
public Map<String, ConfigPair> save() {
|
||||
return save(config);
|
||||
}
|
||||
|
||||
public Map<String, ConfigPair> save(Map<String, ConfigPair> configs) {
|
||||
try {
|
||||
Files.writeString(configFile, YALMOBJECTMAPPER.writeValueAsString(configs));
|
||||
log.info("{} 配置已保存", MinecraftMod.MOD_ID);
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to save config", e);
|
||||
}
|
||||
return configs;
|
||||
}
|
||||
|
||||
public VersionsEnum getVersions() {
|
||||
return versions;
|
||||
}
|
||||
|
||||
public DefConfig getDefConfig() {
|
||||
return defConfig;
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.common;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ConfigPair {
|
||||
|
||||
private Boolean allow;
|
||||
private List<String> allowlist;
|
||||
|
||||
public ConfigPair() {}
|
||||
|
||||
ConfigPair(Boolean allow, List<String> allowlist) {
|
||||
this.allow = allow;
|
||||
this.allowlist = allowlist;
|
||||
}
|
||||
|
||||
public List<String> getAllowlist() {
|
||||
return allowlist;
|
||||
}
|
||||
|
||||
public void setAllowlist(List<String> allowlist) {
|
||||
this.allowlist = new ArrayList<>(allowlist);
|
||||
}
|
||||
|
||||
public ConfigPair add(String item) {
|
||||
allowlist.add(item);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigPair add(String... items) {
|
||||
allowlist.addAll(List.of(items));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Boolean getAllow() {
|
||||
return allow;
|
||||
}
|
||||
|
||||
public void setAllow(Boolean allow) {
|
||||
this.allow = allow;
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.common;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
|
||||
|
||||
public class DataFormat {
|
||||
|
||||
public static final ObjectMapper YALMOBJECTMAPPER = new ObjectMapper(new YAMLFactory());
|
||||
public static final ObjectMapper JSONOBJECTMAPPER = new ObjectMapper();
|
||||
}
|
@ -0,0 +1,248 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.common;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonView;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* <p>自定义时间类
|
||||
*
|
||||
* @author MingLiPro|Armamem0t
|
||||
* @version 1.0
|
||||
* @see LocalDateTime
|
||||
* @see Date
|
||||
* @see ZoneId
|
||||
*/
|
||||
@JsonSerialize(using = DateTimeJsonSerializer.class)
|
||||
@JsonDeserialize(using = DateTimeJsonDeserializer.class)
|
||||
@JsonView(String.class)
|
||||
public class DateTime implements Serializable {
|
||||
|
||||
public LocalDateTime getLocalDateTime() {
|
||||
return localDateTime;
|
||||
}
|
||||
|
||||
public void setLocalDateTime(LocalDateTime localDateTime) {
|
||||
this.localDateTime = localDateTime;
|
||||
}
|
||||
|
||||
private LocalDateTime localDateTime;
|
||||
private ZoneId zoneId = ZoneId.systemDefault();
|
||||
|
||||
DateTime() {
|
||||
this(Instant.now());
|
||||
}
|
||||
|
||||
DateTime(Instant instant) {
|
||||
this(LocalDateTime.ofInstant(instant, ZoneId.systemDefault()));
|
||||
}
|
||||
|
||||
DateTime(LocalDateTime localDateTime) {
|
||||
this.localDateTime = localDateTime;
|
||||
}
|
||||
|
||||
DateTime(Instant instant, ZoneId zoneId) {
|
||||
this(LocalDateTime.ofInstant(instant, zoneId));
|
||||
}
|
||||
|
||||
DateTime(Date date) {
|
||||
this(date.toInstant());
|
||||
}
|
||||
|
||||
public static DateTime now() {
|
||||
return new DateTime();
|
||||
}
|
||||
|
||||
public static DateTime ofCurrentTimeMillis(long time) {
|
||||
return new DateTime(Instant.ofEpochMilli(time));
|
||||
}
|
||||
|
||||
public static DateTime of(Instant instant) {
|
||||
return new DateTime(instant);
|
||||
}
|
||||
|
||||
public static String format(Date date, String formater) {
|
||||
return format(toLocalDateTime(date), formater);
|
||||
}
|
||||
|
||||
public static String format(LocalDateTime date, String formater) {
|
||||
return DateTimeFormatter.ofPattern(formater).format(date);
|
||||
}
|
||||
|
||||
public static LocalDateTime toLocalDateTime(Date date) {
|
||||
return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
|
||||
}
|
||||
|
||||
public static String format(LocalDateTime date, Formats formats) {
|
||||
return format(date, formats.value);
|
||||
}
|
||||
|
||||
public static DateTime parse(String timestr, Formats formater) {
|
||||
return parse(timestr, formater.value);
|
||||
}
|
||||
|
||||
public static DateTime parse(String timestr, String formater) {
|
||||
DateTimeFormatter sdf = DateTimeFormatter.ofPattern(formater);
|
||||
return of(LocalDateTime.parse(timestr, sdf));
|
||||
}
|
||||
|
||||
public static DateTime of(LocalDateTime localDateTime) {
|
||||
return new DateTime(localDateTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return (
|
||||
this.getClass().getName() +
|
||||
'@' +
|
||||
Integer.toHexString(hashCode()) +
|
||||
'(' +
|
||||
format(Formats.STANDARD_DATETIME_MILLISECOUND7) +
|
||||
")"
|
||||
);
|
||||
}
|
||||
|
||||
public String format(Formats formater) {
|
||||
return format(localDateTime, formater.value);
|
||||
}
|
||||
|
||||
public Instant toInstant() {
|
||||
return toInstant(localDateTime);
|
||||
}
|
||||
|
||||
public static Instant toInstant(LocalDateTime localDateTime) {
|
||||
return toInstant(localDateTime, ZoneId.systemDefault());
|
||||
}
|
||||
|
||||
public static Instant toInstant(LocalDateTime localDateTime, ZoneId zoneId) {
|
||||
return localDateTime.atZone(zoneId).toInstant();
|
||||
}
|
||||
|
||||
public Instant toInstant(ZoneId zoneId) {
|
||||
return toInstant(localDateTime, zoneId);
|
||||
}
|
||||
|
||||
public Date toDate() {
|
||||
return toDate(localDateTime);
|
||||
}
|
||||
|
||||
public static Date toDate(LocalDateTime localDateTime) {
|
||||
return Date.from(toInstant(localDateTime));
|
||||
}
|
||||
|
||||
public String format(String formater) {
|
||||
return format(localDateTime, formater);
|
||||
}
|
||||
|
||||
public DateTime plusYears(long years) {
|
||||
return plusYears(this, years);
|
||||
}
|
||||
|
||||
public static DateTime plusYears(DateTime dateTime, long years) {
|
||||
dateTime.setLocalDateTime(dateTime.getLocalDateTime().plusYears(years));
|
||||
return dateTime;
|
||||
}
|
||||
|
||||
public DateTime plusMonths(long months) {
|
||||
return plusMonths(this, months);
|
||||
}
|
||||
|
||||
public static DateTime plusMonths(DateTime dateTime, long months) {
|
||||
dateTime.setLocalDateTime(dateTime.getLocalDateTime().plusMonths(months));
|
||||
return dateTime;
|
||||
}
|
||||
|
||||
public DateTime plusWeeks(long weeks) {
|
||||
return plusWeeks(this, weeks);
|
||||
}
|
||||
|
||||
public static DateTime plusWeeks(DateTime dateTime, long weeks) {
|
||||
dateTime.setLocalDateTime(dateTime.getLocalDateTime().plusWeeks(weeks));
|
||||
return dateTime;
|
||||
}
|
||||
|
||||
public DateTime plusDays(long days) {
|
||||
return plusDays(this, days);
|
||||
}
|
||||
|
||||
public static DateTime plusDays(DateTime dateTime, long days) {
|
||||
dateTime.setLocalDateTime(dateTime.getLocalDateTime().plusDays(days));
|
||||
return dateTime;
|
||||
}
|
||||
|
||||
public DateTime plusHours(long hours) {
|
||||
return plusHours(this, hours);
|
||||
}
|
||||
|
||||
public static DateTime plusHours(DateTime dateTime, long hours) {
|
||||
dateTime.setLocalDateTime(dateTime.getLocalDateTime().plusHours(hours));
|
||||
return dateTime;
|
||||
}
|
||||
|
||||
public DateTime plusMinutes(long minutes) {
|
||||
return plusMinutes(this, minutes);
|
||||
}
|
||||
|
||||
public static DateTime plusMinutes(DateTime dateTime, long minutes) {
|
||||
dateTime.setLocalDateTime(dateTime.getLocalDateTime().plusMinutes(minutes));
|
||||
return dateTime;
|
||||
}
|
||||
|
||||
public DateTime plusSeconds(long seconds) {
|
||||
return plusSeconds(this, seconds);
|
||||
}
|
||||
|
||||
public static DateTime plusSeconds(DateTime dateTime, long seconds) {
|
||||
dateTime.setLocalDateTime(dateTime.getLocalDateTime().plusSeconds(seconds));
|
||||
return dateTime;
|
||||
}
|
||||
|
||||
public DateTime plusNanos(long nanos) {
|
||||
return plusNanos(this, nanos);
|
||||
}
|
||||
|
||||
public static DateTime plusNanos(DateTime dateTime, long nanos) {
|
||||
dateTime.setLocalDateTime(dateTime.getLocalDateTime().plusNanos(nanos));
|
||||
return dateTime;
|
||||
}
|
||||
|
||||
public ZoneId getZoneId() {
|
||||
return zoneId;
|
||||
}
|
||||
|
||||
public void setZoneId(ZoneId zoneId) {
|
||||
this.zoneId = zoneId;
|
||||
}
|
||||
|
||||
public enum Formats {
|
||||
STANDARD_DATETIME("yyyy-MM-dd HH:mm:ss"),
|
||||
STANDARD_DATETIME_MILLISECOUND7("yyyy-MM-dd HH:mm:ss.SSSSSSS"),
|
||||
STANDARD_DATETIME_MILLISECOUND6("yyyy-MM-dd HH:mm:ss.SSSSSS"),
|
||||
STANDARD_DATETIME_MILLISECOUND5("yyyy-MM-dd HH:mm:ss.SSSSS"),
|
||||
STANDARD_DATETIME_MILLISECOUND4("yyyy-MM-dd HH:mm:ss.SSSS"),
|
||||
STANDARD_DATETIME_MILLISECOUND3("yyyy-MM-dd HH:mm:ss.SSS"),
|
||||
STANDARD_DATETIME_MILLISECOUND2("yyyy-MM-dd HH:mm:ss.SS"),
|
||||
STANDARD_DATETIME_MILLISECOUND1("yyyy-MM-dd HH:mm:ss.S"),
|
||||
STANDARD_ISO("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"),
|
||||
STANDARD_DATETIME_SECOUND("yyyy-MM-dd HH:mm:ss"),
|
||||
STANDARD_DATE("yyyy-MM-dd"),
|
||||
ISO8601("yyyy-MM-dd'T'HH:mm:ss.SSS'000'"),
|
||||
COMPACT_DATETIME("yyyyMMddHHmmss");
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
private final String value;
|
||||
|
||||
Formats(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.common;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import java.io.IOException;
|
||||
|
||||
public class DateTimeJsonDeserializer extends JsonDeserializer<DateTime> {
|
||||
|
||||
@Override
|
||||
public DateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
|
||||
if (p.isNaN()) {
|
||||
return null;
|
||||
}
|
||||
return DateTime.parse(p.getValueAsString(), DateTime.Formats.STANDARD_DATETIME_MILLISECOUND6);
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.common;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
import com.fasterxml.jackson.core.type.WritableTypeId;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
|
||||
import java.io.IOException;
|
||||
|
||||
public class DateTimeJsonSerializer extends JsonSerializer<DateTime> {
|
||||
|
||||
@Override
|
||||
public void serialize(DateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
|
||||
if (value == null) {
|
||||
gen.writeNull();
|
||||
return;
|
||||
}
|
||||
gen.writeString(value.format(DateTime.Formats.STANDARD_DATETIME_MILLISECOUND6));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWithType(
|
||||
DateTime value,
|
||||
JsonGenerator gen,
|
||||
SerializerProvider serializers,
|
||||
TypeSerializer typeSer
|
||||
) throws IOException {
|
||||
WritableTypeId typeId = typeSer.writeTypePrefix(gen, typeSer.typeId(value, JsonToken.VALUE_STRING));
|
||||
serialize(value, gen, serializers);
|
||||
typeSer.writeTypeSuffix(gen, typeId);
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.common;
|
||||
|
||||
import static com.mingliqiye.minecraft.enchantment.conflict.common.DataFormat.JSONOBJECTMAPPER;
|
||||
import static com.mingliqiye.minecraft.enchantment.conflict.common.DataFormat.YALMOBJECTMAPPER;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
|
||||
public class DefConfig {
|
||||
|
||||
private static final String DEFCONFIGPATH = "/assets/enchantmentdoesnotconflict/config/";
|
||||
private static final String DEFCONFIGV121PATH = DEFCONFIGPATH + "enchantmentdoesnotconflict_1.21.json";
|
||||
private static final String DEFCONFIGV120PATH = DEFCONFIGPATH + "enchantmentdoesnotconflict_1.20.json";
|
||||
private final Map<String, ConfigPair> config121;
|
||||
private final Map<String, ConfigPair> config120;
|
||||
private final VersionsEnum versionsEnum;
|
||||
|
||||
public static String getResByString(String path) {
|
||||
try (InputStream i = DefConfig.class.getResourceAsStream(path)) {
|
||||
byte[] data = i.readAllBytes();
|
||||
return new String(data, StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public DefConfig(VersionsEnum versionsEnum) {
|
||||
try {
|
||||
config121 = JSONOBJECTMAPPER.readValue(getResByString(DEFCONFIGV121PATH), ConfigManager.MODCONFIGTYPE);
|
||||
config120 = JSONOBJECTMAPPER.readValue(getResByString(DEFCONFIGV120PATH), ConfigManager.MODCONFIGTYPE);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
this.versionsEnum = versionsEnum;
|
||||
}
|
||||
|
||||
public Map<String, ConfigPair> getConfig121() {
|
||||
return config121;
|
||||
}
|
||||
|
||||
public Map<String, ConfigPair> getConfig120() {
|
||||
return config120;
|
||||
}
|
||||
|
||||
public Map<String, ConfigPair> getConfig() {
|
||||
if (versionsEnum == VersionsEnum.V120) {
|
||||
return getConfig120();
|
||||
} else if (versionsEnum == VersionsEnum.V121) {
|
||||
return getConfig121();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.common;
|
||||
|
||||
public enum ExceptionCode {
|
||||
ERROR_INTERNAL_SERVER(500),
|
||||
ERROR_PAYMENT_REQUIRED(402),
|
||||
ERROR_NOT_FOUND(404),
|
||||
ERROR_METHOD_NOT_ALLOWED(405),
|
||||
ERROR_UNAUTHORIZED(401),
|
||||
ERROR_FORBIDDEN(403),
|
||||
OK(200);
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
private final int value;
|
||||
|
||||
ExceptionCode(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static ExceptionCode getExceptionCode(int value) {
|
||||
for (ExceptionCode exceptionCode : ExceptionCode.values()) {
|
||||
if (exceptionCode.value == value) {
|
||||
return exceptionCode;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.common;
|
||||
|
||||
public final class Funs {
|
||||
|
||||
@FunctionalInterface
|
||||
public interface P1Fun<T> {
|
||||
void call(T p);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Fun {
|
||||
void call();
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface R1Fun<T> {
|
||||
T call();
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.common;
|
||||
|
||||
public class MinecraftMod {
|
||||
|
||||
public static final String MOD_ID = "enchantmentdoesnotconflict";
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.common;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
|
||||
public class NetWorkUtils {
|
||||
|
||||
public static boolean isLocalAddress(SocketAddress address) {
|
||||
if (!(address instanceof InetSocketAddress inetAddr)) {
|
||||
return false;
|
||||
}
|
||||
return (inetAddr.getAddress().isLoopbackAddress() || inetAddr.getAddress().isAnyLocalAddress());
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.common;
|
||||
|
||||
public class Respose<T> {
|
||||
|
||||
private int code = ExceptionCode.OK.getValue();
|
||||
private String message = "操作成功";
|
||||
private T data;
|
||||
private DateTime dateTime = DateTime.now();
|
||||
|
||||
public Respose(int code, String message, T data, DateTime dateTime) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
this.data = data;
|
||||
this.dateTime = dateTime;
|
||||
}
|
||||
|
||||
public Respose(int code, String message, T data) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Respose(int code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public Respose(T data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Respose() {}
|
||||
|
||||
public static <T> Respose<T> builder() {
|
||||
return new Respose<>();
|
||||
}
|
||||
|
||||
public static <T> Respose<T> builder(T data) {
|
||||
return new Respose<>().setData(data);
|
||||
}
|
||||
|
||||
public static <T> Respose<T> error(Class<T> type, Integer code, String message) {
|
||||
return new Respose<T>().setCode(code).setMessage(message);
|
||||
}
|
||||
|
||||
public static <T> Respose<T> error(Class<T> type, ExceptionCode code, String message) {
|
||||
return error(type, code.getValue(), message);
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public Respose<T> setMessage(String message) {
|
||||
this.message = message;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public Respose<T> setCode(int code) {
|
||||
this.code = code;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DateTime getDateTime() {
|
||||
return dateTime;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public <TD> Respose<TD> setData(TD data) {
|
||||
return new Respose<>(code, message, data);
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.common;
|
||||
|
||||
public enum VersionsEnum {
|
||||
V120,
|
||||
V121,
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.common;
|
||||
|
||||
import io.javalin.Javalin;
|
||||
import io.javalin.http.Context;
|
||||
import java.util.Map;
|
||||
|
||||
public class WebApis {
|
||||
|
||||
private final ConfigManager configManager;
|
||||
private final WebConfigCoreMeMethod webConfigCoreMeMethod;
|
||||
|
||||
WebApis(ConfigManager configManager, WebConfigCoreMeMethod webConfigCoreMeMethod) {
|
||||
this.configManager = configManager;
|
||||
this.webConfigCoreMeMethod = webConfigCoreMeMethod;
|
||||
}
|
||||
|
||||
public void loadApis(Javalin javalin) {
|
||||
javalin.get("/api/get/info", this::getInfo);
|
||||
javalin.get("/api/get/enchantments", this::getAllEnchantments);
|
||||
javalin.get("/api/get/client/config", this::getClientConfig);
|
||||
javalin.post("/api/get/test", this::getTest);
|
||||
javalin.post("/api/send/config", this::sendConfig);
|
||||
}
|
||||
|
||||
public void getAllEnchantments(Context context) {
|
||||
context.json(Respose.builder(webConfigCoreMeMethod.getAllEnchantments()));
|
||||
}
|
||||
|
||||
public void getClientConfig(Context context) {
|
||||
context.json(Respose.builder(webConfigCoreMeMethod.getConfig()));
|
||||
}
|
||||
|
||||
public void getInfo(Context context) {
|
||||
context.json(
|
||||
Respose.builder(
|
||||
Map.of(
|
||||
"LoaderVersion",
|
||||
webConfigCoreMeMethod.getLoaderVersions(),
|
||||
"LoaderName",
|
||||
webConfigCoreMeMethod.getLoaderName(),
|
||||
"GameVersions",
|
||||
webConfigCoreMeMethod.getGameVersions(),
|
||||
"ModVersions",
|
||||
webConfigCoreMeMethod.getModVersions(),
|
||||
"ModName",
|
||||
webConfigCoreMeMethod.getModName()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public void getTest(Context context) {
|
||||
record BD(Integer fid, Integer sid) {}
|
||||
var d = context.bodyAsClass(BD.class);
|
||||
context.json(Respose.builder(webConfigCoreMeMethod.getTest(d.fid, d.sid)));
|
||||
}
|
||||
|
||||
public void sendConfig(Context context) {
|
||||
webConfigCoreMeMethod.saveConfig(context.bodyAsClass(ConfigManager.MODCONFIGTYPE));
|
||||
context.json(Respose.builder());
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.common;
|
||||
|
||||
import io.javalin.Javalin;
|
||||
import io.javalin.http.staticfiles.Location;
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public class WebConfigCore {
|
||||
|
||||
private Javalin javalin;
|
||||
private final int port;
|
||||
private final ConfigManager configManager;
|
||||
private final WebConfigCoreMeMethod webConfigCoreMeMethod;
|
||||
private final WebApis webApis;
|
||||
private boolean started = false;
|
||||
|
||||
public WebConfigCore(ConfigManager configManager, WebConfigCoreMeMethod webConfigCoreMeMethod) {
|
||||
this.configManager = configManager;
|
||||
this.webConfigCoreMeMethod = webConfigCoreMeMethod;
|
||||
port = getProt();
|
||||
webApis = new WebApis(configManager, webConfigCoreMeMethod);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
javalin = Javalin.create((config) -> {
|
||||
config.staticFiles.add((staticFiles) -> {
|
||||
staticFiles.directory = "/assets/enchantmentdoesnotconflict/web/assets";
|
||||
staticFiles.location = Location.CLASSPATH;
|
||||
staticFiles.hostedPath = "/assets";
|
||||
});
|
||||
});
|
||||
javalin.get("/", (ctx) -> {
|
||||
ctx.html(DefConfig.getResByString("/assets/enchantmentdoesnotconflict/web/index.html"));
|
||||
});
|
||||
webApis.loadApis(javalin);
|
||||
javalin.start(port);
|
||||
started = true;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (started) {
|
||||
javalin.stop();
|
||||
}
|
||||
}
|
||||
|
||||
public int getProt() {
|
||||
if (webConfigCoreMeMethod.getDevMode()) {
|
||||
return 15563;
|
||||
}
|
||||
try (ServerSocket s = new ServerSocket(0)) {
|
||||
return s.getLocalPort();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 15563;
|
||||
}
|
||||
|
||||
public String getLocalUrl() {
|
||||
return "http://localhost:" + port;
|
||||
}
|
||||
|
||||
public void openWeb() {
|
||||
WebOpener.openURL(getLocalUrl());
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.common;
|
||||
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.common.enchantment.EnchantmentEntity;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public interface WebConfigCoreMeMethod {
|
||||
void reloadConfig();
|
||||
|
||||
Map<String, ConfigPair> getDefConfig();
|
||||
|
||||
Map<String, ConfigPair> getConfig();
|
||||
|
||||
String getGameVersions();
|
||||
|
||||
String getModVersions();
|
||||
|
||||
String getLoaderVersions();
|
||||
|
||||
default boolean getDevMode() {
|
||||
String classPath = Objects.requireNonNullElse(
|
||||
WebConfigCoreMeMethod.class.getResource("WebConfigCoreMeMethod.class"),
|
||||
""
|
||||
).toString();
|
||||
return classPath.contains("common.jar");
|
||||
}
|
||||
|
||||
default String getModName() {
|
||||
return "[EDNC] Enchantment Does Not Conflict (附魔不冲突)";
|
||||
}
|
||||
|
||||
String getLoaderName();
|
||||
|
||||
List<EnchantmentEntity> getAllEnchantments();
|
||||
|
||||
boolean getTest(Integer fid, Integer sid);
|
||||
|
||||
void saveConfig(Map<String, ConfigPair> configPairMap);
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.common;
|
||||
|
||||
import java.awt.Desktop;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
public class WebOpener {
|
||||
|
||||
public static void openURL(String url) {
|
||||
String os = System.getProperty("os.name").toLowerCase();
|
||||
Runtime rt = Runtime.getRuntime();
|
||||
try {
|
||||
if (os.contains("win")) {
|
||||
rt.exec("rundll32 url.dll,FileProtocolHandler " + url);
|
||||
} else if (os.contains("mac")) {
|
||||
rt.exec("open " + url);
|
||||
} else if (os.contains("nix") || os.contains("nux")) {
|
||||
rt.exec("xdg-open " + url);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.common.enchantment;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface AddAllowEnchantmentFunInf {
|
||||
Map<String, List<String>> call();
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.common.enchantment;
|
||||
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.common.ConfigManager;
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.common.ConfigPair;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class EnchantmentController {
|
||||
|
||||
private final List<AddAllowEnchantmentFunInf> allowEnchantmentFunInfs = new ArrayList<>();
|
||||
private final ConfigManager configManager;
|
||||
|
||||
public void registerAllowEnchantment(AddAllowEnchantmentFunInf fun) {
|
||||
allowEnchantmentFunInfs.add(fun);
|
||||
}
|
||||
|
||||
public EnchantmentController(ConfigManager configManager) {
|
||||
this.configManager = configManager;
|
||||
}
|
||||
|
||||
public Boolean canBeCombined(String enchantmentA, String enchantmentB) {
|
||||
if (enchantmentA.equals(enchantmentB)) {
|
||||
return true;
|
||||
}
|
||||
List<EnchantmentEntity> groupsA = ofId(enchantmentA);
|
||||
List<EnchantmentEntity> groupsB = ofId(enchantmentB);
|
||||
if (groupsA.isEmpty() && groupsB.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (EnchantmentEntity groupA : groupsA) {
|
||||
for (EnchantmentEntity groupB : groupsB) {
|
||||
if (groupA.getFather().equals(groupB.getFather())) {
|
||||
ConfigPair pair = configManager.getConfig().get(groupA.getFather());
|
||||
if (pair == null) {
|
||||
return null;
|
||||
}
|
||||
return pair.getAllow();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<EnchantmentEntity> ofId(String id) {
|
||||
final List<EnchantmentEntity> enchantmentList = new ArrayList<>();
|
||||
for (String i : configManager.getConfig().keySet()) {
|
||||
if (configManager.getConfig().get(i).getAllowlist().contains(id)) {
|
||||
enchantmentList.add(new EnchantmentEntity(id, i, "", null));
|
||||
}
|
||||
}
|
||||
return enchantmentList;
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.common.enchantment;
|
||||
|
||||
public class EnchantmentEntity {
|
||||
|
||||
private String id;
|
||||
private String father;
|
||||
private String name;
|
||||
private Integer nid;
|
||||
|
||||
public EnchantmentEntity(String id, String father, String name, Integer nid) {
|
||||
this.nid = nid;
|
||||
this.id = id;
|
||||
this.father = father;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setFather(String father) {
|
||||
this.father = father;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getFather() {
|
||||
return father;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Integer getNid() {
|
||||
return nid;
|
||||
}
|
||||
|
||||
public void setNid(Integer nid) {
|
||||
this.nid = nid;
|
||||
}
|
||||
}
|
28
gradle.properties
Normal file
28
gradle.properties
Normal file
@ -0,0 +1,28 @@
|
||||
org.gradle.daemon=true
|
||||
org.gradle.jvmargs=-Xmx8G
|
||||
mod_name=Enchantment Does Not Conflict
|
||||
mod_id=enchantmentdoesnotconflict
|
||||
mod_version=2.0
|
||||
maven_group=com.mingliqiye.minecraft.enchantment.conflict
|
||||
archives_base_name=enchantmentdoesnotconflict
|
||||
mod_description=Now, some enchantments are no longer involved in conflicts.
|
||||
mod_author=mingliqiye
|
||||
mod_contributor=minglipro
|
||||
mod_contributor_2=Armamem0t
|
||||
mod_license=Apache Licence 2.0
|
||||
mod_sources=https://git.mingliqiye.com/MinecraftMod/EnchantmentDoNotConflict
|
||||
mod_issues=https://git.mingliqiye.com/MinecraftMod/EnchantmentDoNotConflict/issues
|
||||
mod_author_email=minglipro@163.com
|
||||
java_version=17
|
||||
mod_minecrat_versions=1.20
|
||||
projects=:common,:modsrc:1.20:Fabric,:modsrc:1.20:Forge
|
||||
mod_relocate_packs_id=\
|
||||
com.fasterxml,\
|
||||
com.mingliqiye.utils,\
|
||||
io.javalin,\
|
||||
jakarta,\
|
||||
kotlin,\
|
||||
org.yaml,\
|
||||
org.jetbrains,\
|
||||
org.intellij,\
|
||||
org.eclipse
|
2
gradle/libs.versions.toml
Normal file
2
gradle/libs.versions.toml
Normal file
@ -0,0 +1,2 @@
|
||||
# This file was generated by the Gradle 'init' task.
|
||||
# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
7
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
7
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
251
gradlew
vendored
Normal file
251
gradlew
vendored
Normal file
@ -0,0 +1,251 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 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
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle 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 Gradle
|
||||
#
|
||||
# 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/HEAD/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
|
||||
|
||||
CLASSPATH="\\\"\\\""
|
||||
|
||||
|
||||
# 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" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
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" \
|
||||
-classpath "$CLASSPATH" \
|
||||
-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" "$@"
|
94
gradlew.bat
vendored
Normal file
94
gradlew.bat
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
@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 Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
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
|
||||
|
||||
goto fail
|
||||
|
||||
: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
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
13
index.html
Normal file
13
index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/src/resources/icon.png">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>附魔不冲突 配置</title>
|
||||
</head>
|
||||
<body>
|
||||
<main></main>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
75
modsrc/1.20/Fabric/build.gradle
Normal file
75
modsrc/1.20/Fabric/build.gradle
Normal file
@ -0,0 +1,75 @@
|
||||
plugins {
|
||||
id 'fabric-loom' version "${fabric_loom_version}"
|
||||
id 'maven-publish'
|
||||
}
|
||||
loom {
|
||||
mixin {
|
||||
defaultRefmapName.set("enchantmentdoesnotconflict.fabric.mixin.refmap.json")
|
||||
}
|
||||
}
|
||||
version = "${loader_name}-${minecraft_version}-${mod_version}"
|
||||
group = project.maven_group
|
||||
|
||||
base {
|
||||
archivesName = project.archives_base_name
|
||||
}
|
||||
sourceSets {
|
||||
main {
|
||||
java { srcDirs = ['src'] }
|
||||
resources { srcDirs = ['resources', project(":common").sourceSets.main.resources] }
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
||||
mappings loom.officialMojangMappings()
|
||||
modImplementation "net.fabricmc:fabric-loader:${project.fabric_loader_version}"
|
||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
||||
implementation project(":common")
|
||||
}
|
||||
|
||||
processResources {
|
||||
inputs.property "mod_id", project.mod_id
|
||||
inputs.property "mod_version", project.mod_version
|
||||
inputs.property "mod_name", project.mod_name
|
||||
inputs.property "mod_description", project.mod_description
|
||||
inputs.property "mod_author", project.mod_author
|
||||
inputs.property "mod_contributor", project.mod_contributor
|
||||
inputs.property "mod_contributor_2", project.mod_contributor_2
|
||||
inputs.property "mod_sources", project.mod_sources
|
||||
inputs.property "mod_issues", project.mod_issues
|
||||
inputs.property "mod_author_email", project.mod_author_email
|
||||
filesMatching("fabric.mod.json") {
|
||||
expand(["mod_id" : project.mod_id,
|
||||
"mod_version" : project.mod_version,
|
||||
"mod_name" : project.mod_name,
|
||||
"mod_description" : project.mod_description,
|
||||
"mod_author" : project.mod_author,
|
||||
"mod_contributor" : project.mod_contributor,
|
||||
"mod_contributor_2": project.mod_contributor_2,
|
||||
"mod_sources" : project.mod_sources,
|
||||
"mod_issues" : project.mod_issues,
|
||||
"mod_author_email" : project.mod_author_email])
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain { languageVersion.set(JavaLanguageVersion.of(java_version)) }
|
||||
}
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
it.options.release.set(java_version as Integer)
|
||||
}
|
||||
|
||||
jar {
|
||||
enabled = true
|
||||
inputs.property "archivesName", project.base.archivesName
|
||||
from("LICENSE") {
|
||||
rename { "${it}_${inputs.properties.archivesName}" }
|
||||
}
|
||||
}
|
||||
|
||||
remapJar{
|
||||
}
|
1
modsrc/1.20/Fabric/gradle.properties
Normal file
1
modsrc/1.20/Fabric/gradle.properties
Normal file
@ -0,0 +1 @@
|
||||
loader_name=Fabric
|
@ -0,0 +1,12 @@
|
||||
{
|
||||
"required": true,
|
||||
"package": "com.mingliqiye.minecraft.enchantment.conflict.fabric.mixin",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"mixins": ["EnchantmentMixin", "PlayerListMixin"],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
},
|
||||
"overwrites": {
|
||||
"requireAnnotations": true
|
||||
}
|
||||
}
|
31
modsrc/1.20/Fabric/resources/fabric.mod.json
Normal file
31
modsrc/1.20/Fabric/resources/fabric.mod.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "${mod_id}",
|
||||
"version": "${mod_version}",
|
||||
"name": "${mod_name}",
|
||||
"description": "${mod_description}",
|
||||
"authors": ["${mod_author}"],
|
||||
"contributors": ["${mod_contributor}", "${mod_contributor_2}"],
|
||||
"contact": {
|
||||
"sources": "${mod_sources}",
|
||||
"issues": "${mod_issues}",
|
||||
"email": "${mod_author_email}"
|
||||
},
|
||||
"license": "Apache License 2.0",
|
||||
"icon": "assets/enchantmentdoesnotconflict/textures/logo/icon.png",
|
||||
"environment": "*",
|
||||
"entrypoints": {
|
||||
"main": ["com.mingliqiye.minecraft.enchantment.conflict.fabric.FabricMod"],
|
||||
"client": ["com.mingliqiye.minecraft.enchantment.conflict.fabric.FabricModClient"]
|
||||
},
|
||||
"mixins": ["enchantmentdoesnotconflict.fabric.mixin.json"],
|
||||
"depends": {
|
||||
"fabricloader": "*",
|
||||
"minecraft": "1.20",
|
||||
"java": ">=17",
|
||||
"fabric-api": "*"
|
||||
},
|
||||
"suggests": {
|
||||
"another-mod": "*"
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.fabric;
|
||||
|
||||
import static com.mingliqiye.minecraft.enchantment.conflict.common.NetWorkUtils.isLocalAddress;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.common.ConfigManager;
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.common.MinecraftMod;
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.common.VersionsEnum;
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.common.WebConfigCore;
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.common.enchantment.EnchantmentController;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.Style;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class FabricMod implements ModInitializer {
|
||||
|
||||
public static final Logger LOGGER = LoggerFactory.getLogger(MinecraftMod.MOD_ID);
|
||||
public static MinecraftServer SERVER;
|
||||
public static final ConfigManager CONFIGMANAGER = new ConfigManager(
|
||||
FabricLoader.getInstance().getConfigDir(),
|
||||
LOGGER,
|
||||
VersionsEnum.V120
|
||||
);
|
||||
|
||||
public static final WebConfigCore WEBCONFIGCORE = new WebConfigCore(
|
||||
CONFIGMANAGER,
|
||||
new FabricWebConfigCoreMeMethod()
|
||||
);
|
||||
public static final EnchantmentController ENCHANTMENTCONTROLLER = new EnchantmentController(CONFIGMANAGER);
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
ServerLifecycleEvents.SERVER_STARTED.register((m) -> {
|
||||
SERVER = m;
|
||||
WEBCONFIGCORE.start();
|
||||
});
|
||||
ServerLifecycleEvents.SERVER_STOPPING.register((m) -> {
|
||||
WEBCONFIGCORE.stop();
|
||||
});
|
||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||
dispatcher.register(
|
||||
literal("enchantmentdoesnotconflict-config").executes((context) -> {
|
||||
var source = context.getSource();
|
||||
boolean isLocal =
|
||||
source.getServer().isSingleplayer() ||
|
||||
source.getEntity() == null ||
|
||||
(source.getPlayer() != null &&
|
||||
isLocalAddress(source.getPlayer().connection.getRemoteAddress()));
|
||||
if (isLocal) {
|
||||
WEBCONFIGCORE.openWeb();
|
||||
source.sendSuccess(
|
||||
() ->
|
||||
Component.literal("打开")
|
||||
.append(Component.literal(WEBCONFIGCORE.getLocalUrl()))
|
||||
.withStyle(
|
||||
Style.EMPTY.withColor(ChatFormatting.BLUE).withUnderlined(true) // 蓝色带下划线
|
||||
)
|
||||
.append(Component.literal("成功"))
|
||||
.withStyle(ChatFormatting.GREEN),
|
||||
true
|
||||
);
|
||||
} else {
|
||||
source.sendFailure(
|
||||
Component.literal("请使用服务器所在的机器执行该命令").withStyle(ChatFormatting.RED)
|
||||
);
|
||||
}
|
||||
return 1;
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.fabric;
|
||||
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.fabric.network.NetworkHandler;
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
|
||||
public class FabricModClient implements ClientModInitializer {
|
||||
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
NetworkHandler.registerReceivers();
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.fabric;
|
||||
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.common.ConfigPair;
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.common.MinecraftMod;
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.common.WebConfigCoreMeMethod;
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.common.enchantment.EnchantmentEntity;
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.fabric.network.NetworkHandler;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.fabricmc.loader.api.ModContainer;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
|
||||
public class FabricWebConfigCoreMeMethod implements WebConfigCoreMeMethod {
|
||||
|
||||
@Override
|
||||
public void reloadConfig() {}
|
||||
|
||||
@Override
|
||||
public Map<String, ConfigPair> getDefConfig() {
|
||||
return FabricMod.CONFIGMANAGER.getDefConfig().getConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ConfigPair> getConfig() {
|
||||
return FabricMod.CONFIGMANAGER.getConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGameVersions() {
|
||||
Optional<ModContainer> minecraftContainer = FabricLoader.getInstance().getModContainer("minecraft");
|
||||
if (minecraftContainer.isPresent()) {
|
||||
return minecraftContainer.get().getMetadata().getVersion().getFriendlyString();
|
||||
} else {
|
||||
return "未知版本";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModVersions() {
|
||||
Optional<ModContainer> EDNCContainer = FabricLoader.getInstance().getModContainer(MinecraftMod.MOD_ID);
|
||||
if (EDNCContainer.isPresent()) {
|
||||
return EDNCContainer.get().getMetadata().getVersion().getFriendlyString();
|
||||
} else {
|
||||
return "未知版本";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLoaderVersions() {
|
||||
Optional<ModContainer> loaderContainer = FabricLoader.getInstance().getModContainer("fabricloader");
|
||||
if (loaderContainer.isPresent()) {
|
||||
return loaderContainer.get().getMetadata().getVersion().getFriendlyString();
|
||||
} else {
|
||||
return "未知版本";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLoaderName() {
|
||||
return "Fabric";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EnchantmentEntity> getAllEnchantments() {
|
||||
return BuiltInRegistries.ENCHANTMENT.stream()
|
||||
.map((a) ->
|
||||
new EnchantmentEntity(
|
||||
a.getDescriptionId(),
|
||||
"null",
|
||||
a.getFullname(a.getMaxLevel()).getString(),
|
||||
BuiltInRegistries.ENCHANTMENT.getId(a)
|
||||
)
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getTest(Integer fid, Integer sid) {
|
||||
var f = BuiltInRegistries.ENCHANTMENT.byId(fid);
|
||||
var s = BuiltInRegistries.ENCHANTMENT.byId(sid);
|
||||
return f.isCompatibleWith(s) && s.isCompatibleWith(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveConfig(Map<String, ConfigPair> configPairMap) {
|
||||
FabricMod.CONFIGMANAGER.setConfig(configPairMap);
|
||||
FabricMod.CONFIGMANAGER.save();
|
||||
NetworkHandler.sendConfigToAllClient();
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.fabric.mixin;
|
||||
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.fabric.FabricMod;
|
||||
import net.minecraft.world.item.enchantment.Enchantment;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(Enchantment.class)
|
||||
public class EnchantmentMixin {
|
||||
|
||||
@Inject(method = "isCompatibleWith", at = @At("HEAD"), cancellable = true)
|
||||
private void isCompatibleWith(Enchantment enchantment, CallbackInfoReturnable<Boolean> cir) {
|
||||
var rb = FabricMod.ENCHANTMENTCONTROLLER.canBeCombined(
|
||||
enchantment.getDescriptionId(),
|
||||
getThis().getDescriptionId()
|
||||
);
|
||||
if (rb != null) {
|
||||
cir.setReturnValue(rb);
|
||||
}
|
||||
}
|
||||
|
||||
@Unique
|
||||
private Enchantment getThis() {
|
||||
return (Enchantment) (Object) this;
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.fabric.mixin;
|
||||
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.fabric.network.NetworkHandler;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.players.PlayerList;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(PlayerList.class)
|
||||
public abstract class PlayerListMixin {
|
||||
|
||||
@Inject(method = "placeNewPlayer", at = @At("RETURN"))
|
||||
private void onPlayerConnect(Connection connection, ServerPlayer serverPlayer, CallbackInfo ci) {
|
||||
NetworkHandler.sendConfigToClient(serverPlayer);
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.fabric.network;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.common.ConfigManager;
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.common.MinecraftMod;
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.fabric.FabricMod;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public class NetworkHandler {
|
||||
|
||||
public static final ResourceLocation CONFIG_PACKET_ID = new ResourceLocation(MinecraftMod.MOD_ID, "config_packet");
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
public static void sendConfigToClient(ServerPlayer player) {
|
||||
var config = FabricMod.CONFIGMANAGER.getConfig();
|
||||
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
|
||||
buf.writeUtf(ConfigManager.toyaml(config));
|
||||
ServerPlayNetworking.send(player, NetworkHandler.CONFIG_PACKET_ID, buf);
|
||||
LOGGER.info(
|
||||
"Send Player({}) Server {} config {}",
|
||||
player.getName().getString(),
|
||||
MinecraftMod.MOD_ID,
|
||||
ConfigManager.tojson(config)
|
||||
);
|
||||
}
|
||||
|
||||
public static void sendConfigToAllClient() {
|
||||
FabricMod.SERVER.getPlayerList().getPlayers().forEach(NetworkHandler::sendConfigToClient);
|
||||
}
|
||||
|
||||
public static void registerReceivers() {
|
||||
ClientPlayNetworking.registerGlobalReceiver(
|
||||
NetworkHandler.CONFIG_PACKET_ID,
|
||||
(client, handler, buf, responseSender) -> {
|
||||
var configData = ConfigManager.fromyaml(buf.readUtf());
|
||||
client.execute(() -> {
|
||||
FabricMod.CONFIGMANAGER.setConfig(configData);
|
||||
LOGGER.info("Load Server {} config {}", MinecraftMod.MOD_ID, ConfigManager.tojson(configData));
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
155
modsrc/1.20/Forge/build.gradle
Normal file
155
modsrc/1.20/Forge/build.gradle
Normal file
@ -0,0 +1,155 @@
|
||||
plugins {
|
||||
id 'eclipse'
|
||||
id 'idea'
|
||||
id 'maven-publish'
|
||||
id 'net.minecraftforge.gradle' version '[6.0,6.2)'
|
||||
id 'org.spongepowered.mixin' version '0.7+'
|
||||
}
|
||||
|
||||
version = "${loader_name}-${minecraft_version}-${mod_version}"
|
||||
group = maven_group
|
||||
|
||||
base {
|
||||
archivesName = mod_id
|
||||
}
|
||||
java.toolchain.languageVersion = JavaLanguageVersion.of(17)
|
||||
|
||||
println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}"
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java { srcDirs = ['src'] }
|
||||
resources { srcDirs = ['resources', project(":common").sourceSets.main.resources] }
|
||||
}
|
||||
}
|
||||
afterEvaluate {
|
||||
tasks.withType(JavaCompile) {
|
||||
options.annotationProcessorPath = files(configurations.annotationProcessor,
|
||||
project(":common").sourceSets.main.output)
|
||||
}
|
||||
}
|
||||
minecraft {
|
||||
mappings channel: mapping_channel, version: mapping_version
|
||||
copyIdeResources = true
|
||||
runs {
|
||||
client {
|
||||
workingDirectory project.file('run')
|
||||
property 'forge.logging.markers', 'REGISTRIES'
|
||||
property 'forge.enabledGameTestNamespaces', mod_id
|
||||
property 'forge.logging.console.level', 'info'
|
||||
mods {
|
||||
"${mod_id}" {
|
||||
source sourceSets.main
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
workingDirectory project.file('run')
|
||||
property 'forge.logging.markers', 'REGISTRIES'
|
||||
property 'forge.enabledGameTestNamespaces', mod_id
|
||||
property 'forge.logging.console.level', 'info'
|
||||
mods {
|
||||
"${mod_id}" {
|
||||
source sourceSets.main
|
||||
}
|
||||
}
|
||||
}
|
||||
gameTestServer {
|
||||
workingDirectory project.file('run')
|
||||
property 'forge.logging.markers', 'REGISTRIES'
|
||||
property 'forge.enabledGameTestNamespaces', mod_id
|
||||
property 'forge.logging.console.level', 'info'
|
||||
mods {
|
||||
"${mod_id}" {
|
||||
source sourceSets.main
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data {
|
||||
workingDirectory project.file('run')
|
||||
property 'forge.logging.markers', 'REGISTRIES'
|
||||
property 'forge.logging.console.level', 'debug'
|
||||
args '--mod', mod_id, '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/')
|
||||
mods {
|
||||
"${mod_id}" {
|
||||
source sourceSets.main
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mixin {
|
||||
add sourceSets.main, "enchantmentdoesnotconflict.forge.mixin.refmap.json"
|
||||
config "enchantmentdoesnotconflict.forge.mixin.json"
|
||||
}
|
||||
|
||||
repositories {}
|
||||
|
||||
dependencies {
|
||||
minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"
|
||||
minecraftLibrary(project(":common")) {
|
||||
exclude group: 'org.jetbrains', module: 'annotations'
|
||||
}
|
||||
annotationProcessor 'org.spongepowered:mixin:0.8.5:processor'
|
||||
}
|
||||
|
||||
def resourceTargets = ['META-INF/mods.toml', 'pack.mcmeta']
|
||||
def replaceProperties = [minecraft_version : minecraft_version,
|
||||
minecraft_version_range: minecraft_version_range,
|
||||
forge_version : forge_version,
|
||||
forge_version_range : forge_version_range,
|
||||
loader_version_range : loader_version_range,
|
||||
mod_id : mod_id,
|
||||
mod_name : mod_name,
|
||||
mod_license : mod_license,
|
||||
mod_version : mod_version,
|
||||
mod_authors : "${mod_author},${mod_contributor},${mod_contributor_2}",
|
||||
mod_description : mod_description]
|
||||
|
||||
processResources {
|
||||
inputs.properties replaceProperties
|
||||
replaceProperties.put 'project', project
|
||||
|
||||
filesMatching(resourceTargets) {
|
||||
expand replaceProperties
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
jar {
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
enabled = true
|
||||
manifest {
|
||||
attributes(["Specification-Title" : mod_id,
|
||||
"Specification-Vendor" : mod_author,
|
||||
"Specification-Version" : "1", // We are version 1 of ourselves
|
||||
"Implementation-Title" : project.name,
|
||||
"Implementation-Version" : project.jar.archiveVersion,
|
||||
"Implementation-Vendor" : mod_author,
|
||||
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
|
||||
"MixinConfigs": "enchantmentdoesnotconflict.forge.mixin.json"])
|
||||
}
|
||||
}
|
||||
|
||||
jar.finalizedBy('reobfJar')
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
mavenJava(MavenPublication) {
|
||||
artifact jar
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
maven {
|
||||
url "file://${project.projectDir}/mcmodsrepo"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.encoding = 'UTF-8'
|
||||
}
|
1
modsrc/1.20/Forge/gradle.properties
Normal file
1
modsrc/1.20/Forge/gradle.properties
Normal file
@ -0,0 +1 @@
|
||||
loader_name=Forge
|
23
modsrc/1.20/Forge/resources/META-INF/mods.toml
Normal file
23
modsrc/1.20/Forge/resources/META-INF/mods.toml
Normal file
@ -0,0 +1,23 @@
|
||||
modLoader="javafml"
|
||||
loaderVersion="${loader_version_range}"
|
||||
license="${mod_license}"
|
||||
[[mods]]
|
||||
modId="${mod_id}"
|
||||
version="${mod_version}"
|
||||
displayName="${mod_name}"
|
||||
authors="${mod_authors}"
|
||||
description='''${mod_description}'''
|
||||
[[mixins]]
|
||||
config="enchantmentdoesnotconflict.forge.mixins.json"
|
||||
[[dependencies.${mod_id}]]
|
||||
modId="forge"
|
||||
mandatory=true
|
||||
versionRange="${forge_version_range}"
|
||||
ordering="NONE"
|
||||
side="BOTH"
|
||||
[[dependencies.${mod_id}]]
|
||||
modId="minecraft"
|
||||
mandatory=true
|
||||
versionRange="${minecraft_version_range}"
|
||||
ordering="NONE"
|
||||
side="BOTH"
|
@ -0,0 +1,14 @@
|
||||
{
|
||||
"required": true,
|
||||
"package": "com.mingliqiye.minecraft.enchantment.conflict.forge.mixin",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"mixins": ["EnchantmentMixin"],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
},
|
||||
"minVersion": "0.8",
|
||||
"overwrites": {
|
||||
"requireAnnotations": true
|
||||
},
|
||||
"refmap": "enchantmentdoesnotconflict.forge.mixin.refmap.json"
|
||||
}
|
8
modsrc/1.20/Forge/resources/pack.mcmeta
Normal file
8
modsrc/1.20/Forge/resources/pack.mcmeta
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"pack": {
|
||||
"description": {
|
||||
"text": "${mod_id} resources"
|
||||
},
|
||||
"pack_format": 15
|
||||
}
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.forge;
|
||||
|
||||
import static com.mingliqiye.minecraft.enchantment.conflict.common.NetWorkUtils.isLocalAddress;
|
||||
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.common.ConfigManager;
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.common.MinecraftMod;
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.common.VersionsEnum;
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.common.WebConfigCore;
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.common.enchantment.EnchantmentController;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.Style;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.RegisterCommandsEvent;
|
||||
import net.minecraftforge.event.server.ServerStartedEvent;
|
||||
import net.minecraftforge.event.server.ServerStoppingEvent;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import net.minecraftforge.fml.loading.FMLPaths;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Mod(MinecraftMod.MOD_ID)
|
||||
public class ForgeMod {
|
||||
|
||||
public static final Logger LOGGER = LoggerFactory.getLogger(MinecraftMod.MOD_ID);
|
||||
public static MinecraftServer SERVER;
|
||||
|
||||
public static final ConfigManager CONFIGMANAGER = new ConfigManager(
|
||||
FMLPaths.CONFIGDIR.get(),
|
||||
LOGGER,
|
||||
VersionsEnum.V120
|
||||
);
|
||||
|
||||
public static final WebConfigCore WEBCONFIGCORE = new WebConfigCore(
|
||||
CONFIGMANAGER,
|
||||
new ForgeWebConfigCoreMeMethod()
|
||||
);
|
||||
|
||||
public static final EnchantmentController ENCHANTMENTCONTROLLER = new EnchantmentController(CONFIGMANAGER);
|
||||
|
||||
public ForgeMod() {
|
||||
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||
modEventBus.addListener(this::commonSetup);
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
}
|
||||
|
||||
private void commonSetup(final FMLCommonSetupEvent event) {}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onServerStarted(ServerStartedEvent event) {
|
||||
SERVER = event.getServer();
|
||||
WEBCONFIGCORE.start();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onServerStopping(ServerStoppingEvent event) {
|
||||
WEBCONFIGCORE.stop();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onRegisterCommands(RegisterCommandsEvent event) {
|
||||
LOGGER.info("onRegisterCommands");
|
||||
event
|
||||
.getDispatcher()
|
||||
.register(
|
||||
Commands.literal("enchantmentdoesnotconflict-config").executes((context) -> {
|
||||
var source = context.getSource();
|
||||
boolean isLocal =
|
||||
source.getServer().isSingleplayer() ||
|
||||
source.getEntity() == null ||
|
||||
(source.getPlayer() != null &&
|
||||
isLocalAddress(source.getPlayer().connection.getRemoteAddress()));
|
||||
if (isLocal) {
|
||||
WEBCONFIGCORE.openWeb();
|
||||
source.sendSuccess(
|
||||
() ->
|
||||
Component.literal("打开")
|
||||
.append(Component.literal(WEBCONFIGCORE.getLocalUrl()))
|
||||
.withStyle(
|
||||
Style.EMPTY.withColor(ChatFormatting.BLUE).withUnderlined(true) // 蓝色带下划线
|
||||
)
|
||||
.append(Component.literal("成功"))
|
||||
.withStyle(ChatFormatting.GREEN),
|
||||
true
|
||||
);
|
||||
} else {
|
||||
source.sendFailure(
|
||||
Component.literal("请使用服务器所在的机器执行该命令").withStyle(ChatFormatting.RED)
|
||||
);
|
||||
}
|
||||
return 1;
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.forge;
|
||||
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.common.ConfigPair;
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.common.MinecraftMod;
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.common.WebConfigCoreMeMethod;
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.common.enchantment.EnchantmentEntity;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
|
||||
public class ForgeWebConfigCoreMeMethod implements WebConfigCoreMeMethod {
|
||||
|
||||
@Override
|
||||
public void reloadConfig() {}
|
||||
|
||||
@Override
|
||||
public Map<String, ConfigPair> getDefConfig() {
|
||||
return ForgeMod.CONFIGMANAGER.getDefConfig().getConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ConfigPair> getConfig() {
|
||||
return ForgeMod.CONFIGMANAGER.getConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGameVersions() {
|
||||
return ModList.get()
|
||||
.getModContainerById("minecraft")
|
||||
.map((mod) -> mod.getModInfo().getVersion().toString())
|
||||
.orElse("未知版本");
|
||||
}
|
||||
|
||||
// 获取 Mod 版本
|
||||
@Override
|
||||
public String getModVersions() {
|
||||
return ModList.get()
|
||||
.getModContainerById(MinecraftMod.MOD_ID)
|
||||
.map((mod) -> mod.getModInfo().getVersion().toString())
|
||||
.orElse("未知版本");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLoaderVersions() {
|
||||
return ModList.get()
|
||||
.getModContainerById("forge")
|
||||
.map((mod) -> mod.getModInfo().getVersion().toString())
|
||||
.orElse("未知版本");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLoaderName() {
|
||||
return "Forge";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EnchantmentEntity> getAllEnchantments() {
|
||||
var registry = ForgeMod.SERVER.registryAccess().registryOrThrow(Registries.ENCHANTMENT);
|
||||
return registry
|
||||
.stream()
|
||||
.map((a) ->
|
||||
new EnchantmentEntity(
|
||||
a.getDescriptionId(),
|
||||
"null",
|
||||
a.getFullname(a.getMaxLevel()).getString(),
|
||||
registry.getId(a)
|
||||
)
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getTest(Integer fid, Integer sid) {
|
||||
var registry = ForgeMod.SERVER.registryAccess().registryOrThrow(Registries.ENCHANTMENT);
|
||||
var f = registry.byId(fid);
|
||||
var s = registry.byId(sid);
|
||||
return f.isCompatibleWith(s) && s.isCompatibleWith(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveConfig(Map<String, ConfigPair> configPairMap) {
|
||||
ForgeMod.CONFIGMANAGER.setConfig(configPairMap);
|
||||
ForgeMod.CONFIGMANAGER.save();
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.mingliqiye.minecraft.enchantment.conflict.forge.mixin;
|
||||
|
||||
import com.mingliqiye.minecraft.enchantment.conflict.forge.ForgeMod;
|
||||
import net.minecraft.world.item.enchantment.Enchantment;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(Enchantment.class)
|
||||
public class EnchantmentMixin {
|
||||
|
||||
@Inject(method = "isCompatibleWith", at = @At("HEAD"), cancellable = true)
|
||||
private void isCompatibleWith(Enchantment enchantment, CallbackInfoReturnable<Boolean> cir) {
|
||||
var rb = ForgeMod.ENCHANTMENTCONTROLLER.canBeCombined(
|
||||
enchantment.getDescriptionId(),
|
||||
getThis().getDescriptionId()
|
||||
);
|
||||
if (rb != null) {
|
||||
cir.setReturnValue(rb);
|
||||
}
|
||||
}
|
||||
|
||||
@Unique
|
||||
private Enchantment getThis() {
|
||||
return (Enchantment) (Object) this;
|
||||
}
|
||||
}
|
98
modsrc/1.20/build.gradle
Normal file
98
modsrc/1.20/build.gradle
Normal file
@ -0,0 +1,98 @@
|
||||
import java.util.jar.JarInputStream
|
||||
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'com.gradleup.shadow' version '9.0.0-rc1'
|
||||
}
|
||||
|
||||
java {
|
||||
withSourcesJar()
|
||||
}
|
||||
version = "${minecraft_version}-${mod_version}"
|
||||
base {
|
||||
archivesName = project.archives_base_name
|
||||
}
|
||||
|
||||
|
||||
def jars = mod_loaders.split(',').toList()
|
||||
def add_outer = mod_add_outer.split(',').toList()
|
||||
|
||||
def getManifestAttributes(File jarFile) {
|
||||
def manifestMap = [:]
|
||||
if (!jarFile.exists()) {
|
||||
return;
|
||||
}
|
||||
new JarInputStream(jarFile.newInputStream()).withCloseable { jarStream ->
|
||||
def manifest = jarStream.manifest
|
||||
if (manifest == null) {
|
||||
println "警告: ${jarFile.name} 中没有MANIFEST.MF"
|
||||
return manifestMap
|
||||
}
|
||||
manifest.mainAttributes.each { key, value -> manifestMap[key.toString()] = value.toString()
|
||||
}
|
||||
}
|
||||
return manifestMap
|
||||
}
|
||||
|
||||
def getJarName(String s) {
|
||||
return rootProject.projectDir.toPath().resolve("mod_build/${mod_id}-${s}-${minecraft_version}-${mod_version}.jar")
|
||||
}
|
||||
|
||||
def getJarNameOuther(String s, String v) {
|
||||
return rootProject.projectDir.toPath().resolve("mod_build/${mod_id}-${s}-${v}-${mod_version}.jar")
|
||||
}
|
||||
|
||||
|
||||
tasks.shadowJar {
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
mod_relocate_packs_id.split(",").toList().forEach {
|
||||
relocate("$it", "com.mingliqiye.minecraft.enchantment.conflict.library.$it")
|
||||
}
|
||||
dependsOn("sourcesJar")
|
||||
jars.forEach { t ->
|
||||
{
|
||||
dependsOn(":modsrc:${minecraft_version}:${t}:clean")
|
||||
dependsOn(":modsrc:${minecraft_version}:${t}:build")
|
||||
}
|
||||
}
|
||||
add_outer.forEach { t ->
|
||||
{
|
||||
dependsOn(":modsrc:${t}:clean")
|
||||
dependsOn(":modsrc:${t}:build")
|
||||
}
|
||||
}
|
||||
def allAttributes = [:]
|
||||
doFirst {
|
||||
jars.forEach { jar ->
|
||||
def file = getJarName(jar).toFile()
|
||||
if (file.exists()) {
|
||||
from(zipTree(file))
|
||||
allAttributes.putAll(getManifestAttributes(file))
|
||||
}
|
||||
}
|
||||
add_outer.forEach { t ->
|
||||
if (!t.isEmpty()) {
|
||||
def sp = t.split(":")
|
||||
def file = getJarNameOuther(sp[1], sp[0]).toFile()
|
||||
if (file.exists()) {
|
||||
from(zipTree(file))
|
||||
allAttributes.putAll(getManifestAttributes(file))
|
||||
}
|
||||
}
|
||||
}
|
||||
manifest.attributes(allAttributes)
|
||||
}
|
||||
archiveClassifier = ''
|
||||
from project(':common').sourceSets.main.output
|
||||
from {
|
||||
project(':common').configurations.runtimeClasspath
|
||||
.filter { it.exists() }
|
||||
.collect { it.isDirectory() ? it : zipTree(it) }
|
||||
} {
|
||||
exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA',
|
||||
'LICENSE', 'org/slf4j/**', "META-INF/maven/**", "META-INF/*LICENSE*",
|
||||
"META-INF/*NOTICE*", "META-INF/versions/**"
|
||||
}
|
||||
mergeServiceFiles()
|
||||
minimize()
|
||||
}
|
15
modsrc/1.20/gradle.properties
Normal file
15
modsrc/1.20/gradle.properties
Normal file
@ -0,0 +1,15 @@
|
||||
minecraft_version=1.20
|
||||
fabric_version=0.83.0+1.20
|
||||
fabric_loader_version=0.16.14
|
||||
fabric_loom_version=1.10.5
|
||||
java_version=17
|
||||
|
||||
mod_loaders=Fabric,Forge
|
||||
mod_add_outer=
|
||||
|
||||
mapping_channel=official
|
||||
mapping_version=1.20
|
||||
forge_version=46.0.14
|
||||
minecraft_version_range=[1.20,1.21)
|
||||
forge_version_range=[46,)
|
||||
loader_version_range=[46,)
|
44
package.json
Normal file
44
package.json
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "enchantmentdoesnotconflict",
|
||||
"version": "2.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "run-p type-check \"build-only {@}\" --",
|
||||
"preview": "vite preview",
|
||||
"build-only": "vite build",
|
||||
"type-check": "vue-tsc --build",
|
||||
"format": "prettier --write \"**/*.{js,ts,jsx,tsx,vue,astro,java,json}\""
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "Apache License 2.0",
|
||||
"packageManager": "pnpm@10.4.1",
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^2.3.1",
|
||||
"alova": "^3.3.4",
|
||||
"bluebird": "^3.7.2",
|
||||
"element-plus": "^2.10.4",
|
||||
"vue": "^3.5.17"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tsconfig/node22": "^22.0.2",
|
||||
"@types/bluebird": "^3.5.42",
|
||||
"@types/node": "^22.15.32",
|
||||
"@vitejs/plugin-vue": "^6.0.0",
|
||||
"@vue/tsconfig": "^0.7.0",
|
||||
"npm-run-all2": "^8.0.4",
|
||||
"prettier": "^3.6.2",
|
||||
"prettier-plugin-java": "^2.7.1",
|
||||
"typescript": "~5.8.0",
|
||||
"vite": "^7.0.0",
|
||||
"vite-plugin-vue-devtools": "^7.7.7",
|
||||
"vue-tsc": "^2.2.10"
|
||||
},
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
"esbuild"
|
||||
]
|
||||
}
|
||||
}
|
8
prettierrc
Normal file
8
prettierrc
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/prettierrc",
|
||||
"plugins": [
|
||||
"prettier-plugin-java"
|
||||
],
|
||||
"tabWidth": 4,
|
||||
"useTabs": false
|
||||
}
|
28
settings.gradle.kts
Normal file
28
settings.gradle.kts
Normal file
@ -0,0 +1,28 @@
|
||||
rootProject.name = "EnchantmentDoesNotConflict"
|
||||
|
||||
|
||||
|
||||
val projects: String by settings.extra
|
||||
val mod_name: String by settings.extra
|
||||
val mod_version: String by settings.extra
|
||||
|
||||
include(projects.split(","))
|
||||
|
||||
rootProject.name = "${mod_name} V${mod_version}"
|
||||
|
||||
pluginManagement {
|
||||
repositories {
|
||||
maven {
|
||||
name = "mingliqiye"
|
||||
url = uri("https://repository.mingliqiye.com/repository/maven-public/")
|
||||
}
|
||||
maven {
|
||||
name = "Fabric"
|
||||
url = uri("https://maven.fabricmc.net/")
|
||||
}
|
||||
maven {
|
||||
name = "MinecraftForge"
|
||||
url = uri("https://maven.minecraftforge.net/")
|
||||
}
|
||||
}
|
||||
}
|
205
src/App.vue
Normal file
205
src/App.vue
Normal file
@ -0,0 +1,205 @@
|
||||
<template>
|
||||
<ElConfigProvider :locale="zhCn">
|
||||
<div style="margin-bottom: 30px">
|
||||
<div style="margin: 15px 0" f-c-c>
|
||||
<h2>{{ info.ModName }} {{ info.ModVersions }}</h2>
|
||||
</div>
|
||||
|
||||
<div f-c-c style="flex-direction: column">
|
||||
<label>Minecraft 版本 {{ info.GameVersions }}</label>
|
||||
<label>{{ info.LoaderName }} 版本 {{ info.LoaderVersion }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div f-c-c style="flex-direction: column">
|
||||
<ElCard style="width: 90%; margin-bottom: 20px">
|
||||
<template #header>
|
||||
<div f-c-c>
|
||||
<h2>配置</h2>
|
||||
</div>
|
||||
</template>
|
||||
<ElCard class="card-config" v-for="(v, index) in config" style="width: 100%">
|
||||
<div style="display: flex">
|
||||
<div f-c-c style="height: auto">
|
||||
<label style="text-wrap: nowrap; margin-right: 10px">配置组</label>
|
||||
</div>
|
||||
|
||||
<div v-if="!v.ed" f-c-c style="height: auto">
|
||||
<label>{{ v.name }}</label>
|
||||
</div>
|
||||
|
||||
<ElInput style="width: 100%" v-else v-model="v.name">
|
||||
<template #append>
|
||||
<ElButton :icon="Select" @click="v.ed = false" />
|
||||
</template>
|
||||
</ElInput>
|
||||
|
||||
<div style="flex-grow: 1; height: 1px"></div>
|
||||
<el-button v-if="!v.ed" style="margin-left: 12px" type="primary" :icon="Edit" circle @click="v.ed = true" />
|
||||
<ElSwitch style="margin-left: 12px" v-model="v.e.allow" class="mb-2" />
|
||||
<ElPopconfirm title="确认删除?" @confirm="config = config.filter((item) => item !== v)">
|
||||
<template #reference>
|
||||
<el-button style="margin-left: 12px" type="danger" :icon="Delete" circle />
|
||||
</template>
|
||||
</ElPopconfirm>
|
||||
<el-button
|
||||
style="margin-left: 12px"
|
||||
type="success"
|
||||
:icon="FullScreen"
|
||||
circle
|
||||
@click="
|
||||
() => {
|
||||
dialogVisible = true;
|
||||
configtempM = v;
|
||||
}
|
||||
" />
|
||||
<el-button
|
||||
v-if="index === config.length - 1"
|
||||
style="margin-left: 12px"
|
||||
type="warning"
|
||||
:icon="Plus"
|
||||
@click="
|
||||
config.push({
|
||||
e: {
|
||||
allow: false,
|
||||
allowlist: [],
|
||||
},
|
||||
ed: false,
|
||||
name: '新组',
|
||||
})
|
||||
"
|
||||
circle />
|
||||
</div>
|
||||
</ElCard>
|
||||
</ElCard>
|
||||
<ElCard style="width: 90%">
|
||||
<template #header>
|
||||
<div f-c-c>
|
||||
<h2>测试是否冲突</h2>
|
||||
</div>
|
||||
</template>
|
||||
<div>
|
||||
<div f-c-c style="justify-content: center">
|
||||
<ElSelect @change="test" style="width: 45%" v-model="testE.f">
|
||||
<ElOption
|
||||
v-for="item in enchantments"
|
||||
:key="item.id"
|
||||
:label="getEnlang(item.id, item.name)"
|
||||
:value="item.nid" />
|
||||
</ElSelect>
|
||||
<div style="flex-grow: 1"></div>
|
||||
{{ iscongtu ? '不冲突' : '冲突' }}
|
||||
<div style="flex-grow: 1"></div>
|
||||
<ElSelect @change="test" style="width: 45%" v-model="testE.s">
|
||||
<ElOption
|
||||
v-for="item in enchantments"
|
||||
:key="item.id"
|
||||
:label="getEnlang(item.id, item.name)"
|
||||
:value="item.nid" />
|
||||
</ElSelect>
|
||||
</div>
|
||||
</div>
|
||||
</ElCard>
|
||||
</div>
|
||||
<ElDialog v-model="dialogVisible" :title="'修改配置组 ' + configtempM.name" align-center width="800">
|
||||
<div class="card-config" f-c-c v-for="(item, index) in configtempM.e.allowlist">
|
||||
<label style="margin-right: 20px">{{ index + 1 }}</label>
|
||||
<ElSelect v-model="configtempM.e.allowlist[index]">
|
||||
<ElOption
|
||||
v-for="item in enchantments"
|
||||
:key="item.id"
|
||||
:label="getEnlang(item.id, item.name)"
|
||||
:value="item.id" />
|
||||
</ElSelect>
|
||||
<ElButton
|
||||
style="margin-left: 10px"
|
||||
type="danger"
|
||||
@click="() => (configtempM.e.allowlist = configtempM.e.allowlist.filter((ee) => ee !== item))">
|
||||
删除
|
||||
</ElButton>
|
||||
</div>
|
||||
<ElButton type="primary" style="margin-left: 28px" @click="() => configtempM.e.allowlist.push('')">添加</ElButton>
|
||||
</ElDialog>
|
||||
</ElConfigProvider>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ElConfigProvider, ElOption, ElSelect } from 'element-plus';
|
||||
import zhCn from 'element-plus/es/locale/lang/zh-cn';
|
||||
import Apis from '@/api/apis.ts';
|
||||
import EnLangs from '@/resources/enLangs.json';
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
import type { Config, ConfigPair, EnchantmentEntity, ModInfoType } from '@/api/types.ts';
|
||||
import { ElButton, ElCard, ElDialog, ElInput, ElPopconfirm, ElSwitch } from 'element-plus';
|
||||
import { Delete, Edit, FullScreen, Plus, Select } from '@element-plus/icons-vue';
|
||||
|
||||
const getEnlang = (i: string, def: string) => {
|
||||
i = i.replace('minecraft:', 'enchantment.minecraft.');
|
||||
return Object.keys(EnLangs).includes(i) ? EnLangs[i] : def;
|
||||
};
|
||||
const testE = ref<{
|
||||
f: number | null;
|
||||
s: number | null;
|
||||
}>({
|
||||
f: null,
|
||||
s: null,
|
||||
});
|
||||
const test = () => {
|
||||
if (testE.value.f != null && testE.value.s != null) {
|
||||
Apis.getTest(testE.value.f, testE.value.s).then((r) => (iscongtu.value = r.data));
|
||||
}
|
||||
};
|
||||
type ConfigTem = { e: ConfigPair; ed: boolean; name: string };
|
||||
const info = ref<ModInfoType>({ GameVersions: '', LoaderName: '', LoaderVersion: '', ModName: '', ModVersions: '' });
|
||||
const config = ref<ConfigTem[]>([]);
|
||||
const dialogVisible = ref(false);
|
||||
const iscongtu = ref(false);
|
||||
const configtempM = ref<ConfigTem>({
|
||||
e: {
|
||||
allow: false,
|
||||
allowlist: [],
|
||||
},
|
||||
ed: false,
|
||||
name: '',
|
||||
});
|
||||
const enchantments = ref<{ [key: string]: EnchantmentEntity }>({});
|
||||
const getdata = () => {
|
||||
Apis.getInfo().then((r) => (info.value = r.data));
|
||||
Apis.getConfig().then((r) => {
|
||||
Object.keys(r.data).forEach((a) => config.value.push({ ed: false, name: a, e: r.data[a] }));
|
||||
startw();
|
||||
});
|
||||
Apis.getEnchantments().then((r) => {
|
||||
r.data.forEach((a) => {
|
||||
enchantments.value[a.id] = a;
|
||||
});
|
||||
});
|
||||
};
|
||||
const startw = () => {
|
||||
watch(
|
||||
() => config.value,
|
||||
() => {
|
||||
const data: Config = {};
|
||||
config.value.forEach((a) => {
|
||||
data[a.name] = a.e;
|
||||
});
|
||||
Apis.sendConfig(data).then();
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
},
|
||||
);
|
||||
};
|
||||
onMounted(getdata);
|
||||
</script>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.card-config {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.card-config:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
</style>
|
13
src/api/alova.ts
Normal file
13
src/api/alova.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { createAlova } from 'alova';
|
||||
import adapterFetch from 'alova/fetch';
|
||||
|
||||
const alovaInstance = createAlova({
|
||||
requestAdapter: adapterFetch(),
|
||||
responded: (response) => {
|
||||
if (response.status == 200) return response.json();
|
||||
else throw new Error('请求失败');
|
||||
},
|
||||
cacheFor: null,
|
||||
});
|
||||
|
||||
export default alovaInstance;
|
16
src/api/apis.ts
Normal file
16
src/api/apis.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import alovaInstance from '@/api/alova.ts';
|
||||
import type { Config, ModInfoType, Respose, EnchantmentEntity } from '@/api/types.ts';
|
||||
|
||||
const map: Map<string, string> = new Map();
|
||||
const baseURL = '/api';
|
||||
export default {
|
||||
getInfo: () => alovaInstance.Get<Respose<ModInfoType>>(baseURL + '/get/info'),
|
||||
getEnchantments: () => alovaInstance.Get<Respose<EnchantmentEntity[]>>(baseURL + '/get/enchantments'),
|
||||
getConfig: () => alovaInstance.Get<Respose<Config>>(baseURL + '/get/client/config'),
|
||||
getTest: (fid: number, sid: number) =>
|
||||
alovaInstance.Post<Respose<boolean>>(baseURL + '/get/test', {
|
||||
fid,
|
||||
sid,
|
||||
}),
|
||||
sendConfig: (config: Config) => alovaInstance.Post(baseURL + '/send/config', config),
|
||||
};
|
30
src/api/types.ts
Normal file
30
src/api/types.ts
Normal file
@ -0,0 +1,30 @@
|
||||
export interface Respose<T> {
|
||||
code: number;
|
||||
message: string;
|
||||
data: T;
|
||||
dateTime: string;
|
||||
}
|
||||
|
||||
export interface ModInfoType {
|
||||
LoaderVersion: string;
|
||||
LoaderName: string;
|
||||
GameVersions: string;
|
||||
ModVersions: string;
|
||||
ModName: string;
|
||||
}
|
||||
|
||||
export interface EnchantmentEntity {
|
||||
id: string;
|
||||
father: string;
|
||||
name: string;
|
||||
nid: number;
|
||||
}
|
||||
|
||||
export interface Config {
|
||||
[key: string]: ConfigPair;
|
||||
}
|
||||
|
||||
export interface ConfigPair {
|
||||
allow: boolean;
|
||||
allowlist: string[];
|
||||
}
|
12
src/main.ts
Normal file
12
src/main.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { createApp } from 'vue';
|
||||
import App from './App.vue';
|
||||
import '/src/resources/index.css';
|
||||
import 'element-plus/es/components/card/style/css';
|
||||
import 'element-plus/es/components/switch/style/css';
|
||||
import 'element-plus/es/components/button/style/css';
|
||||
import 'element-plus/es/components/input/style/css';
|
||||
import 'element-plus/es/components/dialog/style/css';
|
||||
import 'element-plus/es/components/popconfirm/style/css';
|
||||
import 'element-plus/es/components/option/style/css';
|
||||
import 'element-plus/es/components/select/style/css';
|
||||
createApp(App).mount('main');
|
45
src/resources/enLangs.json
Normal file
45
src/resources/enLangs.json
Normal file
@ -0,0 +1,45 @@
|
||||
{
|
||||
"enchantment.minecraft.aqua_affinity": "水下速掘",
|
||||
"enchantment.minecraft.bane_of_arthropods": "节肢杀手",
|
||||
"enchantment.minecraft.binding_curse": "绑定诅咒",
|
||||
"enchantment.minecraft.blast_protection": "爆炸保护",
|
||||
"enchantment.minecraft.breach": "破甲",
|
||||
"enchantment.minecraft.channeling": "引雷",
|
||||
"enchantment.minecraft.density": "致密",
|
||||
"enchantment.minecraft.depth_strider": "深海探索者",
|
||||
"enchantment.minecraft.efficiency": "效率",
|
||||
"enchantment.minecraft.feather_falling": "摔落缓冲",
|
||||
"enchantment.minecraft.fire_aspect": "火焰附加",
|
||||
"enchantment.minecraft.fire_protection": "火焰保护",
|
||||
"enchantment.minecraft.flame": "火矢",
|
||||
"enchantment.minecraft.fortune": "时运",
|
||||
"enchantment.minecraft.frost_walker": "冰霜行者",
|
||||
"enchantment.minecraft.impaling": "穿刺",
|
||||
"enchantment.minecraft.infinity": "无限",
|
||||
"enchantment.minecraft.knockback": "击退",
|
||||
"enchantment.minecraft.looting": "抢夺",
|
||||
"enchantment.minecraft.loyalty": "忠诚",
|
||||
"enchantment.minecraft.luck_of_the_sea": "海之眷顾",
|
||||
"enchantment.minecraft.lure": "饵钓",
|
||||
"enchantment.minecraft.mending": "经验修补",
|
||||
"enchantment.minecraft.multishot": "多重射击",
|
||||
"enchantment.minecraft.piercing": "穿透",
|
||||
"enchantment.minecraft.power": "力量",
|
||||
"enchantment.minecraft.projectile_protection": "弹射物保护",
|
||||
"enchantment.minecraft.protection": "保护",
|
||||
"enchantment.minecraft.punch": "冲击",
|
||||
"enchantment.minecraft.quick_charge": "快速装填",
|
||||
"enchantment.minecraft.respiration": "水下呼吸",
|
||||
"enchantment.minecraft.riptide": "激流",
|
||||
"enchantment.minecraft.sharpness": "锋利",
|
||||
"enchantment.minecraft.silk_touch": "精准采集",
|
||||
"enchantment.minecraft.smite": "亡灵杀手",
|
||||
"enchantment.minecraft.soul_speed": "灵魂疾行",
|
||||
"enchantment.minecraft.sweeping": "横扫之刃",
|
||||
"enchantment.minecraft.sweeping_edge": "横扫之刃",
|
||||
"enchantment.minecraft.swift_sneak": "迅捷潜行",
|
||||
"enchantment.minecraft.thorns": "荆棘",
|
||||
"enchantment.minecraft.unbreaking": "耐久",
|
||||
"enchantment.minecraft.vanishing_curse": "消失诅咒",
|
||||
"enchantment.minecraft.wind_burst": "风爆"
|
||||
}
|
BIN
src/resources/icon.png
Normal file
BIN
src/resources/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 67 KiB |
5
src/resources/index.css
Normal file
5
src/resources/index.css
Normal file
@ -0,0 +1,5 @@
|
||||
*[f-c-c]{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
BIN
src/resources/title_full.png
Normal file
BIN
src/resources/title_full.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 218 KiB |
12
tsconfig.app.json
Normal file
12
tsconfig.app.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"extends": "@vue/tsconfig/tsconfig.dom.json",
|
||||
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
|
||||
"exclude": ["src/**/__tests__/*"],
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
}
|
||||
}
|
11
tsconfig.json
Normal file
11
tsconfig.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.node.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
}
|
||||
]
|
||||
}
|
19
tsconfig.node.json
Normal file
19
tsconfig.node.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"extends": "@tsconfig/node22/tsconfig.json",
|
||||
"include": [
|
||||
"vite.config.*",
|
||||
"vitest.config.*",
|
||||
"cypress.config.*",
|
||||
"nightwatch.conf.*",
|
||||
"playwright.config.*",
|
||||
"eslint.config.*"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"noEmit": true,
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"types": ["node"]
|
||||
}
|
||||
}
|
22
vite.config.ts
Normal file
22
vite.config.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { fileURLToPath, URL } from 'node:url';
|
||||
|
||||
import { defineConfig } from 'vite';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import vueDevTools from 'vite-plugin-vue-devtools';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [vue(), vueDevTools()],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
||||
},
|
||||
},
|
||||
build: {
|
||||
outDir: 'dist/assets/enchantmentdoesnotconflict/web',
|
||||
},
|
||||
server: {
|
||||
proxy: {
|
||||
'/api': 'http://localhost:1355/',
|
||||
},
|
||||
},
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user