Initial Commit
This commit is contained in:
1 parent
377b32db6e
commit
2d9a5eecba
14134 files changed
+1160982
No files matched your search
+100
@@ -0,0 +1,100 @@
|
||||
package net.minecraft.stats;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.inventory.RecipeBookMenu;
|
||||
import net.minecraft.world.inventory.RecipeBookType;
|
||||
import net.minecraft.world.item.crafting.Recipe;
|
||||
|
||||
public class RecipeBook {
|
||||
protected final Set<ResourceLocation> known = Sets.newHashSet();
|
||||
protected final Set<ResourceLocation> highlight = Sets.newHashSet();
|
||||
private final RecipeBookSettings bookSettings = new RecipeBookSettings();
|
||||
|
||||
public void copyOverData(RecipeBook pOther) {
|
||||
this.known.clear();
|
||||
this.highlight.clear();
|
||||
this.bookSettings.replaceFrom(pOther.bookSettings);
|
||||
this.known.addAll(pOther.known);
|
||||
this.highlight.addAll(pOther.highlight);
|
||||
}
|
||||
|
||||
public void add(Recipe<?> pRecipe) {
|
||||
if (!pRecipe.isSpecial()) {
|
||||
this.add(pRecipe.getId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void add(ResourceLocation pRecipeId) {
|
||||
this.known.add(pRecipeId);
|
||||
}
|
||||
|
||||
public boolean contains(@Nullable Recipe<?> pRecipe) {
|
||||
return pRecipe == null ? false : this.known.contains(pRecipe.getId());
|
||||
}
|
||||
|
||||
public boolean contains(ResourceLocation pRecipeId) {
|
||||
return this.known.contains(pRecipeId);
|
||||
}
|
||||
|
||||
public void remove(Recipe<?> pRecipe) {
|
||||
this.remove(pRecipe.getId());
|
||||
}
|
||||
|
||||
protected void remove(ResourceLocation pRecipeId) {
|
||||
this.known.remove(pRecipeId);
|
||||
this.highlight.remove(pRecipeId);
|
||||
}
|
||||
|
||||
public boolean willHighlight(Recipe<?> pRecipe) {
|
||||
return this.highlight.contains(pRecipe.getId());
|
||||
}
|
||||
|
||||
public void removeHighlight(Recipe<?> pRecipe) {
|
||||
this.highlight.remove(pRecipe.getId());
|
||||
}
|
||||
|
||||
public void addHighlight(Recipe<?> pRecipe) {
|
||||
this.addHighlight(pRecipe.getId());
|
||||
}
|
||||
|
||||
protected void addHighlight(ResourceLocation pRecipeId) {
|
||||
this.highlight.add(pRecipeId);
|
||||
}
|
||||
|
||||
public boolean isOpen(RecipeBookType pBookType) {
|
||||
return this.bookSettings.isOpen(pBookType);
|
||||
}
|
||||
|
||||
public void setOpen(RecipeBookType pBookType, boolean pOpen) {
|
||||
this.bookSettings.setOpen(pBookType, pOpen);
|
||||
}
|
||||
|
||||
public boolean isFiltering(RecipeBookMenu<?> pBookMenu) {
|
||||
return this.isFiltering(pBookMenu.getRecipeBookType());
|
||||
}
|
||||
|
||||
public boolean isFiltering(RecipeBookType pBookType) {
|
||||
return this.bookSettings.isFiltering(pBookType);
|
||||
}
|
||||
|
||||
public void setFiltering(RecipeBookType pBookType, boolean pFiltering) {
|
||||
this.bookSettings.setFiltering(pBookType, pFiltering);
|
||||
}
|
||||
|
||||
public void setBookSettings(RecipeBookSettings pSettings) {
|
||||
this.bookSettings.replaceFrom(pSettings);
|
||||
}
|
||||
|
||||
public RecipeBookSettings getBookSettings() {
|
||||
return this.bookSettings.copy();
|
||||
}
|
||||
|
||||
public void setBookSetting(RecipeBookType pBookType, boolean pOpen, boolean pFiltering) {
|
||||
this.bookSettings.setOpen(pBookType, pOpen);
|
||||
this.bookSettings.setFiltering(pBookType, pFiltering);
|
||||
}
|
||||
}
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
package net.minecraft.stats;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import java.util.Map;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.inventory.RecipeBookType;
|
||||
|
||||
public final class RecipeBookSettings {
|
||||
private static final Map<RecipeBookType, Pair<String, String>> TAG_FIELDS = new java.util.HashMap<>(ImmutableMap.of(RecipeBookType.CRAFTING, Pair.of("isGuiOpen", "isFilteringCraftable"), RecipeBookType.FURNACE, Pair.of("isFurnaceGuiOpen", "isFurnaceFilteringCraftable"), RecipeBookType.BLAST_FURNACE, Pair.of("isBlastingFurnaceGuiOpen", "isBlastingFurnaceFilteringCraftable"), RecipeBookType.SMOKER, Pair.of("isSmokerGuiOpen", "isSmokerFilteringCraftable")));
|
||||
private final Map<RecipeBookType, RecipeBookSettings.TypeSettings> states;
|
||||
|
||||
private RecipeBookSettings(Map<RecipeBookType, RecipeBookSettings.TypeSettings> pStates) {
|
||||
this.states = pStates;
|
||||
}
|
||||
|
||||
public RecipeBookSettings() {
|
||||
this(Util.make(Maps.newEnumMap(RecipeBookType.class), (p_12740_) -> {
|
||||
for(RecipeBookType recipebooktype : RecipeBookType.values()) {
|
||||
p_12740_.put(recipebooktype, new RecipeBookSettings.TypeSettings(false, false));
|
||||
}
|
||||
|
||||
}));
|
||||
}
|
||||
|
||||
public boolean isOpen(RecipeBookType pBookType) {
|
||||
return (this.states.get(pBookType)).open;
|
||||
}
|
||||
|
||||
public void setOpen(RecipeBookType pBookType, boolean pOpen) {
|
||||
(this.states.get(pBookType)).open = pOpen;
|
||||
}
|
||||
|
||||
public boolean isFiltering(RecipeBookType pBookType) {
|
||||
return (this.states.get(pBookType)).filtering;
|
||||
}
|
||||
|
||||
public void setFiltering(RecipeBookType pBookType, boolean pFiltering) {
|
||||
(this.states.get(pBookType)).filtering = pFiltering;
|
||||
}
|
||||
|
||||
public static RecipeBookSettings read(FriendlyByteBuf pBuffer) {
|
||||
Map<RecipeBookType, RecipeBookSettings.TypeSettings> map = Maps.newEnumMap(RecipeBookType.class);
|
||||
|
||||
for(RecipeBookType recipebooktype : RecipeBookType.values()) {
|
||||
boolean flag = pBuffer.readBoolean();
|
||||
boolean flag1 = pBuffer.readBoolean();
|
||||
map.put(recipebooktype, new RecipeBookSettings.TypeSettings(flag, flag1));
|
||||
}
|
||||
|
||||
return new RecipeBookSettings(map);
|
||||
}
|
||||
|
||||
public void write(FriendlyByteBuf pBuffer) {
|
||||
for(RecipeBookType recipebooktype : RecipeBookType.values()) {
|
||||
RecipeBookSettings.TypeSettings recipebooksettings$typesettings = this.states.get(recipebooktype);
|
||||
if (recipebooksettings$typesettings == null) {
|
||||
pBuffer.writeBoolean(false);
|
||||
pBuffer.writeBoolean(false);
|
||||
} else {
|
||||
pBuffer.writeBoolean(recipebooksettings$typesettings.open);
|
||||
pBuffer.writeBoolean(recipebooksettings$typesettings.filtering);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static RecipeBookSettings read(CompoundTag pTag) {
|
||||
Map<RecipeBookType, RecipeBookSettings.TypeSettings> map = Maps.newEnumMap(RecipeBookType.class);
|
||||
TAG_FIELDS.forEach((p_12750_, p_12751_) -> {
|
||||
boolean flag = pTag.getBoolean(p_12751_.getFirst());
|
||||
boolean flag1 = pTag.getBoolean(p_12751_.getSecond());
|
||||
map.put(p_12750_, new RecipeBookSettings.TypeSettings(flag, flag1));
|
||||
});
|
||||
return new RecipeBookSettings(map);
|
||||
}
|
||||
|
||||
public void write(CompoundTag pTag) {
|
||||
TAG_FIELDS.forEach((p_12745_, p_12746_) -> {
|
||||
RecipeBookSettings.TypeSettings recipebooksettings$typesettings = this.states.get(p_12745_);
|
||||
pTag.putBoolean(p_12746_.getFirst(), recipebooksettings$typesettings.open);
|
||||
pTag.putBoolean(p_12746_.getSecond(), recipebooksettings$typesettings.filtering);
|
||||
});
|
||||
}
|
||||
|
||||
public RecipeBookSettings copy() {
|
||||
Map<RecipeBookType, RecipeBookSettings.TypeSettings> map = Maps.newEnumMap(RecipeBookType.class);
|
||||
|
||||
for(RecipeBookType recipebooktype : RecipeBookType.values()) {
|
||||
RecipeBookSettings.TypeSettings recipebooksettings$typesettings = this.states.get(recipebooktype);
|
||||
map.put(recipebooktype, recipebooksettings$typesettings.copy());
|
||||
}
|
||||
|
||||
return new RecipeBookSettings(map);
|
||||
}
|
||||
|
||||
public void replaceFrom(RecipeBookSettings pOther) {
|
||||
this.states.clear();
|
||||
|
||||
for(RecipeBookType recipebooktype : RecipeBookType.values()) {
|
||||
RecipeBookSettings.TypeSettings recipebooksettings$typesettings = pOther.states.get(recipebooktype);
|
||||
this.states.put(recipebooktype, recipebooksettings$typesettings.copy());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean equals(Object pOther) {
|
||||
return this == pOther || pOther instanceof RecipeBookSettings && this.states.equals(((RecipeBookSettings)pOther).states);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.states.hashCode();
|
||||
}
|
||||
|
||||
static final class TypeSettings {
|
||||
boolean open;
|
||||
boolean filtering;
|
||||
|
||||
public TypeSettings(boolean pOpen, boolean pFiltering) {
|
||||
this.open = pOpen;
|
||||
this.filtering = pFiltering;
|
||||
}
|
||||
|
||||
public RecipeBookSettings.TypeSettings copy() {
|
||||
return new RecipeBookSettings.TypeSettings(this.open, this.filtering);
|
||||
}
|
||||
|
||||
public boolean equals(Object pOther) {
|
||||
if (this == pOther) {
|
||||
return true;
|
||||
} else if (!(pOther instanceof RecipeBookSettings.TypeSettings)) {
|
||||
return false;
|
||||
} else {
|
||||
RecipeBookSettings.TypeSettings recipebooksettings$typesettings = (RecipeBookSettings.TypeSettings)pOther;
|
||||
return this.open == recipebooksettings$typesettings.open && this.filtering == recipebooksettings$typesettings.filtering;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int i = this.open ? 1 : 0;
|
||||
return 31 * i + (this.filtering ? 1 : 0);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "[open=" + this.open + ", filtering=" + this.filtering + "]";
|
||||
}
|
||||
}
|
||||
//FORGE -- called automatically on Enum creation - used for serialization
|
||||
public static void addTagsForType(RecipeBookType type, String openTag, String filteringTag) {
|
||||
TAG_FIELDS.put(type, Pair.of(openTag, filteringTag));
|
||||
}
|
||||
}
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
package net.minecraft.stats;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import net.minecraft.ResourceLocationException;
|
||||
import net.minecraft.advancements.CriteriaTriggers;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.StringTag;
|
||||
import net.minecraft.network.protocol.game.ClientboundRecipePacket;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.item.crafting.Recipe;
|
||||
import net.minecraft.world.item.crafting.RecipeManager;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public class ServerRecipeBook extends RecipeBook {
|
||||
public static final String RECIPE_BOOK_TAG = "recipeBook";
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
public int addRecipes(Collection<Recipe<?>> pRecipes, ServerPlayer pPlayer) {
|
||||
List<ResourceLocation> list = Lists.newArrayList();
|
||||
int i = 0;
|
||||
|
||||
for(Recipe<?> recipe : pRecipes) {
|
||||
ResourceLocation resourcelocation = recipe.getId();
|
||||
if (!this.known.contains(resourcelocation) && !recipe.isSpecial()) {
|
||||
this.add(resourcelocation);
|
||||
this.addHighlight(resourcelocation);
|
||||
list.add(resourcelocation);
|
||||
CriteriaTriggers.RECIPE_UNLOCKED.trigger(pPlayer, recipe);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
if (list.size() > 0) {
|
||||
this.sendRecipes(ClientboundRecipePacket.State.ADD, pPlayer, list);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
public int removeRecipes(Collection<Recipe<?>> pRecipes, ServerPlayer pPlayer) {
|
||||
List<ResourceLocation> list = Lists.newArrayList();
|
||||
int i = 0;
|
||||
|
||||
for(Recipe<?> recipe : pRecipes) {
|
||||
ResourceLocation resourcelocation = recipe.getId();
|
||||
if (this.known.contains(resourcelocation)) {
|
||||
this.remove(resourcelocation);
|
||||
list.add(resourcelocation);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
this.sendRecipes(ClientboundRecipePacket.State.REMOVE, pPlayer, list);
|
||||
return i;
|
||||
}
|
||||
|
||||
private void sendRecipes(ClientboundRecipePacket.State pState, ServerPlayer pPlayer, List<ResourceLocation> pRecipes) {
|
||||
pPlayer.connection.send(new ClientboundRecipePacket(pState, pRecipes, Collections.emptyList(), this.getBookSettings()));
|
||||
}
|
||||
|
||||
public CompoundTag toNbt() {
|
||||
CompoundTag compoundtag = new CompoundTag();
|
||||
this.getBookSettings().write(compoundtag);
|
||||
ListTag listtag = new ListTag();
|
||||
|
||||
for(ResourceLocation resourcelocation : this.known) {
|
||||
listtag.add(StringTag.valueOf(resourcelocation.toString()));
|
||||
}
|
||||
|
||||
compoundtag.put("recipes", listtag);
|
||||
ListTag listtag1 = new ListTag();
|
||||
|
||||
for(ResourceLocation resourcelocation1 : this.highlight) {
|
||||
listtag1.add(StringTag.valueOf(resourcelocation1.toString()));
|
||||
}
|
||||
|
||||
compoundtag.put("toBeDisplayed", listtag1);
|
||||
return compoundtag;
|
||||
}
|
||||
|
||||
public void fromNbt(CompoundTag pTag, RecipeManager pRecipeManager) {
|
||||
this.setBookSettings(RecipeBookSettings.read(pTag));
|
||||
ListTag listtag = pTag.getList("recipes", 8);
|
||||
this.loadRecipes(listtag, this::add, pRecipeManager);
|
||||
ListTag listtag1 = pTag.getList("toBeDisplayed", 8);
|
||||
this.loadRecipes(listtag1, this::addHighlight, pRecipeManager);
|
||||
}
|
||||
|
||||
private void loadRecipes(ListTag pTags, Consumer<Recipe<?>> pRecipeConsumer, RecipeManager pRecipeManager) {
|
||||
for(int i = 0; i < pTags.size(); ++i) {
|
||||
String s = pTags.getString(i);
|
||||
|
||||
try {
|
||||
ResourceLocation resourcelocation = new ResourceLocation(s);
|
||||
Optional<? extends Recipe<?>> optional = pRecipeManager.byKey(resourcelocation);
|
||||
if (!optional.isPresent()) {
|
||||
LOGGER.error("Tried to load unrecognized recipe: {} removed now.", (Object)resourcelocation);
|
||||
} else {
|
||||
pRecipeConsumer.accept(optional.get());
|
||||
}
|
||||
} catch (ResourceLocationException resourcelocationexception) {
|
||||
LOGGER.error("Tried to load improperly formatted recipe: {} removed now.", (Object)s);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void sendInitialRecipeBook(ServerPlayer pPlayer) {
|
||||
pPlayer.connection.send(new ClientboundRecipePacket(ClientboundRecipePacket.State.INIT, this.known, this.highlight, this.getBookSettings()));
|
||||
}
|
||||
}
|
||||
+190
@@ -0,0 +1,190 @@
|
||||
package net.minecraft.stats;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.internal.Streams;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.mojang.datafixers.DataFixer;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.network.protocol.game.ClientboundAwardStatsPacket;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.datafix.DataFixTypes;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
/**
|
||||
* Server-side implementation of {@link net.minecraft.stats.StatsCounter}; handles counting, serialising, and de-
|
||||
* serialising statistics, as well as sending them to connected clients via the {@linkplain
|
||||
* net.minecraft.network.protocol.game.ClientboundAwardStatsPacket award stats packet}.
|
||||
*/
|
||||
public class ServerStatsCounter extends StatsCounter {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private final MinecraftServer server;
|
||||
private final File file;
|
||||
private final Set<Stat<?>> dirty = Sets.newHashSet();
|
||||
|
||||
public ServerStatsCounter(MinecraftServer pServer, File pFile) {
|
||||
this.server = pServer;
|
||||
this.file = pFile;
|
||||
if (pFile.isFile()) {
|
||||
try {
|
||||
this.parseLocal(pServer.getFixerUpper(), FileUtils.readFileToString(pFile));
|
||||
} catch (IOException ioexception) {
|
||||
LOGGER.error("Couldn't read statistics file {}", pFile, ioexception);
|
||||
} catch (JsonParseException jsonparseexception) {
|
||||
LOGGER.error("Couldn't parse statistics file {}", pFile, jsonparseexception);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void save() {
|
||||
try {
|
||||
FileUtils.writeStringToFile(this.file, this.toJson());
|
||||
} catch (IOException ioexception) {
|
||||
LOGGER.error("Couldn't save stats", (Throwable)ioexception);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setValue(Player pPlayer, Stat<?> pStat, int pValue) {
|
||||
super.setValue(pPlayer, pStat, pValue);
|
||||
this.dirty.add(pStat);
|
||||
}
|
||||
|
||||
private Set<Stat<?>> getDirty() {
|
||||
Set<Stat<?>> set = Sets.newHashSet(this.dirty);
|
||||
this.dirty.clear();
|
||||
return set;
|
||||
}
|
||||
|
||||
public void parseLocal(DataFixer pFixerUpper, String pJson) {
|
||||
try {
|
||||
try (JsonReader jsonreader = new JsonReader(new StringReader(pJson))) {
|
||||
jsonreader.setLenient(false);
|
||||
JsonElement jsonelement = Streams.parse(jsonreader);
|
||||
if (!jsonelement.isJsonNull()) {
|
||||
CompoundTag compoundtag = fromJson(jsonelement.getAsJsonObject());
|
||||
compoundtag = DataFixTypes.STATS.updateToCurrentVersion(pFixerUpper, compoundtag, NbtUtils.getDataVersion(compoundtag, 1343));
|
||||
if (!compoundtag.contains("stats", 10)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CompoundTag compoundtag1 = compoundtag.getCompound("stats");
|
||||
|
||||
for(String s : compoundtag1.getAllKeys()) {
|
||||
if (compoundtag1.contains(s, 10)) {
|
||||
Util.ifElse(BuiltInRegistries.STAT_TYPE.getOptional(new ResourceLocation(s)), (p_12844_) -> {
|
||||
CompoundTag compoundtag2 = compoundtag1.getCompound(s);
|
||||
|
||||
for(String s1 : compoundtag2.getAllKeys()) {
|
||||
if (compoundtag2.contains(s1, 99)) {
|
||||
Util.ifElse(this.getStat(p_12844_, s1), (p_144252_) -> {
|
||||
this.stats.put(p_144252_, compoundtag2.getInt(s1));
|
||||
}, () -> {
|
||||
LOGGER.warn("Invalid statistic in {}: Don't know what {} is", this.file, s1);
|
||||
});
|
||||
} else {
|
||||
LOGGER.warn("Invalid statistic value in {}: Don't know what {} is for key {}", this.file, compoundtag2.get(s1), s1);
|
||||
}
|
||||
}
|
||||
|
||||
}, () -> {
|
||||
LOGGER.warn("Invalid statistic type in {}: Don't know what {} is", this.file, s);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
LOGGER.error("Unable to parse Stat data from {}", (Object)this.file);
|
||||
}
|
||||
|
||||
} catch (IOException | JsonParseException jsonparseexception) {
|
||||
LOGGER.error("Unable to parse Stat data from {}", this.file, jsonparseexception);
|
||||
}
|
||||
}
|
||||
|
||||
private <T> Optional<Stat<T>> getStat(StatType<T> pType, String pLocation) {
|
||||
return Optional.ofNullable(ResourceLocation.tryParse(pLocation)).flatMap(pType.getRegistry()::getOptional).map(pType::get);
|
||||
}
|
||||
|
||||
private static CompoundTag fromJson(JsonObject pJson) {
|
||||
CompoundTag compoundtag = new CompoundTag();
|
||||
|
||||
for(Map.Entry<String, JsonElement> entry : pJson.entrySet()) {
|
||||
JsonElement jsonelement = entry.getValue();
|
||||
if (jsonelement.isJsonObject()) {
|
||||
compoundtag.put(entry.getKey(), fromJson(jsonelement.getAsJsonObject()));
|
||||
} else if (jsonelement.isJsonPrimitive()) {
|
||||
JsonPrimitive jsonprimitive = jsonelement.getAsJsonPrimitive();
|
||||
if (jsonprimitive.isNumber()) {
|
||||
compoundtag.putInt(entry.getKey(), jsonprimitive.getAsInt());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return compoundtag;
|
||||
}
|
||||
|
||||
protected String toJson() {
|
||||
Map<StatType<?>, JsonObject> map = Maps.newHashMap();
|
||||
|
||||
for(Object2IntMap.Entry<Stat<?>> entry : this.stats.object2IntEntrySet()) {
|
||||
Stat<?> stat = entry.getKey();
|
||||
map.computeIfAbsent(stat.getType(), (p_12822_) -> {
|
||||
return new JsonObject();
|
||||
}).addProperty(getKey(stat).toString(), entry.getIntValue());
|
||||
}
|
||||
|
||||
JsonObject jsonobject = new JsonObject();
|
||||
|
||||
for(Map.Entry<StatType<?>, JsonObject> entry1 : map.entrySet()) {
|
||||
jsonobject.add(BuiltInRegistries.STAT_TYPE.getKey(entry1.getKey()).toString(), entry1.getValue());
|
||||
}
|
||||
|
||||
JsonObject jsonobject1 = new JsonObject();
|
||||
jsonobject1.add("stats", jsonobject);
|
||||
jsonobject1.addProperty("DataVersion", SharedConstants.getCurrentVersion().getDataVersion().getVersion());
|
||||
return jsonobject1.toString();
|
||||
}
|
||||
|
||||
private static <T> ResourceLocation getKey(Stat<T> pStat) {
|
||||
return pStat.getType().getRegistry().getKey(pStat.getValue());
|
||||
}
|
||||
|
||||
public void markAllDirty() {
|
||||
this.dirty.addAll(this.stats.keySet());
|
||||
}
|
||||
|
||||
public void sendStats(ServerPlayer pPlayer) {
|
||||
Object2IntMap<Stat<?>> object2intmap = new Object2IntOpenHashMap<>();
|
||||
|
||||
for(Stat<?> stat : this.getDirty()) {
|
||||
object2intmap.put(stat, this.getValue(stat));
|
||||
}
|
||||
|
||||
pPlayer.connection.send(new ClientboundAwardStatsPacket(object2intmap));
|
||||
}
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
package net.minecraft.stats;
|
||||
|
||||
import java.util.Objects;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.scores.criteria.ObjectiveCriteria;
|
||||
|
||||
/**
|
||||
* An immutable statistic to be counted for a particular entry in the {@linkplain #type}'s registry. This is used as a
|
||||
* key in a {@link net.minecraft.stats.StatsCounter} for a corresponding count.
|
||||
* <p>
|
||||
* By default, the statistic's {@linkplain #getName() name} is formatted {@code <stat type namespace>.<stat type
|
||||
* path>:<value namespace>.<value path>}, as created by {@link #buildName(StatType, Object)}.
|
||||
*
|
||||
* @param <T> the type of the registry entry for this statistic
|
||||
* @see net.minecraft.stats.StatType
|
||||
* @see net.minecraft.stats.Stats
|
||||
*/
|
||||
public class Stat<T> extends ObjectiveCriteria {
|
||||
private final StatFormatter formatter;
|
||||
/** The registry entry for this statistic. */
|
||||
private final T value;
|
||||
/** The parent statistic type. */
|
||||
private final StatType<T> type;
|
||||
|
||||
protected Stat(StatType<T> pType, T pValue, StatFormatter pFormatter) {
|
||||
super(buildName(pType, pValue));
|
||||
this.type = pType;
|
||||
this.formatter = pFormatter;
|
||||
this.value = pValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name for the specified {@code type} and {@code value} in the form {@code <stat type namespace>.<stat
|
||||
* type path>:<value namespace>.<value path>}
|
||||
*/
|
||||
public static <T> String buildName(StatType<T> pType, T pValue) {
|
||||
return locationToKey(BuiltInRegistries.STAT_TYPE.getKey(pType)) + ":" + locationToKey(pType.getRegistry().getKey(pValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the specified {@code location} as a string with {@code .} as the separator character
|
||||
*/
|
||||
private static <T> String locationToKey(@Nullable ResourceLocation pLocation) {
|
||||
return pLocation.toString().replace(':', '.');
|
||||
}
|
||||
|
||||
public StatType<T> getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String format(int pValue) {
|
||||
return this.formatter.format(pValue);
|
||||
}
|
||||
|
||||
public boolean equals(Object pOther) {
|
||||
return this == pOther || pOther instanceof Stat && Objects.equals(this.getName(), ((Stat)pOther).getName());
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.getName().hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Stat{name=" + this.getName() + ", formatter=" + this.formatter + "}";
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package net.minecraft.stats;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Locale;
|
||||
import net.minecraft.Util;
|
||||
|
||||
/**
|
||||
* A formatter for a {@linkplain Stat statistic}'s corresponding count.
|
||||
*/
|
||||
public interface StatFormatter {
|
||||
DecimalFormat DECIMAL_FORMAT = Util.make(new DecimalFormat("########0.00"), (p_12881_) -> {
|
||||
p_12881_.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT));
|
||||
});
|
||||
StatFormatter DEFAULT = NumberFormat.getIntegerInstance(Locale.US)::format;
|
||||
StatFormatter DIVIDE_BY_TEN = (p_12885_) -> {
|
||||
return DECIMAL_FORMAT.format((double)p_12885_ * 0.1D);
|
||||
};
|
||||
StatFormatter DISTANCE = (p_12883_) -> {
|
||||
double d0 = (double)p_12883_ / 100.0D;
|
||||
double d1 = d0 / 1000.0D;
|
||||
if (d1 > 0.5D) {
|
||||
return DECIMAL_FORMAT.format(d1) + " km";
|
||||
} else {
|
||||
return d0 > 0.5D ? DECIMAL_FORMAT.format(d0) + " m" : p_12883_ + " cm";
|
||||
}
|
||||
};
|
||||
StatFormatter TIME = (p_12879_) -> {
|
||||
double d0 = (double)p_12879_ / 20.0D;
|
||||
double d1 = d0 / 60.0D;
|
||||
double d2 = d1 / 60.0D;
|
||||
double d3 = d2 / 24.0D;
|
||||
double d4 = d3 / 365.0D;
|
||||
if (d4 > 0.5D) {
|
||||
return DECIMAL_FORMAT.format(d4) + " y";
|
||||
} else if (d3 > 0.5D) {
|
||||
return DECIMAL_FORMAT.format(d3) + " d";
|
||||
} else if (d2 > 0.5D) {
|
||||
return DECIMAL_FORMAT.format(d2) + " h";
|
||||
} else {
|
||||
return d1 > 0.5D ? DECIMAL_FORMAT.format(d1) + " m" : d0 + " s";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats the specified {@code value} of a statistic.
|
||||
*
|
||||
* @return the formatted {@code value}
|
||||
* @param pValue the statistic's associated count to format
|
||||
*/
|
||||
String format(int pValue);
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
package net.minecraft.stats;
|
||||
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
/**
|
||||
* Holds a map of {@linkplain net.minecraft.stats.Stat statistics} with type {@code T} for a corresponding {@link
|
||||
* #registry}.
|
||||
* <p>
|
||||
* A single type usually defines a particular thing to be counted, such as {@linkplain
|
||||
* net.minecraft.stats.Stats#ITEM_USED the number of items used} or {@link net.minecraft.stats.Stats#BLOCK_MINED the
|
||||
* number of blocks mined}. However, there is also a {@link net.minecraft.stats.Stats#CUSTOM custom type} which uses
|
||||
* entries from the {@linkplain Registry#CUSTOM_STAT custom stat registry}. This is keyed by a {@link
|
||||
* net.minecraft.resources.ResourceLocation} and can be used to count any statistic that doesn't require an associated
|
||||
* {@link net.minecraft.core.Registry} entry.
|
||||
*
|
||||
* @param <T> the type of the associated registry's entry values
|
||||
* @see net.minecraft.stats.Stat
|
||||
* @see net.minecraft.stats.Stats
|
||||
* @see net.minecraft.core.Registry#STAT_TYPE
|
||||
* @see net.minecraft.core.Registry#CUSTOM_STAT
|
||||
*/
|
||||
public class StatType<T> implements Iterable<Stat<T>> {
|
||||
private final Registry<T> registry;
|
||||
/**
|
||||
* A map of registry entries to their corresponding {@link Stat statistic}. Lazily populated by {@link #get(Object,
|
||||
* StatFormatter)}.
|
||||
*/
|
||||
private final Map<T, Stat<T>> map = new IdentityHashMap<>();
|
||||
@Nullable
|
||||
private Component displayName;
|
||||
|
||||
public StatType(Registry<T> pRegistry) {
|
||||
this.registry = pRegistry;
|
||||
}
|
||||
|
||||
public boolean contains(T pValue) {
|
||||
return this.map.containsKey(pValue);
|
||||
}
|
||||
|
||||
public Stat<T> get(T pValue, StatFormatter pFormatter) {
|
||||
return this.map.computeIfAbsent(pValue, (p_12896_) -> {
|
||||
return new Stat<>(this, p_12896_, pFormatter);
|
||||
});
|
||||
}
|
||||
|
||||
public Registry<T> getRegistry() {
|
||||
return this.registry;
|
||||
}
|
||||
|
||||
public Iterator<Stat<T>> iterator() {
|
||||
return this.map.values().iterator();
|
||||
}
|
||||
|
||||
public Stat<T> get(T pValue) {
|
||||
return this.get(pValue, StatFormatter.DEFAULT);
|
||||
}
|
||||
|
||||
public String getTranslationKey() {
|
||||
return "stat_type." + BuiltInRegistries.STAT_TYPE.getKey(this).toString().replace(':', '.');
|
||||
}
|
||||
|
||||
public Component getDisplayName() {
|
||||
if (this.displayName == null) {
|
||||
this.displayName = Component.translatable(this.getTranslationKey());
|
||||
}
|
||||
|
||||
return this.displayName;
|
||||
}
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
package net.minecraft.stats;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
||||
public class Stats {
|
||||
public static final StatType<Block> BLOCK_MINED = makeRegistryStatType("mined", BuiltInRegistries.BLOCK);
|
||||
public static final StatType<Item> ITEM_CRAFTED = makeRegistryStatType("crafted", BuiltInRegistries.ITEM);
|
||||
public static final StatType<Item> ITEM_USED = makeRegistryStatType("used", BuiltInRegistries.ITEM);
|
||||
public static final StatType<Item> ITEM_BROKEN = makeRegistryStatType("broken", BuiltInRegistries.ITEM);
|
||||
public static final StatType<Item> ITEM_PICKED_UP = makeRegistryStatType("picked_up", BuiltInRegistries.ITEM);
|
||||
public static final StatType<Item> ITEM_DROPPED = makeRegistryStatType("dropped", BuiltInRegistries.ITEM);
|
||||
public static final StatType<EntityType<?>> ENTITY_KILLED = makeRegistryStatType("killed", BuiltInRegistries.ENTITY_TYPE);
|
||||
public static final StatType<EntityType<?>> ENTITY_KILLED_BY = makeRegistryStatType("killed_by", BuiltInRegistries.ENTITY_TYPE);
|
||||
public static final StatType<ResourceLocation> CUSTOM = makeRegistryStatType("custom", BuiltInRegistries.CUSTOM_STAT);
|
||||
public static final ResourceLocation LEAVE_GAME = makeCustomStat("leave_game", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation PLAY_TIME = makeCustomStat("play_time", StatFormatter.TIME);
|
||||
public static final ResourceLocation TOTAL_WORLD_TIME = makeCustomStat("total_world_time", StatFormatter.TIME);
|
||||
public static final ResourceLocation TIME_SINCE_DEATH = makeCustomStat("time_since_death", StatFormatter.TIME);
|
||||
public static final ResourceLocation TIME_SINCE_REST = makeCustomStat("time_since_rest", StatFormatter.TIME);
|
||||
public static final ResourceLocation CROUCH_TIME = makeCustomStat("sneak_time", StatFormatter.TIME);
|
||||
public static final ResourceLocation WALK_ONE_CM = makeCustomStat("walk_one_cm", StatFormatter.DISTANCE);
|
||||
public static final ResourceLocation CROUCH_ONE_CM = makeCustomStat("crouch_one_cm", StatFormatter.DISTANCE);
|
||||
public static final ResourceLocation SPRINT_ONE_CM = makeCustomStat("sprint_one_cm", StatFormatter.DISTANCE);
|
||||
public static final ResourceLocation WALK_ON_WATER_ONE_CM = makeCustomStat("walk_on_water_one_cm", StatFormatter.DISTANCE);
|
||||
public static final ResourceLocation FALL_ONE_CM = makeCustomStat("fall_one_cm", StatFormatter.DISTANCE);
|
||||
public static final ResourceLocation CLIMB_ONE_CM = makeCustomStat("climb_one_cm", StatFormatter.DISTANCE);
|
||||
public static final ResourceLocation FLY_ONE_CM = makeCustomStat("fly_one_cm", StatFormatter.DISTANCE);
|
||||
public static final ResourceLocation WALK_UNDER_WATER_ONE_CM = makeCustomStat("walk_under_water_one_cm", StatFormatter.DISTANCE);
|
||||
public static final ResourceLocation MINECART_ONE_CM = makeCustomStat("minecart_one_cm", StatFormatter.DISTANCE);
|
||||
public static final ResourceLocation BOAT_ONE_CM = makeCustomStat("boat_one_cm", StatFormatter.DISTANCE);
|
||||
public static final ResourceLocation PIG_ONE_CM = makeCustomStat("pig_one_cm", StatFormatter.DISTANCE);
|
||||
public static final ResourceLocation HORSE_ONE_CM = makeCustomStat("horse_one_cm", StatFormatter.DISTANCE);
|
||||
public static final ResourceLocation AVIATE_ONE_CM = makeCustomStat("aviate_one_cm", StatFormatter.DISTANCE);
|
||||
public static final ResourceLocation SWIM_ONE_CM = makeCustomStat("swim_one_cm", StatFormatter.DISTANCE);
|
||||
public static final ResourceLocation STRIDER_ONE_CM = makeCustomStat("strider_one_cm", StatFormatter.DISTANCE);
|
||||
public static final ResourceLocation JUMP = makeCustomStat("jump", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation DROP = makeCustomStat("drop", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation DAMAGE_DEALT = makeCustomStat("damage_dealt", StatFormatter.DIVIDE_BY_TEN);
|
||||
public static final ResourceLocation DAMAGE_DEALT_ABSORBED = makeCustomStat("damage_dealt_absorbed", StatFormatter.DIVIDE_BY_TEN);
|
||||
public static final ResourceLocation DAMAGE_DEALT_RESISTED = makeCustomStat("damage_dealt_resisted", StatFormatter.DIVIDE_BY_TEN);
|
||||
public static final ResourceLocation DAMAGE_TAKEN = makeCustomStat("damage_taken", StatFormatter.DIVIDE_BY_TEN);
|
||||
public static final ResourceLocation DAMAGE_BLOCKED_BY_SHIELD = makeCustomStat("damage_blocked_by_shield", StatFormatter.DIVIDE_BY_TEN);
|
||||
public static final ResourceLocation DAMAGE_ABSORBED = makeCustomStat("damage_absorbed", StatFormatter.DIVIDE_BY_TEN);
|
||||
public static final ResourceLocation DAMAGE_RESISTED = makeCustomStat("damage_resisted", StatFormatter.DIVIDE_BY_TEN);
|
||||
public static final ResourceLocation DEATHS = makeCustomStat("deaths", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation MOB_KILLS = makeCustomStat("mob_kills", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation ANIMALS_BRED = makeCustomStat("animals_bred", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation PLAYER_KILLS = makeCustomStat("player_kills", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation FISH_CAUGHT = makeCustomStat("fish_caught", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation TALKED_TO_VILLAGER = makeCustomStat("talked_to_villager", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation TRADED_WITH_VILLAGER = makeCustomStat("traded_with_villager", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation EAT_CAKE_SLICE = makeCustomStat("eat_cake_slice", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation FILL_CAULDRON = makeCustomStat("fill_cauldron", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation USE_CAULDRON = makeCustomStat("use_cauldron", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation CLEAN_ARMOR = makeCustomStat("clean_armor", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation CLEAN_BANNER = makeCustomStat("clean_banner", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation CLEAN_SHULKER_BOX = makeCustomStat("clean_shulker_box", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation INTERACT_WITH_BREWINGSTAND = makeCustomStat("interact_with_brewingstand", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation INTERACT_WITH_BEACON = makeCustomStat("interact_with_beacon", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation INSPECT_DROPPER = makeCustomStat("inspect_dropper", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation INSPECT_HOPPER = makeCustomStat("inspect_hopper", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation INSPECT_DISPENSER = makeCustomStat("inspect_dispenser", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation PLAY_NOTEBLOCK = makeCustomStat("play_noteblock", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation TUNE_NOTEBLOCK = makeCustomStat("tune_noteblock", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation POT_FLOWER = makeCustomStat("pot_flower", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation TRIGGER_TRAPPED_CHEST = makeCustomStat("trigger_trapped_chest", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation OPEN_ENDERCHEST = makeCustomStat("open_enderchest", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation ENCHANT_ITEM = makeCustomStat("enchant_item", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation PLAY_RECORD = makeCustomStat("play_record", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation INTERACT_WITH_FURNACE = makeCustomStat("interact_with_furnace", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation INTERACT_WITH_CRAFTING_TABLE = makeCustomStat("interact_with_crafting_table", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation OPEN_CHEST = makeCustomStat("open_chest", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation SLEEP_IN_BED = makeCustomStat("sleep_in_bed", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation OPEN_SHULKER_BOX = makeCustomStat("open_shulker_box", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation OPEN_BARREL = makeCustomStat("open_barrel", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation INTERACT_WITH_BLAST_FURNACE = makeCustomStat("interact_with_blast_furnace", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation INTERACT_WITH_SMOKER = makeCustomStat("interact_with_smoker", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation INTERACT_WITH_LECTERN = makeCustomStat("interact_with_lectern", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation INTERACT_WITH_CAMPFIRE = makeCustomStat("interact_with_campfire", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation INTERACT_WITH_CARTOGRAPHY_TABLE = makeCustomStat("interact_with_cartography_table", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation INTERACT_WITH_LOOM = makeCustomStat("interact_with_loom", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation INTERACT_WITH_STONECUTTER = makeCustomStat("interact_with_stonecutter", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation BELL_RING = makeCustomStat("bell_ring", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation RAID_TRIGGER = makeCustomStat("raid_trigger", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation RAID_WIN = makeCustomStat("raid_win", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation INTERACT_WITH_ANVIL = makeCustomStat("interact_with_anvil", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation INTERACT_WITH_GRINDSTONE = makeCustomStat("interact_with_grindstone", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation TARGET_HIT = makeCustomStat("target_hit", StatFormatter.DEFAULT);
|
||||
public static final ResourceLocation INTERACT_WITH_SMITHING_TABLE = makeCustomStat("interact_with_smithing_table", StatFormatter.DEFAULT);
|
||||
|
||||
private static ResourceLocation makeCustomStat(String pKey, StatFormatter pFormatter) {
|
||||
ResourceLocation resourcelocation = new ResourceLocation(pKey);
|
||||
Registry.register(BuiltInRegistries.CUSTOM_STAT, pKey, resourcelocation);
|
||||
CUSTOM.get(resourcelocation, pFormatter);
|
||||
return resourcelocation;
|
||||
}
|
||||
|
||||
private static <T> StatType<T> makeRegistryStatType(String pKey, Registry<T> pRegistry) {
|
||||
return Registry.register(BuiltInRegistries.STAT_TYPE, pKey, new StatType<>(pRegistry));
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package net.minecraft.stats;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMaps;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
|
||||
/**
|
||||
* Manages counting a set of {@link net.minecraft.stats.Stat} objects, stored by a map of statistics to their count.
|
||||
* <p>
|
||||
* This base {@code StatsCounter} is only used client-side for keeping track of and reading counts sent from the server.
|
||||
*
|
||||
* @see net.minecraft.stats.ServerStatsCounter
|
||||
*/
|
||||
public class StatsCounter {
|
||||
protected final Object2IntMap<Stat<?>> stats = Object2IntMaps.synchronize(new Object2IntOpenHashMap<>());
|
||||
|
||||
public StatsCounter() {
|
||||
this.stats.defaultReturnValue(0);
|
||||
}
|
||||
|
||||
public void increment(Player pPlayer, Stat<?> pStat, int pAmount) {
|
||||
int i = (int)Math.min((long)this.getValue(pStat) + (long)pAmount, 2147483647L);
|
||||
this.setValue(pPlayer, pStat, i);
|
||||
}
|
||||
|
||||
public void setValue(Player pPlayer, Stat<?> pStat, int pValue) {
|
||||
this.stats.put(pStat, pValue);
|
||||
}
|
||||
|
||||
public <T> int getValue(StatType<T> pType, T pValue) {
|
||||
return pType.contains(pValue) ? this.getValue(pType.get(pValue)) : 0;
|
||||
}
|
||||
|
||||
public int getValue(Stat<?> pStat) {
|
||||
return this.stats.getInt(pStat);
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
@FieldsAreNonnullByDefault
|
||||
package net.minecraft.stats;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
import net.minecraft.FieldsAreNonnullByDefault;
|
||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
||||
Reference in new issue
Block a user