Skip to content

Instantly share code, notes, and snippets.

@mcSw4p
Created March 20, 2018 23:05
Show Gist options
  • Save mcSw4p/3b2501bca4d0ed2f12cf3e9ab24ccc11 to your computer and use it in GitHub Desktop.
Save mcSw4p/3b2501bca4d0ed2f12cf3e9ab24ccc11 to your computer and use it in GitHub Desktop.
Minecraft 1.12 Advancement API
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;
}
}
/**
* 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;
}
}
/**
* 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;
}
}
/**
* 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;
}
}
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