├── .gitignore ├── LICENSE ├── README.md ├── pom.xml └── src └── main ├── java └── org │ └── lins │ └── mmmjjkx │ └── rykenslimefuncustomizer │ ├── ProjectAddonManager.java │ ├── RykenSlimefunCustomizer.java │ ├── bulit_in │ └── JavaScriptEval.java │ ├── commands │ └── MainCommand.java │ ├── factories │ └── SimpleMachineFactory.java │ ├── libraries │ ├── colors │ │ ├── CMIChatColor.java │ │ ├── CMIColors.java │ │ └── CMICustomColors.java │ └── version │ │ ├── MinecraftPlatform.java │ │ └── Version.java │ ├── listeners │ ├── BlockListener.java │ ├── ScriptableEventListener.java │ └── SingleItemRecipeGuideListener.java │ ├── objects │ ├── ProjectAddon.java │ ├── ProjectAddonLoader.java │ ├── customs │ │ ├── CustomAddonConfig.java │ │ ├── CustomMenu.java │ │ ├── LinkedOutput.java │ │ ├── item │ │ │ ├── CustomArmorPiece.java │ │ │ ├── CustomDefaultItem.java │ │ │ ├── CustomFood.java │ │ │ ├── CustomGeoResource.java │ │ │ ├── CustomUnplaceableItem.java │ │ │ ├── RSCItemStack.java │ │ │ └── exts │ │ │ │ ├── CustomEnergyItem.java │ │ │ │ ├── CustomMobDrop.java │ │ │ │ └── CustomRainbowBlock.java │ │ ├── machine │ │ │ ├── CustomEnergyGenerator.java │ │ │ ├── CustomGenerator.java │ │ │ ├── CustomLinkedRecipeMachine.java │ │ │ ├── CustomMachine.java │ │ │ ├── CustomMaterialGenerator.java │ │ │ ├── CustomMultiBlockMachine.java │ │ │ ├── CustomNoEnergyMachine.java │ │ │ ├── CustomRecipeMachine.java │ │ │ ├── CustomSolarGenerator.java │ │ │ ├── CustomTemplateMachine.java │ │ │ ├── CustomWorkbench.java │ │ │ └── sf │ │ │ │ ├── AdvancedAnimalGrowthAccelerator.java │ │ │ │ ├── AdvancedAutoAnvil.java │ │ │ │ ├── AdvancedAutoBrewer.java │ │ │ │ ├── AdvancedCropGrowthAccelerator.java │ │ │ │ ├── AdvancedProduceCollector.java │ │ │ │ └── AdvancedTreeGrowthAccelerator.java │ │ └── parent │ │ │ ├── AbstractEmptyMachine.java │ │ │ └── CustomItem.java │ ├── global │ │ ├── DropFromBlock.java │ │ └── RecipeTypeMap.java │ ├── machine │ │ ├── CustomCraftingOperation.java │ │ ├── CustomLinkedMachineOperation.java │ │ ├── CustomLinkedMachineRecipe.java │ │ ├── CustomMachineRecipe.java │ │ ├── CustomTemplateCraftingOperation.java │ │ ├── MachineInfo.java │ │ ├── MachineRecord.java │ │ ├── MachineTemplate.java │ │ ├── ScriptedEvalBreakHandler.java │ │ ├── SimpleMachineType.java │ │ └── SmallerMachineInfo.java │ ├── script │ │ ├── ScriptEval.java │ │ ├── ban │ │ │ └── CommandSafe.java │ │ ├── enhanced │ │ │ └── NBTAPIIntegration.java │ │ └── lambda │ │ │ ├── CiConsumer.java │ │ │ ├── CiFunction.java │ │ │ └── RSCClickHandler.java │ ├── slimefun │ │ ├── AdvancedNestedItemGroup.java │ │ ├── AsyncChanceRecipeTask.java │ │ ├── ItemGroupButton.java │ │ └── WitherProofBlockImpl.java │ └── yaml │ │ ├── ItemGroupReader.java │ │ ├── MenuReader.java │ │ ├── RecipeTypesReader.java │ │ ├── ResearchReader.java │ │ ├── YamlReader.java │ │ ├── item │ │ ├── ArmorReader.java │ │ ├── CapacitorsReader.java │ │ ├── FoodReader.java │ │ ├── GeoResourceReader.java │ │ ├── ItemReader.java │ │ └── MobDropsReader.java │ │ └── machine │ │ ├── GeneratorReader.java │ │ ├── LinkedRecipeMachineReader.java │ │ ├── MachineReader.java │ │ ├── MaterialGeneratorReader.java │ │ ├── MultiBlockMachineReader.java │ │ ├── RecipeMachineReader.java │ │ ├── SimpleMachineReader.java │ │ ├── SolarGeneratorReader.java │ │ ├── SuperReader.java │ │ ├── TemplateMachineReader.java │ │ └── WorkbenchReader.java │ ├── update │ ├── GitHubRelease.java │ └── GithubUpdater.java │ └── utils │ ├── BlockMenuUtil.java │ ├── ClassUtils.java │ ├── CommonUtils.java │ ├── Constants.java │ ├── ExceptionHandler.java │ ├── ItemUtils.java │ ├── ReflectionUtils.java │ └── StackUtils.java └── resources ├── addons └── example │ ├── README.md │ └── info.yml ├── config.yml └── plugin.yml /.gitignore: -------------------------------------------------------------------------------- 1 | # User-specific stuff 2 | .idea/ 3 | 4 | *.iml 5 | *.ipr 6 | *.iws 7 | 8 | # IntelliJ 9 | out/ 10 | 11 | # Compiled class file 12 | *.class 13 | 14 | # Log file 15 | *.log 16 | 17 | # BlueJ files 18 | *.ctxt 19 | 20 | # Package Files # 21 | *.jar 22 | *.war 23 | *.nar 24 | *.ear 25 | *.zip 26 | *.tar.gz 27 | *.rar 28 | 29 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 30 | hs_err_pid* 31 | 32 | *~ 33 | 34 | # temporary files which can be created if a process still has a handle open of a deleted file 35 | .fuse_hidden* 36 | 37 | # KDE directory preferences 38 | .directory 39 | 40 | # Linux trash folder which might appear on any partition or disk 41 | .Trash-* 42 | 43 | # .nfs files are created when an open file is removed but is still being accessed 44 | .nfs* 45 | 46 | # General 47 | .DS_Store 48 | .AppleDouble 49 | .LSOverride 50 | 51 | # Icon must end with two \r 52 | Icon 53 | 54 | # Thumbnails 55 | ._* 56 | 57 | # Files that might appear in the root of a volume 58 | .DocumentRevisions-V100 59 | .fseventsd 60 | .Spotlight-V100 61 | .TemporaryItems 62 | .Trashes 63 | .VolumeIcon.icns 64 | .com.apple.timemachine.donotpresent 65 | 66 | # Directories potentially created on remote AFP share 67 | .AppleDB 68 | .AppleDesktop 69 | Network Trash Folder 70 | Temporary Items 71 | .apdisk 72 | 73 | # Windows thumbnail cache files 74 | Thumbs.db 75 | Thumbs.db:encryptable 76 | ehthumbs.db 77 | ehthumbs_vista.db 78 | 79 | # Dump file 80 | *.stackdump 81 | 82 | # Folder config file 83 | [Dd]esktop.ini 84 | 85 | # Recycle Bin used on file shares 86 | $RECYCLE.BIN/ 87 | 88 | # Windows Installer files 89 | *.cab 90 | *.msi 91 | *.msix 92 | *.msm 93 | *.msp 94 | 95 | # Windows shortcuts 96 | *.lnk 97 | 98 | target/ 99 | 100 | pom.xml.tag 101 | pom.xml.releaseBackup 102 | pom.xml.versionsBackup 103 | pom.xml.next 104 | 105 | release.properties 106 | dependency-reduced-pom.xml 107 | buildNumber.properties 108 | .mvn/timing.properties 109 | .mvn/wrapper/maven-wrapper.jar 110 | .flattened-pom.xml 111 | 112 | # Common working directory 113 | run/ 114 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RykenSlimeCustomizer 2 |
3 | 一款更高级的粘液自定义附属插件 4 | 5 | Wiki: 6 | QQ群: 811756705 7 |
8 | 9 |
10 | 此附属已完善,基本不会有任何更新! 11 |
-------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.lins.mmmjjkx 8 | RykenSlimefunCustomizer 9 | 20 10 | jar 11 | 12 | RykenSlimefunCustomizer 13 | An advanced slimefun customize plugin 14 | 15 | 17 16 | UTF-8 17 | 18 | 19 | 20 | clean package 21 | 22 | 23 | org.apache.maven.plugins 24 | maven-compiler-plugin 25 | 3.8.1 26 | 27 | ${java.version} 28 | ${java.version} 29 | 30 | 31 | org.projectlombok 32 | lombok 33 | 1.18.34 34 | 35 | 36 | 37 | 38 | 39 | org.apache.maven.plugins 40 | maven-shade-plugin 41 | 3.4.1 42 | 43 | 44 | 45 | shade 46 | 47 | package 48 | 49 | 50 | 51 | 52 | 53 | net.byteflux.libby 54 | org.lins.mmmjjkx.rykenslimefuncustomizer.libraries.libby 55 | 56 | 57 | 58 | 59 | 60 | com.diffplug.spotless 61 | spotless-maven-plugin 62 | 2.43.0 63 | 64 | 65 | 66 | 2.38.0 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | src/main/resources 79 | true 80 | 81 | /**/*.zip 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | central 90 | https://repo1.maven.org/maven2/ 91 | 92 | 93 | AlessioDP 94 | https://repo.alessiodp.com/releases/ 95 | 96 | 97 | jitpack 98 | https://jitpack.io 99 | 100 | 101 | minebench-repo 102 | https://repo.minebench.de/ 103 | 104 | 105 | codemc-repo 106 | https://repo.codemc.org/repository/maven-public/ 107 | 108 | 109 | placeholderapi 110 | https://repo.extendedclip.com/content/repositories/placeholderapi/ 111 | 112 | 113 | papermc-repo 114 | https://repo.papermc.io/repository/maven-public/ 115 | 116 | 117 | sonatype 118 | https://oss.sonatype.org/content/groups/public/ 119 | 120 | 121 | 122 | 123 | 124 | net.byteflux 125 | libby-bukkit 126 | 1.3.1 127 | 128 | 129 | 130 | org.graalvm.js 131 | js 132 | 24.1.2 133 | provided 134 | pom 135 | 136 | 137 | 138 | net.guizhanss 139 | GuizhanLibPlugin 140 | 1.7.6 141 | provided 142 | 143 | 144 | 145 | me.clip 146 | placeholderapi 147 | 2.11.5 148 | provided 149 | 150 | 151 | 152 | net.bytebuddy 153 | byte-buddy 154 | 1.14.6 155 | provided 156 | 157 | 158 | io.papermc.paper 159 | paper-api 160 | 1.18.2-R0.1-SNAPSHOT 161 | provided 162 | 163 | 164 | com.github.SlimefunGuguProject 165 | Slimefun4 166 | 2024.3 167 | provided 168 | 169 | 170 | org.projectlombok 171 | lombok 172 | 1.18.34 173 | provided 174 | 175 | 176 | de.tr7zw 177 | item-nbt-api-plugin 178 | 2.14.1 179 | provided 180 | 181 | 182 | 183 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/ProjectAddonManager.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer; 2 | 3 | import io.github.thebusybiscuit.slimefun4.libraries.commons.lang.Validate; 4 | import java.io.File; 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | import lombok.Getter; 10 | import org.bukkit.configuration.file.YamlConfiguration; 11 | import org.bukkit.plugin.Plugin; 12 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.ProjectAddon; 13 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.ProjectAddonLoader; 14 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.global.RecipeTypeMap; 15 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.Constants; 16 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.ExceptionHandler; 17 | 18 | public final class ProjectAddonManager { 19 | public static File ADDONS_DIRECTORY; 20 | public static File CONFIGS_DIRECTORY; 21 | 22 | private final Map projectAddons = new HashMap<>(); 23 | 24 | @Getter 25 | private final Map projectIds = new HashMap<>(); 26 | 27 | public ProjectAddonManager() { 28 | ADDONS_DIRECTORY = new File(RykenSlimefunCustomizer.INSTANCE.getDataFolder(), "addons"); 29 | CONFIGS_DIRECTORY = new File(RykenSlimefunCustomizer.INSTANCE.getDataFolder(), "addon_configs"); 30 | 31 | if (!CONFIGS_DIRECTORY.exists()) { 32 | CONFIGS_DIRECTORY.mkdirs(); 33 | } 34 | } 35 | 36 | public void pushProjectAddon(ProjectAddon addon) { 37 | Validate.notNull(addon, "addon"); 38 | if (!projectAddons.containsKey(addon.getAddonId())) { 39 | projectIds.put(addon.getAddonId(), addon.getFolder()); 40 | projectAddons.put(addon.getAddonId(), addon); 41 | } 42 | } 43 | 44 | public void removeProjectAddon(ProjectAddon addon) { 45 | Validate.notNull(addon, "addon"); 46 | 47 | projectIds.remove(addon.getAddonId()); 48 | projectAddons.remove(addon.getAddonId()); 49 | } 50 | 51 | public void setup(Plugin inst) { 52 | File addons = new File(inst.getDataFolder(), "addons"); 53 | if (!addons.exists()) { 54 | addons.mkdirs(); 55 | return; 56 | } 57 | 58 | File[] folders = addons.listFiles(); 59 | if (folders == null) return; 60 | 61 | List skip = new ArrayList<>(); 62 | 63 | for (File folder : folders) { 64 | if (folder.isFile()) { 65 | ExceptionHandler.handleError(folder.getName() + " 不是文件夹!无法加载此附属!"); 66 | continue; 67 | } 68 | 69 | File info = new File(folder, Constants.INFO_FILE); 70 | if (!info.exists()) { 71 | ExceptionHandler.handleError("在名称为 " + folder.getName() + "的文件夹中有无效的附属信息,导致此附属无法加载!"); 72 | skip.add(folder.getName()); 73 | continue; 74 | } 75 | YamlConfiguration infoConfig = YamlConfiguration.loadConfiguration(info); 76 | String id = infoConfig.getString("id"); 77 | if (id == null || id.isBlank()) { 78 | ExceptionHandler.handleError("在名称为 " + folder.getName() + "的文件夹中有无效的附属ID,导致此附属无法加载!"); 79 | skip.add(folder.getName()); 80 | continue; 81 | } 82 | 83 | if (projectIds.containsKey(id)) { 84 | ProjectAddon addon = projectAddons.get(id); 85 | if (addon == null) { 86 | ExceptionHandler.handleError("无法正常加载附属 " + id + "!请检查所有附属内容!"); 87 | continue; 88 | } 89 | 90 | if (addon.isMarkAsDepend()) { 91 | continue; 92 | } 93 | 94 | ExceptionHandler.handleError("在名称为 " + folder.getName() + "的文件夹中有重复的附属ID,导致此附属无法加载!"); 95 | skip.add(folder.getName()); 96 | continue; 97 | } 98 | 99 | projectIds.put(id, folder); 100 | } 101 | 102 | for (File folder : folders) { 103 | if (skip.contains(folder.getName())) continue; 104 | 105 | YamlConfiguration infoConfig = YamlConfiguration.loadConfiguration(new File(folder, Constants.INFO_FILE)); 106 | String id = infoConfig.getString("id"); 107 | if (projectAddons.containsKey(id)) { 108 | continue; 109 | } 110 | 111 | try { 112 | ProjectAddonLoader loader = new ProjectAddonLoader(folder, projectIds); 113 | ProjectAddon addon = loader.load(); 114 | if (addon != null) { 115 | projectAddons.put(addon.getAddonId(), addon); 116 | } 117 | } catch (Exception e) { 118 | if (folder.isFile()) { 119 | ExceptionHandler.handleError(folder.getName() + " 不是文件夹!无法加载此附属!"); 120 | continue; 121 | } 122 | e.printStackTrace(); 123 | } 124 | } 125 | } 126 | 127 | public void reload(Plugin plugin) { 128 | for (ProjectAddon addon : projectAddons.values()) { 129 | addon.unregister(); 130 | } 131 | 132 | projectAddons.clear(); 133 | projectIds.clear(); 134 | 135 | RecipeTypeMap.clearRecipeTypes(); 136 | 137 | setup(plugin); 138 | } 139 | 140 | public boolean isLoaded(String id) { 141 | return projectAddons.containsKey(id); 142 | } 143 | 144 | public boolean isLoaded(String... ids) { 145 | for (String id : ids) { 146 | if (!isLoaded(id)) { 147 | return false; 148 | } 149 | } 150 | return true; 151 | } 152 | 153 | public ProjectAddon get(String id) { 154 | return projectAddons.get(id); 155 | } 156 | 157 | public List getAllValues() { 158 | return new ArrayList<>(projectAddons.values()); 159 | } 160 | 161 | public File getAddonFolder(String id) { 162 | return projectIds.get(id); 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/bulit_in/JavaScriptEval.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.bulit_in; 2 | 3 | import com.google.errorprone.annotations.CanIgnoreReturnValue; 4 | import com.oracle.truffle.api.TruffleFile; 5 | import com.oracle.truffle.api.TruffleLanguage; 6 | import com.oracle.truffle.js.lang.JavaScriptLanguage; 7 | import com.oracle.truffle.js.runtime.JSRealm; 8 | import com.oracle.truffle.js.runtime.objects.JSAttributes; 9 | import com.oracle.truffle.js.runtime.objects.JSObject; 10 | import com.oracle.truffle.js.runtime.objects.JSObjectUtil; 11 | import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; 12 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; 13 | import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile; 14 | import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; 15 | import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; 16 | import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; 17 | import java.io.File; 18 | import java.io.IOException; 19 | import java.util.HashSet; 20 | import java.util.Objects; 21 | import java.util.Set; 22 | import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; 23 | import org.graalvm.polyglot.*; 24 | import org.graalvm.polyglot.io.IOAccess; 25 | import org.jetbrains.annotations.NotNull; 26 | import org.jetbrains.annotations.Nullable; 27 | import org.lins.mmmjjkx.rykenslimefuncustomizer.RykenSlimefunCustomizer; 28 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.ProjectAddon; 29 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.script.ScriptEval; 30 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.BlockMenuUtil; 31 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.ExceptionHandler; 32 | 33 | public class JavaScriptEval extends ScriptEval { 34 | private static final File PLUGINS_FOLDER = 35 | RykenSlimefunCustomizer.INSTANCE.getDataFolder().getParentFile(); 36 | private final Set failed_functions = new HashSet<>(); 37 | 38 | private Context jsEngine; 39 | 40 | public JavaScriptEval(@NotNull File js, ProjectAddon addon) { 41 | super(js, addon); 42 | reSetup(); 43 | 44 | setup(); 45 | 46 | contextInit(); 47 | 48 | addon.getScriptEvals().add(this); 49 | } 50 | 51 | private void advancedSetup() { 52 | JSRealm realm = JavaScriptLanguage.getJSRealm(jsEngine); 53 | TruffleLanguage.Env env = realm.getEnv(); 54 | addThing("SlimefunItems", env.asHostSymbol(SlimefunItems.class)); 55 | addThing("SlimefunItem", env.asHostSymbol(SlimefunItem.class)); 56 | addThing("StorageCacheUtils", env.asHostSymbol(StorageCacheUtils.class)); 57 | addThing("SlimefunUtils", env.asHostSymbol(SlimefunUtils.class)); 58 | addThing("BlockMenu", env.asHostSymbol(BlockMenu.class)); 59 | addThing("BlockMenuUtil", env.asHostSymbol(BlockMenuUtil.class)); 60 | addThing("PlayerProfile", env.asHostSymbol(PlayerProfile.class)); 61 | addThing("Slimefun", env.asHostSymbol(Slimefun.class)); 62 | 63 | for (File file : Objects.requireNonNull(PLUGINS_FOLDER.listFiles())) { 64 | TruffleFile truffleFile = env.getPublicTruffleFile(file.toURI()); 65 | if (!truffleFile.isDirectory() && truffleFile.getName().endsWith(".jar")) { 66 | env.addToHostClassPath(truffleFile); 67 | } 68 | } 69 | 70 | JSObject java = JSObjectUtil.createOrdinaryPrototypeObject(realm); 71 | JSObjectUtil.putToStringTag(java, JSRealm.JAVA_CLASS_NAME); 72 | 73 | JSObjectUtil.putDataProperty(realm.getGlobalObject(), "Java", java, JSAttributes.getDefaultNotEnumerable()); 74 | 75 | jsEngine.enter(); 76 | } 77 | 78 | @Override 79 | public void close() { 80 | try { 81 | jsEngine.leave(); 82 | jsEngine.close(); 83 | } catch (IllegalStateException ignored) { 84 | } 85 | } 86 | 87 | @Override 88 | public void addThing(String name, Object value) { 89 | jsEngine.getBindings("js").putMember(name, value); 90 | } 91 | 92 | @Override 93 | public String key() { 94 | return "js"; 95 | } 96 | 97 | protected final void contextInit() { 98 | super.contextInit(); 99 | if (jsEngine != null) { 100 | try { 101 | jsEngine.eval( 102 | Source.newBuilder("js", getFileContext(), "JavaScript").build()); 103 | } catch (IOException e) { 104 | e.printStackTrace(); 105 | } 106 | } 107 | } 108 | 109 | @Nullable @CanIgnoreReturnValue 110 | @Override 111 | public Object evalFunction(String funName, Object... args) { 112 | if (getFileContext() == null || getFileContext().isBlank()) { 113 | contextInit(); 114 | } 115 | 116 | // a simple fix for the optimization 117 | if (failed_functions.contains(funName)) { 118 | return null; 119 | } 120 | 121 | Value member = jsEngine.getBindings("js").getMember(funName); 122 | if (member == null) { 123 | failed_functions.add(funName); 124 | return null; 125 | } 126 | 127 | try { 128 | Object result = member.execute(args); 129 | ExceptionHandler.debugLog( 130 | "运行了 " + getAddon().getAddonName() + "的脚本" + getFile().getName() + "中的函数 " + funName); 131 | return result; 132 | } catch (IllegalStateException e) { 133 | String message = e.getMessage(); 134 | if (!message.contains("Multi threaded access")) { 135 | ExceptionHandler.handleError( 136 | "在运行附属" + getAddon().getAddonName() + "的脚本" + getFile().getName() + "时发生错误"); 137 | e.printStackTrace(); 138 | } 139 | } catch (Throwable e) { 140 | ExceptionHandler.handleError( 141 | "在运行" + getAddon().getAddonName() + "的脚本" + getFile().getName() + "时发生意外错误"); 142 | e.printStackTrace(); 143 | } 144 | 145 | return null; 146 | } 147 | 148 | private void reSetup() { 149 | jsEngine = Context.newBuilder("js") 150 | .hostClassLoader(RykenSlimefunCustomizer.class.getClassLoader()) 151 | .allowAllAccess(true) 152 | .allowHostAccess(UNIVERSAL_HOST_ACCESS) 153 | .allowNativeAccess(false) 154 | .allowExperimentalOptions(true) 155 | .allowPolyglotAccess(PolyglotAccess.ALL) 156 | .allowCreateProcess(true) 157 | .allowValueSharing(true) 158 | .allowIO(IOAccess.ALL) 159 | .allowHostClassLookup(s -> true) 160 | .allowHostClassLoading(true) 161 | .engine(Engine.newBuilder("js").allowExperimentalOptions(true).build()) 162 | .currentWorkingDirectory(getAddon().getScriptsFolder().toPath().toAbsolutePath()) 163 | .build(); 164 | 165 | advancedSetup(); 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/factories/SimpleMachineFactory.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.factories; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; 5 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 6 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 7 | import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.*; 8 | import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.enchanting.AutoDisenchanter; 9 | import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.enchanting.AutoEnchanter; 10 | import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.enchanting.BookBinder; 11 | import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer; 12 | import org.bukkit.inventory.ItemStack; 13 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.machine.sf.*; 14 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.machine.SimpleMachineType; 15 | 16 | public class SimpleMachineFactory { 17 | public static SlimefunItem create( 18 | ItemGroup group, 19 | SlimefunItemStack slimefunItemStack, 20 | RecipeType recipeType, 21 | ItemStack[] recipe, 22 | SimpleMachineType machineType, 23 | int capacity, 24 | int consumption, 25 | int speed, 26 | int radius, 27 | int repairFactor) { 28 | SlimefunItem instance = 29 | switch (machineType) { 30 | case ELECTRIC_FURNACE -> new ElectricFurnace(group, slimefunItemStack, recipeType, recipe); 31 | case ELECTRIC_GOLD_PAN -> new ElectricGoldPan(group, slimefunItemStack, recipeType, recipe); 32 | case ELECTRIC_SMELTERY -> new ElectricSmeltery(group, slimefunItemStack, recipeType, recipe); 33 | case ELECTRIC_DUST_WASHER -> new ElectricDustWasher(group, slimefunItemStack, recipeType, recipe); 34 | case ELECTRIC_ORE_GRINDER -> new ElectricOreGrinder(group, slimefunItemStack, recipeType, recipe); 35 | case ELECTRIC_INGOT_FACTORY -> new ElectricIngotFactory( 36 | group, slimefunItemStack, recipeType, recipe); 37 | case ELECTRIC_INGOT_PULVERIZER -> new ElectricIngotPulverizer( 38 | group, slimefunItemStack, recipeType, recipe); 39 | case CHARGING_BENCH -> new ChargingBench(group, slimefunItemStack, recipeType, recipe); 40 | case FREEZER -> new Freezer(group, slimefunItemStack, recipeType, recipe); 41 | case CARBON_PRESS -> new CarbonPress(group, slimefunItemStack, recipeType, recipe); 42 | case ELECTRIC_PRESS -> new ElectricPress(group, slimefunItemStack, recipeType, recipe); 43 | case ELECTRIC_CRUCIBLE -> new ElectrifiedCrucible(group, slimefunItemStack, recipeType, recipe); 44 | case FOOD_FABRICATOR -> new FoodFabricator(group, slimefunItemStack, recipeType, recipe); 45 | case HEATED_PRESSURE_CHAMBER -> new HeatedPressureChamber( 46 | group, slimefunItemStack, recipeType, recipe); 47 | case BOOK_BINDER -> new BookBinder(group, slimefunItemStack, recipeType, recipe); 48 | case AUTO_ENCHANTER -> new AutoEnchanter(group, slimefunItemStack, recipeType, recipe); 49 | case AUTO_DISENCHANTER -> new AutoDisenchanter(group, slimefunItemStack, recipeType, recipe); 50 | case AUTO_DRIER -> new AutoDrier(group, slimefunItemStack, recipeType, recipe); 51 | case AUTO_BREWER -> new AdvancedAutoBrewer(group, slimefunItemStack, recipeType, recipe, speed); 52 | case REFINERY -> new Refinery(group, slimefunItemStack, recipeType, recipe); 53 | case PRODUCE_COLLECTOR -> new AdvancedProduceCollector( 54 | group, slimefunItemStack, recipeType, recipe, speed); 55 | case TREE_GROWTH_ACCELERATOR -> new AdvancedTreeGrowthAccelerator( 56 | group, slimefunItemStack, recipeType, recipe, capacity, radius, consumption); 57 | case ANIMAL_GROWTH_ACCELERATOR -> new AdvancedAnimalGrowthAccelerator( 58 | group, slimefunItemStack, recipeType, recipe, capacity, radius, consumption); 59 | case CROP_GROWTH_ACCELERATOR -> new AdvancedCropGrowthAccelerator( 60 | group, slimefunItemStack, recipeType, recipe, capacity, radius, consumption, speed); 61 | case AUTO_ANVIL -> new AdvancedAutoAnvil( 62 | group, repairFactor, slimefunItemStack, recipeType, recipe, speed); 63 | }; 64 | 65 | if (instance instanceof AContainer aContainer) { 66 | aContainer.setCapacity(capacity); 67 | aContainer.setEnergyConsumption(consumption); 68 | aContainer.setProcessingSpeed(speed); 69 | } 70 | 71 | return instance; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/libraries/colors/CMIColors.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.libraries.colors; 2 | 3 | import java.awt.*; 4 | import lombok.Getter; 5 | import org.bukkit.Material; 6 | 7 | @Getter 8 | public enum CMIColors { 9 | White(0, "White", Material.WHITE_DYE, new Color(249, 255, 254)), 10 | Orange(1, "Orange", Material.ORANGE_DYE, new Color(249, 128, 29)), 11 | Magenta(2, "Magenta", Material.MAGENTA_DYE, new Color(199, 78, 189)), 12 | Light_Blue(3, "Light Blue", Material.LIGHT_BLUE_DYE, new Color(58, 179, 218)), 13 | Yellow(4, "Yellow", Material.YELLOW_DYE, new Color(254, 216, 61)), 14 | Lime(5, "Lime", Material.LIME_DYE, new Color(128, 199, 31)), 15 | Pink(6, "Pink", Material.PINK_DYE, new Color(243, 139, 170)), 16 | Gray(7, "Gray", Material.GRAY_DYE, new Color(71, 79, 82)), 17 | Light_Gray(8, "Light Gray", Material.LIGHT_GRAY_DYE, new Color(157, 157, 151)), 18 | Cyan(9, "Cyan", Material.CYAN_DYE, new Color(22, 156, 156)), 19 | Purple(10, "Purple", Material.PURPLE_DYE, new Color(137, 50, 184)), 20 | Blue(11, "Blue", Material.BLUE_DYE, new Color(60, 68, 170)), 21 | Brown(12, "Brown", Material.BROWN_DYE, new Color(131, 84, 50)), 22 | Green(13, "Green", Material.GREEN_DYE, new Color(94, 124, 22)), 23 | Red(14, "Red", Material.RED_DYE, new Color(176, 46, 38)), 24 | Black(15, "Black", Material.BLACK_DYE, new Color(29, 29, 33)); 25 | 26 | private final int id; 27 | private final String name; 28 | private final Material material; 29 | 30 | private Color color; 31 | 32 | CMIColors(int id, String name, Material material, Color color) { 33 | this.id = id; 34 | this.name = name; 35 | this.material = material; 36 | this.color = color; 37 | } 38 | 39 | CMIColors(int id, String name, Material material) { 40 | this.id = id; 41 | this.name = name; 42 | this.material = material; 43 | } 44 | 45 | public static CMIColors getById(int id) { 46 | for (CMIColors one : CMIColors.values()) { 47 | if (one.getId() == id) return one; 48 | } 49 | return CMIColors.White; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/libraries/version/MinecraftPlatform.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.libraries.version; 2 | 3 | public enum MinecraftPlatform { 4 | paper, 5 | pufferfish, 6 | folia, 7 | purpur, 8 | mohist, 9 | arclight 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/listeners/BlockListener.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.listeners; 2 | 3 | import java.util.List; 4 | import java.util.Random; 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.block.Block; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.block.BlockBreakEvent; 10 | import org.lins.mmmjjkx.rykenslimefuncustomizer.RykenSlimefunCustomizer; 11 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.global.DropFromBlock; 12 | 13 | public class BlockListener implements Listener { 14 | public BlockListener() { 15 | Bukkit.getPluginManager().registerEvents(this, RykenSlimefunCustomizer.INSTANCE); 16 | } 17 | 18 | @EventHandler 19 | public void onBlockBreak(BlockBreakEvent e) { 20 | Block block = e.getBlock(); 21 | List drops = DropFromBlock.getDrops(block.getType()); 22 | List matchedDrops = 23 | drops.stream().filter(drop -> matchChance(drop.dropChance())).toList(); 24 | if (matchedDrops.isEmpty()) return; 25 | 26 | for (DropFromBlock.Drop drop : matchedDrops) { 27 | block.getWorld().dropItemNaturally(e.getBlock().getLocation(), drop.itemStack()); 28 | } 29 | } 30 | 31 | private static boolean matchChance(int chance) { 32 | if (chance >= 100) return true; 33 | 34 | Random rand = new Random(); 35 | return rand.nextInt(100) < chance; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/customs/CustomAddonConfig.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs; 2 | 3 | import java.io.File; 4 | import org.bukkit.configuration.file.YamlConfiguration; 5 | import org.jetbrains.annotations.Nullable; 6 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.script.ScriptEval; 7 | 8 | public record CustomAddonConfig(File configFile, YamlConfiguration config, ScriptEval onReloadHandler) { 9 | public CustomAddonConfig(File configFile, YamlConfiguration config, @Nullable ScriptEval onReloadHandler) { 10 | this.configFile = configFile; 11 | this.config = config; 12 | this.onReloadHandler = onReloadHandler; 13 | } 14 | 15 | public void tryReload() { 16 | try { 17 | config.load(configFile); 18 | if (onReloadHandler != null) { 19 | onReloadHandler.evalFunction("onConfigReload", config); 20 | } 21 | } catch (Exception e) { 22 | e.printStackTrace(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/customs/LinkedOutput.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Map; 6 | import lombok.Getter; 7 | import org.bukkit.inventory.ItemStack; 8 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.ExceptionHandler; 9 | 10 | @Getter 11 | public class LinkedOutput { 12 | private final ItemStack[] freeOutput; 13 | private final Map linkedOutput; 14 | private final int[] freeChances; 15 | private final Map linkedChances; 16 | 17 | public LinkedOutput( 18 | ItemStack[] freeOutput, 19 | Map linkedOutput, 20 | int[] freeChances, 21 | Map linkedChances) { 22 | this.freeOutput = freeOutput; 23 | this.linkedOutput = linkedOutput; 24 | this.freeChances = freeChances; 25 | this.linkedChances = linkedChances; 26 | } 27 | 28 | public ItemStack[] toArray() { 29 | ItemStack[] result = new ItemStack[freeOutput.length + linkedOutput.size()]; 30 | System.arraycopy(freeOutput, 0, result, 0, freeOutput.length); 31 | int i = freeOutput.length; 32 | for (ItemStack item : linkedOutput.values()) { 33 | result[i] = item; 34 | i++; 35 | } 36 | 37 | return result; 38 | } 39 | 40 | public List chancesToArray() { 41 | List result = new ArrayList<>(freeChances.length + linkedChances.size()); 42 | for (int chance : freeChances) { 43 | result.add(chance); 44 | } 45 | result.addAll(linkedChances.values()); 46 | return result; 47 | } 48 | 49 | public void log() { 50 | // log free output & linked output 51 | for (int i = 0; i < freeOutput.length; i++) { 52 | ItemStack item = freeOutput[i]; 53 | ExceptionHandler.info("FreeOutput: " + i + " 物品: " + item); 54 | } 55 | 56 | for (int slot : linkedOutput.keySet()) { 57 | ItemStack item = linkedOutput.get(slot); 58 | ExceptionHandler.info("LinkedOutput: " + slot + " 物品: " + item + " 位置: " + slot); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/customs/item/CustomArmorPiece.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.item; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 5 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 6 | import io.github.thebusybiscuit.slimefun4.core.attributes.ProtectionType; 7 | import io.github.thebusybiscuit.slimefun4.core.attributes.ProtectiveArmor; 8 | import io.github.thebusybiscuit.slimefun4.implementation.items.armor.SlimefunArmorPiece; 9 | import org.bukkit.NamespacedKey; 10 | import org.bukkit.inventory.ItemStack; 11 | import org.bukkit.potion.PotionEffect; 12 | import org.jetbrains.annotations.NotNull; 13 | import org.jetbrains.annotations.Nullable; 14 | import org.lins.mmmjjkx.rykenslimefuncustomizer.RykenSlimefunCustomizer; 15 | 16 | public class CustomArmorPiece extends SlimefunArmorPiece implements ProtectiveArmor { 17 | private final String armorKey; 18 | private final boolean fullSet; 19 | private final ProtectionType[] protectionTypes; 20 | private final String projectId; 21 | 22 | public CustomArmorPiece( 23 | ItemGroup itemGroup, 24 | SlimefunItemStack item, 25 | RecipeType recipeType, 26 | ItemStack[] recipe, 27 | @Nullable PotionEffect[] effects, 28 | boolean fullSet, 29 | String armorKey, 30 | ProtectionType[] protectionTypes, 31 | String projectId) { 32 | super(itemGroup, item, recipeType, recipe, effects); 33 | 34 | this.armorKey = armorKey; 35 | this.fullSet = fullSet; 36 | this.protectionTypes = protectionTypes; 37 | this.projectId = projectId; 38 | 39 | register(RykenSlimefunCustomizer.INSTANCE); 40 | } 41 | 42 | @Override 43 | public @NotNull ProtectionType[] getProtectionTypes() { 44 | return protectionTypes; 45 | } 46 | 47 | @Override 48 | public boolean isFullSetRequired() { 49 | return fullSet; 50 | } 51 | 52 | @Nullable @Override 53 | public NamespacedKey getArmorSetId() { 54 | return new NamespacedKey(RykenSlimefunCustomizer.INSTANCE, projectId + "_" + armorKey); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/customs/item/CustomDefaultItem.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.item; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 5 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 6 | import org.bukkit.inventory.ItemStack; 7 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.parent.CustomItem; 8 | 9 | public class CustomDefaultItem extends CustomItem { 10 | private final Object[] constructorArgs; 11 | 12 | public CustomDefaultItem(ItemGroup itemGroup, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) { 13 | super(itemGroup, item, recipeType, recipe, recipeOutput); 14 | 15 | constructorArgs = new Object[] {itemGroup, item, recipeType, recipe, recipeOutput}; 16 | } 17 | 18 | @Override 19 | public Object[] constructorArgs() { 20 | return constructorArgs; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/customs/item/CustomFood.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.item; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 5 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 6 | import io.github.thebusybiscuit.slimefun4.core.handlers.ItemConsumptionHandler; 7 | import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem; 8 | import org.bukkit.inventory.ItemStack; 9 | import org.jetbrains.annotations.NotNull; 10 | import org.jetbrains.annotations.Nullable; 11 | import org.lins.mmmjjkx.rykenslimefuncustomizer.RykenSlimefunCustomizer; 12 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.script.ScriptEval; 13 | 14 | public class CustomFood extends SimpleSlimefunItem { 15 | private final ScriptEval eval; 16 | 17 | public CustomFood( 18 | ItemGroup itemGroup, 19 | SlimefunItemStack item, 20 | RecipeType recipeType, 21 | ItemStack[] recipe, 22 | @Nullable ScriptEval eval, 23 | ItemStack recipeOutput) { 24 | super(itemGroup, item, recipeType, recipe, recipeOutput); 25 | 26 | this.eval = eval; 27 | 28 | register(RykenSlimefunCustomizer.INSTANCE); 29 | } 30 | 31 | @NotNull @Override 32 | public ItemConsumptionHandler getItemHandler() { 33 | return (e, p, i) -> { 34 | if (eval != null) { 35 | eval.evalFunction("onEat", e, p, i); 36 | } 37 | }; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/customs/item/CustomGeoResource.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.item; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource; 4 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 5 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 6 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 7 | import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.UnplaceableBlock; 8 | import java.util.function.BiFunction; 9 | import org.bukkit.NamespacedKey; 10 | import org.bukkit.World; 11 | import org.bukkit.block.Biome; 12 | import org.bukkit.inventory.ItemStack; 13 | import org.jetbrains.annotations.NotNull; 14 | import org.lins.mmmjjkx.rykenslimefuncustomizer.RykenSlimefunCustomizer; 15 | 16 | public class CustomGeoResource extends UnplaceableBlock implements GEOResource { 17 | private final BiFunction supply; 18 | private final int maxDeviation; 19 | private final boolean obtainableFromGEOMiner; 20 | private final String name; 21 | 22 | public CustomGeoResource( 23 | ItemGroup itemGroup, 24 | SlimefunItemStack item, 25 | RecipeType type, 26 | ItemStack[] recipe, 27 | BiFunction supply, 28 | int maxDeviation, 29 | boolean obtainableFromGEOMiner, 30 | String name) { 31 | super(itemGroup, item, type, recipe); 32 | 33 | this.supply = supply; 34 | this.maxDeviation = maxDeviation; 35 | this.obtainableFromGEOMiner = obtainableFromGEOMiner; 36 | this.name = name; 37 | 38 | register(); 39 | register(RykenSlimefunCustomizer.INSTANCE); 40 | } 41 | 42 | @Override 43 | public int getDefaultSupply(@NotNull World.Environment environment, @NotNull Biome biome) { 44 | return supply.apply(environment, biome); 45 | } 46 | 47 | @Override 48 | public int getMaxDeviation() { 49 | return maxDeviation; 50 | } 51 | 52 | @NotNull @Override 53 | public String getName() { 54 | return name; 55 | } 56 | 57 | @Override 58 | public boolean isObtainableFromGEOMiner() { 59 | return obtainableFromGEOMiner; 60 | } 61 | 62 | @Override 63 | public @NotNull NamespacedKey getKey() { 64 | return new NamespacedKey(RykenSlimefunCustomizer.INSTANCE, getId()); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/customs/item/CustomUnplaceableItem.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.item; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.events.PlayerRightClickEvent; 4 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 5 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 6 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 7 | import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable; 8 | import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler; 9 | import io.github.thebusybiscuit.slimefun4.core.handlers.ToolUseHandler; 10 | import io.github.thebusybiscuit.slimefun4.core.handlers.WeaponUseHandler; 11 | import org.bukkit.inventory.ItemStack; 12 | import org.jetbrains.annotations.Nullable; 13 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.parent.CustomItem; 14 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.script.ScriptEval; 15 | 16 | public class CustomUnplaceableItem extends CustomItem implements NotPlaceable { 17 | private final Object[] constructorArgs; 18 | 19 | public CustomUnplaceableItem( 20 | ItemGroup itemGroup, 21 | SlimefunItemStack item, 22 | RecipeType recipeType, 23 | ItemStack[] recipe, 24 | @Nullable ScriptEval eval, 25 | ItemStack recipeOutput) { 26 | super(itemGroup, item, recipeType, recipe, recipeOutput); 27 | 28 | if (eval != null) { 29 | eval.doInit(); 30 | 31 | this.addItemHandler((ItemUseHandler) e -> { 32 | eval.evalFunction("onUse", e); 33 | e.cancel(); 34 | }); 35 | 36 | this.addItemHandler((WeaponUseHandler) (e, p, it) -> eval.evalFunction("onWeaponHit", e, p, it)); 37 | this.addItemHandler((ToolUseHandler) (e, it, i, drops) -> eval.evalFunction("onToolUse", e, it, i, drops)); 38 | } else { 39 | this.addItemHandler((ItemUseHandler) PlayerRightClickEvent::cancel); 40 | } 41 | 42 | this.constructorArgs = new Object[] {itemGroup, item, recipeType, recipe, eval, recipeOutput}; 43 | } 44 | 45 | @Override 46 | public Object[] constructorArgs() { 47 | return constructorArgs; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/customs/item/RSCItemStack.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.item; 2 | 3 | import io.github.thebusybiscuit.slimefun4.libraries.dough.items.CustomItemStack; 4 | import java.util.List; 5 | import org.bukkit.inventory.ItemStack; 6 | 7 | @SuppressWarnings("deprecation") 8 | public class RSCItemStack extends CustomItemStack { 9 | public RSCItemStack(ItemStack item, String name, List lore) { 10 | super(item, meta -> { 11 | if (name != null && !name.isBlank()) { 12 | meta.setDisplayName(name); 13 | } 14 | 15 | if (lore != null && !lore.isEmpty()) { 16 | meta.setLore(lore); 17 | } 18 | }); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/customs/item/exts/CustomEnergyItem.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.item.exts; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.events.PlayerRightClickEvent; 4 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 5 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 6 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 7 | import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable; 8 | import io.github.thebusybiscuit.slimefun4.core.attributes.Rechargeable; 9 | import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler; 10 | import io.github.thebusybiscuit.slimefun4.core.handlers.ToolUseHandler; 11 | import io.github.thebusybiscuit.slimefun4.core.handlers.WeaponUseHandler; 12 | import org.bukkit.inventory.ItemStack; 13 | import org.jetbrains.annotations.Nullable; 14 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.parent.CustomItem; 15 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.script.ScriptEval; 16 | 17 | public class CustomEnergyItem extends CustomItem implements Rechargeable, NotPlaceable { 18 | private final float capacity; 19 | 20 | private final Object[] constructorArgs; 21 | 22 | public CustomEnergyItem( 23 | ItemGroup itemGroup, 24 | SlimefunItemStack item, 25 | RecipeType recipeType, 26 | ItemStack[] recipe, 27 | float capacity, 28 | @Nullable ScriptEval eval, 29 | ItemStack recipeOutput) { 30 | super(itemGroup, item, recipeType, recipe, recipeOutput); 31 | 32 | this.capacity = capacity; 33 | 34 | if (eval != null) { 35 | eval.doInit(); 36 | 37 | this.addItemHandler((ItemUseHandler) e -> { 38 | eval.evalFunction("onUse", e, this); 39 | e.cancel(); 40 | }); 41 | 42 | this.addItemHandler((WeaponUseHandler) (e, p, it) -> eval.evalFunction("onWeaponHit", e, p, it)); 43 | this.addItemHandler((ToolUseHandler) (e, it, i, drops) -> eval.evalFunction("onToolUse", e, it, i, drops)); 44 | } else { 45 | this.addItemHandler((ItemUseHandler) PlayerRightClickEvent::cancel); 46 | } 47 | 48 | this.constructorArgs = new Object[] {itemGroup, item, recipeType, recipe, capacity, eval, recipeOutput}; 49 | } 50 | 51 | public void setItemCharge(ItemStack item, int charge) { 52 | Rechargeable.super.setItemCharge(item, charge); 53 | } 54 | 55 | public void setItemCharge(ItemStack item, double charge) { 56 | Rechargeable.super.setItemCharge(item, (float) charge); 57 | } 58 | 59 | public void addItemCharge(ItemStack item, int charge) { 60 | Rechargeable.super.addItemCharge(item, charge); 61 | } 62 | 63 | public void addItemCharge(ItemStack item, double charge) { 64 | Rechargeable.super.addItemCharge(item, (float) charge); 65 | } 66 | 67 | public void removeItemCharge(ItemStack item, int charge) { 68 | Rechargeable.super.removeItemCharge(item, charge); 69 | } 70 | 71 | public void removeItemCharge(ItemStack item, double charge) { 72 | Rechargeable.super.addItemCharge(item, (float) charge); 73 | } 74 | 75 | public float getItemCharge(ItemStack item) { 76 | return Rechargeable.super.getItemCharge(item); 77 | } 78 | 79 | @Override 80 | public float getMaxItemCharge(ItemStack itemStack) { 81 | return capacity; 82 | } 83 | 84 | @Override 85 | public Object[] constructorArgs() { 86 | return constructorArgs; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/customs/item/exts/CustomMobDrop.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.item.exts; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 5 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 6 | import io.github.thebusybiscuit.slimefun4.core.attributes.RandomMobDrop; 7 | import lombok.Getter; 8 | import org.bukkit.entity.EntityType; 9 | import org.bukkit.inventory.ItemStack; 10 | import org.lins.mmmjjkx.rykenslimefuncustomizer.RykenSlimefunCustomizer; 11 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.item.CustomUnplaceableItem; 12 | 13 | public class CustomMobDrop extends CustomUnplaceableItem implements RandomMobDrop { 14 | private final int chance; 15 | 16 | @Getter 17 | private final EntityType entityType; 18 | 19 | public CustomMobDrop(ItemGroup itemGroup, SlimefunItemStack item, ItemStack[] recipe, int chance, EntityType type, ItemStack recipeOutput) { 20 | super(itemGroup, item, RecipeType.MOB_DROP, recipe, null, recipeOutput); 21 | this.chance = chance; 22 | this.entityType = type; 23 | 24 | register(RykenSlimefunCustomizer.INSTANCE); 25 | } 26 | 27 | @Override 28 | public int getMobDropChance() { 29 | return chance >= 100 ? 100 : Math.max(chance, 1); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/customs/item/exts/CustomRainbowBlock.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.item.exts; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 5 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 6 | import io.github.thebusybiscuit.slimefun4.core.handlers.RainbowTickHandler; 7 | import io.github.thebusybiscuit.slimefun4.utils.ColoredMaterial; 8 | import java.util.List; 9 | import org.bukkit.Material; 10 | import org.bukkit.inventory.ItemStack; 11 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.parent.CustomItem; 12 | 13 | public class CustomRainbowBlock extends CustomItem { 14 | private final Object[] constructorArgs; 15 | 16 | public CustomRainbowBlock( 17 | ItemGroup itemGroup, 18 | SlimefunItemStack item, 19 | RecipeType recipeType, 20 | ItemStack[] recipe, 21 | RainbowTickHandler ticker, 22 | ItemStack recipeOutput) { 23 | super(itemGroup, item, recipeType, recipe, recipeOutput); 24 | 25 | addItemHandler(ticker); 26 | 27 | constructorArgs = new Object[] {itemGroup, item, recipeType, recipe, ticker, recipeOutput}; 28 | } 29 | 30 | public CustomRainbowBlock( 31 | ItemGroup itemGroup, 32 | SlimefunItemStack item, 33 | RecipeType recipeType, 34 | ItemStack[] recipe, 35 | ColoredMaterial materialType, 36 | ItemStack recipeOutput) { 37 | this(itemGroup, item, recipeType, recipe, new RainbowTickHandler(materialType), recipeOutput); 38 | } 39 | 40 | public CustomRainbowBlock( 41 | ItemGroup itemGroup, 42 | SlimefunItemStack item, 43 | RecipeType recipeType, 44 | ItemStack[] recipe, 45 | List materials, 46 | ItemStack recipeOutput) { 47 | this(itemGroup, item, recipeType, recipe, new RainbowTickHandler(materials), recipeOutput); 48 | } 49 | 50 | @Override 51 | public Object[] constructorArgs() { 52 | return constructorArgs; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/customs/machine/CustomEnergyGenerator.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.machine; 2 | 3 | import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; 4 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 5 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 6 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 7 | import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetProvider; 8 | import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType; 9 | import java.util.List; 10 | import org.bukkit.Location; 11 | import org.bukkit.inventory.ItemStack; 12 | import org.jetbrains.annotations.NotNull; 13 | import org.jetbrains.annotations.Nullable; 14 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.CustomMenu; 15 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.machine.MachineRecord; 16 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.script.ScriptEval; 17 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.ExceptionHandler; 18 | 19 | public class CustomEnergyGenerator extends CustomMachine implements EnergyNetProvider { 20 | private final ScriptEval eval; 21 | private final int defaultOutput; 22 | 23 | public CustomEnergyGenerator( 24 | ItemGroup itemGroup, 25 | SlimefunItemStack item, 26 | RecipeType recipeType, 27 | ItemStack[] recipe, 28 | @Nullable CustomMenu menu, 29 | List input, 30 | List output, 31 | MachineRecord record, 32 | EnergyNetComponentType type, 33 | @Nullable ScriptEval eval, 34 | int defaultOutput) { 35 | super(itemGroup, item, recipeType, recipe, menu, input, output, record, type, eval); 36 | 37 | this.eval = eval; 38 | this.defaultOutput = defaultOutput; 39 | } 40 | 41 | @Override 42 | public int getGeneratedOutput(@NotNull Location l, @NotNull SlimefunBlockData data) { 43 | if (eval == null) { 44 | return defaultOutput; 45 | } else { 46 | try { 47 | Object result = eval.evalFunction("getGeneratedOutput", l, data); 48 | if (result instanceof Integer i) { 49 | return i; 50 | } else { 51 | ExceptionHandler.handleWarning( 52 | "getGeneratedOutput() 返回了一个非整数值: " + result + " 导致自定义发电机的默认输出值将被使用, 请找附属对应作者修复此问题!"); 53 | return defaultOutput; 54 | } 55 | } catch (Exception e) { 56 | return defaultOutput; 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/customs/machine/CustomMachine.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.machine; 2 | 3 | import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; 4 | import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; 5 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 6 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; 7 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 8 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 9 | import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent; 10 | import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler; 11 | import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler; 12 | import io.github.thebusybiscuit.slimefun4.core.handlers.BlockUseHandler; 13 | import io.github.thebusybiscuit.slimefun4.core.machines.MachineOperation; 14 | import io.github.thebusybiscuit.slimefun4.core.machines.MachineProcessor; 15 | import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType; 16 | import java.util.List; 17 | import lombok.Getter; 18 | import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker; 19 | import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; 20 | import org.bukkit.block.Block; 21 | import org.bukkit.event.block.BlockBreakEvent; 22 | import org.bukkit.event.block.BlockPlaceEvent; 23 | import org.bukkit.inventory.ItemStack; 24 | import org.jetbrains.annotations.NotNull; 25 | import org.jetbrains.annotations.Nullable; 26 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.CustomMenu; 27 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.parent.AbstractEmptyMachine; 28 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.machine.MachineInfo; 29 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.machine.MachineRecord; 30 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.machine.ScriptedEvalBreakHandler; 31 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.script.ScriptEval; 32 | 33 | public class CustomMachine extends AbstractEmptyMachine implements EnergyNetComponent { 34 | private final MachineRecord theRecord; 35 | private final List input; 36 | private final List output; 37 | private final EnergyNetComponentType type; 38 | private final MachineProcessor processor; 39 | private final @Nullable ScriptEval eval; 40 | 41 | @Getter 42 | private final CustomMenu menu; 43 | 44 | public CustomMachine( 45 | ItemGroup itemGroup, 46 | SlimefunItemStack item, 47 | RecipeType recipeType, 48 | ItemStack[] recipe, 49 | @Nullable CustomMenu menu, 50 | List input, 51 | List output, 52 | MachineRecord record, 53 | EnergyNetComponentType type, 54 | @Nullable ScriptEval eval) { 55 | super(itemGroup, item, recipeType, recipe); 56 | 57 | this.input = input; 58 | this.output = output; 59 | this.theRecord = record; 60 | this.menu = menu; 61 | 62 | this.type = type; 63 | this.eval = eval; 64 | this.processor = new MachineProcessor<>(this); 65 | 66 | if (eval != null) { 67 | eval.doInit(); 68 | 69 | addItemHandler( 70 | new BlockPlaceHandler(false) { 71 | @Override 72 | public void onPlayerPlace(@NotNull BlockPlaceEvent e) { 73 | CustomMachine.this.eval.evalFunction("onPlace", e); 74 | } 75 | }, 76 | (BlockUseHandler) e -> CustomMachine.this.eval.evalFunction("onUse", e), 77 | new BlockBreakHandler(false, false) { 78 | @Override 79 | public void onPlayerBreak( 80 | @NotNull BlockBreakEvent e, @NotNull ItemStack item, @NotNull List drops) { 81 | MachineOperation operation = getMachineProcessor().getOperation(e.getBlock()); 82 | if (operation != null) { 83 | getMachineProcessor().endOperation(e.getBlock()); 84 | } 85 | 86 | CustomMachine.this.eval.evalFunction("onBreak", e, item, drops); 87 | } 88 | }); 89 | } 90 | 91 | addItemHandler(new ScriptedEvalBreakHandler(this, eval)); 92 | 93 | if (menu != null) { 94 | this.processor.setProgressBar(menu.getProgressBarItem()); 95 | 96 | createPreset(this, menu::apply); 97 | } 98 | } 99 | 100 | @Override 101 | public void preRegister() { 102 | super.preRegister(); 103 | this.addItemHandler(getBlockTicker()); 104 | } 105 | 106 | protected void tick(Block b, SlimefunItem item, SlimefunBlockData data) { 107 | if (eval != null) { 108 | BlockMenu blockMenu = StorageCacheUtils.getMenu(b.getLocation()); 109 | MachineInfo info = new MachineInfo(blockMenu, data, item, b, processor, null, this); 110 | eval.evalFunction("tick", info); 111 | } 112 | } 113 | 114 | @Override 115 | public BlockTicker getBlockTicker() { 116 | return new BlockTicker() { 117 | @Override 118 | public boolean isSynchronized() { 119 | return true; 120 | } 121 | 122 | @Override 123 | public void tick(Block b, SlimefunItem item, SlimefunBlockData data) { 124 | CustomMachine.this.tick(b, item, data); 125 | } 126 | }; 127 | } 128 | 129 | @Override 130 | public int[] getInputSlots() { 131 | return input.stream().mapToInt(i -> i).toArray(); 132 | } 133 | 134 | @Override 135 | public int[] getOutputSlots() { 136 | return output.stream().mapToInt(i -> i).toArray(); 137 | } 138 | 139 | @NotNull @Override 140 | public EnergyNetComponentType getEnergyComponentType() { 141 | return type; 142 | } 143 | 144 | @Override 145 | public int getCapacity() { 146 | return theRecord.capacity(); 147 | } 148 | 149 | @NotNull @Override 150 | public MachineProcessor getMachineProcessor() { 151 | return processor; 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/customs/machine/CustomNoEnergyMachine.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.machine; 2 | 3 | import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; 4 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 5 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; 6 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 7 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 8 | import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler; 9 | import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler; 10 | import io.github.thebusybiscuit.slimefun4.core.handlers.BlockUseHandler; 11 | import io.github.thebusybiscuit.slimefun4.core.machines.MachineOperation; 12 | import io.github.thebusybiscuit.slimefun4.core.machines.MachineProcessor; 13 | import java.util.Collections; 14 | import java.util.List; 15 | import java.util.function.Consumer; 16 | import lombok.Getter; 17 | import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu; 18 | import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ClickAction; 19 | import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker; 20 | import org.bukkit.block.Block; 21 | import org.bukkit.entity.Player; 22 | import org.bukkit.event.block.BlockBreakEvent; 23 | import org.bukkit.event.block.BlockPlaceEvent; 24 | import org.bukkit.inventory.ItemStack; 25 | import org.jetbrains.annotations.NotNull; 26 | import org.jetbrains.annotations.Nullable; 27 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.CustomMenu; 28 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.parent.AbstractEmptyMachine; 29 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.machine.ScriptedEvalBreakHandler; 30 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.machine.SmallerMachineInfo; 31 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.script.ScriptEval; 32 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.script.lambda.RSCClickHandler; 33 | 34 | @SuppressWarnings("deprecation") 35 | public class CustomNoEnergyMachine extends AbstractEmptyMachine { 36 | private final List input; 37 | private final List output; 38 | private final @Nullable ScriptEval eval; 39 | private final MachineProcessor processor; 40 | 41 | @Getter 42 | private final CustomMenu menu; 43 | 44 | public CustomNoEnergyMachine( 45 | ItemGroup itemGroup, 46 | SlimefunItemStack item, 47 | RecipeType recipeType, 48 | ItemStack[] recipe, 49 | CustomMenu menu, 50 | List input, 51 | List output, 52 | @Nullable ScriptEval eval, 53 | int work) { 54 | this(itemGroup, item, recipeType, recipe, menu, input, output, eval, Collections.singletonList(work)); 55 | } 56 | 57 | public CustomNoEnergyMachine( 58 | ItemGroup itemGroup, 59 | SlimefunItemStack item, 60 | RecipeType recipeType, 61 | ItemStack[] recipe, 62 | CustomMenu menu, 63 | List input, 64 | List output, 65 | @Nullable ScriptEval eval, 66 | List work) { 67 | super(itemGroup, item, recipeType, recipe); 68 | 69 | this.input = input; 70 | this.output = output; 71 | this.eval = eval; 72 | this.processor = new MachineProcessor<>(this); 73 | this.menu = menu; 74 | 75 | if (eval != null) { 76 | eval.addThing("setWorking", (Consumer) b -> eval.addThing("working", b)); 77 | eval.addThing("working", false); 78 | 79 | eval.doInit(); 80 | 81 | addItemHandler( 82 | new BlockPlaceHandler(false) { 83 | @Override 84 | public void onPlayerPlace(@NotNull BlockPlaceEvent e) { 85 | CustomNoEnergyMachine.this.eval.evalFunction("onPlace", e); 86 | } 87 | }, 88 | (BlockUseHandler) e -> CustomNoEnergyMachine.this.eval.evalFunction("onUse", e), 89 | new BlockBreakHandler(false, false) { 90 | @Override 91 | public void onPlayerBreak( 92 | @NotNull BlockBreakEvent e, @NotNull ItemStack item, @NotNull List drops) { 93 | MachineOperation operation = getMachineProcessor().getOperation(e.getBlock()); 94 | if (operation != null) { 95 | getMachineProcessor().endOperation(e.getBlock()); 96 | } 97 | 98 | CustomNoEnergyMachine.this.eval.evalFunction("onBreak", e, item, drops); 99 | } 100 | }); 101 | } 102 | 103 | addItemHandler(new ScriptedEvalBreakHandler(this, eval)); 104 | addItemHandler(getBlockTicker()); 105 | 106 | if (this.menu != null) { 107 | for (int workSlot : work) { 108 | if (workSlot > -1 && workSlot < 54) { 109 | ChestMenu.MenuClickHandler mcl = this.menu.getMenuClickHandler(workSlot); 110 | this.menu.addMenuClickHandler(workSlot, new RSCClickHandler() { 111 | @Override 112 | public void mainFunction(Player player, int slot, ItemStack itemStack, ClickAction action) { 113 | if (eval != null) { 114 | eval.addThing("working", true); 115 | } 116 | } 117 | 118 | @Override 119 | public void andThen(Player player, int slot, ItemStack itemStack, ClickAction action) { 120 | if (mcl != null) { 121 | mcl.onClick(player, slot, itemStack, action); 122 | } 123 | } 124 | }); 125 | } 126 | this.processor.setProgressBar(menu.getProgressBarItem()); 127 | } 128 | 129 | createPreset(this, this.menu::apply); 130 | } 131 | } 132 | 133 | @Override 134 | public void preRegister() { 135 | super.preRegister(); 136 | this.addItemHandler(getBlockTicker()); 137 | } 138 | 139 | protected void tick(Block b, SlimefunItem item, SlimefunBlockData data) { 140 | if (eval != null) { 141 | SmallerMachineInfo info = new SmallerMachineInfo(data.getBlockMenu(), data, this, item, b, processor); 142 | eval.evalFunction("tick", info); 143 | } 144 | } 145 | 146 | @Override 147 | public int[] getInputSlots() { 148 | return input.stream().mapToInt(i -> i).toArray(); 149 | } 150 | 151 | @Override 152 | public int[] getOutputSlots() { 153 | return output.stream().mapToInt(i -> i).toArray(); 154 | } 155 | 156 | @Override 157 | public BlockTicker getBlockTicker() { 158 | return new BlockTicker() { 159 | @Override 160 | public boolean isSynchronized() { 161 | return true; 162 | } 163 | 164 | @Override 165 | public void tick(Block b, SlimefunItem item, SlimefunBlockData data) { 166 | CustomNoEnergyMachine.this.tick(b, item, data); 167 | } 168 | }; 169 | } 170 | 171 | @NotNull @Override 172 | public MachineProcessor getMachineProcessor() { 173 | return processor; 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/customs/machine/CustomSolarGenerator.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.machine; 2 | 3 | import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; 4 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 5 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 6 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 7 | import io.github.thebusybiscuit.slimefun4.implementation.items.electric.generators.SolarGenerator; 8 | import org.bukkit.Location; 9 | import org.bukkit.World; 10 | import org.bukkit.inventory.ItemStack; 11 | import org.lins.mmmjjkx.rykenslimefuncustomizer.RykenSlimefunCustomizer; 12 | 13 | public class CustomSolarGenerator extends SolarGenerator { 14 | private final int lightLevel; 15 | 16 | public CustomSolarGenerator( 17 | ItemGroup itemGroup, 18 | int dayEnergy, 19 | int nightEnergy, 20 | SlimefunItemStack item, 21 | RecipeType recipeType, 22 | ItemStack[] recipe, 23 | int capacity, 24 | int lightLevel) { 25 | super(itemGroup, dayEnergy, nightEnergy, item, recipeType, recipe, capacity); 26 | 27 | if (lightLevel > 15 || lightLevel < 0) { 28 | lightLevel = 15; 29 | } 30 | 31 | this.lightLevel = lightLevel; 32 | 33 | register(RykenSlimefunCustomizer.INSTANCE); 34 | } 35 | 36 | public int getGeneratedOutput(Location l, SlimefunBlockData data) { 37 | World world = l.getWorld(); 38 | 39 | if (world.getEnvironment() != World.Environment.NORMAL) { 40 | return 0; 41 | } else { 42 | boolean isDaytime = isDaytime(world); 43 | 44 | if (!isDaytime && getNightEnergy() < 1) { 45 | return 0; 46 | } else if (!world.isChunkLoaded(l.getBlockX() >> 4, l.getBlockZ() >> 4) 47 | || l.getBlock().getRelative(0, 1, 0).getLightFromSky() < (byte) lightLevel) { 48 | return 0; 49 | } else { 50 | return isDaytime ? getDayEnergy() : getNightEnergy(); 51 | } 52 | } 53 | } 54 | 55 | private boolean isDaytime(World world) { 56 | long time = world.getTime(); 57 | return !world.hasStorm() && !world.isThundering() && (time < 12300L || time > 23850L); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/customs/machine/sf/AdvancedAnimalGrowthAccelerator.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.machine.sf; 2 | 3 | import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; 4 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 5 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 6 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 7 | import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; 8 | import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.accelerators.AbstractGrowthAccelerator; 9 | import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; 10 | import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper; 11 | import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; 12 | import org.bukkit.Particle; 13 | import org.bukkit.block.Block; 14 | import org.bukkit.entity.Ageable; 15 | import org.bukkit.entity.Entity; 16 | import org.bukkit.entity.LivingEntity; 17 | import org.bukkit.inventory.ItemStack; 18 | 19 | public class AdvancedAnimalGrowthAccelerator extends AbstractGrowthAccelerator { 20 | private static final ItemStack organicFood = ItemStackWrapper.wrap(SlimefunItems.ORGANIC_FOOD); 21 | 22 | private final int capacity; 23 | private final int radius; 24 | private final int energy_consumption; 25 | 26 | public AdvancedAnimalGrowthAccelerator( 27 | ItemGroup itemGroup, 28 | SlimefunItemStack item, 29 | RecipeType recipeType, 30 | ItemStack[] recipe, 31 | int capacity, 32 | int radius, 33 | int energy_consumption) { 34 | super(itemGroup, item, recipeType, recipe); 35 | 36 | this.capacity = capacity; 37 | this.radius = radius; 38 | this.energy_consumption = energy_consumption; 39 | } 40 | 41 | protected void tick(Block b) { 42 | BlockMenu inv = StorageCacheUtils.getMenu(b.getLocation()); 43 | 44 | if (inv != null) { 45 | for (Entity n : 46 | b.getWorld().getNearbyEntities(b.getLocation(), radius, radius, radius, this::isReadyToGrow)) { 47 | int[] var5 = this.getInputSlots(); 48 | int var6 = var5.length; 49 | 50 | for (int slot : var5) { 51 | if (SlimefunUtils.isItemSimilar(inv.getItemInSlot(slot), organicFood, false, false)) { 52 | if (this.getCharge(b.getLocation()) < energy_consumption) { 53 | return; 54 | } 55 | 56 | Ageable ageable = (Ageable) n; 57 | this.removeCharge(b.getLocation(), energy_consumption); 58 | inv.consumeItem(slot); 59 | ageable.setAge(ageable.getAge() + 2000); 60 | if (ageable.getAge() > 0) { 61 | ageable.setAge(0); 62 | } 63 | 64 | n.getWorld() 65 | .spawnParticle( 66 | Particle.VILLAGER_HAPPY, 67 | ((LivingEntity) n).getEyeLocation(), 68 | 8, 69 | 0.20000000298023224, 70 | 0.20000000298023224, 71 | 0.20000000298023224); 72 | return; 73 | } 74 | } 75 | } 76 | } 77 | } 78 | 79 | private boolean isReadyToGrow(Entity n) { 80 | if (n instanceof Ageable ageable) { 81 | return n.isValid() && !ageable.isAdult(); 82 | } 83 | 84 | return false; 85 | } 86 | 87 | @Override 88 | public int getCapacity() { 89 | return capacity; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/customs/machine/sf/AdvancedAutoAnvil.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.machine.sf; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 5 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 6 | import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; 7 | import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.AutoAnvil; 8 | import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; 9 | import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineRecipe; 10 | import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; 11 | import org.bukkit.inventory.ItemStack; 12 | import org.bukkit.inventory.meta.Damageable; 13 | import org.bukkit.inventory.meta.ItemMeta; 14 | 15 | public class AdvancedAutoAnvil extends AutoAnvil { 16 | private final int repairFactor; 17 | private final int speed; 18 | 19 | public AdvancedAutoAnvil( 20 | ItemGroup itemGroup, 21 | int repairFactor, 22 | SlimefunItemStack item, 23 | RecipeType recipeType, 24 | ItemStack[] recipe, 25 | int speed) { 26 | super(itemGroup, repairFactor, item, recipeType, recipe); 27 | 28 | this.repairFactor = repairFactor; 29 | this.speed = speed; 30 | } 31 | 32 | protected MachineRecipe findNextRecipe(BlockMenu menu) { 33 | for (int slot : this.getInputSlots()) { 34 | ItemStack ductTape = menu.getItemInSlot( 35 | slot == this.getInputSlots()[0] ? this.getInputSlots()[1] : this.getInputSlots()[0]); 36 | ItemStack item = menu.getItemInSlot(slot); 37 | if (item != null 38 | && item.getType().getMaxDurability() > 0 39 | && ((Damageable) item.getItemMeta()).getDamage() > 0) { 40 | if (SlimefunUtils.isItemSimilar(ductTape, SlimefunItems.DUCT_TAPE, true, false)) { 41 | ItemStack repairedItem = this.repair(item); 42 | if (!menu.fits(repairedItem, this.getOutputSlots())) { 43 | return null; 44 | } 45 | 46 | for (int inputSlot : this.getInputSlots()) { 47 | menu.consumeItem(inputSlot); 48 | } 49 | 50 | return new MachineRecipe( 51 | 30 / this.speed, new ItemStack[] {ductTape, item}, new ItemStack[] {repairedItem}); 52 | } 53 | break; 54 | } 55 | } 56 | 57 | return null; 58 | } 59 | 60 | private ItemStack repair(ItemStack item) { 61 | ItemStack repaired = item.clone(); 62 | ItemMeta meta = repaired.getItemMeta(); 63 | short maxDurability = item.getType().getMaxDurability(); 64 | int repairPercentage = 100 / this.repairFactor; 65 | short durability = (short) (((Damageable) meta).getDamage() - maxDurability / repairPercentage); 66 | if (durability < 0) { 67 | durability = 0; 68 | } 69 | 70 | ((Damageable) meta).setDamage(durability); 71 | repaired.setItemMeta(meta); 72 | return repaired; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/customs/machine/sf/AdvancedAutoBrewer.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.machine.sf; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 5 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 6 | import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.AutoBrewer; 7 | import io.github.thebusybiscuit.slimefun4.libraries.dough.inventory.InvUtils; 8 | import java.util.EnumMap; 9 | import java.util.Map; 10 | import javax.annotation.Nonnull; 11 | import javax.annotation.Nullable; 12 | import javax.annotation.ParametersAreNonnullByDefault; 13 | import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineRecipe; 14 | import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; 15 | import org.bukkit.Material; 16 | import org.bukkit.inventory.ItemStack; 17 | import org.bukkit.inventory.meta.PotionMeta; 18 | import org.bukkit.potion.PotionData; 19 | import org.bukkit.potion.PotionType; 20 | 21 | public class AdvancedAutoBrewer extends AutoBrewer { 22 | private static final Map potionRecipes = new EnumMap<>(Material.class); 23 | private static final Map fermentations = new EnumMap<>(PotionType.class); 24 | 25 | private final int speed; 26 | 27 | public AdvancedAutoBrewer( 28 | ItemGroup itemGroup, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, int speed) { 29 | super(itemGroup, item, recipeType, recipe); 30 | 31 | this.speed = speed; 32 | } 33 | 34 | @Nullable protected MachineRecipe findNextRecipe(BlockMenu menu) { 35 | ItemStack input1 = menu.getItemInSlot(this.getInputSlots()[0]); 36 | ItemStack input2 = menu.getItemInSlot(this.getInputSlots()[1]); 37 | if (input1 != null && input2 != null) { 38 | if (!this.isPotion(input1.getType()) && !this.isPotion(input2.getType())) { 39 | return null; 40 | } else { 41 | boolean isPotionInFirstSlot = this.isPotion(input1.getType()); 42 | ItemStack ingredient = isPotionInFirstSlot ? input2 : input1; 43 | if (ingredient.hasItemMeta()) { 44 | return null; 45 | } else { 46 | ItemStack potionItem = isPotionInFirstSlot ? input1 : input2; 47 | PotionMeta potion = (PotionMeta) potionItem.getItemMeta(); 48 | ItemStack output = this.brew(ingredient.getType(), potionItem.getType(), potion); 49 | if (output == null) { 50 | return null; 51 | } else { 52 | output.setItemMeta(potion); 53 | if (!InvUtils.fits(menu.toInventory(), output, this.getOutputSlots())) { 54 | return null; 55 | } else { 56 | for (int slot : this.getInputSlots()) { 57 | menu.consumeItem(slot); 58 | } 59 | 60 | return new MachineRecipe( 61 | 30 / speed, new ItemStack[] {input1, input2}, new ItemStack[] {output}); 62 | } 63 | } 64 | } 65 | } 66 | } else { 67 | return null; 68 | } 69 | } 70 | 71 | @ParametersAreNonnullByDefault 72 | @Nullable private ItemStack brew(Material input, Material potionType, PotionMeta potion) { 73 | PotionData data = potion.getBasePotionData(); 74 | PotionType type = data.getType(); 75 | if (type == PotionType.WATER) { 76 | if (input == Material.FERMENTED_SPIDER_EYE) { 77 | potion.setBasePotionData(new PotionData(PotionType.WEAKNESS, false, false)); 78 | return new ItemStack(potionType); 79 | } 80 | 81 | if (input == Material.NETHER_WART) { 82 | potion.setBasePotionData(new PotionData(PotionType.AWKWARD, false, false)); 83 | return new ItemStack(potionType); 84 | } 85 | 86 | if (potionType == Material.POTION && input == Material.GUNPOWDER) { 87 | return new ItemStack(Material.SPLASH_POTION); 88 | } 89 | 90 | if (potionType == Material.SPLASH_POTION && input == Material.DRAGON_BREATH) { 91 | return new ItemStack(Material.LINGERING_POTION); 92 | } 93 | } else if (input == Material.FERMENTED_SPIDER_EYE) { 94 | PotionType fermented = fermentations.get(type); 95 | if (fermented != null) { 96 | potion.setBasePotionData(new PotionData(fermented, data.isExtended(), data.isUpgraded())); 97 | return new ItemStack(potionType); 98 | } 99 | } else { 100 | if (input == Material.REDSTONE && type.isExtendable() && !data.isUpgraded()) { 101 | potion.setBasePotionData(new PotionData(type, true, false)); 102 | return new ItemStack(potionType); 103 | } 104 | 105 | if (input == Material.GLOWSTONE_DUST && type.isUpgradeable() && !data.isExtended()) { 106 | potion.setBasePotionData(new PotionData(type, false, true)); 107 | return new ItemStack(potionType); 108 | } 109 | 110 | if (type == PotionType.AWKWARD) { 111 | PotionType potionRecipe = potionRecipes.get(input); 112 | if (potionRecipe != null) { 113 | potion.setBasePotionData(new PotionData(potionRecipe, false, false)); 114 | return new ItemStack(potionType); 115 | } 116 | } 117 | } 118 | 119 | return null; 120 | } 121 | 122 | private boolean isPotion(@Nonnull Material mat) { 123 | return mat == Material.POTION || mat == Material.SPLASH_POTION || mat == Material.LINGERING_POTION; 124 | } 125 | 126 | static { 127 | potionRecipes.put(Material.SUGAR, PotionType.SPEED); 128 | potionRecipes.put(Material.RABBIT_FOOT, PotionType.JUMP); 129 | potionRecipes.put(Material.BLAZE_POWDER, PotionType.STRENGTH); 130 | potionRecipes.put(Material.GLISTERING_MELON_SLICE, PotionType.INSTANT_HEAL); 131 | potionRecipes.put(Material.SPIDER_EYE, PotionType.POISON); 132 | potionRecipes.put(Material.GHAST_TEAR, PotionType.REGEN); 133 | potionRecipes.put(Material.MAGMA_CREAM, PotionType.FIRE_RESISTANCE); 134 | potionRecipes.put(Material.PUFFERFISH, PotionType.WATER_BREATHING); 135 | potionRecipes.put(Material.GOLDEN_CARROT, PotionType.NIGHT_VISION); 136 | potionRecipes.put(Material.TURTLE_HELMET, PotionType.TURTLE_MASTER); 137 | potionRecipes.put(Material.PHANTOM_MEMBRANE, PotionType.SLOW_FALLING); 138 | fermentations.put(PotionType.SPEED, PotionType.SLOWNESS); 139 | fermentations.put(PotionType.JUMP, PotionType.SLOWNESS); 140 | fermentations.put(PotionType.INSTANT_HEAL, PotionType.INSTANT_DAMAGE); 141 | fermentations.put(PotionType.POISON, PotionType.INSTANT_DAMAGE); 142 | fermentations.put(PotionType.NIGHT_VISION, PotionType.INVISIBILITY); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/customs/machine/sf/AdvancedCropGrowthAccelerator.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.machine.sf; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 5 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 6 | import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.accelerators.CropGrowthAccelerator; 7 | import org.bukkit.inventory.ItemStack; 8 | 9 | public class AdvancedCropGrowthAccelerator extends CropGrowthAccelerator { 10 | private final int capacity; 11 | private final int radius; 12 | private final int energy_consumption; 13 | private final int speed; 14 | 15 | public AdvancedCropGrowthAccelerator( 16 | ItemGroup itemGroup, 17 | SlimefunItemStack item, 18 | RecipeType recipeType, 19 | ItemStack[] recipe, 20 | int capacity, 21 | int radius, 22 | int energy_consumption, 23 | int speed) { 24 | super(itemGroup, item, recipeType, recipe); 25 | 26 | this.capacity = capacity; 27 | this.radius = radius; 28 | this.energy_consumption = energy_consumption; 29 | this.speed = speed; 30 | } 31 | 32 | @Override 33 | public int getEnergyConsumption() { 34 | return energy_consumption; 35 | } 36 | 37 | @Override 38 | public int getRadius() { 39 | return radius; 40 | } 41 | 42 | @Override 43 | public int getSpeed() { 44 | return speed; 45 | } 46 | 47 | @Override 48 | public int getCapacity() { 49 | return capacity; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/customs/machine/sf/AdvancedProduceCollector.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.machine.sf; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 5 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 6 | import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.entities.AnimalProduce; 7 | import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.entities.ProduceCollector; 8 | import org.bukkit.inventory.ItemStack; 9 | import org.jetbrains.annotations.NotNull; 10 | 11 | public class AdvancedProduceCollector extends ProduceCollector { 12 | private final int speed; 13 | 14 | public AdvancedProduceCollector( 15 | ItemGroup itemGroup, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, int speed) { 16 | super(itemGroup, item, recipeType, recipe); 17 | 18 | this.speed = speed; 19 | } 20 | 21 | @Override 22 | public void addProduce(@NotNull AnimalProduce produce) { 23 | produce.setTicks(produce.getTicks() / speed); 24 | super.addProduce(produce); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/customs/machine/sf/AdvancedTreeGrowthAccelerator.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.machine.sf; 2 | 3 | import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; 4 | import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; 5 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 6 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 7 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 8 | import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; 9 | import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; 10 | import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.accelerators.AbstractGrowthAccelerator; 11 | import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; 12 | import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper; 13 | import javax.annotation.Nonnull; 14 | import javax.annotation.Nullable; 15 | import javax.annotation.ParametersAreNonnullByDefault; 16 | import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; 17 | import org.bukkit.Particle; 18 | import org.bukkit.Tag; 19 | import org.bukkit.block.Block; 20 | import org.bukkit.block.BlockFace; 21 | import org.bukkit.block.data.type.Sapling; 22 | import org.bukkit.inventory.ItemStack; 23 | 24 | public class AdvancedTreeGrowthAccelerator extends AbstractGrowthAccelerator { 25 | private static final ItemStack organicFertilizer = ItemStackWrapper.wrap(SlimefunItems.FERTILIZER); 26 | 27 | private final int capacity; 28 | private final int radius; 29 | private final int energy_consumption; 30 | 31 | public AdvancedTreeGrowthAccelerator( 32 | ItemGroup itemGroup, 33 | SlimefunItemStack item, 34 | RecipeType recipeType, 35 | ItemStack[] recipe, 36 | int capacity, 37 | int radius, 38 | int energy_consumption) { 39 | super(itemGroup, item, recipeType, recipe); 40 | 41 | this.capacity = capacity; 42 | this.radius = radius; 43 | this.energy_consumption = energy_consumption; 44 | } 45 | 46 | @Override 47 | public int getCapacity() { 48 | return capacity; 49 | } 50 | 51 | protected void tick(@Nonnull Block b) { 52 | BlockMenu inv = StorageCacheUtils.getMenu(b.getLocation()); 53 | if (inv != null) { 54 | if (this.getCharge(b.getLocation()) >= energy_consumption) { 55 | for (int x = -radius; x <= radius; ++x) { 56 | for (int z = -radius; z <= radius; ++z) { 57 | Block block = b.getRelative(x, 0, z); 58 | if (Tag.SAPLINGS.isTagged(block.getType())) { 59 | boolean isGrowthBoosted = this.tryToBoostGrowth(b, inv, block); 60 | if (isGrowthBoosted) { 61 | return; 62 | } 63 | } 64 | } 65 | } 66 | } 67 | } 68 | } 69 | 70 | @ParametersAreNonnullByDefault 71 | private boolean tryToBoostGrowth(Block machine, BlockMenu inv, Block sapling) { 72 | if (Slimefun.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_17)) { 73 | return this.applyBoneMeal(machine, sapling, inv); 74 | } else { 75 | Sapling saplingData = (Sapling) sapling.getBlockData(); 76 | return saplingData.getStage() < saplingData.getMaximumStage() 77 | && this.updateSaplingData(machine, sapling, inv, saplingData); 78 | } 79 | } 80 | 81 | @ParametersAreNonnullByDefault 82 | private boolean applyBoneMeal(Block machine, Block sapling, BlockMenu inv) { 83 | int[] var4 = this.getInputSlots(); 84 | 85 | for (int slot : var4) { 86 | if (this.isFertilizer(inv.getItemInSlot(slot))) { 87 | this.removeCharge(machine.getLocation(), energy_consumption); 88 | sapling.applyBoneMeal(BlockFace.UP); 89 | inv.consumeItem(slot); 90 | sapling.getWorld() 91 | .spawnParticle( 92 | Particle.VILLAGER_HAPPY, 93 | sapling.getLocation().add(0.5, 0.5, 0.5), 94 | 4, 95 | 0.10000000149011612, 96 | 0.10000000149011612, 97 | 0.10000000149011612); 98 | return true; 99 | } 100 | } 101 | 102 | return false; 103 | } 104 | 105 | @ParametersAreNonnullByDefault 106 | private boolean updateSaplingData(Block machine, Block block, BlockMenu inv, Sapling sapling) { 107 | int[] var5 = this.getInputSlots(); 108 | 109 | for (int slot : var5) { 110 | if (this.isFertilizer(inv.getItemInSlot(slot))) { 111 | this.removeCharge(machine.getLocation(), 24); 112 | sapling.setStage(sapling.getStage() + 1); 113 | block.setBlockData(sapling, false); 114 | inv.consumeItem(slot); 115 | block.getWorld() 116 | .spawnParticle( 117 | Particle.VILLAGER_HAPPY, 118 | block.getLocation().add(0.5, 0.5, 0.5), 119 | 4, 120 | 0.10000000149011612, 121 | 0.10000000149011612, 122 | 0.10000000149011612); 123 | return true; 124 | } 125 | } 126 | 127 | return false; 128 | } 129 | 130 | protected boolean isFertilizer(@Nullable ItemStack item) { 131 | return SlimefunUtils.isItemSimilar(item, organicFertilizer, false, false); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/customs/parent/AbstractEmptyMachine.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.parent; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; 5 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 6 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 7 | import io.github.thebusybiscuit.slimefun4.core.attributes.MachineProcessHolder; 8 | import io.github.thebusybiscuit.slimefun4.core.machines.MachineOperation; 9 | import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.interfaces.InventoryBlock; 10 | import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker; 11 | import org.bukkit.inventory.ItemStack; 12 | 13 | @SuppressWarnings("deprecation") 14 | public abstract class AbstractEmptyMachine extends SlimefunItem 15 | implements InventoryBlock, MachineProcessHolder { 16 | public AbstractEmptyMachine( 17 | ItemGroup itemGroup, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) { 18 | super(itemGroup, item, recipeType, recipe); 19 | } 20 | 21 | @Override 22 | public abstract BlockTicker getBlockTicker(); 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/customs/parent/CustomItem.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.parent; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; 5 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 6 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 7 | import org.bukkit.inventory.ItemStack; 8 | 9 | public abstract class CustomItem extends SlimefunItem { 10 | public CustomItem(ItemGroup itemGroup, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) { 11 | super(itemGroup, item, recipeType, recipe, recipeOutput); 12 | } 13 | 14 | public abstract Object[] constructorArgs(); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/global/DropFromBlock.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.global; 2 | 3 | import java.util.*; 4 | import org.bukkit.Material; 5 | import org.bukkit.inventory.ItemStack; 6 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.ProjectAddon; 7 | 8 | public class DropFromBlock { 9 | private static final Map> drops; 10 | 11 | static { 12 | drops = new HashMap<>(); 13 | } 14 | 15 | public static void addDrop(Material material, Drop drop) { 16 | drops.computeIfAbsent(material, k -> new ArrayList<>()).add(drop); 17 | } 18 | 19 | public static List getDrops(Material material) { 20 | return drops.getOrDefault(material, Collections.emptyList()); 21 | } 22 | 23 | public static void removeDrop(Material material, Drop drop) { 24 | List dropsList = getDrops(material); 25 | dropsList.remove(drop); 26 | if (dropsList.isEmpty()) { 27 | drops.remove(material); 28 | } 29 | } 30 | 31 | public static void unregisterAddonDrops(ProjectAddon addon) { 32 | for (Material material : new ArrayList<>(drops.keySet())) { 33 | List dropsList = getDrops(material); 34 | dropsList.removeIf(drop -> drop.owner.equals(addon)); 35 | if (dropsList.isEmpty()) { 36 | drops.remove(material); 37 | } 38 | } 39 | } 40 | 41 | public record Drop(ItemStack itemStack, int dropChance, ProjectAddon owner, int minDropAmount, int maxDropAmount) { 42 | public Drop(ItemStack itemStack, int dropChance, ProjectAddon owner) { 43 | this(itemStack, dropChance, owner, itemStack.getAmount(), itemStack.getAmount()); 44 | } 45 | 46 | @Override 47 | public ItemStack itemStack() { 48 | ItemStack itemStack = this.itemStack.clone(); 49 | itemStack.setAmount(randomDropAmount()); 50 | return itemStack; 51 | } 52 | 53 | private int randomDropAmount() { 54 | Random random = new Random(); 55 | int min = Math.min(minDropAmount, maxDropAmount); 56 | int max = Math.max(minDropAmount, maxDropAmount); 57 | return random.nextInt(max - min + 1) + min; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/global/RecipeTypeMap.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.global; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | import org.bukkit.Bukkit; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | public class RecipeTypeMap { 11 | private static final Map recipeTypes; 12 | 13 | static { 14 | recipeTypes = new HashMap<>(); 15 | 16 | RecipeTypeExpandIntegration.registerRecipeTypes(); 17 | } 18 | 19 | public static void removeRecipeTypes(String... keys) { 20 | for (String key : keys) { 21 | recipeTypes.remove(key); 22 | } 23 | } 24 | 25 | public static void pushRecipeType(RecipeType type) { 26 | recipeTypes.put(type.getKey().getKey().toUpperCase(), type); 27 | } 28 | 29 | public static void pushRecipeType(List types) { 30 | types.forEach(RecipeTypeMap::pushRecipeType); 31 | } 32 | 33 | public static void clearRecipeTypes() { 34 | recipeTypes.clear(); 35 | } 36 | 37 | @Nullable public static RecipeType getRecipeType(String s) { 38 | return recipeTypes.get(s); 39 | } 40 | 41 | private enum RecipeTypeExpandIntegration { 42 | INFINITY_EXPANSION("io.github.mooy1.infinityexpansion.items.blocks.InfinityWorkbench", "TYPE", true), 43 | SLIME_TINKER("io.github.sefiraat.slimetinker.items.workstations.workbench.Workbench", "TYPE", true); 44 | 45 | private final String clazz; 46 | private final String fieldName; 47 | private final boolean isStatic; 48 | 49 | RecipeTypeExpandIntegration(String clazz, String fieldName, boolean isStatic) { 50 | this.clazz = clazz; 51 | this.fieldName = fieldName; 52 | this.isStatic = isStatic; 53 | } 54 | 55 | static void registerRecipeTypes() { 56 | for (RecipeTypeExpandIntegration integration : values()) { 57 | String className = integration.clazz; 58 | String fieldName = integration.fieldName; 59 | try { 60 | Class clazz = Class.forName(className); 61 | Object instance; 62 | if (integration.isStatic) { 63 | instance = clazz.getField(fieldName).get(null); 64 | } else { 65 | instance = clazz.newInstance(); // or something sus 66 | } 67 | if (instance instanceof RecipeType) { 68 | RecipeTypeMap.pushRecipeType((RecipeType) instance); 69 | } 70 | } catch (Exception e) { 71 | Bukkit.getLogger() 72 | .warning("Failed to get external recipe type from " + className + "#" + fieldName + ": " 73 | + e.getMessage()); 74 | } 75 | } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/machine/CustomCraftingOperation.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.machine; 2 | 3 | import io.github.thebusybiscuit.slimefun4.implementation.operations.CraftingOperation; 4 | import io.github.thebusybiscuit.slimefun4.libraries.commons.lang.Validate; 5 | import javax.annotation.Nonnull; 6 | import lombok.Getter; 7 | 8 | @Getter 9 | public class CustomCraftingOperation extends CraftingOperation { 10 | private final CustomMachineRecipe recipe; 11 | 12 | public CustomCraftingOperation(@Nonnull CustomMachineRecipe recipe) { 13 | super(recipe.getInput(), recipe.getOutput(), recipe.getTicks()); 14 | Validate.isTrue( 15 | recipe.getTicks() >= 0, 16 | "The amount of total ticks must be a positive integer or zero, received: " + recipe.getTicks()); 17 | this.recipe = recipe; 18 | } 19 | 20 | public int getTotalTicks() { 21 | return recipe.getTicks(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/machine/CustomLinkedMachineOperation.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.machine; 2 | 3 | import io.github.thebusybiscuit.slimefun4.implementation.operations.CraftingOperation; 4 | import io.github.thebusybiscuit.slimefun4.libraries.commons.lang.Validate; 5 | import javax.annotation.Nonnull; 6 | import lombok.Getter; 7 | 8 | @Getter 9 | public class CustomLinkedMachineOperation extends CraftingOperation { 10 | private final CustomLinkedMachineRecipe recipe; 11 | 12 | public CustomLinkedMachineOperation(@Nonnull CustomLinkedMachineRecipe recipe) { 13 | super(recipe.getInput(), recipe.getOutput(), recipe.getTicks()); 14 | Validate.isTrue( 15 | recipe.getTicks() >= 0, 16 | "The amount of total ticks must be a positive integer or zero, received: " + recipe.getTicks()); 17 | this.recipe = recipe; 18 | } 19 | 20 | public int getTotalTicks() { 21 | return recipe.getTicks(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/machine/CustomLinkedMachineRecipe.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.machine; 2 | 3 | import java.util.Map; 4 | import lombok.Getter; 5 | import org.bukkit.inventory.ItemStack; 6 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.LinkedOutput; 7 | 8 | @Getter 9 | public class CustomLinkedMachineRecipe extends CustomMachineRecipe { 10 | private final Map linkedInput; 11 | private final LinkedOutput linkedOutput; 12 | 13 | public CustomLinkedMachineRecipe( 14 | int seconds, 15 | Map input, 16 | LinkedOutput linkedOutput, 17 | boolean chooseOneIfHas, 18 | boolean forDisplay, 19 | boolean hide) { 20 | super( 21 | seconds, 22 | input.values().toArray(new ItemStack[0]), 23 | linkedOutput.toArray(), 24 | linkedOutput.chancesToArray(), 25 | chooseOneIfHas, 26 | forDisplay, 27 | hide); 28 | this.linkedInput = input; 29 | this.linkedOutput = linkedOutput; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/machine/CustomMachineRecipe.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.machine; 2 | 3 | import java.security.SecureRandom; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | import lombok.Getter; 7 | import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineRecipe; 8 | import org.bukkit.inventory.ItemStack; 9 | 10 | @Getter 11 | public class CustomMachineRecipe extends MachineRecipe { 12 | private final List chances; 13 | 14 | private final boolean chooseOneIfHas; 15 | private final boolean forDisplay; 16 | private final boolean hide; 17 | 18 | public CustomMachineRecipe( 19 | int seconds, 20 | ItemStack[] input, 21 | ItemStack[] output, 22 | List chances, 23 | boolean chooseOneIfHas, 24 | boolean forDisplay, 25 | boolean hide) { 26 | super(seconds, input.clone(), output.clone()); 27 | 28 | this.chances = chances; 29 | this.chooseOneIfHas = chooseOneIfHas; 30 | this.forDisplay = forDisplay; 31 | this.hide = hide; 32 | } 33 | 34 | public List getMatchChanceResult() { 35 | List itemStacks = new ArrayList<>(); 36 | 37 | for (int i = 0; i < getOutput().length; i++) { 38 | ItemStack output = getOutput()[i]; 39 | int chance = chances.get(i); 40 | if (matchChance(chance)) { 41 | itemStacks.add(output); 42 | } 43 | } 44 | 45 | return itemStacks; 46 | } 47 | 48 | private boolean matchChance(Integer chance) { 49 | if (chance == null) return false; 50 | if (chance >= 100) return true; 51 | if (chance < 1) return false; 52 | 53 | int result = new SecureRandom().nextInt(100); 54 | return result < chance; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/machine/CustomTemplateCraftingOperation.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.machine; 2 | 3 | import io.github.thebusybiscuit.slimefun4.core.machines.MachineOperation; 4 | import io.github.thebusybiscuit.slimefun4.libraries.commons.lang.Validate; 5 | import lombok.Getter; 6 | 7 | public class CustomTemplateCraftingOperation implements MachineOperation { 8 | @Getter 9 | private final CustomMachineRecipe recipe; 10 | 11 | @Getter 12 | private final MachineTemplate template; 13 | 14 | private final int ticks; 15 | private int currentTicks; 16 | 17 | public CustomTemplateCraftingOperation(MachineTemplate template, CustomMachineRecipe recipe, int totalTicks) { 18 | this.currentTicks = 0; 19 | Validate.isTrue(recipe.getOutput().length != 0, "The recipe must have at least one output."); 20 | Validate.isTrue( 21 | totalTicks >= 0, 22 | "The amount of total ticks must be a positive integer or zero, received: " + totalTicks); 23 | this.recipe = recipe; 24 | this.ticks = totalTicks; 25 | this.template = template; 26 | } 27 | 28 | public void addProgress(int num) { 29 | Validate.isTrue(num > 0, "Progress must be positive."); 30 | this.currentTicks += num; 31 | } 32 | 33 | public int getProgress() { 34 | return this.currentTicks; 35 | } 36 | 37 | public int getTotalTicks() { 38 | return ticks; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/machine/MachineInfo.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.machine; 2 | 3 | import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; 5 | import io.github.thebusybiscuit.slimefun4.core.machines.MachineOperation; 6 | import io.github.thebusybiscuit.slimefun4.core.machines.MachineProcessor; 7 | import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; 8 | import org.bukkit.block.Block; 9 | import org.bukkit.inventory.Inventory; 10 | import org.jetbrains.annotations.Nullable; 11 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.machine.CustomMachine; 12 | 13 | /** 14 | * This data class provides access to machine data for JavaScript integration. 15 | * 16 | * @param blockMenu the menu of the machine, may be null if the machine has no GUI. 17 | * @param data the persistent data of the machine. 18 | * @param machineItem the {@link SlimefunItem} instance of the machine. 19 | * @param block the physical {@link Block} instance of the machine. 20 | * @param processor the {@link MachineProcessor} handling the machine's logic. 21 | * @param operation the current {@link MachineOperation}, ALWAYS be null so far... 22 | * @param machine the {@link CustomMachine} instance defining the machine's behavior. 23 | * @author lijinhong11 24 | * 25 | *

JavaScript Usage Example:

26 | *
{@code
27 |  * function tick(info) {
28 |  *     // May be null
29 |  *     var menu = info.blockMenu();
30 |  *     // Access Java fields in JavaScript should like this:
31 |  *     // var yourObjectName = info.();
32 |  *     // For example:
33 |  *     // var block = info.block();
34 |  *
35 |  *     if (menu !== null) {
36 |  *         // See Slimefun API for more details
37 |  *         var item = blockMenu.getItemInSlot(0);
38 |  *     }
39 |  *
40 |  *     // Displayed name
41 |  *     var itemName = info.machineItem().getItemName();
42 |  * }
43 |  * }
44 | */ 45 | public record MachineInfo( 46 | @Nullable BlockMenu blockMenu, 47 | SlimefunBlockData data, 48 | SlimefunItem machineItem, 49 | Block block, 50 | MachineProcessor processor, 51 | MachineOperation operation, 52 | CustomMachine machine) { 53 | 54 | public Inventory getInventory() { 55 | if (blockMenu == null) { 56 | return null; 57 | } 58 | return blockMenu.getInventory(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/machine/MachineRecord.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.machine; 2 | 3 | public record MachineRecord(int capacity) {} 4 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/machine/MachineTemplate.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.machine; 2 | 3 | import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; 4 | import java.util.List; 5 | import org.bukkit.inventory.ItemStack; 6 | 7 | public record MachineTemplate(ItemStack template, List recipes) { 8 | public boolean isItemSimilar(ItemStack item) { 9 | return SlimefunUtils.isItemSimilar(item, template, true); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/machine/ScriptedEvalBreakHandler.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.machine; 2 | 3 | import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; 4 | import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler; 5 | import java.util.List; 6 | import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.interfaces.InventoryBlock; 7 | import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; 8 | import org.bukkit.Location; 9 | import org.bukkit.block.Block; 10 | import org.bukkit.event.block.BlockBreakEvent; 11 | import org.bukkit.inventory.ItemStack; 12 | import org.jetbrains.annotations.NotNull; 13 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.script.ScriptEval; 14 | 15 | @SuppressWarnings("deprecation") 16 | public class ScriptedEvalBreakHandler extends BlockBreakHandler { 17 | private final ScriptEval eval; 18 | private final InventoryBlock machine; 19 | 20 | public ScriptedEvalBreakHandler(InventoryBlock machine, ScriptEval eval) { 21 | super(false, false); 22 | 23 | this.eval = eval; 24 | this.machine = machine; 25 | } 26 | 27 | @Override 28 | public void onPlayerBreak( 29 | BlockBreakEvent blockBreakEvent, @NotNull ItemStack itemStack, @NotNull List list) { 30 | Block block = blockBreakEvent.getBlock(); 31 | Location loc = block.getLocation(); 32 | BlockMenu bm = StorageCacheUtils.getMenu(loc); 33 | if (bm != null) { 34 | if (machine.getInputSlots().length > 0) { 35 | bm.dropItems(loc, machine.getInputSlots()); 36 | } 37 | if (machine.getOutputSlots().length > 0) { 38 | bm.dropItems(loc, machine.getOutputSlots()); 39 | } 40 | } 41 | 42 | if (eval != null) { 43 | eval.evalFunction("onBreak", blockBreakEvent, itemStack, list); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/machine/SimpleMachineType.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.machine; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public enum SimpleMachineType { 7 | ELECTRIC_SMELTERY(true), 8 | ELECTRIC_FURNACE(true), 9 | ELECTRIC_GOLD_PAN(true), 10 | ELECTRIC_DUST_WASHER(true), 11 | ELECTRIC_ORE_GRINDER(true), 12 | ELECTRIC_INGOT_FACTORY(true), 13 | ELECTRIC_INGOT_PULVERIZER(true), 14 | CHARGING_BENCH(true), 15 | ANIMAL_GROWTH_ACCELERATOR(true), 16 | TREE_GROWTH_ACCELERATOR(true), 17 | CROP_GROWTH_ACCELERATOR(true), 18 | FREEZER(true), 19 | CARBON_PRESS(true), 20 | ELECTRIC_PRESS(true), 21 | ELECTRIC_CRUCIBLE(true), 22 | FOOD_FABRICATOR(true), 23 | HEATED_PRESSURE_CHAMBER(true), 24 | AUTO_ENCHANTER(true), 25 | AUTO_DISENCHANTER(true), 26 | BOOK_BINDER(true), 27 | AUTO_ANVIL(true), 28 | AUTO_DRIER(true), 29 | AUTO_BREWER(true), 30 | REFINERY(true), 31 | PRODUCE_COLLECTOR(true); 32 | 33 | private final boolean energy; 34 | 35 | SimpleMachineType(boolean energy) { 36 | this.energy = energy; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/machine/SmallerMachineInfo.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.machine; 2 | 3 | import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; 5 | import io.github.thebusybiscuit.slimefun4.core.machines.MachineProcessor; 6 | import javax.annotation.Nullable; 7 | import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; 8 | import org.bukkit.block.Block; 9 | import org.bukkit.inventory.Inventory; 10 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.machine.CustomNoEnergyMachine; 11 | 12 | public record SmallerMachineInfo( 13 | @Nullable BlockMenu blockMenu, 14 | SlimefunBlockData data, 15 | CustomNoEnergyMachine machine, 16 | SlimefunItem machineItem, 17 | Block block, 18 | MachineProcessor processor) { 19 | 20 | public Inventory getInventory() { 21 | if (blockMenu == null) { 22 | return null; 23 | } 24 | return blockMenu.getInventory(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/script/ban/CommandSafe.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.script.ban; 2 | 3 | import java.util.List; 4 | 5 | public class CommandSafe { 6 | private static final List badCommands = List.of( 7 | "stop", 8 | "restart", 9 | "op", 10 | "deop", 11 | "whitelist", 12 | "ban-ip", 13 | "banlist", 14 | "pardon", 15 | "kick", 16 | "ban", 17 | "pardon-ip", 18 | "save-all", 19 | "unban", 20 | "luckperms", 21 | "lp", 22 | "cmi:ban", 23 | "cmi:pardon", 24 | "cmi:banlist", 25 | "cmi:unban", 26 | "essentials:ban", 27 | "essentials:pardon", 28 | "essentials:banlist", 29 | "essentials:unban", 30 | "essentials:mute", 31 | "essentials:unmute", 32 | "essentials:jail", 33 | "essentials:unjail", 34 | "cmi:jail", 35 | "cmi:unjail", 36 | "cmi:mute", 37 | "cmi:unmute", 38 | "essentials:sudo", 39 | "cmi:sudo"); 40 | 41 | public static boolean isBadCommand(String command) { 42 | return badCommands.contains(command.toLowerCase()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/script/enhanced/NBTAPIIntegration.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.script.enhanced; 2 | 3 | import de.tr7zw.nbtapi.*; 4 | import de.tr7zw.nbtapi.iface.ReadWriteNBT; 5 | import org.bukkit.block.Block; 6 | import org.bukkit.entity.Entity; 7 | import org.bukkit.inventory.ItemStack; 8 | 9 | public class NBTAPIIntegration { 10 | public static NBTAPIIntegration instance = new NBTAPIIntegration(); 11 | 12 | private NBTAPIIntegration() {} 13 | 14 | public ReadWriteNBT readItem(ItemStack item) { 15 | return NBT.itemStackToNBT(item); 16 | } 17 | 18 | public NBTCompound getOrCreateCompound(NBTCompound parent, String name) { 19 | return parent.getOrCreateCompound(name); 20 | } 21 | 22 | public NBTCompound readBlock(Block block) { 23 | return new NBTBlock(block).getData(); 24 | } 25 | 26 | public ReadWriteNBT readEntity(Entity entity) { 27 | ReadWriteNBT entityNbt = NBT.createNBTObject(); 28 | NBT.get(entity, entityNbt::mergeCompound); 29 | return entityNbt; 30 | } 31 | 32 | public ReadWriteNBT createCompound() { 33 | return NBT.createNBTObject(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/script/lambda/CiConsumer.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.script.lambda; 2 | 3 | @FunctionalInterface 4 | public interface CiConsumer { 5 | void accept(A a, B b, C c); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/script/lambda/CiFunction.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.script.lambda; 2 | 3 | @FunctionalInterface 4 | public interface CiFunction { 5 | R apply(A a, B b, C c); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/script/lambda/RSCClickHandler.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.script.lambda; 2 | 3 | import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu; 4 | import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ClickAction; 5 | import org.bukkit.entity.Player; 6 | import org.bukkit.inventory.ItemStack; 7 | 8 | @SuppressWarnings("deprecation") 9 | @FunctionalInterface 10 | public interface RSCClickHandler extends ChestMenu.MenuClickHandler { 11 | void mainFunction(Player player, int slot, ItemStack itemStack, ClickAction action); 12 | 13 | default boolean onClick(Player var1, int var2, ItemStack var3, ClickAction var4) { 14 | mainFunction(var1, var2, var3, var4); 15 | andThen(var1, var2, var3, var4); 16 | return false; 17 | } 18 | 19 | default void andThen(Player player, int slot, ItemStack itemStack, ClickAction action) {} 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/slimefun/AdvancedNestedItemGroup.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.slimefun; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.groups.NestedItemGroup; 4 | import io.github.thebusybiscuit.slimefun4.api.items.groups.SubItemGroup; 5 | import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile; 6 | import io.github.thebusybiscuit.slimefun4.core.guide.GuideHistory; 7 | import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide; 8 | import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode; 9 | import io.github.thebusybiscuit.slimefun4.core.services.sounds.SoundEffect; 10 | import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; 11 | import io.github.thebusybiscuit.slimefun4.implementation.guide.SurvivalSlimefunGuide; 12 | import io.github.thebusybiscuit.slimefun4.libraries.dough.items.CustomItemStack; 13 | import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils; 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | import java.util.Objects; 17 | import javax.annotation.Nonnull; 18 | import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu; 19 | import org.bukkit.ChatColor; 20 | import org.bukkit.NamespacedKey; 21 | import org.bukkit.entity.Player; 22 | import org.bukkit.inventory.ItemStack; 23 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.ExceptionHandler; 24 | 25 | public class AdvancedNestedItemGroup extends NestedItemGroup { 26 | private final List subGroups; 27 | 28 | public AdvancedNestedItemGroup(NamespacedKey key, ItemStack item, int tier) { 29 | super(key, item, tier); 30 | 31 | ExceptionHandler.debugLog("创建物品组: " + key); 32 | 33 | subGroups = new ArrayList<>(); 34 | } 35 | 36 | @Override 37 | public void open(Player p, PlayerProfile profile, SlimefunGuideMode mode) { 38 | setup(p, profile, mode, 1); 39 | } 40 | 41 | public void addSubGroup(@Nonnull SubItemGroup group) { 42 | super.addSubGroup(group); 43 | 44 | this.subGroups.add(group); 45 | } 46 | 47 | public void removeSubGroup(@Nonnull SubItemGroup group) { 48 | super.removeSubGroup(group); 49 | 50 | this.subGroups.remove(group); 51 | } 52 | 53 | @SuppressWarnings("deprecation") 54 | private void setup(Player p, PlayerProfile profile, SlimefunGuideMode mode, int page) { 55 | GuideHistory history = profile.getGuideHistory(); 56 | if (mode == SlimefunGuideMode.SURVIVAL_MODE) { 57 | history.add(this, page); 58 | } 59 | 60 | ChestMenu menu = new ChestMenu(Slimefun.getLocalization().getMessage(p, "guide.title.main")); 61 | SurvivalSlimefunGuide guide = 62 | (SurvivalSlimefunGuide) Slimefun.getRegistry().getSlimefunGuide(mode); 63 | menu.setEmptySlotsClickable(false); 64 | SoundEffect var10001 = SoundEffect.GUIDE_BUTTON_CLICK_SOUND; 65 | Objects.requireNonNull(var10001); 66 | menu.addMenuOpeningHandler(var10001::playFor); 67 | guide.createHeader(p, profile, menu); 68 | menu.addItem( 69 | 1, 70 | new CustomItemStack(ChestMenuUtils.getBackButton( 71 | p, "", ChatColor.GRAY + Slimefun.getLocalization().getMessage(p, "guide.back.guide")))); 72 | menu.addMenuClickHandler(1, (pl, s, is, action) -> { 73 | SlimefunGuide.openMainMenu(profile, mode, history.getMainMenuPage()); 74 | return false; 75 | }); 76 | 77 | int index = 9; 78 | int target = 36 * (page - 1) - 1; 79 | 80 | while (target < this.subGroups.size() - 1 && index < 45) { 81 | ++target; 82 | SubItemGroup itemGroup = this.subGroups.get(target); 83 | if (itemGroup.isVisibleInNested(p)) { 84 | menu.addItem(index, itemGroup.getItem(p)); 85 | menu.addMenuClickHandler(index, (pl, slot, item, action) -> { 86 | if (itemGroup instanceof ItemGroupButton button) { 87 | button.run(p, slot, item, action, mode); 88 | return false; 89 | } 90 | SlimefunGuide.openItemGroup(profile, itemGroup, mode, 1); 91 | return false; 92 | }); 93 | ++index; 94 | } 95 | } 96 | 97 | int pages = target == this.subGroups.size() - 1 ? page : (this.subGroups.size() - 1) / 36 + 1; 98 | menu.addItem(46, ChestMenuUtils.getPreviousButton(p, page, pages)); 99 | menu.addMenuClickHandler(46, (pl, slot, item, action) -> { 100 | int next = page - 1; 101 | if (next > 0) { 102 | setup(p, profile, mode, next); 103 | } 104 | 105 | return false; 106 | }); 107 | menu.addItem(52, ChestMenuUtils.getNextButton(p, page, pages)); 108 | menu.addMenuClickHandler(52, (pl, slot, item, action) -> { 109 | int next = page + 1; 110 | if (next <= pages) { 111 | setup(p, profile, mode, next); 112 | } 113 | 114 | return false; 115 | }); 116 | menu.open(p); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/slimefun/AsyncChanceRecipeTask.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.slimefun; 2 | 3 | import io.github.thebusybiscuit.slimefun4.libraries.commons.lang.Validate; 4 | import io.github.thebusybiscuit.slimefun4.libraries.dough.collections.LoopIterator; 5 | import java.util.HashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.concurrent.locks.ReadWriteLock; 9 | import java.util.concurrent.locks.ReentrantReadWriteLock; 10 | import javax.annotation.Nonnull; 11 | import org.bukkit.Bukkit; 12 | import org.bukkit.inventory.Inventory; 13 | import org.bukkit.inventory.ItemStack; 14 | import org.lins.mmmjjkx.rykenslimefuncustomizer.RykenSlimefunCustomizer; 15 | 16 | public class AsyncChanceRecipeTask implements Runnable { 17 | private static final int UPDATE_INTERVAL = 15; 18 | private final Map> iterators = new HashMap<>(); 19 | private final ReadWriteLock lock = new ReentrantReadWriteLock(); 20 | private Inventory inventory; 21 | private int id; 22 | 23 | public AsyncChanceRecipeTask() {} 24 | 25 | public void start(@Nonnull Inventory inv) { 26 | Validate.notNull(inv, "Inventory must not be null"); 27 | this.inventory = inv; 28 | this.id = Bukkit.getScheduler() 29 | .runTaskTimerAsynchronously(RykenSlimefunCustomizer.INSTANCE, this, 0L, 14L) 30 | .getTaskId(); 31 | } 32 | 33 | public void add(int slot, @Nonnull List item) { 34 | Validate.notNull(item, "Cannot add a null list of ItemStacks"); 35 | this.lock.writeLock().lock(); 36 | 37 | try { 38 | this.iterators.put(slot, new LoopIterator<>(item)); 39 | } finally { 40 | this.lock.writeLock().unlock(); 41 | } 42 | } 43 | 44 | public boolean isEmpty() { 45 | this.lock.readLock().lock(); 46 | 47 | boolean var1; 48 | try { 49 | var1 = this.iterators.isEmpty(); 50 | } finally { 51 | this.lock.readLock().unlock(); 52 | } 53 | 54 | return var1; 55 | } 56 | 57 | public void clear() { 58 | this.lock.writeLock().lock(); 59 | 60 | try { 61 | this.iterators.clear(); 62 | } finally { 63 | this.lock.writeLock().unlock(); 64 | } 65 | } 66 | 67 | public void run() { 68 | if (this.inventory.getViewers().isEmpty()) { 69 | Bukkit.getScheduler().cancelTask(this.id); 70 | } else { 71 | this.lock.readLock().lock(); 72 | 73 | try { 74 | for (Map.Entry> entry : this.iterators.entrySet()) { 75 | this.inventory.setItem(entry.getKey(), entry.getValue().next()); 76 | } 77 | } finally { 78 | this.lock.readLock().unlock(); 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/slimefun/WitherProofBlockImpl.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.slimefun; 2 | 3 | import io.github.thebusybiscuit.slimefun4.core.attributes.WitherProof; 4 | import javax.annotation.Nonnull; 5 | import org.bukkit.block.Block; 6 | import org.bukkit.entity.Wither; 7 | 8 | public interface WitherProofBlockImpl extends WitherProof { 9 | default void onAttack(@Nonnull Block var1, @Nonnull Wither var2) {} 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/yaml/ItemGroupReader.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.yaml; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 5 | import io.github.thebusybiscuit.slimefun4.api.items.groups.LockedItemGroup; 6 | import io.github.thebusybiscuit.slimefun4.api.items.groups.NestedItemGroup; 7 | import io.github.thebusybiscuit.slimefun4.api.items.groups.SeasonalItemGroup; 8 | import io.github.thebusybiscuit.slimefun4.api.items.groups.SubItemGroup; 9 | import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; 10 | import java.time.Month; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | import org.bukkit.NamespacedKey; 14 | import org.bukkit.configuration.ConfigurationSection; 15 | import org.bukkit.configuration.file.YamlConfiguration; 16 | import org.bukkit.inventory.ItemStack; 17 | import org.lins.mmmjjkx.rykenslimefuncustomizer.RykenSlimefunCustomizer; 18 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.ProjectAddon; 19 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.slimefun.AdvancedNestedItemGroup; 20 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.slimefun.ItemGroupButton; 21 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.CommonUtils; 22 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.ExceptionHandler; 23 | 24 | public class ItemGroupReader extends YamlReader { 25 | public ItemGroupReader(YamlConfiguration config, ProjectAddon addon) { 26 | super(config, addon); 27 | } 28 | 29 | @Override 30 | public ItemGroup readEach(String s) { 31 | ConfigurationSection section = configuration.getConfigurationSection(s); 32 | if (section == null) return null; 33 | ExceptionHandler.HandleResult conflict = ExceptionHandler.handleGroupIdConflict(s); 34 | 35 | if (conflict == ExceptionHandler.HandleResult.FAILED) return null; 36 | 37 | ConfigurationSection item = section.getConfigurationSection("item"); 38 | ItemStack stack = CommonUtils.readItem(item, false, addon); 39 | if (stack == null) { 40 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载物品组" + s + "时遇到了问题: " + "物品为空或格式错误导致无法加载"); 41 | return null; 42 | } 43 | 44 | String type = section.getString("type", ""); 45 | NamespacedKey key = new NamespacedKey(RykenSlimefunCustomizer.INSTANCE, s); 46 | 47 | int tier = section.getInt("tier", 3); 48 | 49 | ItemGroup group = 50 | switch (type) { 51 | default -> new ItemGroup(key, stack, tier); 52 | case "sub" -> { 53 | NamespacedKey parent = new NamespacedKey( 54 | RykenSlimefunCustomizer.INSTANCE, 55 | section.getString("parent", "").toLowerCase()); 56 | ItemGroup raw = CommonUtils.getIf(Slimefun.getRegistry().getAllItemGroups(), ig -> ig.getKey() 57 | .equals(parent)); 58 | if (raw == null) { 59 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载物品组" + s + "时遇到了问题: " 60 | + "无法找到父物品组" + parent.getKey()); 61 | yield null; 62 | } 63 | if (!(raw instanceof NestedItemGroup nig)) { 64 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载物品组" + s + "时遇到了问题: " + "物品组" 65 | + parent.getKey() + "不是一个嵌套物品组"); 66 | yield null; 67 | } 68 | 69 | yield new SubItemGroup(key, nig, stack, tier); 70 | } 71 | case "locked" -> { 72 | List parents = new ArrayList<>(); 73 | for (String ig : section.getStringList("parents")) { 74 | NamespacedKey nk = NamespacedKey.fromString(ig); 75 | if (nk == null) { 76 | ExceptionHandler.handleWarning("在附属" + addon.getAddonId() + "中加载物品组" + s + "时遇到了问题: " 77 | + ig + "不是一个有效的NamespacedKey"); 78 | continue; 79 | } 80 | parents.add(nk); 81 | } 82 | 83 | yield new LockedItemGroup(key, stack, tier, parents.toArray(new NamespacedKey[] {})); 84 | } 85 | case "nested", "parent" -> new AdvancedNestedItemGroup(key, stack, tier); 86 | case "seasonal" -> { 87 | Month month = Month.of(section.getInt("month", 1)); 88 | yield new SeasonalItemGroup(key, month, tier, stack); 89 | } 90 | case "button" -> { 91 | NamespacedKey parent = new NamespacedKey( 92 | RykenSlimefunCustomizer.INSTANCE, 93 | section.getString("parent", "").toLowerCase()); 94 | ItemGroup raw = CommonUtils.getIf(Slimefun.getRegistry().getAllItemGroups(), ig -> ig.getKey() 95 | .equals(parent)); 96 | if (raw == null) { 97 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载物品组" + s + "时遇到了问题: " 98 | + "无法找到父物品组" + parent.getKey()); 99 | yield null; 100 | } 101 | 102 | if (!(raw instanceof AdvancedNestedItemGroup nig)) { 103 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载物品组" + s + "时遇到了问题: " + "物品组" 104 | + parent.getKey() + "不是一个来自RSC的嵌套物品组"); 105 | yield null; 106 | } 107 | 108 | List actions = section.getStringList("actions"); 109 | 110 | yield new ItemGroupButton(addon, key, nig, stack, tier, actions); 111 | } 112 | }; 113 | 114 | if (group != null) { 115 | group.register(RykenSlimefunCustomizer.INSTANCE); 116 | } 117 | 118 | return group; 119 | } 120 | 121 | // 物品组不需要预加载物品 122 | @Override 123 | public List preloadItems(String s) { 124 | return List.of(); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/yaml/RecipeTypesReader.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.yaml; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 4 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 5 | import java.util.List; 6 | import org.bukkit.NamespacedKey; 7 | import org.bukkit.configuration.ConfigurationSection; 8 | import org.bukkit.configuration.file.YamlConfiguration; 9 | import org.bukkit.inventory.ItemStack; 10 | import org.lins.mmmjjkx.rykenslimefuncustomizer.RykenSlimefunCustomizer; 11 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.ProjectAddon; 12 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.CommonUtils; 13 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.ExceptionHandler; 14 | 15 | public class RecipeTypesReader extends YamlReader { 16 | public RecipeTypesReader(YamlConfiguration config, ProjectAddon addon) { 17 | super(config, addon); 18 | } 19 | 20 | @Override 21 | public RecipeType readEach(String s) { 22 | ConfigurationSection configurationSection = configuration.getConfigurationSection(s); 23 | if (configurationSection == null) return null; 24 | 25 | ItemStack item = CommonUtils.readItem(configurationSection, false, addon); 26 | if (item == null) { 27 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载配方类型" + s + "时遇到了问题: " + "物品为空或格式错误导致无法加载"); 28 | return null; 29 | } 30 | 31 | return new RecipeType(new NamespacedKey(RykenSlimefunCustomizer.INSTANCE, s.toLowerCase()), item); 32 | } 33 | 34 | // 配方类型不需要预加载物品 35 | @Override 36 | public List preloadItems(String s) { 37 | return List.of(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/yaml/ResearchReader.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.yaml; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 5 | import io.github.thebusybiscuit.slimefun4.api.researches.Research; 6 | import java.util.List; 7 | import java.util.regex.Pattern; 8 | import org.bukkit.NamespacedKey; 9 | import org.bukkit.configuration.ConfigurationSection; 10 | import org.bukkit.configuration.file.YamlConfiguration; 11 | import org.lins.mmmjjkx.rykenslimefuncustomizer.RykenSlimefunCustomizer; 12 | import org.lins.mmmjjkx.rykenslimefuncustomizer.libraries.colors.CMIChatColor; 13 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.ProjectAddon; 14 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.ExceptionHandler; 15 | 16 | public class ResearchReader extends YamlReader { 17 | private static final Pattern VALID_KEY = Pattern.compile("[a-z0-9/._-]+"); 18 | 19 | public ResearchReader(YamlConfiguration config, ProjectAddon addon) { 20 | super(config, addon); 21 | } 22 | 23 | @Override 24 | public Research readEach(String s) { 25 | ConfigurationSection section = configuration.getConfigurationSection(s); 26 | if (section == null) return null; 27 | 28 | if (!VALID_KEY.matcher(s).matches()) { 29 | ExceptionHandler.handleError( 30 | "在附属" + addon.getAddonId() + "中加载研究" + s + "时遇到了问题: " + "研究" + s + " 的ID无效,只能使用[a-z0-9._-]这些字符。"); 31 | return null; 32 | } 33 | 34 | int researchId = section.getInt("id"); 35 | String name = section.getString("name"); 36 | int cost = section.getInt("levelCost"); 37 | List items = section.getStringList("items"); 38 | 39 | if (researchId <= 0) { 40 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载研究" + s + "时遇到了问题: " + "id必须大于0!"); 41 | return null; 42 | } 43 | if (cost <= 0) { 44 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载研究" + s + "时遇到了问题: " + "等级花费必须大于0!"); 45 | return null; 46 | } 47 | if (name == null || name.isBlank()) { 48 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载研究" + s + "时遇到了问题: " + "名称不能为空!"); 49 | return null; 50 | } 51 | 52 | name = CMIChatColor.translate(name); 53 | 54 | boolean hasCurrency = section.contains("currencyCost"); 55 | double currency = 0; 56 | if (hasCurrency) { 57 | currency = section.getDouble("currencyCost"); 58 | if (currency < 0) { 59 | ExceptionHandler.handleWarning( 60 | "在附属" + addon.getAddonId() + "中加载研究" + s + "时遇到了问题: " + "货币花费不能小于0! 已忽略."); 61 | hasCurrency = false; 62 | } 63 | } 64 | 65 | Research research; 66 | if (hasCurrency) { 67 | research = new Research( 68 | new NamespacedKey(RykenSlimefunCustomizer.INSTANCE, s), researchId, name, cost, currency); 69 | } else { 70 | research = new Research(new NamespacedKey(RykenSlimefunCustomizer.INSTANCE, s), researchId, name, cost); 71 | } 72 | 73 | for (String item : items) { 74 | SlimefunItem sfItem = SlimefunItem.getById(item); 75 | if (sfItem == null) { 76 | ExceptionHandler.handleWarning( 77 | "在附属" + addon.getAddonId() + "中加载研究" + s + "时遇到了问题: " + item + " 不是粘液科技物品! 已跳过."); 78 | continue; 79 | } 80 | research.addItems(sfItem); 81 | } 82 | 83 | research.register(); 84 | 85 | return research; 86 | } 87 | 88 | // 研究不需要预加载物品 89 | @Override 90 | public List preloadItems(String s) { 91 | return List.of(); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/yaml/item/ArmorReader.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.yaml.item; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 5 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 6 | import io.github.thebusybiscuit.slimefun4.core.attributes.ProtectionType; 7 | import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; 8 | import io.github.thebusybiscuit.slimefun4.libraries.dough.collections.Pair; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | import org.bukkit.configuration.ConfigurationSection; 12 | import org.bukkit.configuration.file.YamlConfiguration; 13 | import org.bukkit.inventory.ItemStack; 14 | import org.bukkit.potion.PotionEffect; 15 | import org.bukkit.potion.PotionEffectType; 16 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.ProjectAddon; 17 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.item.CustomArmorPiece; 18 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.yaml.YamlReader; 19 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.CommonUtils; 20 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.ExceptionHandler; 21 | 22 | public class ArmorReader extends YamlReader> { 23 | private final List CHECKS = List.of("helmet", "chestplate", "leggings", "boots"); 24 | 25 | public ArmorReader(YamlConfiguration config, ProjectAddon addon) { 26 | super(config, addon); 27 | } 28 | 29 | @Override 30 | public List readEach(String s) { 31 | ConfigurationSection section = configuration.getConfigurationSection(s); 32 | if (section == null) return null; 33 | 34 | boolean fullSet = section.getBoolean("fullSet", false); 35 | 36 | Pair group = 37 | ExceptionHandler.handleItemGroupGet(addon, section.getString("item_group", "")); 38 | if (group.getFirstValue() == ExceptionHandler.HandleResult.FAILED) return null; 39 | 40 | List pt = section.getStringList("protection_types"); 41 | List protectionTypes = new ArrayList<>(); 42 | for (String type : pt) { 43 | Pair result = ExceptionHandler.handleEnumValueOf( 44 | "在附属" + addon.getAddonId() + "中加载盔甲套" + s + "时遇到了问题: " + "错误的盔甲保护类型: " + type, 45 | ProtectionType.class, 46 | type); 47 | if (result.getFirstValue() == ExceptionHandler.HandleResult.FAILED) return null; 48 | protectionTypes.add(result.getSecondValue()); 49 | } 50 | 51 | List pieces = new ArrayList<>(); 52 | for (String check : CHECKS) { 53 | ConfigurationSection pieceSection = section.getConfigurationSection(check); 54 | if (pieceSection == null) continue; 55 | 56 | String pieceId = addon.getId( 57 | s + "_" + check.toUpperCase(), section.getString("id_alias", pieceSection.getString("id", ""))); 58 | 59 | ExceptionHandler.HandleResult result = ExceptionHandler.handleIdConflict(pieceId); 60 | if (result == ExceptionHandler.HandleResult.FAILED) return null; 61 | 62 | String recipeType = pieceSection.getString("recipe_type", "NULL"); 63 | 64 | Pair rt = ExceptionHandler.getRecipeType( 65 | "在附属" + addon.getAddonId() + "中加载盔甲套" + s + "的" + check + "时遇到了问题: " + "错误的配方类型" + recipeType + "!", 66 | recipeType); 67 | if (rt.getFirstValue() == ExceptionHandler.HandleResult.FAILED) return null; 68 | 69 | SlimefunItemStack sfis = getPreloadItem(pieceId); 70 | if (sfis == null) return null; 71 | 72 | ConfigurationSection recipeSection = pieceSection.getConfigurationSection("recipe"); 73 | ItemStack[] recipe = CommonUtils.readRecipe(recipeSection, addon); 74 | 75 | List potionEffects = new ArrayList<>(); 76 | List effects = pieceSection.getStringList("potion_effects"); 77 | 78 | for (String effect : effects) { 79 | String[] split = effect.split(" "); 80 | if (split.length != 2) { 81 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载盔甲套" + s + "的" + check + "时遇到了问题: " 82 | + "错误的药水效果格式: " + effect); 83 | return null; 84 | } 85 | String effectName = split[0]; 86 | int amplifier = Integer.parseInt(split[1]); 87 | 88 | PotionEffectType type = PotionEffectType.getByName(effectName); 89 | if (type == null) { 90 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载盔甲套" + s + "的" + check + "时遇到了问题: " 91 | + "错误的药水效果类型: " + effectName); 92 | return null; 93 | } 94 | 95 | if (amplifier < 0) { 96 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载盔甲套" + s + "的" + check + "时遇到了问题: " 97 | + "药水效果等级不能为负数: " + effect + ", 但你设置了" + amplifier); 98 | return null; 99 | } 100 | 101 | potionEffects.add(new PotionEffect( 102 | type, (Slimefun.getCfg().getInt("options.armor-update-interval") + 3) * 20, amplifier)); 103 | } 104 | 105 | pieces.add(new CustomArmorPiece( 106 | group.getSecondValue(), 107 | sfis, 108 | rt.getSecondValue(), 109 | recipe, 110 | potionEffects.toArray(new PotionEffect[] {}), 111 | fullSet, 112 | s, 113 | protectionTypes.toArray(new ProtectionType[] {}), 114 | addon.getAddonId())); 115 | } 116 | 117 | if (pieces.isEmpty()) { 118 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载盔甲套" + s + "时遇到了问题: " + "没有找到任何盔甲部分"); 119 | return null; 120 | } 121 | 122 | return pieces; 123 | } 124 | 125 | @Override 126 | public List preloadItems(String s) { 127 | List items = new ArrayList<>(4); 128 | ConfigurationSection section = configuration.getConfigurationSection(s); 129 | if (section == null) return null; 130 | 131 | for (String check : CHECKS) { 132 | ConfigurationSection pieceSection = section.getConfigurationSection(check); 133 | if (pieceSection == null) continue; 134 | 135 | ItemStack stack = CommonUtils.readItem(pieceSection, false, addon); 136 | if (stack == null) { 137 | ExceptionHandler.handleError( 138 | "在附属" + addon.getAddonId() + "中加载盔甲套" + s + "的" + check + "时遇到了问题: " + "物品为空或格式错误导致无法加载,已跳过"); 139 | continue; 140 | } 141 | 142 | SlimefunItemStack sfis = new SlimefunItemStack( 143 | addon.getId( 144 | s + "_" + check.toUpperCase(), 145 | section.getString("id_alias", pieceSection.getString("id", ""))), 146 | stack); 147 | items.add(sfis); 148 | } 149 | 150 | return items; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/yaml/item/CapacitorsReader.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.yaml.item; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 5 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 6 | import io.github.thebusybiscuit.slimefun4.implementation.items.electric.Capacitor; 7 | import io.github.thebusybiscuit.slimefun4.libraries.dough.collections.Pair; 8 | import java.util.List; 9 | import java.util.Objects; 10 | import org.bukkit.configuration.ConfigurationSection; 11 | import org.bukkit.configuration.file.YamlConfiguration; 12 | import org.bukkit.inventory.ItemStack; 13 | import org.lins.mmmjjkx.rykenslimefuncustomizer.RykenSlimefunCustomizer; 14 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.ProjectAddon; 15 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.yaml.YamlReader; 16 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.CommonUtils; 17 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.ExceptionHandler; 18 | 19 | public class CapacitorsReader extends YamlReader { 20 | public CapacitorsReader(YamlConfiguration config, ProjectAddon addon) { 21 | super(config, addon); 22 | } 23 | 24 | @Override 25 | public Capacitor readEach(String s) { 26 | ConfigurationSection section = configuration.getConfigurationSection(s); 27 | if (section == null) return null; 28 | 29 | String id = addon.getId(s, section.getString("id_alias")); 30 | ExceptionHandler.HandleResult result = ExceptionHandler.handleIdConflict(id); 31 | 32 | if (result == ExceptionHandler.HandleResult.FAILED) return null; 33 | 34 | String igId = section.getString("item_group"); 35 | 36 | Pair group = ExceptionHandler.handleItemGroupGet(addon, igId); 37 | if (group.getFirstValue() == ExceptionHandler.HandleResult.FAILED) return null; 38 | 39 | SlimefunItemStack sfis = getPreloadItem(id); 40 | if (sfis == null) return null; 41 | 42 | ItemStack[] recipe = CommonUtils.readRecipe(section.getConfigurationSection("recipe"), addon); 43 | String recipeType = section.getString("recipe_type", "NULL"); 44 | 45 | Pair rt = ExceptionHandler.getRecipeType( 46 | "在附属" + addon.getAddonId() + "中加载电容" + s + "时遇到了问题: " + "错误的配方类型" + recipeType + "!", recipeType); 47 | 48 | if (rt.getFirstValue() == ExceptionHandler.HandleResult.FAILED) return null; 49 | 50 | int capacity = section.getInt("capacity"); 51 | if (capacity < 1) { 52 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载电容" + s + "时遇到了问题: " + "容量不能小于1"); 53 | return null; 54 | } 55 | 56 | Capacitor instance = new Capacitor( 57 | Objects.requireNonNull(group.getSecondValue()), 58 | capacity, 59 | sfis, 60 | Objects.requireNonNull(rt.getSecondValue()), 61 | recipe); 62 | 63 | instance.register(RykenSlimefunCustomizer.INSTANCE); 64 | return instance; 65 | } 66 | 67 | @Override 68 | public List preloadItems(String id) { 69 | ConfigurationSection section = configuration.getConfigurationSection(id); 70 | if (section == null) return null; 71 | 72 | ConfigurationSection item = section.getConfigurationSection("item"); 73 | ItemStack stack = CommonUtils.readItem(item, false, addon); 74 | 75 | if (stack == null) { 76 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载电容" + id + "时遇到了问题: " + "物品为空或格式错误导致无法加载"); 77 | return null; 78 | } 79 | 80 | if (!stack.getType().isBlock()) { 81 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载电容" + id + "时遇到了问题: " + "物品的材料类型必须是可放置的方块"); 82 | return null; 83 | } 84 | 85 | return List.of(new SlimefunItemStack(addon.getId(id, section.getString("id_alias")), stack)); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/yaml/item/FoodReader.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.yaml.item; 2 | 3 | import de.tr7zw.nbtapi.NBT; 4 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 5 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 6 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 7 | import io.github.thebusybiscuit.slimefun4.libraries.dough.collections.Pair; 8 | import java.io.File; 9 | import java.util.List; 10 | import org.bukkit.Bukkit; 11 | import org.bukkit.configuration.ConfigurationSection; 12 | import org.bukkit.configuration.file.YamlConfiguration; 13 | import org.bukkit.inventory.ItemStack; 14 | import org.lins.mmmjjkx.rykenslimefuncustomizer.bulit_in.JavaScriptEval; 15 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.ProjectAddon; 16 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.item.CustomFood; 17 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.yaml.YamlReader; 18 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.CommonUtils; 19 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.ExceptionHandler; 20 | 21 | public class FoodReader extends YamlReader { 22 | public FoodReader(YamlConfiguration config, ProjectAddon addon) { 23 | super(config, addon); 24 | } 25 | 26 | @Override 27 | public CustomFood readEach(String s) { 28 | ConfigurationSection section = configuration.getConfigurationSection(s); 29 | if (section == null) return null; 30 | 31 | String id = addon.getId(s, section.getString("id_alias")); 32 | 33 | ExceptionHandler.HandleResult result = ExceptionHandler.handleIdConflict(id); 34 | 35 | if (result == ExceptionHandler.HandleResult.FAILED) return null; 36 | 37 | String igId = section.getString("item_group"); 38 | 39 | Pair group = ExceptionHandler.handleItemGroupGet(addon, igId); 40 | if (group.getFirstValue() == ExceptionHandler.HandleResult.FAILED) return null; 41 | 42 | SlimefunItemStack sfis = getPreloadItem(id); 43 | if (sfis == null) return null; 44 | 45 | ItemStack[] itemStacks = CommonUtils.readRecipe(section.getConfigurationSection("recipe"), addon); 46 | String recipeType = section.getString("recipe_type", "NULL"); 47 | 48 | Pair rt = ExceptionHandler.getRecipeType( 49 | "在附属" + addon.getAddonId() + "中加载食物" + s + "时遇到了问题: " + "错误的配方类型" + recipeType + "!", recipeType); 50 | 51 | if (rt.getFirstValue() == ExceptionHandler.HandleResult.FAILED) return null; 52 | 53 | JavaScriptEval eval = null; 54 | if (section.contains("script")) { 55 | String script = section.getString("script", ""); 56 | File file = new File(addon.getScriptsFolder(), script + ".js"); 57 | if (!file.exists()) { 58 | ExceptionHandler.handleWarning( 59 | "在附属" + addon.getAddonId() + "中加载食物" + s + "时遇到了问题: " + "找不到脚本文件 " + file.getName()); 60 | } else { 61 | eval = new JavaScriptEval(file, addon); 62 | } 63 | } 64 | 65 | if (CommonUtils.versionToCode(Bukkit.getMinecraftVersion()) >= 1205) { 66 | if (Bukkit.getPluginManager().isPluginEnabled("NBTAPI")) { 67 | sfis = nbtApply(id, section, sfis); 68 | } 69 | } 70 | 71 | return new CustomFood(group.getSecondValue(), sfis, rt.getSecondValue(), itemStacks, eval, sfis); 72 | } 73 | 74 | private SlimefunItemStack nbtApply(String s, ConfigurationSection section, SlimefunItemStack sfis) { 75 | int nutrition = section.getInt("nutrition"); 76 | float saturation = section.getInt("saturation"); 77 | boolean alwaysEatable = section.getBoolean("always_eatable", false); 78 | float eatseconds = section.getInt("eat_seconds", 0); 79 | if (nutrition < 1) { 80 | ExceptionHandler.handleError( 81 | "在附属" + addon.getAddonId() + "中加载食物" + s + "时遇到了问题: " + "饥饿值 " + nutrition + "小于1! 已转为1"); 82 | nutrition = 1; 83 | } 84 | if (saturation < 0f) { 85 | ExceptionHandler.handleError( 86 | "在附属" + addon.getAddonId() + "中加载食物" + s + "时遇到了问题: " + "饱和度 " + saturation + "小于0! 已转为0"); 87 | saturation = 0f; 88 | } 89 | if (eatseconds < 0) { 90 | ExceptionHandler.handleError( 91 | "在附属" + addon.getAddonId() + "中加载食物" + s + "时遇到了问题: " + "食用时间 " + eatseconds + "小于0! 已转为1.6"); 92 | eatseconds = 1.6f; 93 | } 94 | 95 | int finalNutrition = nutrition; 96 | float finalSaturation = saturation; 97 | float finalEatSeconds = eatseconds; 98 | NBT.modify(sfis, c -> { 99 | c.setInteger("nutrition", finalNutrition); 100 | c.setFloat("saturation", finalSaturation); 101 | c.setBoolean("can_always_eat", alwaysEatable); 102 | c.setFloat("eat_seconds", finalEatSeconds); 103 | }); 104 | 105 | return sfis; 106 | } 107 | 108 | @Override 109 | public List preloadItems(String id) { 110 | ConfigurationSection section = configuration.getConfigurationSection(id); 111 | 112 | if (section == null) return null; 113 | 114 | ConfigurationSection item = section.getConfigurationSection("item"); 115 | ItemStack stack = CommonUtils.readItem(item, false, addon); 116 | if (stack == null) { 117 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载食物" + id + "时遇到了问题: " + "物品为空或格式错误导致无法加载"); 118 | return null; 119 | } 120 | 121 | return List.of(new SlimefunItemStack(addon.getId(id, section.getString("id_alias")), stack)); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/yaml/item/MobDropsReader.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.yaml.item; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 5 | import io.github.thebusybiscuit.slimefun4.libraries.dough.collections.Pair; 6 | import io.github.thebusybiscuit.slimefun4.libraries.dough.items.CustomItemStack; 7 | import java.util.List; 8 | import net.kyori.adventure.text.Component; 9 | import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; 10 | import org.bukkit.Material; 11 | import org.bukkit.configuration.ConfigurationSection; 12 | import org.bukkit.configuration.file.YamlConfiguration; 13 | import org.bukkit.entity.EntityType; 14 | import org.bukkit.inventory.ItemStack; 15 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.ProjectAddon; 16 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.item.exts.CustomMobDrop; 17 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.yaml.YamlReader; 18 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.CommonUtils; 19 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.ExceptionHandler; 20 | 21 | @SuppressWarnings("deprecation") 22 | public class MobDropsReader extends YamlReader { 23 | public MobDropsReader(YamlConfiguration config, ProjectAddon addon) { 24 | super(config, addon); 25 | } 26 | 27 | @Override 28 | public CustomMobDrop readEach(String s) { 29 | ConfigurationSection section = configuration.getConfigurationSection(s); 30 | if (section != null) { 31 | String id = addon.getId(s, section.getString("id_alias")); 32 | 33 | ExceptionHandler.HandleResult result = ExceptionHandler.handleIdConflict(id); 34 | if (result == ExceptionHandler.HandleResult.FAILED) return null; 35 | 36 | String igId = section.getString("item_group"); 37 | 38 | Pair group = ExceptionHandler.handleItemGroupGet(addon, igId); 39 | if (group.getFirstValue() == ExceptionHandler.HandleResult.FAILED) return null; 40 | 41 | SlimefunItemStack sfis = getPreloadItem(id); 42 | if (sfis == null) return null; 43 | 44 | String type = section.getString("entity"); 45 | 46 | Pair entity = ExceptionHandler.handleEnumValueOf( 47 | "在附属" + addon.getAddonId() + "中加载生物掉落物" + s + "时遇到了问题: " + "错误的生物类型", EntityType.class, type); 48 | if (entity.getFirstValue() == ExceptionHandler.HandleResult.FAILED) { 49 | return null; 50 | } 51 | 52 | Material eggMaterial; 53 | EntityType entityType = entity.getSecondValue(); 54 | if (entityType == null) return null; 55 | 56 | Pair egg = 57 | ExceptionHandler.handleEnumValueOf("", Material.class, entityType + "_SPAWN_EGG"); 58 | if (egg.getFirstValue() == ExceptionHandler.HandleResult.SUCCESS && egg.getSecondValue() != null) { 59 | eggMaterial = egg.getSecondValue(); 60 | } else { 61 | eggMaterial = Material.EGG; 62 | } 63 | 64 | int chance = section.getInt("chance"); 65 | 66 | if (chance < 1 || chance > 100) { 67 | ExceptionHandler.handleError( 68 | "在附属" + addon.getAddonId() + "中加载生物掉落物" + s + "时遇到了问题: " + "掉落概率未设置或不应该小于1或大于100,已转换为1或100"); 69 | chance = chance >= 100 ? 100 : 1; 70 | } 71 | 72 | Component lore = LegacyComponentSerializer.legacyAmpersand() 73 | .deserialize("&a击杀 ") 74 | .append(LegacyComponentSerializer.legacyAmpersand().deserialize("&b")) 75 | .append(Component.translatable(entityType.translationKey())) 76 | .append(LegacyComponentSerializer.legacyAmpersand().deserialize(" &a时会有")) 77 | .append(LegacyComponentSerializer.legacyAmpersand().deserialize(" &b " + chance + "%")) 78 | .append(LegacyComponentSerializer.legacyAmpersand().deserialize(" &a的概率掉落")); 79 | 80 | ItemStack itemStack = new CustomItemStack(eggMaterial, meta -> { 81 | meta.setDisplayName(entityType.toString()); 82 | meta.lore(List.of(lore)); 83 | }); 84 | ItemStack[] recipe = new ItemStack[] {null, null, null, null, itemStack}; 85 | 86 | return new CustomMobDrop(group.getSecondValue(), sfis, recipe, chance, entityType, sfis); 87 | } 88 | return null; 89 | } 90 | 91 | @Override 92 | public List preloadItems(String id) { 93 | ConfigurationSection section = configuration.getConfigurationSection(id); 94 | 95 | if (section == null) return null; 96 | 97 | ConfigurationSection item = section.getConfigurationSection("item"); 98 | ItemStack stack = CommonUtils.readItem(item, false, addon); 99 | if (stack == null) { 100 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载生物掉落物" + id + "时遇到了问题: " + "物品为空或格式错误导致无法加载"); 101 | return null; 102 | } 103 | 104 | return List.of(new SlimefunItemStack(addon.getId(id, section.getString("id_alias")), stack)); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/yaml/machine/GeneratorReader.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.yaml.machine; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 5 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 6 | import io.github.thebusybiscuit.slimefun4.libraries.dough.collections.Pair; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import lombok.SneakyThrows; 10 | import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineFuel; 11 | import org.bukkit.configuration.ConfigurationSection; 12 | import org.bukkit.configuration.file.YamlConfiguration; 13 | import org.bukkit.inventory.ItemStack; 14 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.ProjectAddon; 15 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.CustomMenu; 16 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.machine.CustomGenerator; 17 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.yaml.YamlReader; 18 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.CommonUtils; 19 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.ExceptionHandler; 20 | 21 | public class GeneratorReader extends YamlReader { 22 | public GeneratorReader(YamlConfiguration config, ProjectAddon addon) { 23 | super(config, addon); 24 | } 25 | 26 | @SneakyThrows 27 | @Override 28 | public CustomGenerator readEach(String s) { 29 | ConfigurationSection section = configuration.getConfigurationSection(s); 30 | if (section == null) return null; 31 | String id = addon.getId(s, section.getString("id_alias")); 32 | 33 | ExceptionHandler.HandleResult result = ExceptionHandler.handleIdConflict(id); 34 | 35 | if (result == ExceptionHandler.HandleResult.FAILED) return null; 36 | 37 | String igId = section.getString("item_group"); 38 | 39 | SlimefunItemStack sfis = getPreloadItem(id); 40 | if (sfis == null) return null; 41 | 42 | Pair group = ExceptionHandler.handleItemGroupGet(addon, igId); 43 | if (group.getFirstValue() == ExceptionHandler.HandleResult.FAILED) return null; 44 | ItemStack[] recipe = CommonUtils.readRecipe(section.getConfigurationSection("recipe"), addon); 45 | String recipeType = section.getString("recipe_type", "NULL"); 46 | 47 | Pair rt = ExceptionHandler.getRecipeType( 48 | "在附属" + addon.getAddonId() + "中加载发电机" + s + "时遇到了问题: " + "错误的配方类型" + recipeType + "!", recipeType); 49 | 50 | if (rt.getFirstValue() == ExceptionHandler.HandleResult.FAILED) return null; 51 | 52 | CustomMenu menu = CommonUtils.getIf(addon.getMenus(), m -> m.getID().equalsIgnoreCase(id)); 53 | 54 | List input = section.getIntegerList("input"); 55 | List output = section.getIntegerList("output"); 56 | 57 | ConfigurationSection fuelsSection = section.getConfigurationSection("fuels"); 58 | List fuels = readFuels(s, fuelsSection, addon); 59 | int capacity = section.getInt("capacity", 0); 60 | int production = section.getInt("production"); 61 | 62 | if (production < 1) { 63 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载发电机" + s + "时遇到了问题: " + "产电量不能小于1"); 64 | return null; 65 | } 66 | 67 | return new CustomGenerator( 68 | group.getSecondValue(), 69 | sfis, 70 | rt.getSecondValue(), 71 | recipe, 72 | menu, 73 | capacity, 74 | input, 75 | output, 76 | production, 77 | fuels); 78 | } 79 | 80 | @Override 81 | public List preloadItems(String id) { 82 | ConfigurationSection section = configuration.getConfigurationSection(id); 83 | if (section == null) return null; 84 | 85 | ConfigurationSection item = section.getConfigurationSection("item"); 86 | ItemStack stack = CommonUtils.readItem(item, false, addon); 87 | 88 | if (stack == null) { 89 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载发电机" + id + "时遇到了问题: " + "物品为空或格式错误导致无法加载"); 90 | return null; 91 | } 92 | return List.of(new SlimefunItemStack(addon.getId(id, section.getString("id_alias")), stack)); 93 | } 94 | 95 | private List readFuels(String s, ConfigurationSection section, ProjectAddon addon) { 96 | List fuels = new ArrayList<>(); 97 | 98 | if (section == null) return fuels; 99 | 100 | for (String key : section.getKeys(false)) { 101 | ConfigurationSection section1 = section.getConfigurationSection(key); 102 | if (section1 == null) continue; 103 | ConfigurationSection item = section1.getConfigurationSection("item"); 104 | ItemStack stack = CommonUtils.readItem(item, true, addon); 105 | if (stack == null) { 106 | ExceptionHandler.handleError( 107 | "在附属" + addon.getAddonId() + "中加载发电机" + s + "的燃料" + key + "时遇到了问题: " + "输入物品为空或格式错误,已跳过加载"); 108 | continue; 109 | } 110 | int seconds = section1.getInt("seconds"); 111 | 112 | if (seconds < 1) { 113 | ExceptionHandler.handleError( 114 | "在附属" + addon.getAddonId() + "中加载发电机" + s + "的燃料" + key + "时遇到了问题: " + "秒数不能小于1,已跳过加载"); 115 | continue; 116 | } 117 | 118 | ItemStack output = null; 119 | if (section1.contains("output")) { 120 | ConfigurationSection outputSet = section1.getConfigurationSection("output"); 121 | output = CommonUtils.readItem(outputSet, true, addon); 122 | if (output == null) { 123 | ExceptionHandler.handleError( 124 | "在附属" + addon.getAddonId() + "中加载发电机" + s + "的燃料" + key + "时遇到了问题: " + "输出物品为空或格式错误,已转为空"); 125 | } 126 | } 127 | 128 | MachineFuel fuel = new MachineFuel(seconds, stack, output); 129 | fuels.add(fuel); 130 | } 131 | return fuels; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/yaml/machine/MaterialGeneratorReader.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.yaml.machine; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 5 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 6 | import io.github.thebusybiscuit.slimefun4.libraries.dough.collections.Pair; 7 | import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils; 8 | import java.util.ArrayList; 9 | import java.util.Arrays; 10 | import java.util.List; 11 | import org.bukkit.configuration.ConfigurationSection; 12 | import org.bukkit.configuration.file.YamlConfiguration; 13 | import org.bukkit.inventory.ItemStack; 14 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.ProjectAddon; 15 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.CustomMenu; 16 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.machine.CustomMaterialGenerator; 17 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.yaml.YamlReader; 18 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.CommonUtils; 19 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.ExceptionHandler; 20 | 21 | public class MaterialGeneratorReader extends YamlReader { 22 | public MaterialGeneratorReader(YamlConfiguration config, ProjectAddon addon) { 23 | super(config, addon); 24 | } 25 | 26 | @Override 27 | public CustomMaterialGenerator readEach(String s) { 28 | ConfigurationSection section = configuration.getConfigurationSection(s); 29 | if (section == null) return null; 30 | String id = addon.getId(s, section.getString("id_alias")); 31 | 32 | ExceptionHandler.HandleResult result = ExceptionHandler.handleIdConflict(id); 33 | 34 | if (result == ExceptionHandler.HandleResult.FAILED) return null; 35 | 36 | String igId = section.getString("item_group"); 37 | 38 | SlimefunItemStack slimefunItemStack = getPreloadItem(id); 39 | if (slimefunItemStack == null) return null; 40 | 41 | Pair group = ExceptionHandler.handleItemGroupGet(addon, igId); 42 | if (group.getFirstValue() == ExceptionHandler.HandleResult.FAILED) return null; 43 | ItemStack[] recipe = CommonUtils.readRecipe(section.getConfigurationSection("recipe"), addon); 44 | String recipeType = section.getString("recipe_type", "NULL"); 45 | 46 | Pair rt = ExceptionHandler.getRecipeType( 47 | "在附属" + addon.getAddonId() + "中加载材料生成器" + s + "时遇到了问题: " + "错误的配方类型" + recipeType + "!", recipeType); 48 | 49 | if (rt.getFirstValue() == ExceptionHandler.HandleResult.FAILED) return null; 50 | 51 | CustomMenu menu = CommonUtils.getIf(addon.getMenus(), m -> m.getID().equalsIgnoreCase(id)); 52 | if (menu == null) { 53 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载材料生成器" + s + "时遇到了问题: " + "对应菜单不存在"); 54 | return null; 55 | } 56 | 57 | List output = section.getIntegerList("output"); 58 | int capacity = section.getInt("capacity", 0); 59 | ConfigurationSection outputItems = section.getConfigurationSection("outputs"); 60 | ItemStack[] out = CommonUtils.readRecipe(outputItems, addon, output.size()); 61 | List chances = new ArrayList<>(); 62 | boolean chooseOne = section.getBoolean("chooseOne", false); 63 | 64 | if (out.length == 0) { 65 | ConfigurationSection outputItem = section.getConfigurationSection("outputItem"); 66 | ItemStack outItem = CommonUtils.readItem(outputItem, true, addon); 67 | if (outItem == null) { 68 | ExceptionHandler.handleError( 69 | "在附属" + addon.getAddonId() + "中加载材料生成器" + s + "时遇到了问题: " + "输出物品为空或格式错误导致无法加载"); 70 | return null; 71 | } else { 72 | out = new ItemStack[] {outItem}; 73 | chances = List.of(outputItem.getInt("chance", 100)); 74 | } 75 | } 76 | 77 | if (out.length > 1) { 78 | for (String key : outputItems.getKeys(false)) { 79 | ConfigurationSection chanceItem = outputItems.getConfigurationSection(key); 80 | if (CommonUtils.readItem(chanceItem, true, addon) == null) { 81 | continue; 82 | } 83 | chances.add(chanceItem.getInt("chance", 100)); 84 | } 85 | } 86 | 87 | out = CommonUtils.removeNulls(out); 88 | 89 | int tickRate = section.getInt("tickRate"); 90 | if (tickRate < 1) { 91 | ExceptionHandler.handleError( 92 | "在附属" + addon.getAddonId() + "中加载材料生成器" + s + "时遇到了问题: " + "tickRate未设置或不能小于1"); 93 | return null; 94 | } 95 | 96 | int per = section.getInt("per"); 97 | if (per < 1) { 98 | ExceptionHandler.handleError( 99 | "在附属" + addon.getAddonId() + "中加载材料生成器" + s + "时遇到了问题: " + "单次生成能量花费未设置或不能小于1"); 100 | return null; 101 | } 102 | 103 | int status = -1; 104 | if (section.contains("status")) { 105 | status = section.getInt("status"); 106 | } 107 | 108 | CustomMaterialGenerator cmg = new CustomMaterialGenerator( 109 | group.getSecondValue(), 110 | slimefunItemStack, 111 | rt.getSecondValue(), 112 | recipe, 113 | capacity, 114 | output, 115 | status, 116 | tickRate, 117 | Arrays.asList(out), 118 | menu, 119 | per, 120 | chances, 121 | chooseOne); 122 | 123 | menu.addMenuClickHandler(status, ChestMenuUtils.getEmptyClickHandler()); 124 | 125 | return cmg; 126 | } 127 | 128 | @Override 129 | public List preloadItems(String s) { 130 | ConfigurationSection section = configuration.getConfigurationSection(s); 131 | if (section == null) return null; 132 | 133 | ConfigurationSection item = section.getConfigurationSection("item"); 134 | ItemStack stack = CommonUtils.readItem(item, false, addon); 135 | 136 | if (stack == null) { 137 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载材料生成器" + s + "时遇到了问题: " + "物品为空或格式错误导致无法加载"); 138 | return null; 139 | } 140 | 141 | return List.of(new SlimefunItemStack(addon.getId(s, section.getString("id_alias")), stack)); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/yaml/machine/MultiBlockMachineReader.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.yaml.machine; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 5 | import io.github.thebusybiscuit.slimefun4.core.services.sounds.SoundEffect; 6 | import io.github.thebusybiscuit.slimefun4.libraries.dough.collections.Pair; 7 | import java.io.File; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | import org.bukkit.Material; 12 | import org.bukkit.configuration.ConfigurationSection; 13 | import org.bukkit.configuration.file.YamlConfiguration; 14 | import org.bukkit.inventory.ItemStack; 15 | import org.lins.mmmjjkx.rykenslimefuncustomizer.bulit_in.JavaScriptEval; 16 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.ProjectAddon; 17 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.machine.CustomMultiBlockMachine; 18 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.yaml.YamlReader; 19 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.CommonUtils; 20 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.ExceptionHandler; 21 | 22 | public class MultiBlockMachineReader extends YamlReader { 23 | public MultiBlockMachineReader(YamlConfiguration config, ProjectAddon addon) { 24 | super(config, addon); 25 | } 26 | 27 | @Override 28 | public CustomMultiBlockMachine readEach(String s) { 29 | ConfigurationSection section = configuration.getConfigurationSection(s); 30 | if (section == null) return null; 31 | String id = addon.getId(s, section.getString("id_alias")); 32 | 33 | ExceptionHandler.HandleResult result = ExceptionHandler.handleIdConflict(id); 34 | 35 | if (result == ExceptionHandler.HandleResult.FAILED) return null; 36 | 37 | String igId = section.getString("item_group"); 38 | 39 | Pair group = ExceptionHandler.handleItemGroupGet(addon, igId); 40 | if (group.getFirstValue() == ExceptionHandler.HandleResult.FAILED) return null; 41 | 42 | SlimefunItemStack slimefunItemStack = getPreloadItem(id); 43 | if (slimefunItemStack == null) return null; 44 | 45 | ItemStack[] recipe = CommonUtils.readRecipe(section.getConfigurationSection("recipe"), addon); 46 | 47 | ConfigurationSection recipesSection = section.getConfigurationSection("recipes"); 48 | 49 | int workSlot = section.getInt("work"); 50 | if (workSlot < 1) { 51 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载多方块机器" + s + "时遇到了问题: " + "没有设置工作槽"); 52 | return null; 53 | } 54 | 55 | if (recipe == null) { 56 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载多方块机器" + s + "时遇到了问题: " + "放置配方为空"); 57 | return null; 58 | } 59 | 60 | boolean hasDispenser = false; 61 | 62 | for (ItemStack is : recipe) { 63 | if (is != null) { 64 | if (is.getType() == Material.DISPENSER) { 65 | hasDispenser = true; 66 | break; 67 | } 68 | } 69 | } 70 | 71 | if (!hasDispenser) { 72 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载多方块机器" + s + "时遇到了问题: " + "放置配方里没有发射器"); 73 | return null; 74 | } 75 | 76 | if (recipe[workSlot - 1] == null) { 77 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载多方块机器" + s + "时遇到了问题: " + "对应工作方块不存在"); 78 | return null; 79 | } 80 | 81 | Map recipes = readRecipes(s, recipesSection, addon); 82 | SoundEffect sound = null; 83 | if (section.contains("sound")) { 84 | String soundString = section.getString("sound"); 85 | Pair soundEffectPair = ExceptionHandler.handleEnumValueOf( 86 | "在附属" + addon.getAddonId() + "中加载多方块机器" + s + "无法获取声音类型" + soundString, 87 | SoundEffect.class, 88 | soundString); 89 | ExceptionHandler.HandleResult result1 = soundEffectPair.getFirstValue(); 90 | if (result1 != ExceptionHandler.HandleResult.FAILED && soundEffectPair.getSecondValue() != null) { 91 | sound = soundEffectPair.getSecondValue(); 92 | } 93 | } 94 | 95 | JavaScriptEval eval = null; 96 | if (section.contains("script")) { 97 | String script = section.getString("script", ""); 98 | File file = new File(addon.getScriptsFolder(), script + ".js"); 99 | if (!file.exists()) { 100 | ExceptionHandler.handleWarning( 101 | "在附属" + addon.getAddonId() + "中加载多方块机器" + s + "时遇到了问题: " + "找不到脚本文件 " + file.getName()); 102 | } else { 103 | eval = new JavaScriptEval(file, addon); 104 | } 105 | } 106 | 107 | return new CustomMultiBlockMachine( 108 | group.getSecondValue(), slimefunItemStack, recipe, recipes, workSlot, sound, eval); 109 | } 110 | 111 | @Override 112 | public List preloadItems(String s) { 113 | ConfigurationSection section = configuration.getConfigurationSection(s); 114 | if (section == null) return null; 115 | 116 | ConfigurationSection item = section.getConfigurationSection("item"); 117 | ItemStack stack = CommonUtils.readItem(item, false, addon); 118 | 119 | if (stack == null) { 120 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载多方块机器" + s + "时遇到了问题: " + "物品为空或格式错误导致无法加载"); 121 | return null; 122 | } 123 | 124 | return List.of(new SlimefunItemStack(addon.getId(s, section.getString("id_alias")), stack)); 125 | } 126 | 127 | private Map readRecipes(String s, ConfigurationSection section, ProjectAddon addon) { 128 | Map map = new HashMap<>(); 129 | if (section == null) return map; 130 | 131 | for (String key : section.getKeys(false)) { 132 | ConfigurationSection recipe = section.getConfigurationSection(key); 133 | if (recipe == null) continue; 134 | ConfigurationSection inputs = recipe.getConfigurationSection("input"); 135 | if (inputs == null) { 136 | ExceptionHandler.handleError( 137 | "在附属" + addon.getAddonId() + "中加载多方块机器" + s + "的工作配方" + key + "时遇到了问题: " + "没有输入物品"); 138 | continue; 139 | } 140 | ItemStack[] input = CommonUtils.readRecipe(inputs, addon); 141 | if (input == null) { 142 | ExceptionHandler.handleError( 143 | "在附属" + addon.getAddonId() + "中加载多方块机器" + s + "的工作配方" + key + "时遇到了问题: " + "输入物品为空或格式错误"); 144 | continue; 145 | } 146 | ConfigurationSection outputs = recipe.getConfigurationSection("output"); 147 | if (outputs == null) { 148 | ExceptionHandler.handleError( 149 | "在附属" + addon.getAddonId() + "中加载多方块机器" + s + "的工作配方" + key + "时遇到了问题: " + "没有输出物品"); 150 | continue; 151 | } 152 | ItemStack output = CommonUtils.readItem(outputs, true, addon); 153 | if (output == null) { 154 | ExceptionHandler.handleError( 155 | "在附属" + addon.getAddonId() + "中加载多方块机器" + s + "的工作配方" + key + "时遇到了问题: " + "输出物品为空或格式错误"); 156 | continue; 157 | } 158 | map.put(input, output); 159 | } 160 | return map; 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/yaml/machine/SimpleMachineReader.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.yaml.machine; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; 5 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 6 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 7 | import io.github.thebusybiscuit.slimefun4.libraries.dough.collections.Pair; 8 | import java.util.List; 9 | import org.bukkit.configuration.ConfigurationSection; 10 | import org.bukkit.configuration.file.YamlConfiguration; 11 | import org.bukkit.inventory.ItemStack; 12 | import org.lins.mmmjjkx.rykenslimefuncustomizer.RykenSlimefunCustomizer; 13 | import org.lins.mmmjjkx.rykenslimefuncustomizer.factories.SimpleMachineFactory; 14 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.ProjectAddon; 15 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.machine.SimpleMachineType; 16 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.yaml.YamlReader; 17 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.CommonUtils; 18 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.ExceptionHandler; 19 | 20 | public class SimpleMachineReader extends YamlReader { 21 | public SimpleMachineReader(YamlConfiguration config, ProjectAddon addon) { 22 | super(config, addon); 23 | } 24 | 25 | @Override 26 | public SlimefunItem readEach(String s) { 27 | ConfigurationSection section = configuration.getConfigurationSection(s); 28 | if (section == null) return null; 29 | String id = addon.getId(s, section.getString("id_alias")); 30 | 31 | ExceptionHandler.HandleResult result = ExceptionHandler.handleIdConflict(id); 32 | 33 | if (result == ExceptionHandler.HandleResult.FAILED) return null; 34 | 35 | String igId = section.getString("item_group"); 36 | 37 | SlimefunItemStack slimefunItemStack = getPreloadItem(id); 38 | if (slimefunItemStack == null) return null; 39 | 40 | Pair itemGroupPair = ExceptionHandler.handleItemGroupGet(addon, igId); 41 | if (itemGroupPair.getFirstValue() == ExceptionHandler.HandleResult.FAILED 42 | || itemGroupPair.getSecondValue() == null) return null; 43 | ItemStack[] recipe = CommonUtils.readRecipe(section.getConfigurationSection("recipe"), addon); 44 | String recipeType = section.getString("recipe_type", "NULL"); 45 | 46 | Pair resultRecipeTypePair = ExceptionHandler.getRecipeType( 47 | "在附属" + addon.getAddonId() + "中加载简单机器" + s + "时遇到了问题: " + "错误的配方类型" + recipeType + "!", recipeType); 48 | 49 | if (resultRecipeTypePair.getFirstValue() == ExceptionHandler.HandleResult.FAILED 50 | || resultRecipeTypePair.getSecondValue() == null) return null; 51 | 52 | String machineTypeStr = section.getString("type"); 53 | 54 | Pair machineTypePair = ExceptionHandler.handleEnumValueOf( 55 | "错误的简单机器类型 " + machineTypeStr, SimpleMachineType.class, machineTypeStr); 56 | if (machineTypePair.getFirstValue() == ExceptionHandler.HandleResult.FAILED 57 | || machineTypePair.getSecondValue() == null) { 58 | return null; 59 | } 60 | 61 | SimpleMachineType machineType = machineTypePair.getSecondValue(); 62 | ConfigurationSection settings = section.getConfigurationSection("settings"); 63 | 64 | if (settings == null) { 65 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载简单机器" + s + "时遇到了问题: " + "机器没有设置"); 66 | return null; 67 | } 68 | 69 | int capacity = 0; 70 | int consumption = 0; 71 | int speed = 1; 72 | int radius = 1; 73 | int repairFactor = 10; 74 | 75 | if (machineType.isEnergy()) { 76 | capacity = settings.getInt("capacity"); 77 | if (capacity < 1) { 78 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载简单机器" + s + "时遇到了问题: " + "容量小于1"); 79 | return null; 80 | } 81 | 82 | consumption = settings.getInt("consumption"); 83 | if (consumption < 1) { 84 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载简单机器" + s + "时遇到了问题: " + "消耗能量小于1"); 85 | return null; 86 | } 87 | 88 | if (!isAccelerator(machineType)) { 89 | speed = settings.getInt("speed", 1); 90 | if (speed < 1) { 91 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载简单机器" + s + "时遇到了问题: " + "处理速度小于1"); 92 | return null; 93 | } 94 | } else { 95 | radius = settings.getInt("radius", 1); 96 | if (radius < 1) { 97 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载简单机器" + s + "时遇到了问题: " + "范围小于1"); 98 | return null; 99 | } 100 | 101 | if (machineType == SimpleMachineType.CROP_GROWTH_ACCELERATOR) { 102 | speed = settings.getInt("speed", 1); 103 | if (speed < 1) { 104 | ExceptionHandler.handleError( 105 | "在附属" + addon.getAddonId() + "中加载简单机器" + s + "时遇到了问题: " + "处理速度小于1"); 106 | return null; 107 | } 108 | } 109 | } 110 | 111 | if (machineType == SimpleMachineType.AUTO_ANVIL) { 112 | repairFactor = settings.getInt("repair_factor", 10); 113 | if (repairFactor < 1) { 114 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载简单机器" + s + "时遇到了问题: " + "修理因子小于1"); 115 | return null; 116 | } 117 | } 118 | } 119 | 120 | SlimefunItem instance = SimpleMachineFactory.create( 121 | itemGroupPair.getSecondValue(), 122 | slimefunItemStack, 123 | resultRecipeTypePair.getSecondValue(), 124 | recipe, 125 | machineType, 126 | capacity, 127 | consumption, 128 | speed, 129 | radius, 130 | repairFactor); 131 | 132 | instance.register(RykenSlimefunCustomizer.INSTANCE); 133 | 134 | return instance; 135 | } 136 | 137 | @Override 138 | public List preloadItems(String s) { 139 | ConfigurationSection section = configuration.getConfigurationSection(s); 140 | if (section == null) return null; 141 | 142 | ConfigurationSection item = section.getConfigurationSection("item"); 143 | ItemStack stack = CommonUtils.readItem(item, false, addon); 144 | 145 | if (stack == null) { 146 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载简单机器" + s + "时遇到了问题: " + "物品为空或格式错误导致无法加载"); 147 | return null; 148 | } 149 | 150 | return List.of(new SlimefunItemStack(addon.getId(s, section.getString("id_alias")), stack)); 151 | } 152 | 153 | private boolean isAccelerator(SimpleMachineType type) { 154 | return type == SimpleMachineType.TREE_GROWTH_ACCELERATOR 155 | || type == SimpleMachineType.CROP_GROWTH_ACCELERATOR 156 | || type == SimpleMachineType.ANIMAL_GROWTH_ACCELERATOR; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/objects/yaml/machine/SolarGeneratorReader.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.objects.yaml.machine; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; 5 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 6 | import io.github.thebusybiscuit.slimefun4.libraries.dough.collections.Pair; 7 | import java.util.List; 8 | import java.util.Objects; 9 | import org.bukkit.configuration.ConfigurationSection; 10 | import org.bukkit.configuration.file.YamlConfiguration; 11 | import org.bukkit.inventory.ItemStack; 12 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.ProjectAddon; 13 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.machine.CustomSolarGenerator; 14 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.yaml.YamlReader; 15 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.CommonUtils; 16 | import org.lins.mmmjjkx.rykenslimefuncustomizer.utils.ExceptionHandler; 17 | 18 | public class SolarGeneratorReader extends YamlReader { 19 | public SolarGeneratorReader(YamlConfiguration config, ProjectAddon addon) { 20 | super(config, addon); 21 | } 22 | 23 | @Override 24 | public CustomSolarGenerator readEach(String s) { 25 | ConfigurationSection section = configuration.getConfigurationSection(s); 26 | if (section == null) return null; 27 | String id = addon.getId(s, section.getString("id_alias")); 28 | 29 | ExceptionHandler.HandleResult result = ExceptionHandler.handleIdConflict(id); 30 | 31 | if (result == ExceptionHandler.HandleResult.FAILED) return null; 32 | 33 | String igId = section.getString("item_group"); 34 | 35 | Pair group = ExceptionHandler.handleItemGroupGet(addon, igId); 36 | if (group.getFirstValue() == ExceptionHandler.HandleResult.FAILED) return null; 37 | 38 | SlimefunItemStack slimefunItemStack = getPreloadItem(id); 39 | if (slimefunItemStack == null) return null; 40 | 41 | ItemStack[] recipe = CommonUtils.readRecipe(section.getConfigurationSection("recipe"), addon); 42 | String recipeType = section.getString("recipe_type", "NULL"); 43 | 44 | Pair rt = ExceptionHandler.getRecipeType( 45 | "在附属" + addon.getAddonId() + "中加载太阳能发电机" + s + "时遇到了问题: " + "错误的配方类型" + recipeType + "!", recipeType); 46 | 47 | if (rt.getFirstValue() == ExceptionHandler.HandleResult.FAILED) return null; 48 | 49 | int dayEnergy = section.getInt("dayEnergy"); 50 | int nightEnergy = section.getInt("nightEnergy"); 51 | 52 | if (dayEnergy < 1) { 53 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载太阳能发电机" + s + "时遇到了问题: " + "白天产电量不能小于1"); 54 | return null; 55 | } 56 | 57 | if (nightEnergy < 1) { 58 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载太阳能发电机" + s + "时遇到了问题: " + "夜晚产电量不能小于1"); 59 | return null; 60 | } 61 | 62 | int capacity = section.getInt("capacity", 0); 63 | int lightLevel = section.getInt("lightLevel", 15); 64 | 65 | if (lightLevel < 0 || lightLevel > 15) { 66 | ExceptionHandler.handleError( 67 | "在附属" + addon.getAddonId() + "中加载太阳能发电机" + s + "时遇到了问题: " + "所需光照等级不能小于0或大于15,已转为15"); 68 | lightLevel = 15; 69 | } 70 | 71 | return new CustomSolarGenerator( 72 | Objects.requireNonNull(group.getSecondValue()), 73 | dayEnergy, 74 | nightEnergy, 75 | slimefunItemStack, 76 | Objects.requireNonNull(rt.getSecondValue()), 77 | recipe, 78 | capacity, 79 | lightLevel); 80 | } 81 | 82 | @Override 83 | public List preloadItems(String s) { 84 | ConfigurationSection section = configuration.getConfigurationSection(s); 85 | if (section == null) return null; 86 | 87 | ConfigurationSection item = section.getConfigurationSection("item"); 88 | ItemStack stack = CommonUtils.readItem(item, false, addon); 89 | 90 | if (stack == null) { 91 | ExceptionHandler.handleError("在附属" + addon.getAddonId() + "中加载太阳能发电机" + s + "时遇到了问题: " + "物品为空或格式错误导致无法加载"); 92 | return null; 93 | } 94 | 95 | return List.of(new SlimefunItemStack(addon.getId(s, section.getString("id_alias")), stack)); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/update/GitHubRelease.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.update; 2 | 3 | import java.util.List; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | public class GitHubRelease { 8 | private String url; 9 | private String html_url; 10 | private String assets_url; 11 | private String upload_url; 12 | private String tarball_url; 13 | private String zipball_url; 14 | private int id; 15 | private String node_id; 16 | private String tag_name; 17 | private String target_commitish; 18 | private String name; 19 | private String body; 20 | private boolean draft; 21 | private boolean prerelease; 22 | private String created_at; 23 | private String published_at; 24 | private Author author; 25 | private List assets; 26 | 27 | @Getter 28 | public static class Author { 29 | private String login; 30 | private int id; 31 | private String node_id; 32 | private String avatar_url; 33 | private String gravatar_id; 34 | private String url; 35 | private String html_url; 36 | private String followers_url; 37 | private String following_url; 38 | private String gists_url; 39 | private String starred_url; 40 | private String subscriptions_url; 41 | private String organizations_url; 42 | private String repos_url; 43 | private String events_url; 44 | private String received_events_url; 45 | private String type; 46 | private boolean site_admin; 47 | } 48 | 49 | @Getter 50 | public static class Asset { 51 | private String url; 52 | private String browser_download_url; 53 | private int id; 54 | private String node_id; 55 | private String name; 56 | private String label; 57 | private String state; 58 | private String content_type; 59 | private int size; 60 | private int download_count; 61 | private String created_at; 62 | private String updated_at; 63 | private Author uploader; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/utils/ClassUtils.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.utils; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.function.Function; 6 | import net.bytebuddy.ByteBuddy; 7 | import net.bytebuddy.dynamic.DynamicType; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | public class ClassUtils { 11 | private static final Map> cache = new HashMap<>(); 12 | 13 | public static Class generateClass( 14 | Class extendClass, 15 | String centerName, 16 | String nameReplacement, 17 | Class[] interfaces, 18 | @Nullable Function, DynamicType.Builder> delegation) { 19 | 20 | String finalClassName = extendClass.getSimpleName().replace(nameReplacement, "") + centerName + nameReplacement; 21 | if (cache.containsKey(finalClassName)) { 22 | return cache.get(finalClassName); 23 | } 24 | 25 | DynamicType.Builder builder = new ByteBuddy().subclass(extendClass); 26 | 27 | if (delegation != null) { 28 | builder = delegation.apply(builder); 29 | } 30 | 31 | builder = builder.implement(interfaces).name(finalClassName); 32 | 33 | Class clazz; 34 | try (DynamicType.Unloaded unloaded = builder.make()) { 35 | clazz = unloaded.load(extendClass.getClassLoader()).getLoaded(); 36 | } 37 | cache.put(finalClassName, clazz); 38 | return clazz; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/utils/Constants.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.utils; 2 | 3 | public class Constants { 4 | public static final String INFO_FILE = "info.yml"; 5 | public static final String MENUS_FILE = "menus.yml"; 6 | public static final String ITEMS_FILE = "items.yml"; 7 | public static final String GROUPS_FILE = "groups.yml"; 8 | public static final String GEO_RES_FILE = "geo_resources.yml"; 9 | public static final String RESEARCHES_FILE = "researches.yml"; 10 | public static final String MACHINES_FILE = "machines.yml"; 11 | public static final String GENERATORS_FILE = "generators.yml"; 12 | public static final String MATERIAL_GENERATORS_FILE = "mat_generators.yml"; 13 | public static final String RECIPE_MACHINES_FILE = "recipe_machines.yml"; 14 | public static final String MULTI_BLOCK_MACHINES_FILE = "mb_machines.yml"; 15 | public static final String SOLAR_GENERATORS_FILE = "solar_generators.yml"; 16 | public static final String MOB_DROPS_FILE = "mob_drops.yml"; 17 | public static final String RECIPE_TYPES_FILE = "recipe_types.yml"; 18 | public static final String CAPACITORS_FILE = "capacitors.yml"; 19 | public static final String SIMPLE_MACHINES_FILE = "simple_machines.yml"; 20 | public static final String FOODS_FILE = "foods.yml"; 21 | public static final String ARMORS_FILE = "armors.yml"; 22 | public static final String SUPERS_FILE = "supers.yml"; 23 | public static final String TEMPLATE_MACHINES_FILE = "template_machines.yml"; 24 | public static final String LINKED_RECIPE_MACHINES_FILE = "linked_recipe_machines.yml"; 25 | public static final String WORKBENCHES_FILE = "workbenches.yml"; 26 | public static final String ADDON_CONFIG_FILE = "default_config.yml"; 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/utils/ExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.utils; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; 4 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; 5 | import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; 6 | import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; 7 | import io.github.thebusybiscuit.slimefun4.libraries.dough.collections.Pair; 8 | import java.lang.reflect.Field; 9 | import org.bukkit.Bukkit; 10 | import org.bukkit.command.ConsoleCommandSender; 11 | import org.jetbrains.annotations.NotNull; 12 | import org.lins.mmmjjkx.rykenslimefuncustomizer.RykenSlimefunCustomizer; 13 | import org.lins.mmmjjkx.rykenslimefuncustomizer.libraries.colors.CMIChatColor; 14 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.ProjectAddon; 15 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.customs.CustomMenu; 16 | import org.lins.mmmjjkx.rykenslimefuncustomizer.objects.global.RecipeTypeMap; 17 | 18 | public class ExceptionHandler { 19 | private static final @NotNull ConsoleCommandSender console = Bukkit.getConsoleSender(); 20 | 21 | public static HandleResult handleIdConflict(String id) { 22 | SlimefunItem i = SlimefunItem.getById(id); 23 | if (i != null) { 24 | console.sendMessage(CMIChatColor.translate( 25 | "&4ERROR | ID冲突:" + id + "与" + i.getAddon().getName() + "中的物品发生了ID冲突")); 26 | return HandleResult.FAILED; 27 | } 28 | return HandleResult.SUCCESS; 29 | } 30 | 31 | public static HandleResult handleMenuConflict(String id, ProjectAddon addon) { 32 | CustomMenu menu = CommonUtils.getIf(addon.getMenus(), m -> m.getID().equalsIgnoreCase(id)); 33 | if (menu != null) { 34 | console.sendMessage(CMIChatColor.translate("&4ERROR | ID冲突:已存在菜单ID为" + id + "的菜单")); 35 | return HandleResult.FAILED; 36 | } 37 | return HandleResult.SUCCESS; 38 | } 39 | 40 | public static HandleResult handleGroupIdConflict(String id) { 41 | ItemGroup ig = CommonUtils.getIf( 42 | Slimefun.getRegistry().getAllItemGroups(), 43 | i -> i.getKey().getKey().equalsIgnoreCase(id)); 44 | if (ig != null) { 45 | if (ig.getAddon() != null) { 46 | if (ig.getAddon().getClass() == RykenSlimefunCustomizer.class) { 47 | console.sendMessage(CMIChatColor.translate( 48 | "&4ERROR | ID冲突:" + id + "与物品组 " + ig.getKey().getKey() + "发生ID冲突")); 49 | return HandleResult.FAILED; 50 | } 51 | return HandleResult.SUCCESS; 52 | } 53 | console.sendMessage(CMIChatColor.translate( 54 | "&4ERROR | ID冲突:" + id + "与物品组 " + ig.getKey().getKey() + "发生ID冲突")); 55 | return HandleResult.FAILED; 56 | } 57 | return HandleResult.SUCCESS; 58 | } 59 | 60 | public static void handleWarning(String message) { 61 | if (message == null || message.isBlank()) return; 62 | 63 | console.sendMessage(CMIChatColor.translate("&eWARNING | " + message)); 64 | } 65 | 66 | public static void handleError(String message) { 67 | if (message == null || message.isBlank()) return; 68 | 69 | console.sendMessage(CMIChatColor.translate("&4ERROR | " + message)); 70 | } 71 | 72 | public static void handleError(String message, Throwable e) { 73 | if (message == null || message.isBlank()) return; 74 | 75 | if (e != null) { 76 | console.sendMessage(CMIChatColor.translate("&4ERROR | " + message)); 77 | e.printStackTrace(); 78 | } else { 79 | handleError(message); 80 | } 81 | } 82 | 83 | public static void debugLog(String message) { 84 | if (RykenSlimefunCustomizer.INSTANCE.getConfig().getBoolean("debug")) { 85 | if (message == null || message.isBlank()) return; 86 | 87 | console.sendMessage(CMIChatColor.translate("&6DEBUG | " + message)); 88 | } 89 | } 90 | 91 | /** 92 | * 检测后门等 93 | * @param message the message 94 | */ 95 | public static void handleDanger(String message) { 96 | if (message == null || message.isBlank()) return; 97 | 98 | console.sendMessage(CMIChatColor.translate("&c&u&l&bD&4&lA&c&lN&b&lG&4&lE&c&lR | " + message)); 99 | } 100 | 101 | public static void info(String message) { 102 | if (message == null || message.isBlank()) return; 103 | 104 | console.sendMessage(CMIChatColor.translate("&aINFO | " + message)); 105 | } 106 | 107 | public static > Pair handleEnumValueOf( 108 | String msg, Class enumClass, String name) { 109 | try { 110 | return new Pair<>(HandleResult.SUCCESS, Enum.valueOf(enumClass, name.toUpperCase())); 111 | } catch (NullPointerException | IllegalArgumentException e) { 112 | handleError(msg); 113 | } 114 | return new Pair<>(HandleResult.FAILED, null); 115 | } 116 | 117 | public static Pair handleItemGroupGet(ProjectAddon addon, String id) { 118 | ItemGroup ig = CommonUtils.getIf( 119 | addon.getItemGroups(), i -> i.getKey().getKey().equalsIgnoreCase(id)); 120 | if (ig == null) { 121 | ItemGroup ig2 = CommonUtils.getIf( 122 | Slimefun.getRegistry().getAllItemGroups(), 123 | i -> i.getKey().toString().equalsIgnoreCase(id)); 124 | if (ig2 == null) { 125 | handleError("无法在附属" + addon.getAddonName() + "中找到该物品组 " + id); 126 | return new Pair<>(HandleResult.FAILED, null); 127 | } 128 | return new Pair<>(HandleResult.SUCCESS, ig2); 129 | } 130 | return new Pair<>(HandleResult.SUCCESS, ig); 131 | } 132 | 133 | public static Pair getRecipeType(String msg, String fieldName) { 134 | try { 135 | Field field = RecipeType.class.getDeclaredField(fieldName); 136 | return new Pair<>(HandleResult.SUCCESS, (RecipeType) field.get(null)); 137 | } catch (NoSuchFieldException e) { 138 | RecipeType recipeType = RecipeTypeMap.getRecipeType(fieldName); 139 | if (recipeType == null) { 140 | handleError(msg); 141 | return new Pair<>(HandleResult.FAILED, null); 142 | } 143 | return new Pair<>(HandleResult.SUCCESS, recipeType); 144 | } catch (IllegalAccessException ignored) { 145 | // it doesn't happen 146 | } 147 | return new Pair<>(HandleResult.FAILED, null); 148 | } 149 | 150 | public enum HandleResult { 151 | SUCCESS, 152 | FAILED 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/utils/ItemUtils.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.utils; 2 | 3 | import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | import javax.annotation.Nonnull; 7 | import org.bukkit.Material; 8 | import org.bukkit.inventory.ItemStack; 9 | 10 | public class ItemUtils { 11 | /** 12 | * @param itemStacks original item array 13 | * @return how many items there are in total 14 | */ 15 | public static int getAllItemAmount(@Nonnull ItemStack... itemStacks) { 16 | int amount = 0; 17 | for (ItemStack itemStack : itemStacks) { 18 | if (itemStack == null || itemStack.getType().isAir()) { 19 | continue; 20 | } 21 | 22 | amount += itemStack.getAmount(); 23 | } 24 | 25 | return amount; 26 | } 27 | 28 | /** 29 | * @param itemStacks original item array 30 | * @return how many kinds of item there are in total 31 | */ 32 | public static int getAllItemTypeAmount(@Nonnull ItemStack... itemStacks) { 33 | Set sfItems = new HashSet<>(); 34 | Set materials = new HashSet<>(); 35 | 36 | for (ItemStack itemStack : itemStacks) { 37 | 38 | if (itemStack == null || itemStack.getType().isAir()) { 39 | continue; 40 | } 41 | 42 | SlimefunItem sfItem = SlimefunItem.getByItem(itemStack); 43 | if (sfItem != null) { 44 | sfItems.add(sfItem); 45 | } else { 46 | materials.add(itemStack.getType()); 47 | } 48 | } 49 | 50 | return sfItems.size() + materials.size(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/org/lins/mmmjjkx/rykenslimefuncustomizer/utils/ReflectionUtils.java: -------------------------------------------------------------------------------- 1 | package org.lins.mmmjjkx.rykenslimefuncustomizer.utils; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.Method; 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.List; 8 | import javax.annotation.Nonnull; 9 | import javax.annotation.Nullable; 10 | 11 | public class ReflectionUtils { 12 | @Nullable public static T getField(@Nonnull Object object, @Nonnull String fieldName) 13 | throws NoSuchFieldException, IllegalAccessException { 14 | Field[] fields = getAllFields(object); 15 | Field field = null; 16 | for (Field f : fields) { 17 | if (f.getName().equals(fieldName)) { 18 | field = f; 19 | break; 20 | } 21 | } 22 | if (field == null) throw new NoSuchFieldException(fieldName); 23 | field.setAccessible(true); 24 | return (T) field.get(object); 25 | } 26 | 27 | public static void setField(@Nonnull Object object, @Nonnull String fieldName, @Nullable T value) 28 | throws NoSuchFieldException, IllegalAccessException { 29 | Field[] fields = getAllFields(object); 30 | Field field = null; 31 | for (Field f : fields) { 32 | if (f.getName().equals(fieldName)) { 33 | field = f; 34 | break; 35 | } 36 | } 37 | if (field == null) throw new NoSuchFieldException(fieldName); 38 | field.setAccessible(true); 39 | field.set(object, value); 40 | } 41 | 42 | @Nonnull 43 | public static Field[] getAllFields(@Nonnull Object object) { 44 | Class clazz = object.getClass(); 45 | List fieldList = new ArrayList<>(); 46 | while (clazz != null) { 47 | fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields()))); 48 | clazz = clazz.getSuperclass(); 49 | } 50 | Field[] fields = new Field[fieldList.size()]; 51 | fieldList.toArray(fields); 52 | return fields; 53 | } 54 | 55 | @Nonnull 56 | public static Method[] getAllMethods(@Nonnull Object object) { 57 | Class clazz = object.getClass(); 58 | List methodList = new ArrayList<>(); 59 | while (clazz != null) { 60 | methodList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredMethods()))); 61 | clazz = clazz.getSuperclass(); 62 | } 63 | Method[] methods = new Method[methodList.size()]; 64 | methodList.toArray(methods); 65 | return methods; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/resources/addons/example/README.md: -------------------------------------------------------------------------------- 1 | ## 此处不再会放入示例 2 | ## 如需获取示例(最新),请前往 3 | ## -------------------------------------------------------------------------------- /src/main/resources/addons/example/info.yml: -------------------------------------------------------------------------------- 1 | id: example 2 | name: "示例附属" 3 | depends: [] 4 | pluginDepends: [] 5 | version: "1.0" 6 | description: "RSC示例附属" 7 | authors: ["mmmjjkx"] 8 | repo: "SlimefunReloadingProject/rsc-example" -------------------------------------------------------------------------------- /src/main/resources/config.yml: -------------------------------------------------------------------------------- 1 | # 是否自动获取示例 2 | saveExample: false 3 | # 是否获取调试日志,如果插件没有意外错误时,可以关闭该选项 4 | debug: false 5 | # 是否是否启用插件更新(需要GuizhanLibPlugin) 6 | pluginUpdate: true 7 | # 附属更新配置 8 | update: 9 | # 是否更新附属为预发布版本(一般这些版本很不稳定!) 10 | pre-releases: false 11 | # 自动更新附属 12 | auto: true 13 | # 禁止更新的附属 14 | # 请填写附属ID,而不是附属名字 15 | blocks: 16 | - "" 17 | #依赖下载仓库 18 | repositories: 19 | - https://maven.aliyun.com/repository/public 20 | - https://repo1.maven.org/maven2 -------------------------------------------------------------------------------- /src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: RykenSlimefunCustomizer 2 | version: '${project.version}' 3 | main: org.lins.mmmjjkx.rykenslimefuncustomizer.RykenSlimefunCustomizer 4 | api-version: '1.19' 5 | depend: [Slimefun] 6 | softdepend: 7 | - GuizhanLibPlugin 8 | - SlimeGlue 9 | - ColoredEnderChests 10 | - DyedBackpacks 11 | - EnderCargo 12 | - EcoPower 13 | - ElectricSpawners 14 | - ExoticGarden 15 | - ExtraGear 16 | - ExtraHeads 17 | - HotbarPets 18 | - luckyblocks-sf 19 | - RedstoneConnector 20 | - PrivateStorage 21 | - SlimefunOreChunks 22 | - SlimyTreeTaps 23 | - SoulJars 24 | - CommandOverride 25 | - EmeraldEnchants2 26 | - QuickMarket 27 | - QuickSell 28 | - RankPrefixPlus 29 | - MoreTools 30 | - LiteXpansion 31 | - MobCapturer 32 | - SoundMuffler 33 | - ExtraTools 34 | - TranscEndence 35 | - Liquid 36 | - SFCalc 37 | - SlimefunWarfare 38 | - Slimy-Power-Suits 39 | - InfernalExpansion 40 | - FluffyMachines 41 | - SlimyRepair 42 | - InfinityExpansion 43 | - FoxyMachines 44 | - GlobalWarming 45 | - GlobiaMachines 46 | - DynaTech 47 | - GeneticChickengineering 48 | - HeadLimiter 49 | - BlockLimiter 50 | - SlimeXpansion 51 | - Barrels 52 | #- ClayTech 53 | - FNAmplifications 54 | - SimpleMaterialGenerators 55 | - Netheopoiesis 56 | - Networks 57 | - EMC2 58 | - Nexcavate 59 | - SimpleStorage 60 | - SimpleUtils 61 | - AlchimiaVitae 62 | - SlimeTinker 63 | - PotionExpansion 64 | - FlowerPower 65 | - Galactifun 66 | - ElementManipulation 67 | - CrystamaeHistoria 68 | - DankTech 69 | - DankTech2 70 | - Networks-Changed 71 | - VillagerUtil 72 | - MissileWarfare 73 | - SensibleToolbox 74 | - Endrex 75 | - Bump 76 | - FinalTech # For build 29- (included) 77 | - FinalTECH # For build 29+ 78 | - SlimefunLuckyBlocks 79 | - FutureTech 80 | - DemonicExpansion 81 | - BedrockTechnology 82 | - SlimefunItemExpansion 83 | - SupplementalServiceableness 84 | - GuizhanCraft 85 | - Magmanimous 86 | - UltimateGenerators-RC27 # 不确定是否存在这个版本 87 | - UltimateGenerators # 构建站有 88 | - UltimateGenerators2 # 同上 89 | - CrispyMachine 90 | - DimensionTraveler 91 | - Chocohills 92 | - draconic # 疑似新版 93 | - DracFun # 疑似旧版(? 94 | - EzSFAddon # 疑似旧版 95 | - EzTech # 疑似新版 96 | - RandomExpansion 97 | - ExLimus 98 | - MoneyAndThings 99 | - VoidHarvesters 100 | - SlimyBees 101 | - GeneticManipulation 102 | - ObsidianExpansion 103 | - NotEnoughAddons 104 | - SlimeSec 105 | - EMCTech 106 | - RelicsOfCthonia 107 | - Supreme 108 | - DyeBench 109 | - MiniBlocks 110 | - SlimeHUD 111 | - SpiritsUnchained 112 | - Cultivation 113 | - Gastronomicon 114 | - SmallSpace 115 | - BetterReactor 116 | - BetterGenerator 117 | - VillagerTrade 118 | - SlimeFrame 119 | - AdvancedTech 120 | - Quaptics 121 | - CompressionCraft 122 | - CringleBosses 123 | - ThermalFun 124 | - FastMachines 125 | - MomoTech 126 | - OreGeneration 127 | - Huolaiy 128 | - EnchanterLimit 129 | - LogicTech 130 | - LogiTech 131 | - LogicTECH 132 | - LogiTECH 133 | - SlimeAE 134 | - SlimeChem 135 | - WilderNether 136 | - MapJammers 137 | - Cakecraft 138 | - SFMobDrops 139 | - Drugfun 140 | - SlimefunNukes 141 | - SlimeCustomizer 142 | - HardcoreSlimefun 143 | - SfChunkInfo 144 | - SlimefunTranslation 145 | - FinalTECH-Changed 146 | - Blueprint 147 | - SlimefunMobDrops 148 | - BearFluidTanks 149 | - SCrafter 150 | - EquivalencyTech 151 | - LuckyPandas 152 | - FasterTools 153 | - Beyond_Horizons 154 | - BloodAlchemy 155 | - ExtraUtils 156 | - BlueSlime 157 | - XpCreator 158 | - BetterFarming 159 | - Automation 160 | - Ex-Limus 161 | - EzMiner 162 | - NetherEnough 163 | - magic-powder 164 | - BoxOfChocolates 165 | - AdditionalWeaponry 166 | - DisguiseCookies 167 | - MagicXpansion 168 | - Tofu-Addons 169 | - IDreamOfEasy 170 | # Other plugins 171 | - PlaceholderAPI 172 | - NBTAPI 173 | loadBefore: 174 | - SaneCrafting 175 | - SlimefunAdvancements 176 | authors: [mmmjjkx] 177 | description: An advanced Slimefun customize plugin 178 | commands: 179 | rykenslimecustomizer: 180 | aliases: ["rsc"] 181 | permission: rsc.command.help 182 | permissions: 183 | rsc.command: 184 | default: op 185 | children: 186 | rsc.command.help: true 187 | rsc.command.reload: true 188 | rsc.command.list: true 189 | rsc.command.reloadPlugin: true 190 | rsc.command.saveitem: true 191 | rsc.command.enable: true 192 | rsc.command.disable: true 193 | rsc.command.menupreview: true 194 | rsc.command.info: true 195 | rsc.command.help: 196 | default: op 197 | rsc.command.reload: 198 | default: op 199 | rsc.command.list: 200 | default: op 201 | rsc.command.reloadPlugin: 202 | default: op 203 | rsc.command.saveitem: 204 | default: op 205 | rsc.command.enable: 206 | default: op 207 | rsc.command.disable: 208 | default: op 209 | rsc.command.menupreview: 210 | default: op 211 | rsc.command.info: 212 | default: op 213 | --------------------------------------------------------------------------------