Created
March 20, 2018 23:05
-
-
Save mcSw4p/3b2501bca4d0ed2f12cf3e9ab24ccc11 to your computer and use it in GitHub Desktop.
Minecraft 1.12 Advancement API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.google.common.base.Charsets; | |
import com.google.common.collect.Lists; | |
import com.google.common.collect.Maps; | |
import com.google.common.io.Files; | |
import com.google.gson.Gson; | |
import com.google.gson.GsonBuilder; | |
import net.minecraft.server.v1_12_R1.AdvancementDataWorld; | |
import net.minecraft.server.v1_12_R1.ChatDeserializer; | |
import net.minecraft.server.v1_12_R1.MinecraftServer; | |
import net.minecraft.server.v1_12_R1.Advancement.SerializedAdvancement; | |
import org.bukkit.Bukkit; | |
import org.bukkit.NamespacedKey; | |
import org.bukkit.World; | |
import org.bukkit.craftbukkit.v1_12_R1.util.CraftNamespacedKey; | |
import org.json.simple.JSONArray; | |
import org.json.simple.JSONObject; | |
import java.io.File; | |
import java.io.IOException; | |
import java.nio.file.Path; | |
import java.util.ArrayList; | |
import java.util.Collections; | |
import java.util.List; | |
import java.util.logging.Level; | |
/** | |
* Advancement API | |
* Build simple minecraft 1.12 custom advancements and functions | |
* | |
* @author Sw4p | |
*/ | |
public class Advancement { | |
private Gson gson = new GsonBuilder().setPrettyPrinting().create(); | |
private JSONObject advancementJson = new JSONObject(); | |
private NamespacedKey id; | |
private NamespacedKey parent; | |
private NamespacedKey iconMaterial = NamespacedKey.minecraft("stone"); | |
private NamespacedKey background = NamespacedKey.minecraft("textures/gui/advancements/backgrounds/cobblestone.png"); | |
private int iconData = 0; | |
private String title = "Advancement"; | |
private String description = "Install the Advancement"; | |
private boolean announceToChat = true; | |
private boolean showToast = true; | |
private boolean hidden = false; | |
private Integer experience; | |
private Path function; | |
private FrameType frame = FrameType.TASK; | |
private List<NamespacedKey> recipes = Lists.newArrayList(); | |
private List<NamespacedKey> loots = Lists.newArrayList(); | |
private List<Criteria> criteria = new ArrayList<>(); | |
private List<String> requirements = Lists.newArrayList(); | |
public Advancement(NamespacedKey id) { | |
this.id = id; | |
} | |
public Advancement icon(NamespacedKey nsk) { | |
iconMaterial = nsk; | |
return this; | |
} | |
public Advancement icon(NamespacedKey nsk, int data) { | |
iconMaterial = nsk; | |
iconData = data; | |
return this; | |
} | |
public Advancement iconData(int data) { | |
iconData = data; | |
return this; | |
} | |
public Advancement title(String title){ | |
this.title = title; | |
return this; | |
} | |
public Advancement description(String desc) { | |
description = desc; | |
return this; | |
} | |
public Advancement background(NamespacedKey nsk) { | |
background = nsk; | |
return this; | |
} | |
public Advancement frame(FrameType frame) { | |
this.frame = frame; | |
return this; | |
} | |
public Advancement announce(boolean announce) { | |
announceToChat = announce; | |
return this; | |
} | |
public Advancement toast(boolean toast) { | |
showToast = toast; | |
return this; | |
} | |
public Advancement hide(boolean hide) { | |
hidden = hide; | |
return this; | |
} | |
public Advancement experience(int experience) { | |
this.experience = experience; | |
return this; | |
} | |
public Advancement function(Path path) { | |
function = path; | |
return this; | |
} | |
public Advancement parent(NamespacedKey parent) { | |
this.parent = parent; | |
return this; | |
} | |
public Advancement setCriteria(List<Criteria> criteria) { | |
this.criteria = criteria; | |
return this; | |
} | |
public Advancement addCriteria(Criteria criteria) { | |
this.criteria.add(criteria); | |
return this; | |
} | |
public Advancement setRequirements(List<String> requirements) { | |
this.requirements = requirements; | |
return this; | |
} | |
public Advancement addRequirement(String requirement) { | |
this.requirements.add(requirement); | |
return this; | |
} | |
public Advancement setRecipes(List<NamespacedKey> recipes) { | |
this.recipes = recipes; | |
return this; | |
} | |
public Advancement addRecipe(NamespacedKey nsk) { | |
this.recipes.add(nsk); | |
return this; | |
} | |
public Advancement setLoots(List<NamespacedKey> loots) { | |
this.loots = loots; | |
return this; | |
} | |
public Advancement addLoot(NamespacedKey nsk) { | |
this.loots.add(nsk); | |
return this; | |
} | |
public org.bukkit.advancement.Advancement craft() { | |
return craft(Bukkit.getWorlds().get(0)); // Can't have a server without a world! | |
} | |
// Magic | |
public org.bukkit.advancement.Advancement craft(World... worlds) { | |
buildJson(); | |
String json = gson.toJson(advancementJson); | |
List<World> worldsList = Lists.newArrayList(worlds); | |
if(!worldsList.contains(Bukkit.getWorlds().get(0))){ | |
worldsList.add(Bukkit.getWorlds().get(0)); | |
} | |
SerializedAdvancement nms = ChatDeserializer.a(AdvancementDataWorld.DESERIALIZER, json, SerializedAdvancement.class); | |
if (nms != null) { | |
AdvancementDataWorld.REGISTRY.a(Maps.newHashMap(Collections.singletonMap(CraftNamespacedKey.toMinecraft(id), nms))); | |
for (World world : worldsList){ | |
File file = new File(world.getWorldFolder() + File.separator + "data" + File.separator + "advancements" + File.separator + id.getNamespace() + File.separator + id.getKey().replace("/", File.separator) + ".json"); | |
try { | |
file.getParentFile().mkdirs(); | |
Files.write(json, file, Charsets.UTF_8); | |
Bukkit.getLogger().info(() -> "Loading advancement " + id.toString() + " in world " + world.getName()); | |
} catch (IOException e) { | |
Bukkit.getLogger().log(Level.WARNING, "Error crafting advancement " + id.toString(), e); | |
} | |
} | |
MinecraftServer.getServer().getPlayerList().reload(); | |
} | |
return Bukkit.getAdvancement(id); | |
} | |
private void buildJson() { | |
JSONObject display = new JSONObject(); | |
JSONObject icon = new JSONObject(); | |
JSONObject criteriaObj = new JSONObject(); | |
JSONObject rewards = new JSONObject(); | |
JSONArray requirementsMasterArray = new JSONArray(); | |
JSONArray requirementsArray = new JSONArray(); | |
JSONArray recipesObj = new JSONArray(); | |
JSONArray loot = new JSONArray(); | |
icon.put("item", iconMaterial.toString()); | |
icon.put("data", iconData); | |
display.put("icon", icon); | |
display.put("title", title); | |
display.put("frame", frame.toString()); | |
if(parent == null) | |
display.put("background", background.toString()); | |
display.put("description", description); | |
display.put("show_toast", showToast); | |
display.put("announce_to_chat", announceToChat); | |
display.put("hidden", hidden); | |
advancementJson.put("display", display); | |
if(parent != null) | |
advancementJson.put("parent", parent.toString()); | |
if(criteria.isEmpty()){ | |
criteria.add(new Criteria("elytra").trigger(Triggers.IMPOSSIBLE)); | |
} | |
this.criteria.forEach(cri -> criteriaObj.put(cri.getName(), cri.toJSONObject())); | |
advancementJson.put("criteria", criteriaObj); | |
if(!requirements.isEmpty()) { | |
requirementsArray.addAll(requirements); | |
requirementsMasterArray.add(requirementsArray); | |
advancementJson.put("requirements", requirementsMasterArray); | |
} | |
if(!this.recipes.isEmpty()) { | |
recipesObj.addAll(recipes); | |
rewards.put("recipes", recipesObj); | |
} | |
if(!loots.isEmpty()) { | |
loot.addAll(loots); | |
rewards.put("loot", loot); | |
} | |
if(experience != null) | |
rewards.put("experience", experience); | |
if(function != null) | |
rewards.put("function", function.toAbsolutePath().toString()); | |
if(rewards.size() > 0) | |
advancementJson.put("rewards", rewards); | |
} | |
public NamespacedKey getId() { | |
return id; | |
} | |
public NamespacedKey getParent() { | |
return parent; | |
} | |
public NamespacedKey getIconMaterial() { | |
return iconMaterial; | |
} | |
public NamespacedKey getBackground() { | |
return background; | |
} | |
public int getIconData() { | |
return iconData; | |
} | |
public String getTitle() { | |
return title; | |
} | |
public String getDescription() { | |
return description; | |
} | |
public boolean isAnnounceToChat() { | |
return announceToChat; | |
} | |
public boolean isShowToast() { | |
return showToast; | |
} | |
public boolean isHidden() { | |
return hidden; | |
} | |
public Integer getExperience() { | |
return experience; | |
} | |
public Path getFunction() { | |
return function; | |
} | |
public FrameType getFrame() { | |
return frame; | |
} | |
public List<NamespacedKey> getRecipes() { | |
return recipes; | |
} | |
public List<NamespacedKey> getLoots() { | |
return loots; | |
} | |
public List<Criteria> getCriteria() { | |
return criteria; | |
} | |
public List<String> getRequirements() { | |
return requirements; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Advancement API | |
* Build simple minecraft 1.12 custom advancements and functions | |
* | |
* @author Sw4p | |
*/ | |
public class Condition { | |
private String key; | |
private String value; | |
private Map<String, String> conditions = Maps.newHashMap(); | |
public Condition(String key, String value) { | |
this.key = key; | |
this.value = value; | |
} | |
public Condition addCondition(Condition condition) { | |
conditions.put(condition.key, condition.value); | |
return this; | |
} | |
public JSONObject toJSONObject() { | |
JSONObject obj = new JSONObject(); | |
obj.put(key, value); | |
conditions.forEach(obj::put); | |
return obj; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Advancement API | |
* Build simple minecraft 1.12 custom advancements and functions | |
* | |
* @author Sw4p | |
*/ | |
public class Criteria { | |
private String name; | |
private Triggers trigger = Triggers.IMPOSSIBLE; | |
private Condition condition = null; | |
public Criteria(String name) { | |
this.name = name; | |
} | |
public Criteria trigger(Triggers trigger) { | |
this.trigger = trigger; | |
return this; | |
} | |
public Criteria condition(Condition condition) { | |
this.condition = condition; | |
return this; | |
} | |
public String getName() { | |
return name; | |
} | |
public JSONObject toJSONObject() { | |
JSONObject obj = new JSONObject(); | |
obj.put("trigger", trigger.toString()); | |
if(condition != null) { | |
obj.put("conditions", condition.toJSONObject()); | |
} | |
return obj; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Advancement API | |
* Build simple minecraft 1.12 custom advancements and functions | |
* | |
* @author Sw4p | |
*/ | |
public enum FrameType { | |
TASK("task"), | |
GOAL("goal"), | |
CHALLENGE("challenge"); | |
private final String name; | |
FrameType(String name){ | |
this.name = name; | |
} | |
@Override | |
public String toString(){ | |
return name; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.bukkit.NamespacedKey; | |
/** | |
* Advancement API | |
* Build simple minecraft 1.12 custom advancements and functions | |
* | |
* @author Sw4p | |
*/ | |
public enum Triggers { | |
BRED_ANIMALS("bred_animals"), | |
BREWED_POTION("brewed_potion"), | |
CHANGED_DIMENSION("bred_animals"), | |
CONSTRUCT_BEACON("construct_beacon"), | |
CONSUME_ITEM("consume_item"), | |
CURED_ZOMBIE_VILLAGER("cured_zombie_villager"), | |
EFFECTS_CHANGED("effects_changed"), | |
ENCHANTED_ITEM("enchanted_item"), | |
ENTER_BLOCK("enter_block"), | |
ENTITY_HURT_PLAYER("entity_hurt_player"), | |
ENTITY_KILLED_PLAYER("entity_killed_player"), | |
IMPOSSIBLE("impossible"), | |
INVENTORY_CHANGED("inventory_changed"), | |
ITEM_DURABILITY_CHANGED("item_durability_changed"), | |
LEVITATION("levitation"), | |
LOCATION("location"), | |
NETHER_TRAVEL("nether_travel"), | |
PLACED_BLOCK("placed_block"), | |
PLAYER_HURT_ENTITY("player_hurt_entity"), | |
PLAYER_KILLED_ENTITY("player_killed_entity"), | |
RECIPE_UNLOCKED("recipe_unlocked"), | |
SELPT_IN_BED("slept_in_bed"), | |
SUMMONED_ENTITY("summoned_entity"), | |
TAME_ANIMAL("tame_animal"), | |
TICK("tick"), | |
USED_ENDER_EYE("used_ender_eye"), | |
USED_TOTEM("used_totem"), | |
VILLAGER_TRADE("villager_trade"); | |
String trigger; | |
Triggers(String trigger) { | |
this.trigger = trigger; | |
} | |
@Override | |
public String toString() { | |
return NamespacedKey.minecraft(trigger).toString(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment