use of com.minecolonies.coremod.research.GlobalResearch in project minecolonies by ldtteam.
the class ResearchListener method apply.
@Override
protected void apply(@NotNull final Map<ResourceLocation, JsonElement> object, @NotNull final IResourceManager resourceManagerIn, @NotNull final IProfiler profilerIn) {
Log.getLogger().info("Beginning load of research for University.");
// First, index and map out all research effects. We need to be able to map them before creating Researches themselves.
// Because data packs, can't assume effects are in one specific location.
// For now, we'll populate relative levels when doing so, but we probably want to do that dynamically.
final Map<ResourceLocation, ResearchEffectCategory> effectCategories = parseResearchEffects(object);
// We /shouldn't/ get any removes before the Research they're trying to remove exists,
// but it can happen if multiple data packs affect each other.
// Instead, get lists of research locations for researches and branches to not load and quit their parsing early.
final Tuple<Collection<ResourceLocation>, Collection<ResourceLocation>> removeResearchesAndBranches = parseRemoveResearches(object);
// Next, populate a new map of IGlobalResearches, identified by researchID.
// This allows us to figure out root/branch relationships more sanely.
// We need the effectCategories and levels to do this.
MinecraftServer server = ServerLifecycleHooks.getCurrentServer();
final Map<ResourceLocation, GlobalResearch> researchMap = parseResearches(object, effectCategories, removeResearchesAndBranches.getA(), removeResearchesAndBranches.getB(), !(server instanceof DedicatedServer));
// After we've loaded all researches, we can then try to assign child relationships.
// This is also the phase where we'd try to support back-calculating university levels for researches without them/with incorrect ones.
final IGlobalResearchTree researchTree = calcResearchTree(researchMap);
// Finally, check for branch-specific settings -- these are optional and only apply to the IGlobalResearchTree.
parseResearchBranches(object, researchTree);
Log.getLogger().info("Loaded " + researchMap.values().size() + " recipes for " + researchTree.getBranches().size() + " research branches");
// We only need to send to players during a data pack reload event during live play.
if (server != null) {
for (ServerPlayerEntity player : server.getPlayerList().getPlayers()) {
researchTree.sendGlobalResearchTreePackets(player);
}
}
}
use of com.minecolonies.coremod.research.GlobalResearch in project minecolonies by Minecolonies.
the class ResearchListener method calcResearchTree.
/**
* Parses out a GlobalResearch map to apply parent/child relationships between researches, and to graft and warn about inconsistent relationships.
*
* @param researchMap A Map of ResearchIDs to GlobalResearches to turn into a GlobalResearchTree.
* @return An IGlobalResearchTree containing the validated researches.
*/
private IGlobalResearchTree calcResearchTree(final Map<ResourceLocation, GlobalResearch> researchMap) {
final IGlobalResearchTree researchTree = MinecoloniesAPIProxy.getInstance().getGlobalResearchTree();
// The research tree should be reset on world unload, but certain events and disconnects break that. Do it here, too.
researchTree.reset();
// Next, set up child relationships, and handle cases where they're not logically consistent.
for (final Map.Entry<ResourceLocation, GlobalResearch> entry : researchMap.entrySet()) {
if (entry.getValue().getParent().getPath().isEmpty() && entry.getValue().getDepth() > 1) {
// For now, log and re-graft entries with no parent and depth to the root of their branch.
entry.setValue(new GlobalResearch(entry.getValue().getId(), entry.getValue().getBranch(), 1, entry.getValue().getEffects(), entry.getValue().getIconTextureResourceLocation(), entry.getValue().getIconItemStack(), entry.getValue().isImmutable()));
Log.getLogger().error(entry.getValue().getBranch() + "/" + entry.getKey() + "could not be attached to tree: inconsistent depth for parentage.");
} else if (!entry.getValue().getParent().getPath().isEmpty()) {
if (researchMap.containsKey(entry.getValue().getParent())) {
if (researchMap.get(entry.getValue().getParent()).getBranch().equals(entry.getValue().getBranch())) {
researchMap.get(entry.getValue().getParent()).addChild(entry.getValue());
} else {
Log.getLogger().error(entry.getValue().getBranch() + "/" + entry.getKey() + "could not be attached to " + entry.getValue().getParent() + " on " + researchMap.get(entry.getValue().getParent()).getBranch());
// For now, log and re-graft entries with inconsistent parent-child relationships as a separate primary research.
entry.setValue(new GlobalResearch(entry.getValue().getId(), entry.getValue().getBranch(), 1, entry.getValue().getEffects(), entry.getValue().getIconTextureResourceLocation(), entry.getValue().getIconItemStack(), entry.getValue().isImmutable()));
}
} else {
Log.getLogger().error(entry.getValue().getBranch() + "/" + entry.getKey() + " could not find parent " + entry.getValue().getParent());
// For now, log and re-graft entries with inconsistent parent-child relationships as a separate primary research.
entry.setValue(new GlobalResearch(entry.getValue().getId(), entry.getValue().getBranch(), 1, entry.getValue().getEffects(), entry.getValue().getIconTextureResourceLocation(), entry.getValue().getIconItemStack(), entry.getValue().isImmutable()));
}
}
researchTree.addResearch(entry.getValue().getBranch(), entry.getValue(), true);
}
return researchTree;
}
use of com.minecolonies.coremod.research.GlobalResearch in project minecolonies by Minecolonies.
the class ResearchListener method apply.
@Override
protected void apply(@NotNull final Map<ResourceLocation, JsonElement> object, @NotNull final IResourceManager resourceManagerIn, @NotNull final IProfiler profilerIn) {
Log.getLogger().info("Beginning load of research for University.");
// First, index and map out all research effects. We need to be able to map them before creating Researches themselves.
// Because data packs, can't assume effects are in one specific location.
// For now, we'll populate relative levels when doing so, but we probably want to do that dynamically.
final Map<ResourceLocation, ResearchEffectCategory> effectCategories = parseResearchEffects(object);
// We /shouldn't/ get any removes before the Research they're trying to remove exists,
// but it can happen if multiple data packs affect each other.
// Instead, get lists of research locations for researches and branches to not load and quit their parsing early.
final Tuple<Collection<ResourceLocation>, Collection<ResourceLocation>> removeResearchesAndBranches = parseRemoveResearches(object);
// Next, populate a new map of IGlobalResearches, identified by researchID.
// This allows us to figure out root/branch relationships more sanely.
// We need the effectCategories and levels to do this.
MinecraftServer server = ServerLifecycleHooks.getCurrentServer();
final Map<ResourceLocation, GlobalResearch> researchMap = parseResearches(object, effectCategories, removeResearchesAndBranches.getA(), removeResearchesAndBranches.getB(), !(server instanceof DedicatedServer));
// After we've loaded all researches, we can then try to assign child relationships.
// This is also the phase where we'd try to support back-calculating university levels for researches without them/with incorrect ones.
final IGlobalResearchTree researchTree = calcResearchTree(researchMap);
// Finally, check for branch-specific settings -- these are optional and only apply to the IGlobalResearchTree.
parseResearchBranches(object, researchTree);
Log.getLogger().info("Loaded " + researchMap.values().size() + " recipes for " + researchTree.getBranches().size() + " research branches");
// We only need to send to players during a data pack reload event during live play.
if (server != null) {
for (ServerPlayerEntity player : server.getPlayerList().getPlayers()) {
researchTree.sendGlobalResearchTreePackets(player);
}
}
}
use of com.minecolonies.coremod.research.GlobalResearch in project minecolonies by Minecolonies.
the class ResearchListener method parseResearches.
/**
* Parses out a json map for elements containing Researches, validates that they have required fields, and generates a GlobalResearch for each.
*
* @param object A Map containing the resource location of each json file, and the element within that json file.
* @param effectCategories A Map containing the effect categories by effectId.
* @param removeResearches A Collection of researches to remove, if present.
* @param removeBranches A Collection of research branches to remove, including all component researches, if present.
* @param checkResourceLoc If the client should check resource locations at the time. This can not be run on the server.
* @return A Map containing the ResearchIds and the GlobalResearches each ID corresponds to.
*/
private Map<ResourceLocation, GlobalResearch> parseResearches(final Map<ResourceLocation, JsonElement> object, final Map<ResourceLocation, ResearchEffectCategory> effectCategories, final Collection<ResourceLocation> removeResearches, final Collection<ResourceLocation> removeBranches, boolean checkResourceLoc) {
final Map<ResourceLocation, GlobalResearch> researchMap = new HashMap<>();
for (final Map.Entry<ResourceLocation, JsonElement> entry : object.entrySet()) {
// Cancel removed individual researches first, to save parsing time.
if (removeResearches.contains(entry.getKey())) {
if (MinecoloniesAPIProxy.getInstance().getConfig().getServer().researchDebugLog.get()) {
Log.getLogger().info(entry.getKey() + " was removed by data pack.");
}
continue;
}
// Note that we don't actually use the resource folders or file names; those are only for organization purposes.
final JsonObject researchJson = entry.getValue().getAsJsonObject();
// Can ignore those effects json now:
if (researchJson.has(RESEARCH_EFFECT_PROP)) {
continue;
}
// Next, check for remove-type recipes. We don't want to accidentally add them just because they have too much detail.
if (researchJson.has(RESEARCH_REMOVE_PROP) && researchJson.get(RESEARCH_REMOVE_PROP).getAsJsonPrimitive().isString()) {
continue;
}
// And same for research-branch-specific settings, to avoid extraneous warnings.
if (researchJson.has(RESEARCH_BRANCH_NAME_PROP) || researchJson.has(RESEARCH_BASE_TIME_PROP) || researchJson.has(RESEARCH_BRANCH_TYPE_PROP)) {
continue;
}
// Check for absolute minimum required types, and log as warning if malformed.
if (!(researchJson.has(RESEARCH_BRANCH_PROP) && researchJson.get(RESEARCH_BRANCH_PROP).isJsonPrimitive() && researchJson.get(RESEARCH_BRANCH_PROP).getAsJsonPrimitive().isString())) {
if (MinecoloniesAPIProxy.getInstance().getConfig().getServer().researchDebugLog.get()) {
Log.getLogger().warn(entry.getKey() + " is a Research , but does not contain all required fields. Researches must have a branch:string properties.");
}
continue;
} else // Now that we've confirmed a branch exists at all, cancel the add if it's from a removed branch.
if (removeBranches.contains(new ResourceLocation(researchJson.get(RESEARCH_BRANCH_PROP).getAsString()))) {
if (MinecoloniesAPIProxy.getInstance().getConfig().getServer().researchDebugLog.get()) {
Log.getLogger().info(entry.getKey() + " was removed, as its branch had been removed by data pack.");
}
continue;
}
// Missing university level data may not necessarily be a show-stopper, but it is worth warning about.
if (MinecoloniesAPIProxy.getInstance().getConfig().getServer().researchDebugLog.get() && !(researchJson.has(RESEARCH_UNIVERSITY_LEVEL_PROP) && researchJson.get(RESEARCH_UNIVERSITY_LEVEL_PROP).getAsJsonPrimitive().isNumber())) {
Log.getLogger().warn(entry.getKey() + " is a Research, but has invalid or no university level requirements.");
}
// Pretty much anything else should be allowed: it's plausible pack designers may want a research type without a cost or effect.
// It's possible we could dynamically derive university levels from parents, but doing so as a rule will prevent research branches that start at T2 or deeper.
final GlobalResearch research = new GlobalResearch(researchJson, entry.getKey(), effectCategories, checkResourceLoc);
if (MinecoloniesAPIProxy.getInstance().getConfig().getServer().researchDebugLog.get()) {
Log.getLogger().info("Parsed research recipe from " + entry.getKey() + " [" + research.getBranch() + "/" + research.getId() + "]");
Log.getLogger().info(research.getName() + " at " + research.getDepth() + "/" + research.getParent());
for (IResearchRequirement requirement : research.getResearchRequirement()) {
Log.getLogger().info("Requirement: " + requirement.getDesc());
}
for (ItemStorage itemS : research.getCostList()) {
Log.getLogger().info("Cost: " + itemS.toString());
}
for (IResearchEffect<?> researchEffect : research.getEffects()) {
Log.getLogger().info("Effect: " + researchEffect.getId() + " " + researchEffect.getDesc());
}
}
researchMap.put(research.getId(), research);
}
return researchMap;
}
use of com.minecolonies.coremod.research.GlobalResearch in project minecolonies by ldtteam.
the class ResearchListener method parseResearches.
/**
* Parses out a json map for elements containing Researches, validates that they have required fields, and generates a GlobalResearch for each.
*
* @param object A Map containing the resource location of each json file, and the element within that json file.
* @param effectCategories A Map containing the effect categories by effectId.
* @param removeResearches A Collection of researches to remove, if present.
* @param removeBranches A Collection of research branches to remove, including all component researches, if present.
* @param checkResourceLoc If the client should check resource locations at the time. This can not be run on the server.
* @return A Map containing the ResearchIds and the GlobalResearches each ID corresponds to.
*/
private Map<ResourceLocation, GlobalResearch> parseResearches(final Map<ResourceLocation, JsonElement> object, final Map<ResourceLocation, ResearchEffectCategory> effectCategories, final Collection<ResourceLocation> removeResearches, final Collection<ResourceLocation> removeBranches, boolean checkResourceLoc) {
final Map<ResourceLocation, GlobalResearch> researchMap = new HashMap<>();
for (final Map.Entry<ResourceLocation, JsonElement> entry : object.entrySet()) {
// Cancel removed individual researches first, to save parsing time.
if (removeResearches.contains(entry.getKey())) {
if (MinecoloniesAPIProxy.getInstance().getConfig().getServer().researchDebugLog.get()) {
Log.getLogger().info(entry.getKey() + " was removed by data pack.");
}
continue;
}
// Note that we don't actually use the resource folders or file names; those are only for organization purposes.
final JsonObject researchJson = entry.getValue().getAsJsonObject();
// Can ignore those effects json now:
if (researchJson.has(RESEARCH_EFFECT_PROP)) {
continue;
}
// Next, check for remove-type recipes. We don't want to accidentally add them just because they have too much detail.
if (researchJson.has(RESEARCH_REMOVE_PROP) && researchJson.get(RESEARCH_REMOVE_PROP).getAsJsonPrimitive().isString()) {
continue;
}
// And same for research-branch-specific settings, to avoid extraneous warnings.
if (researchJson.has(RESEARCH_BRANCH_NAME_PROP) || researchJson.has(RESEARCH_BASE_TIME_PROP) || researchJson.has(RESEARCH_BRANCH_TYPE_PROP)) {
continue;
}
// Check for absolute minimum required types, and log as warning if malformed.
if (!(researchJson.has(RESEARCH_BRANCH_PROP) && researchJson.get(RESEARCH_BRANCH_PROP).isJsonPrimitive() && researchJson.get(RESEARCH_BRANCH_PROP).getAsJsonPrimitive().isString())) {
if (MinecoloniesAPIProxy.getInstance().getConfig().getServer().researchDebugLog.get()) {
Log.getLogger().warn(entry.getKey() + " is a Research , but does not contain all required fields. Researches must have a branch:string properties.");
}
continue;
} else // Now that we've confirmed a branch exists at all, cancel the add if it's from a removed branch.
if (removeBranches.contains(new ResourceLocation(researchJson.get(RESEARCH_BRANCH_PROP).getAsString()))) {
if (MinecoloniesAPIProxy.getInstance().getConfig().getServer().researchDebugLog.get()) {
Log.getLogger().info(entry.getKey() + " was removed, as its branch had been removed by data pack.");
}
continue;
}
// Missing university level data may not necessarily be a show-stopper, but it is worth warning about.
if (MinecoloniesAPIProxy.getInstance().getConfig().getServer().researchDebugLog.get() && !(researchJson.has(RESEARCH_UNIVERSITY_LEVEL_PROP) && researchJson.get(RESEARCH_UNIVERSITY_LEVEL_PROP).getAsJsonPrimitive().isNumber())) {
Log.getLogger().warn(entry.getKey() + " is a Research, but has invalid or no university level requirements.");
}
// Pretty much anything else should be allowed: it's plausible pack designers may want a research type without a cost or effect.
// It's possible we could dynamically derive university levels from parents, but doing so as a rule will prevent research branches that start at T2 or deeper.
final GlobalResearch research = new GlobalResearch(researchJson, entry.getKey(), effectCategories, checkResourceLoc);
if (MinecoloniesAPIProxy.getInstance().getConfig().getServer().researchDebugLog.get()) {
Log.getLogger().info("Parsed research recipe from " + entry.getKey() + " [" + research.getBranch() + "/" + research.getId() + "]");
Log.getLogger().info(research.getName() + " at " + research.getDepth() + "/" + research.getParent());
for (IResearchRequirement requirement : research.getResearchRequirement()) {
Log.getLogger().info("Requirement: " + requirement.getDesc());
}
for (ItemStorage itemS : research.getCostList()) {
Log.getLogger().info("Cost: " + itemS.toString());
}
for (IResearchEffect<?> researchEffect : research.getEffects()) {
Log.getLogger().info("Effect: " + researchEffect.getId() + " " + researchEffect.getDesc());
}
}
researchMap.put(research.getId(), research);
}
return researchMap;
}
Aggregations