From acae100dd2cc9547d8ffb3fb9ad4e83a2989d954 Mon Sep 17 00:00:00 2001 From: Dries007 Date: Fri, 19 Aug 2016 01:57:49 +0200 Subject: [PATCH] init 1.9/1.10 --- .gitattributes | 22 ++ .gitignore | 9 + LICENSE.txt | 27 +++ README.md | 46 ++++ build.gradle | 181 +++++++++++++++ examples/bags/Example.json | 12 + examples/bags/Example2.json | 5 + examples/bags/Stick.json | 6 + examples/tables/fishing.json | 27 +++ examples/tables/fishing/fish.json | 53 +++++ examples/tables/fishing/junk.json | 88 ++++++++ examples/tables/fishing/treasure.json | 74 ++++++ .../jsonlootbags/JsonLootBags.java | 126 +++++++++++ .../jsonlootbags/client/ClientHelper.java | 101 +++++++++ .../client/ModConfigGuiFactory.java | 104 +++++++++ .../jsonlootbags/item/ItemLootBag.java | 212 ++++++++++++++++++ .../jsonlootbags/util/Constants.java | 48 ++++ .../jsonlootbags/util/Helper.java | 59 +++++ .../jsonlootbags/util/LootTableHook.java | 147 ++++++++++++ .../assets/jsonlootbags/lang/en_US.lang | 0 .../assets/jsonlootbags/models/item/bag.json | 7 + .../jsonlootbags/textures/items/bag_bg.png | Bin 0 -> 289 bytes .../textures/items/bag_string.png | Bin 0 -> 299 bytes src/main/resources/mcmod.info | 21 ++ 24 files changed, 1375 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 build.gradle create mode 100644 examples/bags/Example.json create mode 100644 examples/bags/Example2.json create mode 100644 examples/bags/Stick.json create mode 100644 examples/tables/fishing.json create mode 100644 examples/tables/fishing/fish.json create mode 100644 examples/tables/fishing/junk.json create mode 100644 examples/tables/fishing/treasure.json create mode 100644 src/main/java/net/doubledoordev/jsonlootbags/JsonLootBags.java create mode 100644 src/main/java/net/doubledoordev/jsonlootbags/client/ClientHelper.java create mode 100644 src/main/java/net/doubledoordev/jsonlootbags/client/ModConfigGuiFactory.java create mode 100644 src/main/java/net/doubledoordev/jsonlootbags/item/ItemLootBag.java create mode 100644 src/main/java/net/doubledoordev/jsonlootbags/util/Constants.java create mode 100644 src/main/java/net/doubledoordev/jsonlootbags/util/Helper.java create mode 100644 src/main/java/net/doubledoordev/jsonlootbags/util/LootTableHook.java create mode 100644 src/main/resources/assets/jsonlootbags/lang/en_US.lang create mode 100644 src/main/resources/assets/jsonlootbags/models/item/bag.json create mode 100644 src/main/resources/assets/jsonlootbags/textures/items/bag_bg.png create mode 100644 src/main/resources/assets/jsonlootbags/textures/items/bag_string.png create mode 100644 src/main/resources/mcmod.info diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..412eeda --- /dev/null +++ b/.gitattributes @@ -0,0 +1,22 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..070d3f3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.gradle +build +jars +out +*.iml +*.ipr +*.iws +.idea +versions.json diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..536347f --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,27 @@ +Copyright (c) 2014-2016, Dries007 & DoubleDoorDevelopment +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of DoubleDoorDevelopment nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..8dfeb78 --- /dev/null +++ b/README.md @@ -0,0 +1,46 @@ +JsonLootBags +============ + +This mod adds JSON file based lootbags! + +Since MC 1.9 it uses the new, build in, json based loot table system. + +Any `.json` files under `config/JsonLootBags/bags`, including in sub-directories, are added as new lootbag items. (File names don't matter.) + +Any `.json` files under `config/JsonLootBags/tables` will be loaded as loot tables in the `jsonlootbags` resource domain. (The path + filename is the table name.) + + +Loot tables +----------- + +Loot tables can be super complex in 1.9, see the build in ones (can be found in `/assets/minecraft/loot_tables/` for +vanilla examples.) For more help, use online generators or the Minecraft wiki. If you want to send us a nice +(preferably vanilla only) example to put here, let us know. + +You specify what loot table to use in the `loot-table` field, see below. + +Luck +---- + +If you spawn the itemstack with an NBT data field (float / number type) called `luck` it will be passed on to the loot table. +You can use that to manipulate the drops a within 1 loot table. You are not required to use this, by default luck will be 0. + +Json format +----------- + +```json +{ + "loot-table": "minecraft:chests/village_blacksmith", // REQUIRED What loot table to use. See above. + "name": "bag1", // REQUIRED Internal item name: alphanumerical and underscores only + "human-name": "Example bag", // REQUIRED Human readable name. + "texture": "jsonlootbags:bag", // Model file for item. Provide your own via resource pack if desired. Default is "jsonlootbags:bag" + "rarity": "Epic", // Color of text. (Common, Uncommon, Rare, or Epic) "Common" is default. + "effect": true, // Give item the 'enchanted' effect. Defaults to true if rarity is not common. + "colors": [ // Colors to use on texture layers. Allows you to ship 1 model/texture and have multiple visuals. + "0x90C3D4", // Every line is a number, but you can also encode it in a string and use the more common # or 0x notation. + "#DB32DB" // Do not prefix the number with a 0. It will be interpreted as octal based! + // If you use "0xFFFFFF" (white), it will have no effect. Use this if you want to skip a layer. + ] +} +``` + diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..4b87b61 --- /dev/null +++ b/build.gradle @@ -0,0 +1,181 @@ +buildscript { + repositories { + jcenter() + maven { + name = "forge" + url = "http://files.minecraftforge.net/maven" + } + maven { + name = "sonatype" + url = "https://oss.sonatype.org/content/repositories/snapshots/" + } + } + dependencies { + classpath 'net.minecraftforge.gradle:ForgeGradle:2.2-SNAPSHOT' + classpath group: 'com.github.rodionmoiseev.gradle.plugins', name: 'idea-utils', version: '0.2' + } +} + + +import groovy.json.* + +configurations { + compile + deployJars +} + +apply plugin: "net.minecraftforge.gradle.forge" +apply plugin: "idea-utils" +apply plugin: "maven" + +group = "net.doubledoordev.jsonlootbags" +version = "1.0.0" + +targetCompatibility = 1.7 +sourceCompatibility = 1.7 + +archivesBaseName = 'JsonLootBags' +def githuborg = 'DoubleDoorDevelopment' +def description = 'Json Loot bags' +minecraft { + version = "1.9.4-12.17.0.1976" + runDir = "jars" + mappings = "stable_26" +} + +repositories { + maven { + name "DDD repo" + url "http://doubledoordev.net/maven/" + } +} + +dependencies { + compile "net.doubledoordev.d3core:D3Core:" + project.minecraft.version + "-+:dev" +} + +if (System.getenv().BUILD_NUMBER != null) version += "." + System.getenv().BUILD_NUMBER + +//noinspection GroovyAssignabilityCheck +processResources { + from(sourceSets.main.resources.srcDirs) { + include 'mcmod.info' + expand 'version':project.version, 'mcversion':project.minecraft.version, 'modid':project.archivesBaseName, 'githuborg':githuborg, 'description':description, 'group':project.group, 'artifactId':project.archivesBaseName + } + + doLast { + def updateFile = new File(project.archivesBaseName + '.json') + def json; + if (updateFile.exists()) { + json = new JsonSlurper().parseText(updateFile.getText()) + } + else { + def builder = new JsonBuilder() + json = builder( + homepage: "http://doubledoordev.net/", + promos: new HashMap<>() + ) + } + def outStream = new ByteArrayOutputStream() + def result = exec { + executable = 'git' + args = [ 'log', '-n', '1', "--format='%B'"] + standardOutput = outStream + } + def fullLog = outStream.toString().replaceAll("^\\s*'\\s*|\\s*'\\s*\$", "").replaceAll("[\\r\\n]+", "\n") + + json['promos'][project.minecraft.version + '-latest'] = project.version + json['promos'][project.minecraft.version + '-recomended'] = project.version + if (!json.containsKey(project.minecraft.version)) json.put(project.minecraft.version, new HashMap<>()) + def version = json[project.minecraft.version] + version.put(project.version, fullLog) + updateFile.write JsonOutput.prettyPrint(JsonOutput.toJson(json)) + } +} + +task deobfJar(type: Jar, dependsOn: 'jar') { + from sourceSets.main.output + from "LICENSE.txt" + classifier "dev" + appendix = project.minecraft.version +} +sourceJar { + from "LICENSE.txt" + exclude("com/**") + classifier "src" + appendix = project.minecraft.version +} +//noinspection GroovyAssignabilityCheck +jar { + from "LICENSE.txt" + exclude("com/**") + appendix = project.minecraft.version +} +artifacts { + archives deobfJar +} + +idea { + project { + copyright { + name = 'New BSD License' + license = file('LICENSE.txt') + } + } +} + +//noinspection GroovyAssignabilityCheck +uploadArchives { + if (project.hasProperty("dddUser") && project.hasProperty("dddUrl") && project.hasProperty("dddPass")) { + repositories { + mavenDeployer { + repository(url: dddUrl) { + authentication(userName: dddUser, password: dddPass) + } + pom { + groupId = project.group + version = project.minecraft.version + "-" + project.version + artifactId = project.archivesBaseName + project { + name project.archivesBaseName + packaging 'jar' + description = project.description + url 'https://github.com/' + githuborg + '/' + project.archivesBaseName + + scm { + url 'https://github.com/' + githuborg + '/' + project.archivesBaseName + connection 'scm:git:git://github.com/' + githuborg + '/' + project.archivesBaseName + '.git' + developerConnection 'scm:git:git@github.com:' + githuborg + '/' + project.archivesBaseName + '.git' + } + + issueManagement { + system 'github' + url 'https://github.com/' + githuborg + '/' + project.archivesBaseName + '/issues' + } + + licenses { + license { + name 'New BSD License' + url 'https://raw.github.com/' + githuborg + '/' + project.archivesBaseName + '/master/LICENCE.txt' + distribution 'repo' + } + } + + developers { + developer { + id 'Dries007' + name 'Dries007' + roles { role 'developer' } + } + developer { + id 'Claycorp' + name 'Claycorp' + roles { role 'developer' } + } + } + } + } + } + } + } +} diff --git a/examples/bags/Example.json b/examples/bags/Example.json new file mode 100644 index 0000000..e384f9e --- /dev/null +++ b/examples/bags/Example.json @@ -0,0 +1,12 @@ +{ + "loot-table": "jsonlootbags:fishing", + "name": "bag1", + "human-name": "Example bag", + "texture": "jsonlootbags:bag", + "rarity": "Epic", + "effect": true, + "colors": [ + "0x90C3D4", + "#DB32DB" + ] +} \ No newline at end of file diff --git a/examples/bags/Example2.json b/examples/bags/Example2.json new file mode 100644 index 0000000..104d232 --- /dev/null +++ b/examples/bags/Example2.json @@ -0,0 +1,5 @@ +{ + "loot-table": "jsonlootbags:fishing/treasure", + "name": "bag2", + "human-name": "Example bag 2" +} \ No newline at end of file diff --git a/examples/bags/Stick.json b/examples/bags/Stick.json new file mode 100644 index 0000000..c7afc71 --- /dev/null +++ b/examples/bags/Stick.json @@ -0,0 +1,6 @@ +{ + "loot-table": "jsonlootbags:fishing/junk", + "name": "stick", + "texture": "stick", + "human-name": "Stick" +} \ No newline at end of file diff --git a/examples/tables/fishing.json b/examples/tables/fishing.json new file mode 100644 index 0000000..62cd172 --- /dev/null +++ b/examples/tables/fishing.json @@ -0,0 +1,27 @@ +{ + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "loot_table", + "name": "jsonlootbags:fishing/junk", + "weight": 10, + "quality": -2 + }, + { + "type": "loot_table", + "name": "jsonlootbags:fishing/treasure", + "weight": 5, + "quality": 2 + }, + { + "type": "loot_table", + "name": "jsonlootbags:fishing/fish", + "weight": 85, + "quality": -1 + } + ] + } + ] +} \ No newline at end of file diff --git a/examples/tables/fishing/fish.json b/examples/tables/fishing/fish.json new file mode 100644 index 0000000..3376910 --- /dev/null +++ b/examples/tables/fishing/fish.json @@ -0,0 +1,53 @@ +{ + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "item", + "name": "minecraft:fish", + "functions": [ + { + "function": "set_data", + "data": 0 + } + ], + "weight": 60 + }, + { + "type": "item", + "name": "minecraft:fish", + "functions": [ + { + "function": "set_data", + "data": 1 + } + ], + "weight": 25 + }, + { + "type": "item", + "name": "minecraft:fish", + "functions": [ + { + "function": "set_data", + "data": 2 + } + ], + "weight": 2 + }, + { + "type": "item", + "name": "minecraft:fish", + "functions": [ + { + "function": "set_data", + "data": 3 + } + ], + "weight": 13 + } + ] + } + ] +} \ No newline at end of file diff --git a/examples/tables/fishing/junk.json b/examples/tables/fishing/junk.json new file mode 100644 index 0000000..b4fe0f5 --- /dev/null +++ b/examples/tables/fishing/junk.json @@ -0,0 +1,88 @@ +{ + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "item", + "name": "minecraft:leather_boots", + "weight": 10, + "functions": [ + { + "function": "set_damage", + "damage": { + "min": 0, + "max": 0.90 + } + } + ] + }, + { + "type": "item", + "name": "minecraft:leather", + "weight": 10 + }, + { + "type": "item", + "name": "minecraft:bone", + "weight": 10 + }, + { + "type": "item", + "name": "minecraft:potion", + "weight": 10 + }, + { + "type": "item", + "name": "minecraft:string", + "weight": 5 + }, + { + "type": "item", + "name": "minecraft:fishing_rod", + "weight": 2, + "functions": [ + { + "function": "set_damage", + "damage": { + "min": 0, + "max": 0.90 + } + } + ] + }, + { + "type": "item", + "name": "minecraft:bowl", + "weight": 10 + }, + { + "type": "item", + "name": "minecraft:stick", + "weight": 5 + }, + { + "type": "item", + "name": "minecraft:dye", + "weight": 10, + "functions": [ + { + "function": "set_data", + "data": 0 + } + ] + }, + { + "type": "item", + "name": "minecraft:tripwire_hook", + "weight": 10 + }, + { + "type": "item", + "name": "minecraft:rotten_flesh", + "weight": 10 + } + ] + } + ] +} \ No newline at end of file diff --git a/examples/tables/fishing/treasure.json b/examples/tables/fishing/treasure.json new file mode 100644 index 0000000..eb443fa --- /dev/null +++ b/examples/tables/fishing/treasure.json @@ -0,0 +1,74 @@ +{ + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "item", + "name": "minecraft:waterlily", + "weight": 1 + }, + { + "type": "item", + "name": "minecraft:name_tag", + "weight": 1 + }, + { + "type": "item", + "name": "minecraft:saddle", + "weight": 1 + }, + { + "type": "item", + "name": "minecraft:bow", + "weight": 1, + "functions": [ + { + "function": "set_damage", + "damage": { + "min": 0, + "max": 0.25 + } + }, + { + "function": "enchant_with_levels", + "levels": 30, + "treasure": true + } + ] + }, + { + "type": "item", + "name": "minecraft:fishing_rod", + "weight": 1, + "functions": [ + { + "function": "set_damage", + "damage": { + "min": 0, + "max": 0.25 + } + }, + { + "function": "enchant_with_levels", + "levels": 30, + "treasure": true + } + ] + }, + { + "type": "item", + "name": "minecraft:book", + "weight": 1, + "functions": [ + { + "function": "enchant_with_levels", + "levels": 30, + "treasure": true + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/java/net/doubledoordev/jsonlootbags/JsonLootBags.java b/src/main/java/net/doubledoordev/jsonlootbags/JsonLootBags.java new file mode 100644 index 0000000..eefd35e --- /dev/null +++ b/src/main/java/net/doubledoordev/jsonlootbags/JsonLootBags.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2014-2016, Dries007 & DoubleDoorDevelopment + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of DoubleDoorDevelopment nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package net.doubledoordev.jsonlootbags; + +import net.doubledoordev.jsonlootbags.client.ClientHelper; +import net.doubledoordev.jsonlootbags.item.ItemLootBag; +import net.doubledoordev.jsonlootbags.util.LootTableHook; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.config.Configuration; +import net.minecraftforge.fml.client.event.ConfigChangedEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.apache.commons.io.FileUtils; +import org.apache.logging.log4j.Logger; + +import java.io.File; +import java.nio.file.Path; +import java.util.HashSet; +import java.util.Set; + +import static net.doubledoordev.jsonlootbags.util.Constants.*; + +@Mod(modid = MODID, name = MODID, updateJSON = UPDATE_URL, guiFactory = MOD_GUI_FACTORY, dependencies = "required-after:D3Core@[1.3,)") +public class JsonLootBags +{ + @Mod.Instance(MODID) + public static JsonLootBags instance; + + private Logger logger; + private Configuration config; + + @Mod.EventHandler + public void preInit(FMLPreInitializationEvent event) throws Exception + { + logger = event.getModLog(); + + MinecraftForge.EVENT_BUS.register(this); + + config = new Configuration(); + updateConfig(); + + File folder = new File(event.getModConfigurationDirectory(), MODID); + if (!folder.exists()) folder.mkdir(); + + LootTableHook.init(new File(folder, "tables")); + + { + File bagsFolder = new File(folder, "bags"); + if (!bagsFolder.exists()) bagsFolder.mkdir(); + Path basePath = bagsFolder.toPath(); + Set errors = new HashSet<>(); + for (File file : FileUtils.listFiles(bagsFolder, new String[]{"json"}, true)) + { + if (ItemLootBag.fromFile(file) == null) + errors.add(basePath.relativize(file.toPath()).toString()); + } + if (!errors.isEmpty()) + { + Exception e = new Exception("One or more LootBags failed to load. Abort game loading."); + e.setStackTrace(new StackTraceElement[0]); + throw e; + } + JsonLootBags.getLogger().info("Loaded {} loot bags.", ItemLootBag.getLootBags().length); + } + + if (event.getSide().isClient()) ClientHelper.preInit(); + } + + @Mod.EventHandler + public void init(FMLInitializationEvent event) + { + if (event.getSide().isClient()) ClientHelper.init(); + } + + @SubscribeEvent + public void onConfigChanged(ConfigChangedEvent.OnConfigChangedEvent event) + { + if (event.getModID().equals(MODID)) updateConfig(); + } + + private void updateConfig() + { + if (config.hasChanged()) config.save(); + } + + public static Configuration getConfig() + { + return instance.config; + } + + public static Logger getLogger() + { + return instance.logger; + } +} diff --git a/src/main/java/net/doubledoordev/jsonlootbags/client/ClientHelper.java b/src/main/java/net/doubledoordev/jsonlootbags/client/ClientHelper.java new file mode 100644 index 0000000..8dd42d4 --- /dev/null +++ b/src/main/java/net/doubledoordev/jsonlootbags/client/ClientHelper.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2014-2016, Dries007 & DoubleDoorDevelopment + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of DoubleDoorDevelopment nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package net.doubledoordev.jsonlootbags.client; + +import net.doubledoordev.d3core.events.D3LanguageInjectEvent; +import net.doubledoordev.jsonlootbags.JsonLootBags; +import net.doubledoordev.jsonlootbags.item.ItemLootBag; +import net.doubledoordev.jsonlootbags.util.Constants; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.ItemMeshDefinition; +import net.minecraft.client.renderer.ItemModelMesher; +import net.minecraft.client.renderer.RenderItem; +import net.minecraft.client.renderer.block.model.ModelBlock; +import net.minecraft.client.renderer.block.model.ModelResourceLocation; +import net.minecraft.client.renderer.color.IItemColor; +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.model.ICustomModelLoader; +import net.minecraftforge.client.model.IModel; +import net.minecraftforge.client.model.ModelLoader; +import net.minecraftforge.client.model.ModelLoaderRegistry; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.client.FMLClientHandler; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +public class ClientHelper +{ + public static final ClientHelper I = new ClientHelper(); + + public static void preInit() + { + MinecraftForge.EVENT_BUS.register(I); + + for (final ItemLootBag item : ItemLootBag.getLootBags()) + { + // IDK which one is effective, or which one is recommended. So I'm using them all. + // The modeling system is confusing... + ModelLoader.registerItemVariants(item, new ModelResourceLocation(item.texture), new ModelResourceLocation(item.texture, "inventory")); + ModelLoader.setCustomMeshDefinition(item, new ItemMeshDefinition() { + @Override + public ModelResourceLocation getModelLocation(ItemStack stack) + { + return new ModelResourceLocation(item.texture); + } + }); + ModelLoader.registerItemVariants(item, new ModelResourceLocation(item.texture)); + ModelLoader.setCustomModelResourceLocation(item, 0, new ModelResourceLocation(item.texture)); + } + } + + public static void init() + { + Minecraft.getMinecraft().getItemColors().registerItemColorHandler(new IItemColor() { + @Override + public int getColorFromItemstack(ItemStack stack, int tintIndex) + { + return ((ItemLootBag) stack.getItem()).getColor(stack, tintIndex); + } + }, (Item[]) ItemLootBag.getLootBags()); + } + + @SubscribeEvent + public void d3LanguageInjectEvent(D3LanguageInjectEvent event) + { + for (ItemLootBag axe : ItemLootBag.getLootBags()) + { + event.map.put(axe.getUnlocalizedName() + ".name", axe.human_name); + } + } +} diff --git a/src/main/java/net/doubledoordev/jsonlootbags/client/ModConfigGuiFactory.java b/src/main/java/net/doubledoordev/jsonlootbags/client/ModConfigGuiFactory.java new file mode 100644 index 0000000..70fdff5 --- /dev/null +++ b/src/main/java/net/doubledoordev/jsonlootbags/client/ModConfigGuiFactory.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2014-2016, Dries007 & DoubleDoorDevelopment + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of DoubleDoorDevelopment nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package net.doubledoordev.jsonlootbags.client; + +import net.doubledoordev.d3core.util.CoreConstants; +import net.doubledoordev.jsonlootbags.JsonLootBags; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.resources.I18n; +import net.minecraftforge.common.config.ConfigElement; +import net.minecraftforge.common.config.Configuration; +import net.minecraftforge.fml.client.IModGuiFactory; +import net.minecraftforge.fml.client.config.GuiConfig; +import net.minecraftforge.fml.client.config.IConfigElement; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +@SuppressWarnings({"unused", "WeakerAccess"}) +public class ModConfigGuiFactory implements IModGuiFactory +{ + public static class D3ConfigGuiScreen extends GuiConfig + { + public D3ConfigGuiScreen(GuiScreen parentScreen) + { + super(parentScreen, getConfigElements(), CoreConstants.MODID, false, false, I18n.format("d3.lumberjack.config.lumberjack")); + } + + private static List getConfigElements() + { + Configuration c = JsonLootBags.getConfig(); + if (c.getCategoryNames().size() == 1) + { + //noinspection LoopStatementThatDoesntLoop + for (String k : c.getCategoryNames()) + { + // Let forge do the work, for loop abused to avoid other strange constructs + return new ConfigElement(c.getCategory(k)).getChildElements(); + } + } + + List list = new ArrayList<>(); + for (String k : c.getCategoryNames()) + { + list.add(new ConfigElement(c.getCategory(k))); + } + return list; + } + } + + @Override + public void initialize(Minecraft minecraftInstance) + { + + } + + @Override + public Class mainConfigGuiClass() + { + return null; + } + + @Override + public Set runtimeGuiCategories() + { + return null; + } + + @Override + public RuntimeOptionGuiHandler getHandlerFor(RuntimeOptionCategoryElement element) + { + return null; + } +} diff --git a/src/main/java/net/doubledoordev/jsonlootbags/item/ItemLootBag.java b/src/main/java/net/doubledoordev/jsonlootbags/item/ItemLootBag.java new file mode 100644 index 0000000..36fbc8f --- /dev/null +++ b/src/main/java/net/doubledoordev/jsonlootbags/item/ItemLootBag.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2014-2016, Dries007 & DoubleDoorDevelopment + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of DoubleDoorDevelopment nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package net.doubledoordev.jsonlootbags.item; + +import com.google.gson.*; +import net.doubledoordev.jsonlootbags.JsonLootBags; +import net.doubledoordev.jsonlootbags.util.Constants; +import net.doubledoordev.jsonlootbags.util.Helper; +import net.doubledoordev.jsonlootbags.util.LootTableHook; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +import net.minecraftforge.fml.common.registry.GameRegistry; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import org.apache.commons.io.FileUtils; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class ItemLootBag extends Item +{ + // REQUIRED + private static final String JSON_NAME = "name"; // String (alphanumerical and underscores) + private static final String JSON_HUMAN_NAME = "human-name"; // String + private static final String JSON_LOOT_TABLE = "loot-table"; // String (resource location) + // OPTIONAL + private static final String JSON_COLORS = "colors"; // Array of numbers or strings (must be decodable numbers) + private static final String JSON_TEXTURE = "texture"; // String (resource location) Build in bag texture by default. + private static final String JSON_RARITY = "rarity"; // String (Common, Uncommon, Rare, or Epic) Common is default. + private static final String JSON_EFFECT = "effect"; // Boolean (Defaults to true if rarity is not common) + + private static final String DEFAULT_TEXTURE = Constants.MODID.toLowerCase() + ":bag"; + + private static final Gson GSON = new GsonBuilder() + .registerTypeHierarchyAdapter(ItemLootBag.class, new JsonDeserializer() + { + @Override + public ItemLootBag deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException + { + final JsonObject object = json.getAsJsonObject(); + + for (String req : new String[]{JSON_NAME, JSON_HUMAN_NAME, JSON_LOOT_TABLE}) + if (!object.has(req)) + throw new JsonParseException("Missing required field: " + req); + final String name = object.get(JSON_NAME).getAsString(); + if (!name.matches("^\\w+$")) + throw new JsonParseException("Name '" + name + "' has non-word characters in it. Only alphanumerical and underscores are allowed."); + final String human_name = object.get(JSON_HUMAN_NAME).getAsString(); + final String table = object.get(JSON_LOOT_TABLE).getAsString(); + + final int[] colors = object.has(JSON_COLORS) ? Helper.jsonArrayToIntArray(object.getAsJsonArray(JSON_COLORS)) : new int[0]; + final String texture = object.has(JSON_TEXTURE) ? object.get(JSON_TEXTURE).getAsString() : DEFAULT_TEXTURE; + final EnumRarity rarity = object.has(JSON_RARITY) ? Helper.getEnum(object.get(JSON_RARITY).getAsString(), true, EnumRarity.values()) : EnumRarity.COMMON; + final boolean effect = object.has(JSON_EFFECT) ? object.get(JSON_EFFECT).getAsBoolean() : rarity != EnumRarity.COMMON; + + return new ItemLootBag(name, human_name, table, texture, rarity, colors, effect); + } + }).setPrettyPrinting().create(); + private static final List LOOT_BAG_LIST = new ArrayList<>(); + + public static ItemLootBag fromFile(File file) throws IOException + { + try + { + return GSON.fromJson(FileUtils.readFileToString(file), ItemLootBag.class); + } + catch (Exception e) + { + JsonLootBags.getLogger().fatal("An error occurred trying to load {} as LootBag. Will abort loading after the last files is parsed.", file); + JsonLootBags.getLogger().catching(e); + } + return null; + } + + public static ItemLootBag[] getLootBags() + { + return LOOT_BAG_LIST.toArray(new ItemLootBag[LOOT_BAG_LIST.size()]); + } + + public final String name; + public final String human_name; + public final String texture; + private final ResourceLocation table; + private final EnumRarity rarity; + private final int[] colors; + private final boolean effect; + + public ItemLootBag(String name, String human_name, String table, String texture, EnumRarity rarity, int[] colors, boolean effect) + { + this.name = name; + this.human_name = human_name; + this.table = new ResourceLocation(table); + this.texture = texture; + this.rarity = rarity; + this.colors = colors; + this.effect = effect; + + LOOT_BAG_LIST.add(this); + + setCreativeTab(CreativeTabs.MISC); + setUnlocalizedName(Constants.MODID.toLowerCase() + Character.toUpperCase(name.charAt(0)) + name.substring(1)); + setRegistryName(Constants.MODID.toLowerCase(), name); + + GameRegistry.register(this); + + JsonLootBags.getLogger().info("Successfully loaded {}", this); + } + + @Override + public String toString() + { + return "ItemLootBag{" + + "registry_name='" + getRegistryName() + '\'' + + ", name='" + name + '\'' + + ", human_name='" + human_name + '\'' + + ", texture='" + texture + '\'' + + ", table=" + table + + ", rarity=" + rarity + + ", colors=" + Arrays.toString(colors) + + '}'; + } + + @Override + public ActionResult onItemRightClick(ItemStack itemStackIn, World worldIn, EntityPlayer playerIn, EnumHand hand) + { + if (!playerIn.capabilities.isCreativeMode) --itemStackIn.stackSize; + if (!worldIn.isRemote) + { + for (ItemStack stack : LootTableHook.makeLoot((WorldServer) worldIn, playerIn, getLuck(itemStackIn), this.table)) + { + EntityItem entityitem = new EntityItem(worldIn, playerIn.posX, playerIn.posY, playerIn.posZ, stack); + entityitem.setNoPickupDelay(); + worldIn.spawnEntityInWorld(entityitem); + } + } + return new ActionResult<>(EnumActionResult.SUCCESS, itemStackIn); + } + + @Override + public EnumRarity getRarity(ItemStack stack) + { + return rarity; + } + + @Override + @SideOnly(Side.CLIENT) + public boolean hasEffect(ItemStack stack) + { + return super.hasEffect(stack) || effect; + } + + @Override + public void addInformation(ItemStack stack, EntityPlayer playerIn, List tooltip, boolean advanced) + { + float luck = getLuck(stack); + if (luck != 0) tooltip.add("Luck: " + luck); + super.addInformation(stack, playerIn, tooltip, advanced); + } + + private float getLuck(ItemStack stack) + { + return !stack.hasTagCompound() ? 0 : stack.getTagCompound().getInteger("luck"); + } + + public int getColor(ItemStack stack, int tintIndex) + { + return tintIndex < colors.length ? colors[tintIndex] : 0xFFFFFF; + } +} diff --git a/src/main/java/net/doubledoordev/jsonlootbags/util/Constants.java b/src/main/java/net/doubledoordev/jsonlootbags/util/Constants.java new file mode 100644 index 0000000..10d14a7 --- /dev/null +++ b/src/main/java/net/doubledoordev/jsonlootbags/util/Constants.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014-2016, Dries007 & DoubleDoorDevelopment + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of DoubleDoorDevelopment nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package net.doubledoordev.jsonlootbags.util; + +import net.doubledoordev.d3core.util.CoreConstants; +import org.apache.commons.io.IOCase; +import org.apache.commons.io.filefilter.IOFileFilter; +import org.apache.commons.io.filefilter.SuffixFileFilter; + +public class Constants +{ + public static final String MODID = "JsonLootBags"; + public static final String UPDATE_URL = CoreConstants.BASE_URL + MODID + ".json"; + + /** + * @see net.doubledoordev.jsonlootbags.client.ModConfigGuiFactory + */ + public static final String MOD_GUI_FACTORY = "net.doubledoordev.jsonlootbags.client.ModConfigGuiFactory"; +} diff --git a/src/main/java/net/doubledoordev/jsonlootbags/util/Helper.java b/src/main/java/net/doubledoordev/jsonlootbags/util/Helper.java new file mode 100644 index 0000000..c286a40 --- /dev/null +++ b/src/main/java/net/doubledoordev/jsonlootbags/util/Helper.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014-2016, Dries007 & DoubleDoorDevelopment + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of DoubleDoorDevelopment nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package net.doubledoordev.jsonlootbags.util; + +import com.google.gson.JsonArray; +import com.google.gson.JsonParseException; +import net.minecraft.item.EnumRarity; + +public class Helper +{ + public static int[] jsonArrayToIntArray(JsonArray colors) throws JsonParseException + { + int[] out = new int[colors.size()]; + for (int i = 0; i < colors.size(); i++) out[i] = Integer.decode(colors.get(i).getAsString()); + return out; + } + + @SafeVarargs + public static T getEnum(String name, boolean mustMatch, T... values) + { + for (T i : values) + { + if (i.name().equalsIgnoreCase(name)) + return i; + } + if (mustMatch) + throw new IllegalArgumentException("The enum constant '" + name + "' does not exist."); + return null; + } +} diff --git a/src/main/java/net/doubledoordev/jsonlootbags/util/LootTableHook.java b/src/main/java/net/doubledoordev/jsonlootbags/util/LootTableHook.java new file mode 100644 index 0000000..f9531fa --- /dev/null +++ b/src/main/java/net/doubledoordev/jsonlootbags/util/LootTableHook.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2014-2016, Dries007 & DoubleDoorDevelopment + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of DoubleDoorDevelopment nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package net.doubledoordev.jsonlootbags.util; + +import com.google.common.base.Charsets; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.io.Files; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import net.doubledoordev.jsonlootbags.JsonLootBags; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.WorldServer; +import net.minecraft.world.storage.loot.*; +import net.minecraft.world.storage.loot.conditions.LootCondition; +import net.minecraft.world.storage.loot.conditions.LootConditionManager; +import net.minecraft.world.storage.loot.functions.LootFunction; +import net.minecraft.world.storage.loot.functions.LootFunctionManager; +import net.minecraftforge.common.ForgeHooks; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.FilenameUtils; + +import java.io.File; +import java.nio.file.Path; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * This is a wrapper around the existing {@link LootTableManager}, with its own cache, loaded from the tables folder. + */ +public class LootTableHook extends LootTableManager +{ + private static final Gson GSON_INSTANCE = new GsonBuilder().registerTypeAdapter(RandomValueRange.class, new RandomValueRange.Serializer()).registerTypeAdapter(LootPool.class, new LootPool.Serializer()).registerTypeAdapter(LootTable.class, new LootTable.Serializer()).registerTypeHierarchyAdapter(LootEntry.class, new LootEntry.Serializer()).registerTypeHierarchyAdapter(LootFunction.class, new LootFunctionManager.Serializer()).registerTypeHierarchyAdapter(LootCondition.class, new LootConditionManager.Serializer()).registerTypeHierarchyAdapter(LootContext.EntityTarget.class, new LootContext.EntityTarget.Serializer()).create(); + private static LootTableManager fallback; + private final LoadingCache cache = CacheBuilder.newBuilder().build(new Loader()); + private File tablesFolder; + + private static LootTableHook instance; + + public LootTableHook(File folder) + { + // Only possible because we kill reloadLootTables + // noinspection ConstantConditions + super(null); + tablesFolder = folder; + // Custom reload, because we can't access super's folder. Otherwise this would be so much simpler. + reload(); + } + + @Override + public void reloadLootTables() + { + // Fuck no + } + + public static void init(File tables) + { + instance = new LootTableHook(tables); + } + + //todo: call this when stuff reloads... + private void reload() + { + cache.invalidateAll(); + + if (!tablesFolder.exists()) tablesFolder.mkdir(); + Path basePath = tablesFolder.toPath(); + Set errors = new HashSet<>(); + for (File file : FileUtils.listFiles(tablesFolder, new String[]{"json"}, true)) + { + String name = FilenameUtils.removeExtension(basePath.relativize(file.toPath()).toString()); + if (cache.getUnchecked(new ResourceLocation(Constants.MODID.toLowerCase(), name)) == null) + errors.add(name); + } + if (!errors.isEmpty()) + { + RuntimeException e = new RuntimeException("One or more LootTables failed to load. Abort game loading."); + e.setStackTrace(new StackTraceElement[0]); + throw e; + } + + JsonLootBags.getLogger().info("Loaded {} custom loot tables.", cache.size()); + } + + public static List makeLoot(WorldServer worldIn, EntityPlayer playerIn, float luck, ResourceLocation location) + { + LootContext lootContext = new LootContext(luck, worldIn, instance, null, playerIn, null); + fallback = worldIn.getLootTableManager(); + LootTable table = instance.cache.getIfPresent(location); + if (table == null) table = fallback.getLootTableFromLocation(location); + return table.generateLootForPools(worldIn.rand, lootContext); + } + + @Override + public LootTable getLootTableFromLocation(ResourceLocation location) + { + LootTable table = instance.cache.getIfPresent(location); + if (table == null) table = fallback.getLootTableFromLocation(location); + return table; + } + + private class Loader extends CacheLoader + { + @Override + public LootTable load(ResourceLocation key) throws Exception + { + File file = new File(tablesFolder, key.getResourcePath() + ".json"); + if (!file.exists()) return null; + if (!file.isFile()) throw new IllegalArgumentException(file + " has to be a file, not a folder."); + + return ForgeHooks.loadLootTable(GSON_INSTANCE, key, Files.toString(file, Charsets.UTF_8), true); + } + } +} diff --git a/src/main/resources/assets/jsonlootbags/lang/en_US.lang b/src/main/resources/assets/jsonlootbags/lang/en_US.lang new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/assets/jsonlootbags/models/item/bag.json b/src/main/resources/assets/jsonlootbags/models/item/bag.json new file mode 100644 index 0000000..38acd0d --- /dev/null +++ b/src/main/resources/assets/jsonlootbags/models/item/bag.json @@ -0,0 +1,7 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "jsonlootbags:items/bag_bg", + "layer1": "jsonlootbags:items/bag_string" + } +} diff --git a/src/main/resources/assets/jsonlootbags/textures/items/bag_bg.png b/src/main/resources/assets/jsonlootbags/textures/items/bag_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..2ec26223209aadfe12671b2c04587b9cec56769b GIT binary patch literal 289 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6n3BBRT^Rni_n+Ah4nJ za0`PlBg3pY5H=O_6Hn-JklD|?*zyKg*JJ*IEHAPUwhFo=&*rE%R~Q7u>xs_ z1QS;5aLSu7`!(MegUmwVV}*Z$7D%v4ac!IU?CtuSwaWk2)!uvl?N89IxU!EA?j;nM zRR*uxyh*h-LZv%7*_=UDHsz+H=VHNR>4ki0w%a6f^BZILaGZR!wKK!Z?o~?5;_srK z;lCr}-)_FSMd|PNY$qqP6Z1MIX*qBNhI1trt-2^`;c3;)*KIH(ztQ^S$>n}xY0}d6 hUjP2hp7f_%uWG8T(yV~4nJ za0`PlBg3pY5H=O_6Hn-JkqK!b9EK~h4y&5IEHAPUwhHe@34bF>%;u=+$AbX z3m3XAdc?KQG4Gvq0QXQT__PO4F8cNIzu#`uowjzfj&*kFMb=my9SPyRT)$n!e{W%u(swedh>e&s|I_3H z2^&5>*uo}t{$0o>6_wl4LC@}QHSwLBa`fO{;Z+-*IShM64jnDsG^1hl5(yC=r?v6S t(kHJjSK{8g_HEVGv-;aJ|Mu@=)L&!bHuc@KbwGbGc)I$ztaD0e0ssJ5a<~8h literal 0 HcmV?d00001 diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info new file mode 100644 index 0000000..428fb53 --- /dev/null +++ b/src/main/resources/mcmod.info @@ -0,0 +1,21 @@ +{ + "modListVersion": 2, + "modList": [{ + "modid": "${modid}", + "name": "${modid}", + "description": "${description}", + "version": "${version}", + "mcversion": "${mcversion}", + "url": "https://github.com/${githuborg}/${modid}", + "updateUrl": "", + "authorList": [ "Dries007", "DoubleDoor team" ], + "credits": "", + "logoFile": "", + "screenshots": [], + "parent": "", + "requiredMods": [ "Forge", "D3Core" ], + "dependencies": [ "D3Core" ], + "dependants": [ ], + "useDependencyInformation": true + }] +} \ No newline at end of file