commit 7784fddd2753d35d2440e5270401b75a6082a023 Author: minglipro Date: Sun Jul 20 23:08:54 2025 +0800 add 1.20 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..bc74af5 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +/gradlew text eol=lf +*.jar binary +*.png binary +*.jpg binary +*.class binary +* text=auto eol=lf +*.bat text eol=crlf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f7e171c --- /dev/null +++ b/.gitignore @@ -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 diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..0494c5b --- /dev/null +++ b/.prettierrc @@ -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 + } + } + ] +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE @@ -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. diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..7fbc3f9 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,64 @@ + + +subprojects { + apply(plugin = "java") + apply(plugin = "idea") + tasks.withType().configureEach() { + destinationDirectory.set( + rootProject.projectDir.resolve("mod_build") + ) + } + tasks.named("jar") { + enabled = false + } + tasks.withType().configureEach { + options.release.set(17) + } +} +tasks.withType { + jvmArgs = listOf( + "-Dfile.encoding=UTF-8", + "-Dsun.stdout.encoding=UTF-8", + "-Dsun.stderr.encoding=UTF-8" + ) +} +tasks.withType { + 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") +} diff --git a/common/build.gradle.kts b/common/build.gradle.kts new file mode 100644 index 0000000..f0fbbe8 --- /dev/null +++ b/common/build.gradle.kts @@ -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 +} diff --git a/common/gradle.properties b/common/gradle.properties new file mode 100644 index 0000000..d2b409d --- /dev/null +++ b/common/gradle.properties @@ -0,0 +1 @@ +java_version=17 diff --git a/common/resources/assets/enchantmentdoesnotconflict/config/enchantmentdoesnotconflict_1.20.json b/common/resources/assets/enchantmentdoesnotconflict/config/enchantmentdoesnotconflict_1.20.json new file mode 100644 index 0000000..74e4bb0 --- /dev/null +++ b/common/resources/assets/enchantmentdoesnotconflict/config/enchantmentdoesnotconflict_1.20.json @@ -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"] + } +} diff --git a/common/resources/assets/enchantmentdoesnotconflict/config/enchantmentdoesnotconflict_1.21.json b/common/resources/assets/enchantmentdoesnotconflict/config/enchantmentdoesnotconflict_1.21.json new file mode 100644 index 0000000..8eafa13 --- /dev/null +++ b/common/resources/assets/enchantmentdoesnotconflict/config/enchantmentdoesnotconflict_1.21.json @@ -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" + ] + } +} diff --git a/common/resources/assets/enchantmentdoesnotconflict/textures/logo/icon.png b/common/resources/assets/enchantmentdoesnotconflict/textures/logo/icon.png new file mode 100644 index 0000000..69181e3 Binary files /dev/null and b/common/resources/assets/enchantmentdoesnotconflict/textures/logo/icon.png differ diff --git a/common/resources/assets/enchantmentdoesnotconflict/textures/logo/title_full.png b/common/resources/assets/enchantmentdoesnotconflict/textures/logo/title_full.png new file mode 100644 index 0000000..3870a00 Binary files /dev/null and b/common/resources/assets/enchantmentdoesnotconflict/textures/logo/title_full.png differ diff --git a/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/ConfigManager.java b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/ConfigManager.java new file mode 100644 index 0000000..ac10833 --- /dev/null +++ b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/ConfigManager.java @@ -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 fromyaml(String s) { + try { + return YALMOBJECTMAPPER.readValue(s, MODCONFIGTYPE); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + public static String toyaml(Map c) { + try { + return YALMOBJECTMAPPER.writeValueAsString(c); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + public static Map fromjson(String s) { + try { + return JSONOBJECTMAPPER.readValue(s, MODCONFIGTYPE); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + public static String tojson(Map c) { + try { + return JSONOBJECTMAPPER.writeValueAsString(c); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + public Map getConfig() { + return config; + } + + public void setConfig(Map config) { + this.config = config; + } + + private Map 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 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 save() { + return save(config); + } + + public Map save(Map 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; + } +} diff --git a/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/ConfigPair.java b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/ConfigPair.java new file mode 100644 index 0000000..19ceb5f --- /dev/null +++ b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/ConfigPair.java @@ -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 allowlist; + + public ConfigPair() {} + + ConfigPair(Boolean allow, List allowlist) { + this.allow = allow; + this.allowlist = allowlist; + } + + public List getAllowlist() { + return allowlist; + } + + public void setAllowlist(List 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; + } +} diff --git a/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/DataFormat.java b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/DataFormat.java new file mode 100644 index 0000000..dc9dcbb --- /dev/null +++ b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/DataFormat.java @@ -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(); +} diff --git a/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/DateTime.java b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/DateTime.java new file mode 100644 index 0000000..bbca443 --- /dev/null +++ b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/DateTime.java @@ -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; + +/** + *

自定义时间类 + * + * @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; + } + } +} diff --git a/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/DateTimeJsonDeserializer.java b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/DateTimeJsonDeserializer.java new file mode 100644 index 0000000..8a7f284 --- /dev/null +++ b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/DateTimeJsonDeserializer.java @@ -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 { + + @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); + } +} diff --git a/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/DateTimeJsonSerializer.java b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/DateTimeJsonSerializer.java new file mode 100644 index 0000000..508f7d4 --- /dev/null +++ b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/DateTimeJsonSerializer.java @@ -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 { + + @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); + } +} diff --git a/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/DefConfig.java b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/DefConfig.java new file mode 100644 index 0000000..7ffbcaa --- /dev/null +++ b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/DefConfig.java @@ -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 config121; + private final Map 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 getConfig121() { + return config121; + } + + public Map getConfig120() { + return config120; + } + + public Map getConfig() { + if (versionsEnum == VersionsEnum.V120) { + return getConfig120(); + } else if (versionsEnum == VersionsEnum.V121) { + return getConfig121(); + } + return null; + } +} diff --git a/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/ExceptionCode.java b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/ExceptionCode.java new file mode 100644 index 0000000..5f39508 --- /dev/null +++ b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/ExceptionCode.java @@ -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; + } +} diff --git a/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/Funs.java b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/Funs.java new file mode 100644 index 0000000..ba9c062 --- /dev/null +++ b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/Funs.java @@ -0,0 +1,19 @@ +package com.mingliqiye.minecraft.enchantment.conflict.common; + +public final class Funs { + + @FunctionalInterface + public interface P1Fun { + void call(T p); + } + + @FunctionalInterface + public interface Fun { + void call(); + } + + @FunctionalInterface + public interface R1Fun { + T call(); + } +} diff --git a/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/MinecraftMod.java b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/MinecraftMod.java new file mode 100644 index 0000000..cf6495d --- /dev/null +++ b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/MinecraftMod.java @@ -0,0 +1,6 @@ +package com.mingliqiye.minecraft.enchantment.conflict.common; + +public class MinecraftMod { + + public static final String MOD_ID = "enchantmentdoesnotconflict"; +} diff --git a/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/NetWorkUtils.java b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/NetWorkUtils.java new file mode 100644 index 0000000..071a876 --- /dev/null +++ b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/NetWorkUtils.java @@ -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()); + } +} diff --git a/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/Respose.java b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/Respose.java new file mode 100644 index 0000000..6f79e38 --- /dev/null +++ b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/Respose.java @@ -0,0 +1,79 @@ +package com.mingliqiye.minecraft.enchantment.conflict.common; + +public class Respose { + + 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 Respose builder() { + return new Respose<>(); + } + + public static Respose builder(T data) { + return new Respose<>().setData(data); + } + + public static Respose error(Class type, Integer code, String message) { + return new Respose().setCode(code).setMessage(message); + } + + public static Respose error(Class type, ExceptionCode code, String message) { + return error(type, code.getValue(), message); + } + + public String getMessage() { + return message; + } + + public Respose setMessage(String message) { + this.message = message; + return this; + } + + public int getCode() { + return code; + } + + public Respose setCode(int code) { + this.code = code; + return this; + } + + public DateTime getDateTime() { + return dateTime; + } + + public T getData() { + return data; + } + + public Respose setData(TD data) { + return new Respose<>(code, message, data); + } +} diff --git a/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/VersionsEnum.java b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/VersionsEnum.java new file mode 100644 index 0000000..1c3ab31 --- /dev/null +++ b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/VersionsEnum.java @@ -0,0 +1,6 @@ +package com.mingliqiye.minecraft.enchantment.conflict.common; + +public enum VersionsEnum { + V120, + V121, +} diff --git a/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/WebApis.java b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/WebApis.java new file mode 100644 index 0000000..e73ccad --- /dev/null +++ b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/WebApis.java @@ -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()); + } +} diff --git a/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/WebConfigCore.java b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/WebConfigCore.java new file mode 100644 index 0000000..620b3dc --- /dev/null +++ b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/WebConfigCore.java @@ -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()); + } +} diff --git a/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/WebConfigCoreMeMethod.java b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/WebConfigCoreMeMethod.java new file mode 100644 index 0000000..98cb49c --- /dev/null +++ b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/WebConfigCoreMeMethod.java @@ -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 getDefConfig(); + + Map 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 getAllEnchantments(); + + boolean getTest(Integer fid, Integer sid); + + void saveConfig(Map configPairMap); +} diff --git a/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/WebOpener.java b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/WebOpener.java new file mode 100644 index 0000000..df3d3fe --- /dev/null +++ b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/WebOpener.java @@ -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(); + } + } +} diff --git a/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/enchantment/AddAllowEnchantmentFunInf.java b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/enchantment/AddAllowEnchantmentFunInf.java new file mode 100644 index 0000000..16ca70e --- /dev/null +++ b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/enchantment/AddAllowEnchantmentFunInf.java @@ -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> call(); +} diff --git a/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/enchantment/EnchantmentController.java b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/enchantment/EnchantmentController.java new file mode 100644 index 0000000..5ac0ad5 --- /dev/null +++ b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/enchantment/EnchantmentController.java @@ -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 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 groupsA = ofId(enchantmentA); + List 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 ofId(String id) { + final List 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; + } +} diff --git a/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/enchantment/EnchantmentEntity.java b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/enchantment/EnchantmentEntity.java new file mode 100644 index 0000000..026f1b5 --- /dev/null +++ b/common/src/com/mingliqiye/minecraft/enchantment/conflict/common/enchantment/EnchantmentEntity.java @@ -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; + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..dd8580a --- /dev/null +++ b/gradle.properties @@ -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 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..4ac3234 --- /dev/null +++ b/gradle/libs.versions.toml @@ -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 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..1b33c55 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..ff23a68 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -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 diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..23d15a9 --- /dev/null +++ b/gradlew @@ -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" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..db3a6ac --- /dev/null +++ b/gradlew.bat @@ -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 diff --git a/index.html b/index.html new file mode 100644 index 0000000..005a01a --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + + 附魔不冲突 配置 + + +

+ + + diff --git a/modsrc/1.20/Fabric/build.gradle b/modsrc/1.20/Fabric/build.gradle new file mode 100644 index 0000000..7373593 --- /dev/null +++ b/modsrc/1.20/Fabric/build.gradle @@ -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{ +} diff --git a/modsrc/1.20/Fabric/gradle.properties b/modsrc/1.20/Fabric/gradle.properties new file mode 100644 index 0000000..88c9bf7 --- /dev/null +++ b/modsrc/1.20/Fabric/gradle.properties @@ -0,0 +1 @@ +loader_name=Fabric diff --git a/modsrc/1.20/Fabric/resources/enchantmentdoesnotconflict.fabric.mixin.json b/modsrc/1.20/Fabric/resources/enchantmentdoesnotconflict.fabric.mixin.json new file mode 100644 index 0000000..fe18d8d --- /dev/null +++ b/modsrc/1.20/Fabric/resources/enchantmentdoesnotconflict.fabric.mixin.json @@ -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 + } +} diff --git a/modsrc/1.20/Fabric/resources/fabric.mod.json b/modsrc/1.20/Fabric/resources/fabric.mod.json new file mode 100644 index 0000000..1edd7d5 --- /dev/null +++ b/modsrc/1.20/Fabric/resources/fabric.mod.json @@ -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": "*" + } +} diff --git a/modsrc/1.20/Fabric/src/com/mingliqiye/minecraft/enchantment/conflict/fabric/FabricMod.java b/modsrc/1.20/Fabric/src/com/mingliqiye/minecraft/enchantment/conflict/fabric/FabricMod.java new file mode 100644 index 0000000..581b6b1 --- /dev/null +++ b/modsrc/1.20/Fabric/src/com/mingliqiye/minecraft/enchantment/conflict/fabric/FabricMod.java @@ -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; + }) + ); + }); + } +} diff --git a/modsrc/1.20/Fabric/src/com/mingliqiye/minecraft/enchantment/conflict/fabric/FabricModClient.java b/modsrc/1.20/Fabric/src/com/mingliqiye/minecraft/enchantment/conflict/fabric/FabricModClient.java new file mode 100644 index 0000000..74391df --- /dev/null +++ b/modsrc/1.20/Fabric/src/com/mingliqiye/minecraft/enchantment/conflict/fabric/FabricModClient.java @@ -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(); + } +} diff --git a/modsrc/1.20/Fabric/src/com/mingliqiye/minecraft/enchantment/conflict/fabric/FabricWebConfigCoreMeMethod.java b/modsrc/1.20/Fabric/src/com/mingliqiye/minecraft/enchantment/conflict/fabric/FabricWebConfigCoreMeMethod.java new file mode 100644 index 0000000..f2c2cdf --- /dev/null +++ b/modsrc/1.20/Fabric/src/com/mingliqiye/minecraft/enchantment/conflict/fabric/FabricWebConfigCoreMeMethod.java @@ -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 getDefConfig() { + return FabricMod.CONFIGMANAGER.getDefConfig().getConfig(); + } + + @Override + public Map getConfig() { + return FabricMod.CONFIGMANAGER.getConfig(); + } + + @Override + public String getGameVersions() { + Optional minecraftContainer = FabricLoader.getInstance().getModContainer("minecraft"); + if (minecraftContainer.isPresent()) { + return minecraftContainer.get().getMetadata().getVersion().getFriendlyString(); + } else { + return "未知版本"; + } + } + + @Override + public String getModVersions() { + Optional EDNCContainer = FabricLoader.getInstance().getModContainer(MinecraftMod.MOD_ID); + if (EDNCContainer.isPresent()) { + return EDNCContainer.get().getMetadata().getVersion().getFriendlyString(); + } else { + return "未知版本"; + } + } + + @Override + public String getLoaderVersions() { + Optional 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 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 configPairMap) { + FabricMod.CONFIGMANAGER.setConfig(configPairMap); + FabricMod.CONFIGMANAGER.save(); + NetworkHandler.sendConfigToAllClient(); + } +} diff --git a/modsrc/1.20/Fabric/src/com/mingliqiye/minecraft/enchantment/conflict/fabric/mixin/EnchantmentMixin.java b/modsrc/1.20/Fabric/src/com/mingliqiye/minecraft/enchantment/conflict/fabric/mixin/EnchantmentMixin.java new file mode 100644 index 0000000..94ca7b2 --- /dev/null +++ b/modsrc/1.20/Fabric/src/com/mingliqiye/minecraft/enchantment/conflict/fabric/mixin/EnchantmentMixin.java @@ -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 cir) { + var rb = FabricMod.ENCHANTMENTCONTROLLER.canBeCombined( + enchantment.getDescriptionId(), + getThis().getDescriptionId() + ); + if (rb != null) { + cir.setReturnValue(rb); + } + } + + @Unique + private Enchantment getThis() { + return (Enchantment) (Object) this; + } +} diff --git a/modsrc/1.20/Fabric/src/com/mingliqiye/minecraft/enchantment/conflict/fabric/mixin/PlayerListMixin.java b/modsrc/1.20/Fabric/src/com/mingliqiye/minecraft/enchantment/conflict/fabric/mixin/PlayerListMixin.java new file mode 100644 index 0000000..56ee024 --- /dev/null +++ b/modsrc/1.20/Fabric/src/com/mingliqiye/minecraft/enchantment/conflict/fabric/mixin/PlayerListMixin.java @@ -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); + } +} diff --git a/modsrc/1.20/Fabric/src/com/mingliqiye/minecraft/enchantment/conflict/fabric/network/NetworkHandler.java b/modsrc/1.20/Fabric/src/com/mingliqiye/minecraft/enchantment/conflict/fabric/network/NetworkHandler.java new file mode 100644 index 0000000..08bce96 --- /dev/null +++ b/modsrc/1.20/Fabric/src/com/mingliqiye/minecraft/enchantment/conflict/fabric/network/NetworkHandler.java @@ -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)); + }); + } + ); + } +} diff --git a/modsrc/1.20/Forge/build.gradle b/modsrc/1.20/Forge/build.gradle new file mode 100644 index 0000000..47aa625 --- /dev/null +++ b/modsrc/1.20/Forge/build.gradle @@ -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' +} diff --git a/modsrc/1.20/Forge/gradle.properties b/modsrc/1.20/Forge/gradle.properties new file mode 100644 index 0000000..bf67137 --- /dev/null +++ b/modsrc/1.20/Forge/gradle.properties @@ -0,0 +1 @@ +loader_name=Forge diff --git a/modsrc/1.20/Forge/resources/META-INF/mods.toml b/modsrc/1.20/Forge/resources/META-INF/mods.toml new file mode 100644 index 0000000..9ec2259 --- /dev/null +++ b/modsrc/1.20/Forge/resources/META-INF/mods.toml @@ -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" diff --git a/modsrc/1.20/Forge/resources/enchantmentdoesnotconflict.forge.mixin.json b/modsrc/1.20/Forge/resources/enchantmentdoesnotconflict.forge.mixin.json new file mode 100644 index 0000000..e80fd9b --- /dev/null +++ b/modsrc/1.20/Forge/resources/enchantmentdoesnotconflict.forge.mixin.json @@ -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" +} diff --git a/modsrc/1.20/Forge/resources/pack.mcmeta b/modsrc/1.20/Forge/resources/pack.mcmeta new file mode 100644 index 0000000..eca79ae --- /dev/null +++ b/modsrc/1.20/Forge/resources/pack.mcmeta @@ -0,0 +1,8 @@ +{ + "pack": { + "description": { + "text": "${mod_id} resources" + }, + "pack_format": 15 + } +} \ No newline at end of file diff --git a/modsrc/1.20/Forge/src/com/mingliqiye/minecraft/enchantment/conflict/forge/ForgeMod.java b/modsrc/1.20/Forge/src/com/mingliqiye/minecraft/enchantment/conflict/forge/ForgeMod.java new file mode 100644 index 0000000..954e943 --- /dev/null +++ b/modsrc/1.20/Forge/src/com/mingliqiye/minecraft/enchantment/conflict/forge/ForgeMod.java @@ -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; + }) + ); + } +} diff --git a/modsrc/1.20/Forge/src/com/mingliqiye/minecraft/enchantment/conflict/forge/ForgeWebConfigCoreMeMethod.java b/modsrc/1.20/Forge/src/com/mingliqiye/minecraft/enchantment/conflict/forge/ForgeWebConfigCoreMeMethod.java new file mode 100644 index 0000000..6bf8890 --- /dev/null +++ b/modsrc/1.20/Forge/src/com/mingliqiye/minecraft/enchantment/conflict/forge/ForgeWebConfigCoreMeMethod.java @@ -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 getDefConfig() { + return ForgeMod.CONFIGMANAGER.getDefConfig().getConfig(); + } + + @Override + public Map 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 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 configPairMap) { + ForgeMod.CONFIGMANAGER.setConfig(configPairMap); + ForgeMod.CONFIGMANAGER.save(); + } +} diff --git a/modsrc/1.20/Forge/src/com/mingliqiye/minecraft/enchantment/conflict/forge/mixin/EnchantmentMixin.java b/modsrc/1.20/Forge/src/com/mingliqiye/minecraft/enchantment/conflict/forge/mixin/EnchantmentMixin.java new file mode 100644 index 0000000..c4c9c58 --- /dev/null +++ b/modsrc/1.20/Forge/src/com/mingliqiye/minecraft/enchantment/conflict/forge/mixin/EnchantmentMixin.java @@ -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 cir) { + var rb = ForgeMod.ENCHANTMENTCONTROLLER.canBeCombined( + enchantment.getDescriptionId(), + getThis().getDescriptionId() + ); + if (rb != null) { + cir.setReturnValue(rb); + } + } + + @Unique + private Enchantment getThis() { + return (Enchantment) (Object) this; + } +} diff --git a/modsrc/1.20/build.gradle b/modsrc/1.20/build.gradle new file mode 100644 index 0000000..3a349d0 --- /dev/null +++ b/modsrc/1.20/build.gradle @@ -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() +} diff --git a/modsrc/1.20/gradle.properties b/modsrc/1.20/gradle.properties new file mode 100644 index 0000000..bc21fb7 --- /dev/null +++ b/modsrc/1.20/gradle.properties @@ -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,) diff --git a/package.json b/package.json new file mode 100644 index 0000000..d04ac61 --- /dev/null +++ b/package.json @@ -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" + ] + } +} diff --git a/prettierrc b/prettierrc new file mode 100644 index 0000000..0d348b2 --- /dev/null +++ b/prettierrc @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/prettierrc", + "plugins": [ + "prettier-plugin-java" + ], + "tabWidth": 4, + "useTabs": false +} diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..b2c3f9c --- /dev/null +++ b/settings.gradle.kts @@ -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/") + } + } +} diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..1e5841f --- /dev/null +++ b/src/App.vue @@ -0,0 +1,205 @@ + + + diff --git a/src/api/alova.ts b/src/api/alova.ts new file mode 100644 index 0000000..2cb65cf --- /dev/null +++ b/src/api/alova.ts @@ -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; diff --git a/src/api/apis.ts b/src/api/apis.ts new file mode 100644 index 0000000..6bcfe2a --- /dev/null +++ b/src/api/apis.ts @@ -0,0 +1,16 @@ +import alovaInstance from '@/api/alova.ts'; +import type { Config, ModInfoType, Respose, EnchantmentEntity } from '@/api/types.ts'; + +const map: Map = new Map(); +const baseURL = '/api'; +export default { + getInfo: () => alovaInstance.Get>(baseURL + '/get/info'), + getEnchantments: () => alovaInstance.Get>(baseURL + '/get/enchantments'), + getConfig: () => alovaInstance.Get>(baseURL + '/get/client/config'), + getTest: (fid: number, sid: number) => + alovaInstance.Post>(baseURL + '/get/test', { + fid, + sid, + }), + sendConfig: (config: Config) => alovaInstance.Post(baseURL + '/send/config', config), +}; diff --git a/src/api/types.ts b/src/api/types.ts new file mode 100644 index 0000000..4eead07 --- /dev/null +++ b/src/api/types.ts @@ -0,0 +1,30 @@ +export interface Respose { + 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[]; +} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..3960714 --- /dev/null +++ b/src/main.ts @@ -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'); diff --git a/src/resources/enLangs.json b/src/resources/enLangs.json new file mode 100644 index 0000000..4d6a2cf --- /dev/null +++ b/src/resources/enLangs.json @@ -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": "风爆" +} diff --git a/src/resources/icon.png b/src/resources/icon.png new file mode 100644 index 0000000..69181e3 Binary files /dev/null and b/src/resources/icon.png differ diff --git a/src/resources/index.css b/src/resources/index.css new file mode 100644 index 0000000..ff3bcc4 --- /dev/null +++ b/src/resources/index.css @@ -0,0 +1,5 @@ +*[f-c-c]{ + display: flex; + justify-content: center; + align-items: center; +} diff --git a/src/resources/title_full.png b/src/resources/title_full.png new file mode 100644 index 0000000..3870a00 Binary files /dev/null and b/src/resources/title_full.png differ diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..913b8f2 --- /dev/null +++ b/tsconfig.app.json @@ -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/*"] + } + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..66b5e57 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..a83dfc9 --- /dev/null +++ b/tsconfig.node.json @@ -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"] + } +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..34fc439 --- /dev/null +++ b/vite.config.ts @@ -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/', + }, + }, +});