base mod created
This commit is contained in:
@@ -0,0 +1,388 @@
|
||||
package net.minecraft.advancements;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import net.minecraft.util.text.event.HoverEvent;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
public class Advancement
|
||||
{
|
||||
private final Advancement parent;
|
||||
private final DisplayInfo display;
|
||||
private final AdvancementRewards rewards;
|
||||
private final ResourceLocation id;
|
||||
private final Map<String, Criterion> criteria;
|
||||
private final String[][] requirements;
|
||||
private final Set<Advancement> children = Sets.<Advancement>newLinkedHashSet();
|
||||
private final ITextComponent displayText;
|
||||
|
||||
public Advancement(ResourceLocation id, @Nullable Advancement parentIn, @Nullable DisplayInfo displayIn, AdvancementRewards rewardsIn, Map<String, Criterion> criteriaIn, String[][] requirementsIn)
|
||||
{
|
||||
this.id = id;
|
||||
this.display = displayIn;
|
||||
this.criteria = ImmutableMap.copyOf(criteriaIn);
|
||||
this.parent = parentIn;
|
||||
this.rewards = rewardsIn;
|
||||
this.requirements = requirementsIn;
|
||||
|
||||
if (parentIn != null)
|
||||
{
|
||||
parentIn.addChild(this);
|
||||
}
|
||||
|
||||
if (displayIn == null)
|
||||
{
|
||||
this.displayText = new TextComponentString(id.toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
this.displayText = new TextComponentString("[");
|
||||
this.displayText.getStyle().setColor(displayIn.getFrame().getFormat());
|
||||
ITextComponent itextcomponent = displayIn.getTitle().createCopy();
|
||||
ITextComponent itextcomponent1 = new TextComponentString("");
|
||||
ITextComponent itextcomponent2 = itextcomponent.createCopy();
|
||||
itextcomponent2.getStyle().setColor(displayIn.getFrame().getFormat());
|
||||
itextcomponent1.appendSibling(itextcomponent2);
|
||||
itextcomponent1.appendText("\n");
|
||||
itextcomponent1.appendSibling(displayIn.getDescription());
|
||||
itextcomponent.getStyle().setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, itextcomponent1));
|
||||
this.displayText.appendSibling(itextcomponent);
|
||||
this.displayText.appendText("]");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new advancement builder with the data from this advancement
|
||||
*/
|
||||
public Advancement.Builder copy()
|
||||
{
|
||||
return new Advancement.Builder(this.parent == null ? null : this.parent.getId(), this.display, this.rewards, this.criteria, this.requirements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@code Advancement} that is this {@code Advancement}'s parent. This determines the tree structure that
|
||||
* appears in the {@linkplain GuiScreenAdvancements GUI}.
|
||||
*
|
||||
* @return the parent {@code Advancement} of this {@code Advancement}, or {@code null} to signify that this {@code
|
||||
* Advancement} is a root with no parent.
|
||||
*/
|
||||
@Nullable
|
||||
public Advancement getParent()
|
||||
{
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information that defines this {@code Advancement}'s appearance in GUIs.
|
||||
*
|
||||
* @return information that defines this {@code Advancement}'s appearance in GUIs. If {@code null}, signifies an
|
||||
* invisible {@code Advancement}.
|
||||
*/
|
||||
@Nullable
|
||||
public DisplayInfo getDisplay()
|
||||
{
|
||||
return this.display;
|
||||
}
|
||||
|
||||
public AdvancementRewards getRewards()
|
||||
{
|
||||
return this.rewards;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "SimpleAdvancement{id=" + this.getId() + ", parent=" + (this.parent == null ? "null" : this.parent.getId()) + ", display=" + this.display + ", rewards=" + this.rewards + ", criteria=" + this.criteria + ", requirements=" + Arrays.deepToString(this.requirements) + '}';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the children of this {@code Advancement}.
|
||||
*
|
||||
* @return an {@code Iterable} of this {@code Advancement}'s children.
|
||||
* @see #getParent()
|
||||
*/
|
||||
public Iterable<Advancement> getChildren()
|
||||
{
|
||||
return this.children;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link Criterion Criteria} used to decide the completion of this {@code Advancement}. Each key-value pair
|
||||
* consists of a {@code Criterion} and its name.
|
||||
*
|
||||
* @return the criteria used to decide the completion of this {@code Advancement}
|
||||
* @see #getRequirements()
|
||||
*/
|
||||
public Map<String, Criterion> getCriteria()
|
||||
{
|
||||
return this.criteria;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get how many requirements this {@code Advancement} has.
|
||||
*
|
||||
* @return {@code this.getRequirements().length}
|
||||
* @see #getRequirements()
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
public int getRequirementCount()
|
||||
{
|
||||
return this.requirements.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the given {@code Advancement} as a child of this {@code Advancement}.
|
||||
*
|
||||
* @see #getParent()
|
||||
*/
|
||||
public void addChild(Advancement advancementIn)
|
||||
{
|
||||
this.children.add(advancementIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this {@code Advancement}'s unique identifier.
|
||||
*
|
||||
* @return this {@code Advancement}'s unique identifier
|
||||
*/
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public boolean equals(Object p_equals_1_)
|
||||
{
|
||||
if (this == p_equals_1_)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (!(p_equals_1_ instanceof Advancement))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Advancement advancement = (Advancement)p_equals_1_;
|
||||
return this.id.equals(advancement.id);
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
return this.id.hashCode();
|
||||
}
|
||||
|
||||
public String[][] getRequirements()
|
||||
{
|
||||
return this.requirements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@code ITextComponent} that is shown in the chat message sent after this {@code Advancement} is
|
||||
* completed.
|
||||
*
|
||||
* @return the {@code ITextComponent} that is shown in the chat message sent after this {@code Advancement} is
|
||||
* completed. If this {@code Advancement} is {@linkplain #getDisplay() invisible}, then it consists simply of {@link
|
||||
* #getId()}. Otherwise, it is the {@linkplain DisplayInfo#getTitle() title} inside square brackets, colored by the
|
||||
* {@linkplain net.minecraft.advancements.FrameType#getFormat frame type}, and hovering over it shows the
|
||||
* {@linkplain DisplayInfo#getDescription() description}.
|
||||
*/
|
||||
public ITextComponent getDisplayText()
|
||||
{
|
||||
return this.displayText;
|
||||
}
|
||||
|
||||
public static class Builder
|
||||
{
|
||||
private final ResourceLocation parentId;
|
||||
private Advancement parent;
|
||||
private final DisplayInfo display;
|
||||
private final AdvancementRewards rewards;
|
||||
private final Map<String, Criterion> criteria;
|
||||
private final String[][] requirements;
|
||||
|
||||
Builder(@Nullable ResourceLocation p_i47414_1_, @Nullable DisplayInfo p_i47414_2_, AdvancementRewards p_i47414_3_, Map<String, Criterion> p_i47414_4_, String[][] p_i47414_5_)
|
||||
{
|
||||
this.parentId = p_i47414_1_;
|
||||
this.display = p_i47414_2_;
|
||||
this.rewards = p_i47414_3_;
|
||||
this.criteria = p_i47414_4_;
|
||||
this.requirements = p_i47414_5_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to resolve the parent of this advancement, if possible. Returns true on success.
|
||||
*/
|
||||
public boolean resolveParent(Function<ResourceLocation, Advancement> lookup)
|
||||
{
|
||||
if (this.parentId == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.parent = lookup.apply(this.parentId);
|
||||
return this.parent != null;
|
||||
}
|
||||
}
|
||||
|
||||
public Advancement build(ResourceLocation id)
|
||||
{
|
||||
return new Advancement(id, this.parent, this.display, this.rewards, this.criteria, this.requirements);
|
||||
}
|
||||
|
||||
public void writeTo(PacketBuffer buf)
|
||||
{
|
||||
if (this.parentId == null)
|
||||
{
|
||||
buf.writeBoolean(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.writeBoolean(true);
|
||||
buf.writeResourceLocation(this.parentId);
|
||||
}
|
||||
|
||||
if (this.display == null)
|
||||
{
|
||||
buf.writeBoolean(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.writeBoolean(true);
|
||||
this.display.write(buf);
|
||||
}
|
||||
|
||||
Criterion.serializeToNetwork(this.criteria, buf);
|
||||
buf.writeVarInt(this.requirements.length);
|
||||
|
||||
for (String[] astring : this.requirements)
|
||||
{
|
||||
buf.writeVarInt(astring.length);
|
||||
|
||||
for (String s : astring)
|
||||
{
|
||||
buf.writeString(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "Task Advancement{parentId=" + this.parentId + ", display=" + this.display + ", rewards=" + this.rewards + ", criteria=" + this.criteria + ", requirements=" + Arrays.deepToString(this.requirements) + '}';
|
||||
}
|
||||
|
||||
public static Advancement.Builder deserialize(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
ResourceLocation resourcelocation = json.has("parent") ? new ResourceLocation(JsonUtils.getString(json, "parent")) : null;
|
||||
DisplayInfo displayinfo = json.has("display") ? DisplayInfo.deserialize(JsonUtils.getJsonObject(json, "display"), context) : null;
|
||||
AdvancementRewards advancementrewards = (AdvancementRewards)JsonUtils.deserializeClass(json, "rewards", AdvancementRewards.EMPTY, context, AdvancementRewards.class);
|
||||
Map<String, Criterion> map = Criterion.criteriaFromJson(JsonUtils.getJsonObject(json, "criteria"), context);
|
||||
|
||||
if (map.isEmpty())
|
||||
{
|
||||
throw new JsonSyntaxException("Advancement criteria cannot be empty");
|
||||
}
|
||||
else
|
||||
{
|
||||
JsonArray jsonarray = JsonUtils.getJsonArray(json, "requirements", new JsonArray());
|
||||
String[][] astring = new String[jsonarray.size()][];
|
||||
|
||||
for (int i = 0; i < jsonarray.size(); ++i)
|
||||
{
|
||||
JsonArray jsonarray1 = JsonUtils.getJsonArray(jsonarray.get(i), "requirements[" + i + "]");
|
||||
astring[i] = new String[jsonarray1.size()];
|
||||
|
||||
for (int j = 0; j < jsonarray1.size(); ++j)
|
||||
{
|
||||
astring[i][j] = JsonUtils.getString(jsonarray1.get(j), "requirements[" + i + "][" + j + "]");
|
||||
}
|
||||
}
|
||||
|
||||
if (astring.length == 0)
|
||||
{
|
||||
astring = new String[map.size()][];
|
||||
int k = 0;
|
||||
|
||||
for (String s2 : map.keySet())
|
||||
{
|
||||
astring[k++] = new String[] {s2};
|
||||
}
|
||||
}
|
||||
|
||||
for (String[] astring1 : astring)
|
||||
{
|
||||
if (astring1.length == 0 && map.isEmpty())
|
||||
{
|
||||
throw new JsonSyntaxException("Requirement entry cannot be empty");
|
||||
}
|
||||
|
||||
for (String s : astring1)
|
||||
{
|
||||
if (!map.containsKey(s))
|
||||
{
|
||||
throw new JsonSyntaxException("Unknown required criterion '" + s + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (String s1 : map.keySet())
|
||||
{
|
||||
boolean flag = false;
|
||||
|
||||
for (String[] astring2 : astring)
|
||||
{
|
||||
if (ArrayUtils.contains(astring2, s1))
|
||||
{
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!flag)
|
||||
{
|
||||
throw new JsonSyntaxException("Criterion '" + s1 + "' isn't a requirement for completion. This isn't supported behaviour, all criteria must be required.");
|
||||
}
|
||||
}
|
||||
|
||||
return new Advancement.Builder(resourcelocation, displayinfo, advancementrewards, map, astring);
|
||||
}
|
||||
}
|
||||
|
||||
public static Advancement.Builder readFrom(PacketBuffer buf) throws IOException
|
||||
{
|
||||
ResourceLocation resourcelocation = buf.readBoolean() ? buf.readResourceLocation() : null;
|
||||
DisplayInfo displayinfo = buf.readBoolean() ? DisplayInfo.read(buf) : null;
|
||||
Map<String, Criterion> map = Criterion.criteriaFromNetwork(buf);
|
||||
String[][] astring = new String[buf.readVarInt()][];
|
||||
|
||||
for (int i = 0; i < astring.length; ++i)
|
||||
{
|
||||
astring[i] = new String[buf.readVarInt()];
|
||||
|
||||
for (int j = 0; j < astring[i].length; ++j)
|
||||
{
|
||||
astring[i][j] = buf.readString(32767);
|
||||
}
|
||||
}
|
||||
|
||||
return new Advancement.Builder(resourcelocation, displayinfo, AdvancementRewards.EMPTY, map, astring);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
package net.minecraft.advancements;
|
||||
|
||||
import com.google.common.base.Functions;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.function.Function;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class AdvancementList
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private final Map<ResourceLocation, Advancement> advancements = Maps.<ResourceLocation, Advancement>newHashMap();
|
||||
/** All advancements that do not have a parent. */
|
||||
private final Set<Advancement> roots = Sets.<Advancement>newLinkedHashSet();
|
||||
private final Set<Advancement> nonRoots = Sets.<Advancement>newLinkedHashSet();
|
||||
private AdvancementList.Listener listener;
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
private void remove(Advancement advancementIn)
|
||||
{
|
||||
for (Advancement advancement : advancementIn.getChildren())
|
||||
{
|
||||
this.remove(advancement);
|
||||
}
|
||||
|
||||
LOGGER.info("Forgot about advancement " + advancementIn.getId());
|
||||
this.advancements.remove(advancementIn.getId());
|
||||
|
||||
if (advancementIn.getParent() == null)
|
||||
{
|
||||
this.roots.remove(advancementIn);
|
||||
|
||||
if (this.listener != null)
|
||||
{
|
||||
this.listener.rootAdvancementRemoved(advancementIn);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.nonRoots.remove(advancementIn);
|
||||
|
||||
if (this.listener != null)
|
||||
{
|
||||
this.listener.nonRootAdvancementRemoved(advancementIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void removeAll(Set<ResourceLocation> ids)
|
||||
{
|
||||
for (ResourceLocation resourcelocation : ids)
|
||||
{
|
||||
Advancement advancement = this.advancements.get(resourcelocation);
|
||||
|
||||
if (advancement == null)
|
||||
{
|
||||
LOGGER.warn("Told to remove advancement " + resourcelocation + " but I don't know what that is");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.remove(advancement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void loadAdvancements(Map<ResourceLocation, Advancement.Builder> advancementsIn)
|
||||
{
|
||||
Function<ResourceLocation, Advancement> function = Functions.<ResourceLocation, Advancement>forMap(this.advancements, null);
|
||||
label42:
|
||||
|
||||
while (!advancementsIn.isEmpty())
|
||||
{
|
||||
boolean flag = false;
|
||||
Iterator<Entry<ResourceLocation, Advancement.Builder>> iterator = advancementsIn.entrySet().iterator();
|
||||
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
Entry<ResourceLocation, Advancement.Builder> entry = (Entry)iterator.next();
|
||||
ResourceLocation resourcelocation = entry.getKey();
|
||||
Advancement.Builder advancement$builder = entry.getValue();
|
||||
|
||||
if (advancement$builder.resolveParent(function))
|
||||
{
|
||||
Advancement advancement = advancement$builder.build(resourcelocation);
|
||||
this.advancements.put(resourcelocation, advancement);
|
||||
flag = true;
|
||||
iterator.remove();
|
||||
|
||||
if (advancement.getParent() == null)
|
||||
{
|
||||
this.roots.add(advancement);
|
||||
|
||||
if (this.listener != null)
|
||||
{
|
||||
this.listener.rootAdvancementAdded(advancement);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.nonRoots.add(advancement);
|
||||
|
||||
if (this.listener != null)
|
||||
{
|
||||
this.listener.nonRootAdvancementAdded(advancement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!flag)
|
||||
{
|
||||
iterator = advancementsIn.entrySet().iterator();
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (!iterator.hasNext())
|
||||
{
|
||||
break label42;
|
||||
}
|
||||
|
||||
Entry<ResourceLocation, Advancement.Builder> entry1 = (Entry)iterator.next();
|
||||
LOGGER.error("Couldn't load advancement " + entry1.getKey() + ": " + entry1.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.info("Loaded " + this.advancements.size() + " advancements");
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
this.advancements.clear();
|
||||
this.roots.clear();
|
||||
this.nonRoots.clear();
|
||||
|
||||
if (this.listener != null)
|
||||
{
|
||||
this.listener.advancementsCleared();
|
||||
}
|
||||
}
|
||||
|
||||
public Iterable<Advancement> getRoots()
|
||||
{
|
||||
return this.roots;
|
||||
}
|
||||
|
||||
public Iterable<Advancement> getAdvancements()
|
||||
{
|
||||
return this.advancements.values();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Advancement getAdvancement(ResourceLocation id)
|
||||
{
|
||||
return this.advancements.get(id);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void setListener(@Nullable AdvancementList.Listener listenerIn)
|
||||
{
|
||||
this.listener = listenerIn;
|
||||
|
||||
if (listenerIn != null)
|
||||
{
|
||||
for (Advancement advancement : this.roots)
|
||||
{
|
||||
listenerIn.rootAdvancementAdded(advancement);
|
||||
}
|
||||
|
||||
for (Advancement advancement1 : this.nonRoots)
|
||||
{
|
||||
listenerIn.nonRootAdvancementAdded(advancement1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface Listener
|
||||
{
|
||||
void rootAdvancementAdded(Advancement advancementIn);
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
void rootAdvancementRemoved(Advancement advancementIn);
|
||||
|
||||
void nonRootAdvancementAdded(Advancement advancementIn);
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
void nonRootAdvancementRemoved(Advancement advancementIn);
|
||||
|
||||
void advancementsCleared();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
package net.minecraft.advancements;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.lang.reflect.Type;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.item.crafting.CraftingManager;
|
||||
import net.minecraft.util.EnumTypeAdapterFactory;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.Style;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class AdvancementManager
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
public static final Gson GSON = (new GsonBuilder()).registerTypeHierarchyAdapter(Advancement.Builder.class, new JsonDeserializer<Advancement.Builder>()
|
||||
{
|
||||
public Advancement.Builder deserialize(JsonElement p_deserialize_1_, Type p_deserialize_2_, JsonDeserializationContext p_deserialize_3_) throws JsonParseException
|
||||
{
|
||||
JsonObject jsonobject = JsonUtils.getJsonObject(p_deserialize_1_, "advancement");
|
||||
return Advancement.Builder.deserialize(jsonobject, p_deserialize_3_);
|
||||
}
|
||||
}).registerTypeAdapter(AdvancementRewards.class, new AdvancementRewards.Deserializer()).registerTypeHierarchyAdapter(ITextComponent.class, new ITextComponent.Serializer()).registerTypeHierarchyAdapter(Style.class, new Style.Serializer()).registerTypeAdapterFactory(new EnumTypeAdapterFactory()).create();
|
||||
private static final AdvancementList ADVANCEMENT_LIST = new AdvancementList();
|
||||
/** The directory where this manager looks for custom advancement files. */
|
||||
private final File advancementsDir;
|
||||
private boolean hasErrored;
|
||||
|
||||
public AdvancementManager(@Nullable File advancementsDirIn)
|
||||
{
|
||||
this.advancementsDir = advancementsDirIn;
|
||||
this.reload();
|
||||
}
|
||||
|
||||
public void reload()
|
||||
{
|
||||
this.hasErrored = false;
|
||||
ADVANCEMENT_LIST.clear();
|
||||
Map<ResourceLocation, Advancement.Builder> map = this.loadCustomAdvancements();
|
||||
this.loadBuiltInAdvancements(map);
|
||||
this.hasErrored |= net.minecraftforge.common.ForgeHooks.loadAdvancements(map);
|
||||
ADVANCEMENT_LIST.loadAdvancements(map);
|
||||
|
||||
for (Advancement advancement : ADVANCEMENT_LIST.getRoots())
|
||||
{
|
||||
if (advancement.getDisplay() != null)
|
||||
{
|
||||
AdvancementTreeNode.layout(advancement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasErrored()
|
||||
{
|
||||
return this.hasErrored;
|
||||
}
|
||||
|
||||
private Map<ResourceLocation, Advancement.Builder> loadCustomAdvancements()
|
||||
{
|
||||
if (this.advancementsDir == null)
|
||||
{
|
||||
return Maps.<ResourceLocation, Advancement.Builder>newHashMap();
|
||||
}
|
||||
else
|
||||
{
|
||||
Map<ResourceLocation, Advancement.Builder> map = Maps.<ResourceLocation, Advancement.Builder>newHashMap();
|
||||
this.advancementsDir.mkdirs();
|
||||
|
||||
for (File file1 : FileUtils.listFiles(this.advancementsDir, new String[] {"json"}, true))
|
||||
{
|
||||
String s = FilenameUtils.removeExtension(this.advancementsDir.toURI().relativize(file1.toURI()).toString());
|
||||
String[] astring = s.split("/", 2);
|
||||
|
||||
if (astring.length == 2)
|
||||
{
|
||||
ResourceLocation resourcelocation = new ResourceLocation(astring[0], astring[1]);
|
||||
|
||||
try
|
||||
{
|
||||
Advancement.Builder advancement$builder = (Advancement.Builder)JsonUtils.gsonDeserialize(GSON, FileUtils.readFileToString(file1, StandardCharsets.UTF_8), Advancement.Builder.class);
|
||||
|
||||
if (advancement$builder == null)
|
||||
{
|
||||
LOGGER.error("Couldn't load custom advancement " + resourcelocation + " from " + file1 + " as it's empty or null");
|
||||
}
|
||||
else
|
||||
{
|
||||
map.put(resourcelocation, advancement$builder);
|
||||
}
|
||||
}
|
||||
catch (IllegalArgumentException | JsonParseException jsonparseexception)
|
||||
{
|
||||
LOGGER.error("Parsing error loading custom advancement " + resourcelocation, (Throwable)jsonparseexception);
|
||||
this.hasErrored = true;
|
||||
}
|
||||
catch (IOException ioexception)
|
||||
{
|
||||
LOGGER.error("Couldn't read custom advancement " + resourcelocation + " from " + file1, (Throwable)ioexception);
|
||||
this.hasErrored = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
private void loadBuiltInAdvancements(Map<ResourceLocation, Advancement.Builder> map)
|
||||
{
|
||||
FileSystem filesystem = null;
|
||||
|
||||
try
|
||||
{
|
||||
URL url = AdvancementManager.class.getResource("/assets/.mcassetsroot");
|
||||
|
||||
if (url != null)
|
||||
{
|
||||
URI uri = url.toURI();
|
||||
Path path;
|
||||
|
||||
if ("file".equals(uri.getScheme()))
|
||||
{
|
||||
path = Paths.get(CraftingManager.class.getResource("/assets/minecraft/advancements").toURI());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!"jar".equals(uri.getScheme()))
|
||||
{
|
||||
LOGGER.error("Unsupported scheme " + uri + " trying to list all built-in advancements (NYI?)");
|
||||
this.hasErrored = true;
|
||||
return;
|
||||
}
|
||||
|
||||
filesystem = FileSystems.newFileSystem(uri, Collections.emptyMap());
|
||||
path = filesystem.getPath("/assets/minecraft/advancements");
|
||||
}
|
||||
|
||||
Iterator<Path> iterator = Files.walk(path).iterator();
|
||||
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
Path path1 = iterator.next();
|
||||
|
||||
if ("json".equals(FilenameUtils.getExtension(path1.toString())))
|
||||
{
|
||||
Path path2 = path.relativize(path1);
|
||||
String s = FilenameUtils.removeExtension(path2.toString()).replaceAll("\\\\", "/");
|
||||
ResourceLocation resourcelocation = new ResourceLocation("minecraft", s);
|
||||
|
||||
if (!map.containsKey(resourcelocation))
|
||||
{
|
||||
BufferedReader bufferedreader = null;
|
||||
|
||||
try
|
||||
{
|
||||
bufferedreader = Files.newBufferedReader(path1);
|
||||
Advancement.Builder advancement$builder = (Advancement.Builder)JsonUtils.fromJson(GSON, bufferedreader, Advancement.Builder.class);
|
||||
map.put(resourcelocation, advancement$builder);
|
||||
}
|
||||
catch (JsonParseException jsonparseexception)
|
||||
{
|
||||
LOGGER.error("Parsing error loading built-in advancement " + resourcelocation, (Throwable)jsonparseexception);
|
||||
this.hasErrored = true;
|
||||
}
|
||||
catch (IOException ioexception)
|
||||
{
|
||||
LOGGER.error("Couldn't read advancement " + resourcelocation + " from " + path1, (Throwable)ioexception);
|
||||
this.hasErrored = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtils.closeQuietly((Reader)bufferedreader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
LOGGER.error("Couldn't find .mcassetsroot");
|
||||
this.hasErrored = true;
|
||||
}
|
||||
catch (IOException | URISyntaxException urisyntaxexception)
|
||||
{
|
||||
LOGGER.error("Couldn't get a list of all built-in advancement files", (Throwable)urisyntaxexception);
|
||||
this.hasErrored = true;
|
||||
return;
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtils.closeQuietly((Closeable)filesystem);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Advancement getAdvancement(ResourceLocation id)
|
||||
{
|
||||
return ADVANCEMENT_LIST.getAdvancement(id);
|
||||
}
|
||||
|
||||
public Iterable<Advancement> getAdvancements()
|
||||
{
|
||||
return ADVANCEMENT_LIST.getAdvancements();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,345 @@
|
||||
package net.minecraft.advancements;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class AdvancementProgress implements Comparable<AdvancementProgress>
|
||||
{
|
||||
private final Map<String, CriterionProgress> criteria = Maps.<String, CriterionProgress>newHashMap();
|
||||
private String[][] requirements = new String[0][];
|
||||
|
||||
/**
|
||||
* Update this AdvancementProgress' criteria and requirements
|
||||
*/
|
||||
public void update(Map<String, Criterion> criteriaIn, String[][] requirements)
|
||||
{
|
||||
Set<String> set = criteriaIn.keySet();
|
||||
Iterator<Entry<String, CriterionProgress>> iterator = this.criteria.entrySet().iterator();
|
||||
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
Entry<String, CriterionProgress> entry = (Entry)iterator.next();
|
||||
|
||||
if (!set.contains(entry.getKey()))
|
||||
{
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
for (String s : set)
|
||||
{
|
||||
if (!this.criteria.containsKey(s))
|
||||
{
|
||||
this.criteria.put(s, new CriterionProgress(this));
|
||||
}
|
||||
}
|
||||
|
||||
this.requirements = requirements;
|
||||
}
|
||||
|
||||
public boolean isDone()
|
||||
{
|
||||
if (this.requirements.length == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (String[] astring : this.requirements)
|
||||
{
|
||||
boolean flag = false;
|
||||
|
||||
for (String s : astring)
|
||||
{
|
||||
CriterionProgress criterionprogress = this.getCriterionProgress(s);
|
||||
|
||||
if (criterionprogress != null && criterionprogress.isObtained())
|
||||
{
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!flag)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasProgress()
|
||||
{
|
||||
for (CriterionProgress criterionprogress : this.criteria.values())
|
||||
{
|
||||
if (criterionprogress.isObtained())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean grantCriterion(String criterionIn)
|
||||
{
|
||||
CriterionProgress criterionprogress = this.criteria.get(criterionIn);
|
||||
|
||||
if (criterionprogress != null && !criterionprogress.isObtained())
|
||||
{
|
||||
criterionprogress.obtain();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean revokeCriterion(String criterionIn)
|
||||
{
|
||||
CriterionProgress criterionprogress = this.criteria.get(criterionIn);
|
||||
|
||||
if (criterionprogress != null && criterionprogress.isObtained())
|
||||
{
|
||||
criterionprogress.reset();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "AdvancementProgress{criteria=" + this.criteria + ", requirements=" + Arrays.deepToString(this.requirements) + '}';
|
||||
}
|
||||
|
||||
public void serializeToNetwork(PacketBuffer p_192104_1_)
|
||||
{
|
||||
p_192104_1_.writeVarInt(this.criteria.size());
|
||||
|
||||
for (Entry<String, CriterionProgress> entry : this.criteria.entrySet())
|
||||
{
|
||||
p_192104_1_.writeString(entry.getKey());
|
||||
((CriterionProgress)entry.getValue()).write(p_192104_1_);
|
||||
}
|
||||
}
|
||||
|
||||
public static AdvancementProgress fromNetwork(PacketBuffer p_192100_0_)
|
||||
{
|
||||
AdvancementProgress advancementprogress = new AdvancementProgress();
|
||||
int i = p_192100_0_.readVarInt();
|
||||
|
||||
for (int j = 0; j < i; ++j)
|
||||
{
|
||||
advancementprogress.criteria.put(p_192100_0_.readString(32767), CriterionProgress.read(p_192100_0_, advancementprogress));
|
||||
}
|
||||
|
||||
return advancementprogress;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CriterionProgress getCriterionProgress(String criterionIn)
|
||||
{
|
||||
return this.criteria.get(criterionIn);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public float getPercent()
|
||||
{
|
||||
if (this.criteria.isEmpty())
|
||||
{
|
||||
return 0.0F;
|
||||
}
|
||||
else
|
||||
{
|
||||
float f = (float)this.requirements.length;
|
||||
float f1 = (float)this.countCompletedRequirements();
|
||||
return f1 / f;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@SideOnly(Side.CLIENT)
|
||||
public String getProgressText()
|
||||
{
|
||||
if (this.criteria.isEmpty())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = this.requirements.length;
|
||||
|
||||
if (i <= 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
int j = this.countCompletedRequirements();
|
||||
return j + "/" + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
private int countCompletedRequirements()
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (String[] astring : this.requirements)
|
||||
{
|
||||
boolean flag = false;
|
||||
|
||||
for (String s : astring)
|
||||
{
|
||||
CriterionProgress criterionprogress = this.getCriterionProgress(s);
|
||||
|
||||
if (criterionprogress != null && criterionprogress.isObtained())
|
||||
{
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag)
|
||||
{
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
public Iterable<String> getRemaningCriteria()
|
||||
{
|
||||
List<String> list = Lists.<String>newArrayList();
|
||||
|
||||
for (Entry<String, CriterionProgress> entry : this.criteria.entrySet())
|
||||
{
|
||||
if (!((CriterionProgress)entry.getValue()).isObtained())
|
||||
{
|
||||
list.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public Iterable<String> getCompletedCriteria()
|
||||
{
|
||||
List<String> list = Lists.<String>newArrayList();
|
||||
|
||||
for (Entry<String, CriterionProgress> entry : this.criteria.entrySet())
|
||||
{
|
||||
if (((CriterionProgress)entry.getValue()).isObtained())
|
||||
{
|
||||
list.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Date getFirstProgressDate()
|
||||
{
|
||||
Date date = null;
|
||||
|
||||
for (CriterionProgress criterionprogress : this.criteria.values())
|
||||
{
|
||||
if (criterionprogress.isObtained() && (date == null || criterionprogress.getObtained().before(date)))
|
||||
{
|
||||
date = criterionprogress.getObtained();
|
||||
}
|
||||
}
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
public int compareTo(AdvancementProgress p_compareTo_1_)
|
||||
{
|
||||
Date date = this.getFirstProgressDate();
|
||||
Date date1 = p_compareTo_1_.getFirstProgressDate();
|
||||
|
||||
if (date == null && date1 != null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (date != null && date1 == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return date == null && date1 == null ? 0 : date.compareTo(date1);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Serializer implements JsonDeserializer<AdvancementProgress>, JsonSerializer<AdvancementProgress>
|
||||
{
|
||||
public JsonElement serialize(AdvancementProgress p_serialize_1_, Type p_serialize_2_, JsonSerializationContext p_serialize_3_)
|
||||
{
|
||||
JsonObject jsonobject = new JsonObject();
|
||||
JsonObject jsonobject1 = new JsonObject();
|
||||
|
||||
for (Entry<String, CriterionProgress> entry : p_serialize_1_.criteria.entrySet())
|
||||
{
|
||||
CriterionProgress criterionprogress = entry.getValue();
|
||||
|
||||
if (criterionprogress.isObtained())
|
||||
{
|
||||
jsonobject1.add(entry.getKey(), criterionprogress.serialize());
|
||||
}
|
||||
}
|
||||
|
||||
if (!jsonobject1.entrySet().isEmpty())
|
||||
{
|
||||
jsonobject.add("criteria", jsonobject1);
|
||||
}
|
||||
|
||||
jsonobject.addProperty("done", Boolean.valueOf(p_serialize_1_.isDone()));
|
||||
return jsonobject;
|
||||
}
|
||||
|
||||
public AdvancementProgress deserialize(JsonElement p_deserialize_1_, Type p_deserialize_2_, JsonDeserializationContext p_deserialize_3_) throws JsonParseException
|
||||
{
|
||||
JsonObject jsonobject = JsonUtils.getJsonObject(p_deserialize_1_, "advancement");
|
||||
JsonObject jsonobject1 = JsonUtils.getJsonObject(jsonobject, "criteria", new JsonObject());
|
||||
AdvancementProgress advancementprogress = new AdvancementProgress();
|
||||
|
||||
for (Entry<String, JsonElement> entry : jsonobject1.entrySet())
|
||||
{
|
||||
String s = entry.getKey();
|
||||
advancementprogress.criteria.put(s, CriterionProgress.fromDateTime(advancementprogress, JsonUtils.getString(entry.getValue(), s)));
|
||||
}
|
||||
|
||||
return advancementprogress;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
package net.minecraft.advancements;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
import net.minecraft.command.CommandResultStats;
|
||||
import net.minecraft.command.FunctionObject;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.item.EntityItem;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.init.SoundEvents;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.crafting.CraftingManager;
|
||||
import net.minecraft.item.crafting.IRecipe;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.storage.loot.LootContext;
|
||||
|
||||
public class AdvancementRewards
|
||||
{
|
||||
public static final AdvancementRewards EMPTY = new AdvancementRewards(0, new ResourceLocation[0], new ResourceLocation[0], FunctionObject.CacheableFunction.EMPTY);
|
||||
private final int experience;
|
||||
private final ResourceLocation[] loot;
|
||||
private final ResourceLocation[] recipes;
|
||||
private final FunctionObject.CacheableFunction function;
|
||||
|
||||
public AdvancementRewards(int experience, ResourceLocation[] loot, ResourceLocation[] recipes, FunctionObject.CacheableFunction function)
|
||||
{
|
||||
this.experience = experience;
|
||||
this.loot = loot;
|
||||
this.recipes = recipes;
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
public void apply(final EntityPlayerMP player)
|
||||
{
|
||||
player.addExperience(this.experience);
|
||||
LootContext lootcontext = (new LootContext.Builder(player.getServerWorld())).withLootedEntity(player).withPlayer(player).withLuck(player.getLuck()).build(); // Forge: add player & luck to LootContext
|
||||
boolean flag = false;
|
||||
|
||||
for (ResourceLocation resourcelocation : this.loot)
|
||||
{
|
||||
for (ItemStack itemstack : player.world.getLootTableManager().getLootTableFromLocation(resourcelocation).generateLootForPools(player.getRNG(), lootcontext))
|
||||
{
|
||||
if (player.addItemStackToInventory(itemstack))
|
||||
{
|
||||
player.world.playSound((EntityPlayer)null, player.posX, player.posY, player.posZ, SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.PLAYERS, 0.2F, ((player.getRNG().nextFloat() - player.getRNG().nextFloat()) * 0.7F + 1.0F) * 2.0F);
|
||||
flag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
EntityItem entityitem = player.dropItem(itemstack, false);
|
||||
|
||||
if (entityitem != null)
|
||||
{
|
||||
entityitem.setNoPickupDelay();
|
||||
entityitem.setOwner(player.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flag)
|
||||
{
|
||||
player.inventoryContainer.detectAndSendChanges();
|
||||
}
|
||||
|
||||
if (this.recipes.length > 0)
|
||||
{
|
||||
player.unlockRecipes(this.recipes);
|
||||
}
|
||||
|
||||
final MinecraftServer minecraftserver = player.mcServer;
|
||||
FunctionObject functionobject = this.function.get(minecraftserver.getFunctionManager());
|
||||
|
||||
if (functionobject != null)
|
||||
{
|
||||
ICommandSender icommandsender = new ICommandSender()
|
||||
{
|
||||
/**
|
||||
* Get the name of this object. For players this returns their username
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return player.getName();
|
||||
}
|
||||
/**
|
||||
* Get the formatted ChatComponent that will be used for the sender's username in chat
|
||||
*/
|
||||
public ITextComponent getDisplayName()
|
||||
{
|
||||
return player.getDisplayName();
|
||||
}
|
||||
/**
|
||||
* Send a chat message to the CommandSender
|
||||
*/
|
||||
public void sendMessage(ITextComponent component)
|
||||
{
|
||||
}
|
||||
/**
|
||||
* Returns {@code true} if the CommandSender is allowed to execute the command, {@code false} if not
|
||||
*/
|
||||
public boolean canUseCommand(int permLevel, String commandName)
|
||||
{
|
||||
return permLevel <= 2;
|
||||
}
|
||||
/**
|
||||
* Get the position in the world. <b>{@code null} is not allowed!</b> If you are not an entity in the
|
||||
* world, return the coordinates 0, 0, 0
|
||||
*/
|
||||
public BlockPos getPosition()
|
||||
{
|
||||
return player.getPosition();
|
||||
}
|
||||
/**
|
||||
* Get the position vector. <b>{@code null} is not allowed!</b> If you are not an entity in the world,
|
||||
* return 0.0D, 0.0D, 0.0D
|
||||
*/
|
||||
public Vec3d getPositionVector()
|
||||
{
|
||||
return player.getPositionVector();
|
||||
}
|
||||
/**
|
||||
* Get the world, if available. <b>{@code null} is not allowed!</b> If you are not an entity in the
|
||||
* world, return the overworld
|
||||
*/
|
||||
public World getEntityWorld()
|
||||
{
|
||||
return player.world;
|
||||
}
|
||||
/**
|
||||
* Returns the entity associated with the command sender. MAY BE NULL!
|
||||
*/
|
||||
public Entity getCommandSenderEntity()
|
||||
{
|
||||
return player;
|
||||
}
|
||||
/**
|
||||
* Returns true if the command sender should be sent feedback about executed commands
|
||||
*/
|
||||
public boolean sendCommandFeedback()
|
||||
{
|
||||
return minecraftserver.worlds[0].getGameRules().getBoolean("commandBlockOutput");
|
||||
}
|
||||
public void setCommandStat(CommandResultStats.Type type, int amount)
|
||||
{
|
||||
player.setCommandStat(type, amount);
|
||||
}
|
||||
/**
|
||||
* Get the Minecraft server instance
|
||||
*/
|
||||
public MinecraftServer getServer()
|
||||
{
|
||||
return player.getServer();
|
||||
}
|
||||
};
|
||||
minecraftserver.getFunctionManager().execute(functionobject, icommandsender);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "AdvancementRewards{experience=" + this.experience + ", loot=" + Arrays.toString((Object[])this.loot) + ", recipes=" + Arrays.toString((Object[])this.recipes) + ", function=" + this.function + '}';
|
||||
}
|
||||
|
||||
public static class Deserializer implements JsonDeserializer<AdvancementRewards>
|
||||
{
|
||||
public AdvancementRewards deserialize(JsonElement p_deserialize_1_, Type p_deserialize_2_, JsonDeserializationContext p_deserialize_3_) throws JsonParseException
|
||||
{
|
||||
JsonObject jsonobject = JsonUtils.getJsonObject(p_deserialize_1_, "rewards");
|
||||
int i = JsonUtils.getInt(jsonobject, "experience", 0);
|
||||
JsonArray jsonarray = JsonUtils.getJsonArray(jsonobject, "loot", new JsonArray());
|
||||
ResourceLocation[] aresourcelocation = new ResourceLocation[jsonarray.size()];
|
||||
|
||||
for (int j = 0; j < aresourcelocation.length; ++j)
|
||||
{
|
||||
aresourcelocation[j] = new ResourceLocation(JsonUtils.getString(jsonarray.get(j), "loot[" + j + "]"));
|
||||
}
|
||||
|
||||
JsonArray jsonarray1 = JsonUtils.getJsonArray(jsonobject, "recipes", new JsonArray());
|
||||
ResourceLocation[] aresourcelocation1 = new ResourceLocation[jsonarray1.size()];
|
||||
|
||||
for (int k = 0; k < aresourcelocation1.length; ++k)
|
||||
{
|
||||
aresourcelocation1[k] = new ResourceLocation(JsonUtils.getString(jsonarray1.get(k), "recipes[" + k + "]"));
|
||||
IRecipe irecipe = CraftingManager.getRecipe(aresourcelocation1[k]);
|
||||
|
||||
if (irecipe == null)
|
||||
{
|
||||
throw new JsonSyntaxException("Unknown recipe '" + aresourcelocation1[k] + "'");
|
||||
}
|
||||
}
|
||||
|
||||
FunctionObject.CacheableFunction functionobject$cacheablefunction;
|
||||
|
||||
if (jsonobject.has("function"))
|
||||
{
|
||||
functionobject$cacheablefunction = new FunctionObject.CacheableFunction(new ResourceLocation(JsonUtils.getString(jsonobject, "function")));
|
||||
}
|
||||
else
|
||||
{
|
||||
functionobject$cacheablefunction = FunctionObject.CacheableFunction.EMPTY;
|
||||
}
|
||||
|
||||
return new AdvancementRewards(i, aresourcelocation, aresourcelocation1, functionobject$cacheablefunction);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,286 @@
|
||||
package net.minecraft.advancements;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class AdvancementTreeNode
|
||||
{
|
||||
private final Advancement advancement;
|
||||
private final AdvancementTreeNode parent;
|
||||
private final AdvancementTreeNode sibling;
|
||||
private final int index;
|
||||
private final List<AdvancementTreeNode> children = Lists.<AdvancementTreeNode>newArrayList();
|
||||
private AdvancementTreeNode ancestor;
|
||||
private AdvancementTreeNode thread;
|
||||
private int x;
|
||||
private float y;
|
||||
private float mod;
|
||||
private float change;
|
||||
private float shift;
|
||||
|
||||
public AdvancementTreeNode(Advancement advancementIn, @Nullable AdvancementTreeNode parentIn, @Nullable AdvancementTreeNode siblingIn, int indexIn, int xIn)
|
||||
{
|
||||
if (advancementIn.getDisplay() == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Can't position an invisible advancement!");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.advancement = advancementIn;
|
||||
this.parent = parentIn;
|
||||
this.sibling = siblingIn;
|
||||
this.index = indexIn;
|
||||
this.ancestor = this;
|
||||
this.x = xIn;
|
||||
this.y = -1.0F;
|
||||
AdvancementTreeNode advancementtreenode = null;
|
||||
|
||||
for (Advancement advancement : advancementIn.getChildren())
|
||||
{
|
||||
advancementtreenode = this.buildSubTree(advancement, advancementtreenode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private AdvancementTreeNode buildSubTree(Advancement advancementIn, @Nullable AdvancementTreeNode previous)
|
||||
{
|
||||
if (advancementIn.getDisplay() != null)
|
||||
{
|
||||
previous = new AdvancementTreeNode(advancementIn, this, previous, this.children.size() + 1, this.x + 1);
|
||||
this.children.add(previous);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Advancement advancement : advancementIn.getChildren())
|
||||
{
|
||||
previous = this.buildSubTree(advancement, previous);
|
||||
}
|
||||
}
|
||||
|
||||
return previous;
|
||||
}
|
||||
|
||||
private void firstWalk()
|
||||
{
|
||||
if (this.children.isEmpty())
|
||||
{
|
||||
if (this.sibling != null)
|
||||
{
|
||||
this.y = this.sibling.y + 1.0F;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.y = 0.0F;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AdvancementTreeNode advancementtreenode = null;
|
||||
|
||||
for (AdvancementTreeNode advancementtreenode1 : this.children)
|
||||
{
|
||||
advancementtreenode1.firstWalk();
|
||||
advancementtreenode = advancementtreenode1.apportion(advancementtreenode == null ? advancementtreenode1 : advancementtreenode);
|
||||
}
|
||||
|
||||
this.executeShifts();
|
||||
float f = ((this.children.get(0)).y + (this.children.get(this.children.size() - 1)).y) / 2.0F;
|
||||
|
||||
if (this.sibling != null)
|
||||
{
|
||||
this.y = this.sibling.y + 1.0F;
|
||||
this.mod = this.y - f;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.y = f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private float secondWalk(float p_192319_1_, int p_192319_2_, float p_192319_3_)
|
||||
{
|
||||
this.y += p_192319_1_;
|
||||
this.x = p_192319_2_;
|
||||
|
||||
if (this.y < p_192319_3_)
|
||||
{
|
||||
p_192319_3_ = this.y;
|
||||
}
|
||||
|
||||
for (AdvancementTreeNode advancementtreenode : this.children)
|
||||
{
|
||||
p_192319_3_ = advancementtreenode.secondWalk(p_192319_1_ + this.mod, p_192319_2_ + 1, p_192319_3_);
|
||||
}
|
||||
|
||||
return p_192319_3_;
|
||||
}
|
||||
|
||||
private void thirdWalk(float yIn)
|
||||
{
|
||||
this.y += yIn;
|
||||
|
||||
for (AdvancementTreeNode advancementtreenode : this.children)
|
||||
{
|
||||
advancementtreenode.thirdWalk(yIn);
|
||||
}
|
||||
}
|
||||
|
||||
private void executeShifts()
|
||||
{
|
||||
float f = 0.0F;
|
||||
float f1 = 0.0F;
|
||||
|
||||
for (int i = this.children.size() - 1; i >= 0; --i)
|
||||
{
|
||||
AdvancementTreeNode advancementtreenode = this.children.get(i);
|
||||
advancementtreenode.y += f;
|
||||
advancementtreenode.mod += f;
|
||||
f1 += advancementtreenode.change;
|
||||
f += advancementtreenode.shift + f1;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private AdvancementTreeNode getFirstChild()
|
||||
{
|
||||
if (this.thread != null)
|
||||
{
|
||||
return this.thread;
|
||||
}
|
||||
else
|
||||
{
|
||||
return !this.children.isEmpty() ? (AdvancementTreeNode)this.children.get(0) : null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private AdvancementTreeNode getLastChild()
|
||||
{
|
||||
if (this.thread != null)
|
||||
{
|
||||
return this.thread;
|
||||
}
|
||||
else
|
||||
{
|
||||
return !this.children.isEmpty() ? (AdvancementTreeNode)this.children.get(this.children.size() - 1) : null;
|
||||
}
|
||||
}
|
||||
|
||||
private AdvancementTreeNode apportion(AdvancementTreeNode nodeIn)
|
||||
{
|
||||
if (this.sibling == null)
|
||||
{
|
||||
return nodeIn;
|
||||
}
|
||||
else
|
||||
{
|
||||
AdvancementTreeNode advancementtreenode = this;
|
||||
AdvancementTreeNode advancementtreenode1 = this;
|
||||
AdvancementTreeNode advancementtreenode2 = this.sibling;
|
||||
AdvancementTreeNode advancementtreenode3 = this.parent.children.get(0);
|
||||
float f = this.mod;
|
||||
float f1 = this.mod;
|
||||
float f2 = advancementtreenode2.mod;
|
||||
float f3;
|
||||
|
||||
for (f3 = advancementtreenode3.mod; advancementtreenode2.getLastChild() != null && advancementtreenode.getFirstChild() != null; f1 += advancementtreenode1.mod)
|
||||
{
|
||||
advancementtreenode2 = advancementtreenode2.getLastChild();
|
||||
advancementtreenode = advancementtreenode.getFirstChild();
|
||||
advancementtreenode3 = advancementtreenode3.getFirstChild();
|
||||
advancementtreenode1 = advancementtreenode1.getLastChild();
|
||||
advancementtreenode1.ancestor = this;
|
||||
float f4 = advancementtreenode2.y + f2 - (advancementtreenode.y + f) + 1.0F;
|
||||
|
||||
if (f4 > 0.0F)
|
||||
{
|
||||
advancementtreenode2.getAncestor(this, nodeIn).moveSubtree(this, f4);
|
||||
f += f4;
|
||||
f1 += f4;
|
||||
}
|
||||
|
||||
f2 += advancementtreenode2.mod;
|
||||
f += advancementtreenode.mod;
|
||||
f3 += advancementtreenode3.mod;
|
||||
}
|
||||
|
||||
if (advancementtreenode2.getLastChild() != null && advancementtreenode1.getLastChild() == null)
|
||||
{
|
||||
advancementtreenode1.thread = advancementtreenode2.getLastChild();
|
||||
advancementtreenode1.mod += f2 - f1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (advancementtreenode.getFirstChild() != null && advancementtreenode3.getFirstChild() == null)
|
||||
{
|
||||
advancementtreenode3.thread = advancementtreenode.getFirstChild();
|
||||
advancementtreenode3.mod += f - f3;
|
||||
}
|
||||
|
||||
nodeIn = this;
|
||||
}
|
||||
|
||||
return nodeIn;
|
||||
}
|
||||
}
|
||||
|
||||
private void moveSubtree(AdvancementTreeNode nodeIn, float p_192316_2_)
|
||||
{
|
||||
float f = (float)(nodeIn.index - this.index);
|
||||
|
||||
if (f != 0.0F)
|
||||
{
|
||||
nodeIn.change -= p_192316_2_ / f;
|
||||
this.change += p_192316_2_ / f;
|
||||
}
|
||||
|
||||
nodeIn.shift += p_192316_2_;
|
||||
nodeIn.y += p_192316_2_;
|
||||
nodeIn.mod += p_192316_2_;
|
||||
}
|
||||
|
||||
private AdvancementTreeNode getAncestor(AdvancementTreeNode p_192326_1_, AdvancementTreeNode p_192326_2_)
|
||||
{
|
||||
return this.ancestor != null && p_192326_1_.parent.children.contains(this.ancestor) ? this.ancestor : p_192326_2_;
|
||||
}
|
||||
|
||||
private void updatePosition()
|
||||
{
|
||||
if (this.advancement.getDisplay() != null)
|
||||
{
|
||||
this.advancement.getDisplay().setPosition((float)this.x, this.y);
|
||||
}
|
||||
|
||||
if (!this.children.isEmpty())
|
||||
{
|
||||
for (AdvancementTreeNode advancementtreenode : this.children)
|
||||
{
|
||||
advancementtreenode.updatePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void layout(Advancement root)
|
||||
{
|
||||
if (root.getDisplay() == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Can't position children of an invisible root!");
|
||||
}
|
||||
else
|
||||
{
|
||||
AdvancementTreeNode advancementtreenode = new AdvancementTreeNode(root, (AdvancementTreeNode)null, (AdvancementTreeNode)null, 1, 0);
|
||||
advancementtreenode.firstWalk();
|
||||
float f = advancementtreenode.secondWalk(0.0F, 0, advancementtreenode.y);
|
||||
|
||||
if (f < 0.0F)
|
||||
{
|
||||
advancementtreenode.thirdWalk(-f);
|
||||
}
|
||||
|
||||
advancementtreenode.updatePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package net.minecraft.advancements;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.advancements.critereon.BredAnimalsTrigger;
|
||||
import net.minecraft.advancements.critereon.BrewedPotionTrigger;
|
||||
import net.minecraft.advancements.critereon.ChangeDimensionTrigger;
|
||||
import net.minecraft.advancements.critereon.ConstructBeaconTrigger;
|
||||
import net.minecraft.advancements.critereon.ConsumeItemTrigger;
|
||||
import net.minecraft.advancements.critereon.CuredZombieVillagerTrigger;
|
||||
import net.minecraft.advancements.critereon.EffectsChangedTrigger;
|
||||
import net.minecraft.advancements.critereon.EnchantedItemTrigger;
|
||||
import net.minecraft.advancements.critereon.EnterBlockTrigger;
|
||||
import net.minecraft.advancements.critereon.EntityHurtPlayerTrigger;
|
||||
import net.minecraft.advancements.critereon.ImpossibleTrigger;
|
||||
import net.minecraft.advancements.critereon.InventoryChangeTrigger;
|
||||
import net.minecraft.advancements.critereon.ItemDurabilityTrigger;
|
||||
import net.minecraft.advancements.critereon.KilledTrigger;
|
||||
import net.minecraft.advancements.critereon.LevitationTrigger;
|
||||
import net.minecraft.advancements.critereon.NetherTravelTrigger;
|
||||
import net.minecraft.advancements.critereon.PlacedBlockTrigger;
|
||||
import net.minecraft.advancements.critereon.PlayerHurtEntityTrigger;
|
||||
import net.minecraft.advancements.critereon.PositionTrigger;
|
||||
import net.minecraft.advancements.critereon.RecipeUnlockedTrigger;
|
||||
import net.minecraft.advancements.critereon.SummonedEntityTrigger;
|
||||
import net.minecraft.advancements.critereon.TameAnimalTrigger;
|
||||
import net.minecraft.advancements.critereon.TickTrigger;
|
||||
import net.minecraft.advancements.critereon.UsedEnderEyeTrigger;
|
||||
import net.minecraft.advancements.critereon.UsedTotemTrigger;
|
||||
import net.minecraft.advancements.critereon.VillagerTradeTrigger;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class CriteriaTriggers
|
||||
{
|
||||
private static final Map < ResourceLocation, ICriterionTrigger<? >> REGISTRY = Maps. < ResourceLocation, ICriterionTrigger<? >> newHashMap();
|
||||
public static final ImpossibleTrigger IMPOSSIBLE = (ImpossibleTrigger)register(new ImpossibleTrigger());
|
||||
public static final KilledTrigger PLAYER_KILLED_ENTITY = (KilledTrigger)register(new KilledTrigger(new ResourceLocation("player_killed_entity")));
|
||||
public static final KilledTrigger ENTITY_KILLED_PLAYER = (KilledTrigger)register(new KilledTrigger(new ResourceLocation("entity_killed_player")));
|
||||
public static final EnterBlockTrigger ENTER_BLOCK = (EnterBlockTrigger)register(new EnterBlockTrigger());
|
||||
public static final InventoryChangeTrigger INVENTORY_CHANGED = (InventoryChangeTrigger)register(new InventoryChangeTrigger());
|
||||
public static final RecipeUnlockedTrigger RECIPE_UNLOCKED = (RecipeUnlockedTrigger)register(new RecipeUnlockedTrigger());
|
||||
public static final PlayerHurtEntityTrigger PLAYER_HURT_ENTITY = (PlayerHurtEntityTrigger)register(new PlayerHurtEntityTrigger());
|
||||
public static final EntityHurtPlayerTrigger ENTITY_HURT_PLAYER = (EntityHurtPlayerTrigger)register(new EntityHurtPlayerTrigger());
|
||||
public static final EnchantedItemTrigger ENCHANTED_ITEM = (EnchantedItemTrigger)register(new EnchantedItemTrigger());
|
||||
public static final BrewedPotionTrigger BREWED_POTION = (BrewedPotionTrigger)register(new BrewedPotionTrigger());
|
||||
public static final ConstructBeaconTrigger CONSTRUCT_BEACON = (ConstructBeaconTrigger)register(new ConstructBeaconTrigger());
|
||||
public static final UsedEnderEyeTrigger USED_ENDER_EYE = (UsedEnderEyeTrigger)register(new UsedEnderEyeTrigger());
|
||||
public static final SummonedEntityTrigger SUMMONED_ENTITY = (SummonedEntityTrigger)register(new SummonedEntityTrigger());
|
||||
public static final BredAnimalsTrigger BRED_ANIMALS = (BredAnimalsTrigger)register(new BredAnimalsTrigger());
|
||||
public static final PositionTrigger LOCATION = (PositionTrigger)register(new PositionTrigger(new ResourceLocation("location")));
|
||||
public static final PositionTrigger SLEPT_IN_BED = (PositionTrigger)register(new PositionTrigger(new ResourceLocation("slept_in_bed")));
|
||||
public static final CuredZombieVillagerTrigger CURED_ZOMBIE_VILLAGER = (CuredZombieVillagerTrigger)register(new CuredZombieVillagerTrigger());
|
||||
public static final VillagerTradeTrigger VILLAGER_TRADE = (VillagerTradeTrigger)register(new VillagerTradeTrigger());
|
||||
public static final ItemDurabilityTrigger ITEM_DURABILITY_CHANGED = (ItemDurabilityTrigger)register(new ItemDurabilityTrigger());
|
||||
public static final LevitationTrigger LEVITATION = (LevitationTrigger)register(new LevitationTrigger());
|
||||
public static final ChangeDimensionTrigger CHANGED_DIMENSION = (ChangeDimensionTrigger)register(new ChangeDimensionTrigger());
|
||||
public static final TickTrigger TICK = (TickTrigger)register(new TickTrigger());
|
||||
public static final TameAnimalTrigger TAME_ANIMAL = (TameAnimalTrigger)register(new TameAnimalTrigger());
|
||||
public static final PlacedBlockTrigger PLACED_BLOCK = (PlacedBlockTrigger)register(new PlacedBlockTrigger());
|
||||
public static final ConsumeItemTrigger CONSUME_ITEM = (ConsumeItemTrigger)register(new ConsumeItemTrigger());
|
||||
public static final EffectsChangedTrigger EFFECTS_CHANGED = (EffectsChangedTrigger)register(new EffectsChangedTrigger());
|
||||
public static final UsedTotemTrigger USED_TOTEM = (UsedTotemTrigger)register(new UsedTotemTrigger());
|
||||
public static final NetherTravelTrigger NETHER_TRAVEL = (NetherTravelTrigger)register(new NetherTravelTrigger());
|
||||
|
||||
public static <T extends ICriterionTrigger> T register(T criterion)
|
||||
{
|
||||
if (REGISTRY.containsKey(criterion.getId()))
|
||||
{
|
||||
throw new IllegalArgumentException("Duplicate criterion id " + criterion.getId());
|
||||
}
|
||||
else
|
||||
{
|
||||
REGISTRY.put(criterion.getId(), criterion);
|
||||
return criterion;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T extends ICriterionInstance> ICriterionTrigger<T> get(ResourceLocation id)
|
||||
{
|
||||
return (ICriterionTrigger)REGISTRY.get(id);
|
||||
}
|
||||
|
||||
public static Iterable <? extends ICriterionTrigger<? >> getAll()
|
||||
{
|
||||
return REGISTRY.values();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package net.minecraft.advancements;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class Criterion
|
||||
{
|
||||
private final ICriterionInstance criterionInstance;
|
||||
|
||||
public Criterion(ICriterionInstance p_i47470_1_)
|
||||
{
|
||||
this.criterionInstance = p_i47470_1_;
|
||||
}
|
||||
|
||||
public Criterion()
|
||||
{
|
||||
this.criterionInstance = null;
|
||||
}
|
||||
|
||||
public void serializeToNetwork(PacketBuffer p_192140_1_)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a <em>single</em> {@code Criterion} from {@code json}. The {@link ICriterionTrigger} is chosen by the
|
||||
* {@code "trigger"} property of the object, which can then handle the optional {@code "conditions"} in the object.
|
||||
* The {@code "conditions"}, if present, must be a {@code JsonObject}. The resulting {@link ICriterionInstance} is
|
||||
* wrapped in a {@code Criterion}.
|
||||
*
|
||||
* @return the deserialized {@code Criterion}.
|
||||
* @see ICriterionTrigger#deserializeInstance(JsonObject, JsonDeserializationContext)
|
||||
*
|
||||
* @param json the {@code JsonObject} to deserialize from
|
||||
* @param context the {@code JsonDeserializationContext} to deserialize in
|
||||
*/
|
||||
public static Criterion criterionFromJson(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
ResourceLocation resourcelocation = new ResourceLocation(JsonUtils.getString(json, "trigger"));
|
||||
ICriterionTrigger<?> icriteriontrigger = CriteriaTriggers.get(resourcelocation);
|
||||
|
||||
if (icriteriontrigger == null)
|
||||
{
|
||||
throw new JsonSyntaxException("Invalid criterion trigger: " + resourcelocation);
|
||||
}
|
||||
else
|
||||
{
|
||||
ICriterionInstance icriterioninstance = icriteriontrigger.deserializeInstance(JsonUtils.getJsonObject(json, "conditions", new JsonObject()), context);
|
||||
return new Criterion(icriterioninstance);
|
||||
}
|
||||
}
|
||||
|
||||
public static Criterion criterionFromNetwork(PacketBuffer p_192146_0_)
|
||||
{
|
||||
return new Criterion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read criteria from {@code json}. The keys of the object name the criteria, and the values (which must be objects)
|
||||
* are the criteria themselves.
|
||||
*
|
||||
* @return the deserialized criteria. Each key-value pair consists of a {@code Criterion} and its name.
|
||||
* @see #criterionFromJson(JsonObject, JsonDeserializationContext)
|
||||
*
|
||||
* @param json the {@code JsonObject} to deserialize from
|
||||
* @param context the {@code JsonDeserializationContext} to deserialize in
|
||||
*/
|
||||
public static Map<String, Criterion> criteriaFromJson(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
Map<String, Criterion> map = Maps.<String, Criterion>newHashMap();
|
||||
|
||||
for (Entry<String, JsonElement> entry : json.entrySet())
|
||||
{
|
||||
map.put(entry.getKey(), criterionFromJson(JsonUtils.getJsonObject(entry.getValue(), "criterion"), context));
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read criteria from {@code buf}.
|
||||
*
|
||||
* @return the read criteria. Each key-value pair consists of a {@code Criterion} and its name.
|
||||
* @see #serializeToNetwork(Map, PacketBuffer)
|
||||
*
|
||||
* @param bus the {@code PacketBuffer} to read from
|
||||
*/
|
||||
public static Map<String, Criterion> criteriaFromNetwork(PacketBuffer bus)
|
||||
{
|
||||
Map<String, Criterion> map = Maps.<String, Criterion>newHashMap();
|
||||
int i = bus.readVarInt();
|
||||
|
||||
for (int j = 0; j < i; ++j)
|
||||
{
|
||||
map.put(bus.readString(32767), criterionFromNetwork(bus));
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write {@code criteria} to {@code buf}.
|
||||
*
|
||||
* @see #criteriaFromNetwork(PacketBuffer)
|
||||
*
|
||||
* @param criteria the criteria to write to {@code buf}. Each key-value pair consists of a {@code Criterion} and its
|
||||
* name.
|
||||
* @param buf the {@code PacketBuffer} to write to
|
||||
*/
|
||||
public static void serializeToNetwork(Map<String, Criterion> criteria, PacketBuffer buf)
|
||||
{
|
||||
buf.writeVarInt(criteria.size());
|
||||
|
||||
for (Entry<String, Criterion> entry : criteria.entrySet())
|
||||
{
|
||||
buf.writeString(entry.getKey());
|
||||
((Criterion)entry.getValue()).serializeToNetwork(buf);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ICriterionInstance getCriterionInstance()
|
||||
{
|
||||
return this.criterionInstance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package net.minecraft.advancements;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonNull;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
|
||||
public class CriterionProgress
|
||||
{
|
||||
private static final SimpleDateFormat DATE_TIME_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
|
||||
private final AdvancementProgress advancementProgress;
|
||||
private Date obtained;
|
||||
|
||||
public CriterionProgress(AdvancementProgress advancementProgressIn)
|
||||
{
|
||||
this.advancementProgress = advancementProgressIn;
|
||||
}
|
||||
|
||||
public boolean isObtained()
|
||||
{
|
||||
return this.obtained != null;
|
||||
}
|
||||
|
||||
public void obtain()
|
||||
{
|
||||
this.obtained = new Date();
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
this.obtained = null;
|
||||
}
|
||||
|
||||
public Date getObtained()
|
||||
{
|
||||
return this.obtained;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "CriterionProgress{obtained=" + (this.obtained == null ? "false" : this.obtained) + '}';
|
||||
}
|
||||
|
||||
public void write(PacketBuffer buf)
|
||||
{
|
||||
buf.writeBoolean(this.obtained != null);
|
||||
|
||||
if (this.obtained != null)
|
||||
{
|
||||
buf.writeTime(this.obtained);
|
||||
}
|
||||
}
|
||||
|
||||
public JsonElement serialize()
|
||||
{
|
||||
return (JsonElement)(this.obtained != null ? new JsonPrimitive(DATE_TIME_FORMATTER.format(this.obtained)) : JsonNull.INSTANCE);
|
||||
}
|
||||
|
||||
public static CriterionProgress read(PacketBuffer buf, AdvancementProgress advancementProgressIn)
|
||||
{
|
||||
CriterionProgress criterionprogress = new CriterionProgress(advancementProgressIn);
|
||||
|
||||
if (buf.readBoolean())
|
||||
{
|
||||
criterionprogress.obtained = buf.readTime();
|
||||
}
|
||||
|
||||
return criterionprogress;
|
||||
}
|
||||
|
||||
public static CriterionProgress fromDateTime(AdvancementProgress advancementProgressIn, String dateTime)
|
||||
{
|
||||
CriterionProgress criterionprogress = new CriterionProgress(advancementProgressIn);
|
||||
|
||||
try
|
||||
{
|
||||
criterionprogress.obtained = DATE_TIME_FORMATTER.parse(dateTime);
|
||||
return criterionprogress;
|
||||
}
|
||||
catch (ParseException parseexception)
|
||||
{
|
||||
throw new JsonSyntaxException("Invalid datetime: " + dateTime, parseexception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
package net.minecraft.advancements;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import java.io.IOException;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class DisplayInfo
|
||||
{
|
||||
private final ITextComponent title;
|
||||
private final ITextComponent description;
|
||||
private final ItemStack icon;
|
||||
private final ResourceLocation background;
|
||||
private final FrameType frame;
|
||||
private final boolean showToast;
|
||||
private final boolean announceToChat;
|
||||
private final boolean hidden;
|
||||
private float x;
|
||||
private float y;
|
||||
|
||||
public DisplayInfo(ItemStack icon, ITextComponent title, ITextComponent description, @Nullable ResourceLocation background, FrameType frame, boolean showToast, boolean announceToChat, boolean hidden)
|
||||
{
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.icon = icon;
|
||||
this.background = background;
|
||||
this.frame = frame;
|
||||
this.showToast = showToast;
|
||||
this.announceToChat = announceToChat;
|
||||
this.hidden = hidden;
|
||||
}
|
||||
|
||||
public void setPosition(float x, float y)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public ITextComponent getTitle()
|
||||
{
|
||||
return this.title;
|
||||
}
|
||||
|
||||
public ITextComponent getDescription()
|
||||
{
|
||||
return this.description;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public ItemStack getIcon()
|
||||
{
|
||||
return this.icon;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@SideOnly(Side.CLIENT)
|
||||
public ResourceLocation getBackground()
|
||||
{
|
||||
return this.background;
|
||||
}
|
||||
|
||||
public FrameType getFrame()
|
||||
{
|
||||
return this.frame;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public float getX()
|
||||
{
|
||||
return this.x;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public float getY()
|
||||
{
|
||||
return this.y;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public boolean shouldShowToast()
|
||||
{
|
||||
return this.showToast;
|
||||
}
|
||||
|
||||
public boolean shouldAnnounceToChat()
|
||||
{
|
||||
return this.announceToChat;
|
||||
}
|
||||
|
||||
public boolean isHidden()
|
||||
{
|
||||
return this.hidden;
|
||||
}
|
||||
|
||||
public static DisplayInfo deserialize(JsonObject object, JsonDeserializationContext context)
|
||||
{
|
||||
ITextComponent itextcomponent = (ITextComponent)JsonUtils.deserializeClass(object, "title", context, ITextComponent.class);
|
||||
ITextComponent itextcomponent1 = (ITextComponent)JsonUtils.deserializeClass(object, "description", context, ITextComponent.class);
|
||||
|
||||
if (itextcomponent != null && itextcomponent1 != null)
|
||||
{
|
||||
ItemStack itemstack = deserializeIcon(JsonUtils.getJsonObject(object, "icon"));
|
||||
ResourceLocation resourcelocation = object.has("background") ? new ResourceLocation(JsonUtils.getString(object, "background")) : null;
|
||||
FrameType frametype = object.has("frame") ? FrameType.byName(JsonUtils.getString(object, "frame")) : FrameType.TASK;
|
||||
boolean flag = JsonUtils.getBoolean(object, "show_toast", true);
|
||||
boolean flag1 = JsonUtils.getBoolean(object, "announce_to_chat", true);
|
||||
boolean flag2 = JsonUtils.getBoolean(object, "hidden", false);
|
||||
return new DisplayInfo(itemstack, itextcomponent, itextcomponent1, resourcelocation, frametype, flag, flag1, flag2);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new JsonSyntaxException("Both title and description must be set");
|
||||
}
|
||||
}
|
||||
|
||||
private static ItemStack deserializeIcon(JsonObject object)
|
||||
{
|
||||
if (!object.has("item"))
|
||||
{
|
||||
throw new JsonSyntaxException("Unsupported icon type, currently only items are supported (add 'item' key)");
|
||||
}
|
||||
else
|
||||
{
|
||||
Item item = JsonUtils.getItem(object, "item");
|
||||
int i = JsonUtils.getInt(object, "data", 0);
|
||||
ItemStack ret = new ItemStack(item, 1, i);
|
||||
ret.setTagCompound(net.minecraftforge.common.util.JsonUtils.readNBT(object, "nbt"));
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
public void write(PacketBuffer buf)
|
||||
{
|
||||
buf.writeTextComponent(this.title);
|
||||
buf.writeTextComponent(this.description);
|
||||
buf.writeItemStack(this.icon);
|
||||
buf.writeEnumValue(this.frame);
|
||||
int i = 0;
|
||||
|
||||
if (this.background != null)
|
||||
{
|
||||
i |= 1;
|
||||
}
|
||||
|
||||
if (this.showToast)
|
||||
{
|
||||
i |= 2;
|
||||
}
|
||||
|
||||
if (this.hidden)
|
||||
{
|
||||
i |= 4;
|
||||
}
|
||||
|
||||
buf.writeInt(i);
|
||||
|
||||
if (this.background != null)
|
||||
{
|
||||
buf.writeResourceLocation(this.background);
|
||||
}
|
||||
|
||||
buf.writeFloat(this.x);
|
||||
buf.writeFloat(this.y);
|
||||
}
|
||||
|
||||
public static DisplayInfo read(PacketBuffer buf) throws IOException
|
||||
{
|
||||
ITextComponent itextcomponent = buf.readTextComponent();
|
||||
ITextComponent itextcomponent1 = buf.readTextComponent();
|
||||
ItemStack itemstack = buf.readItemStack();
|
||||
FrameType frametype = (FrameType)buf.readEnumValue(FrameType.class);
|
||||
int i = buf.readInt();
|
||||
ResourceLocation resourcelocation = (i & 1) != 0 ? buf.readResourceLocation() : null;
|
||||
boolean flag = (i & 2) != 0;
|
||||
boolean flag1 = (i & 4) != 0;
|
||||
DisplayInfo displayinfo = new DisplayInfo(itemstack, itextcomponent, itextcomponent1, resourcelocation, frametype, flag, false, flag1);
|
||||
displayinfo.setPosition(buf.readFloat(), buf.readFloat());
|
||||
return displayinfo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package net.minecraft.advancements;
|
||||
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public enum FrameType
|
||||
{
|
||||
TASK("task", 0, TextFormatting.GREEN),
|
||||
CHALLENGE("challenge", 26, TextFormatting.DARK_PURPLE),
|
||||
GOAL("goal", 52, TextFormatting.GREEN);
|
||||
|
||||
private final String name;
|
||||
private final int icon;
|
||||
private final TextFormatting format;
|
||||
|
||||
private FrameType(String nameIn, int iconIn, TextFormatting formatIn)
|
||||
{
|
||||
this.name = nameIn;
|
||||
this.icon = iconIn;
|
||||
this.format = formatIn;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public static FrameType byName(String nameIn)
|
||||
{
|
||||
for (FrameType frametype : values())
|
||||
{
|
||||
if (frametype.name.equals(nameIn))
|
||||
{
|
||||
return frametype;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unknown frame type '" + nameIn + "'");
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public int getIcon()
|
||||
{
|
||||
return this.icon;
|
||||
}
|
||||
|
||||
public TextFormatting getFormat()
|
||||
{
|
||||
return this.format;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
package net.minecraft.advancements;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.io.Files;
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.command.FunctionObject;
|
||||
import net.minecraft.command.ICommandManager;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.util.ITickable;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.World;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class FunctionManager implements ITickable
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private final File functionDir;
|
||||
private final MinecraftServer server;
|
||||
private final Map<ResourceLocation, FunctionObject> functions = Maps.<ResourceLocation, FunctionObject>newHashMap();
|
||||
private String currentGameLoopFunctionId = "-";
|
||||
private FunctionObject gameLoopFunction;
|
||||
private final ArrayDeque<FunctionManager.QueuedCommand> commandQueue = new ArrayDeque<FunctionManager.QueuedCommand>();
|
||||
private boolean isExecuting = false;
|
||||
private final ICommandSender gameLoopFunctionSender = new ICommandSender()
|
||||
{
|
||||
/**
|
||||
* Get the name of this object. For players this returns their username
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return FunctionManager.this.currentGameLoopFunctionId;
|
||||
}
|
||||
/**
|
||||
* Returns {@code true} if the CommandSender is allowed to execute the command, {@code false} if not
|
||||
*/
|
||||
public boolean canUseCommand(int permLevel, String commandName)
|
||||
{
|
||||
return permLevel <= 2;
|
||||
}
|
||||
/**
|
||||
* Get the world, if available. <b>{@code null} is not allowed!</b> If you are not an entity in the world,
|
||||
* return the overworld
|
||||
*/
|
||||
public World getEntityWorld()
|
||||
{
|
||||
return FunctionManager.this.server.worlds[0];
|
||||
}
|
||||
/**
|
||||
* Get the Minecraft server instance
|
||||
*/
|
||||
public MinecraftServer getServer()
|
||||
{
|
||||
return FunctionManager.this.server;
|
||||
}
|
||||
};
|
||||
|
||||
public FunctionManager(@Nullable File functionDirIn, MinecraftServer serverIn)
|
||||
{
|
||||
this.functionDir = functionDirIn;
|
||||
this.server = serverIn;
|
||||
this.reload();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FunctionObject getFunction(ResourceLocation id)
|
||||
{
|
||||
return this.functions.get(id);
|
||||
}
|
||||
|
||||
public ICommandManager getCommandManager()
|
||||
{
|
||||
return this.server.getCommandManager();
|
||||
}
|
||||
|
||||
public int getMaxCommandChainLength()
|
||||
{
|
||||
return this.server.worlds[0].getGameRules().getInt("maxCommandChainLength");
|
||||
}
|
||||
|
||||
public Map<ResourceLocation, FunctionObject> getFunctions()
|
||||
{
|
||||
return this.functions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Like the old updateEntity(), except more generic.
|
||||
*/
|
||||
public void update()
|
||||
{
|
||||
String s = this.server.worlds[0].getGameRules().getString("gameLoopFunction");
|
||||
|
||||
if (!s.equals(this.currentGameLoopFunctionId))
|
||||
{
|
||||
this.currentGameLoopFunctionId = s;
|
||||
this.gameLoopFunction = this.getFunction(new ResourceLocation(s));
|
||||
}
|
||||
|
||||
if (this.gameLoopFunction != null)
|
||||
{
|
||||
this.execute(this.gameLoopFunction, this.gameLoopFunctionSender);
|
||||
}
|
||||
}
|
||||
|
||||
public int execute(FunctionObject function, ICommandSender sender)
|
||||
{
|
||||
int i = this.getMaxCommandChainLength();
|
||||
|
||||
if (this.isExecuting)
|
||||
{
|
||||
if (this.commandQueue.size() < i)
|
||||
{
|
||||
this.commandQueue.addFirst(new FunctionManager.QueuedCommand(this, sender, new FunctionObject.FunctionEntry(function)));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int l;
|
||||
|
||||
try
|
||||
{
|
||||
this.isExecuting = true;
|
||||
int j = 0;
|
||||
FunctionObject.Entry[] afunctionobject$entry = function.getEntries();
|
||||
|
||||
for (int k = afunctionobject$entry.length - 1; k >= 0; --k)
|
||||
{
|
||||
this.commandQueue.push(new FunctionManager.QueuedCommand(this, sender, afunctionobject$entry[k]));
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (this.commandQueue.isEmpty())
|
||||
{
|
||||
l = j;
|
||||
return l;
|
||||
}
|
||||
|
||||
(this.commandQueue.removeFirst()).execute(this.commandQueue, i);
|
||||
++j;
|
||||
|
||||
if (j >= i)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
l = j;
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.commandQueue.clear();
|
||||
this.isExecuting = false;
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
}
|
||||
|
||||
public void reload()
|
||||
{
|
||||
this.functions.clear();
|
||||
this.gameLoopFunction = null;
|
||||
this.currentGameLoopFunctionId = "-";
|
||||
this.loadFunctions();
|
||||
}
|
||||
|
||||
private void loadFunctions()
|
||||
{
|
||||
if (this.functionDir != null)
|
||||
{
|
||||
this.functionDir.mkdirs();
|
||||
|
||||
for (File file1 : FileUtils.listFiles(this.functionDir, new String[] {"mcfunction"}, true))
|
||||
{
|
||||
String s = FilenameUtils.removeExtension(this.functionDir.toURI().relativize(file1.toURI()).toString());
|
||||
String[] astring = s.split("/", 2);
|
||||
|
||||
if (astring.length == 2)
|
||||
{
|
||||
ResourceLocation resourcelocation = new ResourceLocation(astring[0], astring[1]);
|
||||
|
||||
try
|
||||
{
|
||||
this.functions.put(resourcelocation, FunctionObject.create(this, Files.readLines(file1, StandardCharsets.UTF_8)));
|
||||
}
|
||||
catch (Throwable throwable)
|
||||
{
|
||||
LOGGER.error("Couldn't read custom function " + resourcelocation + " from " + file1, throwable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.functions.isEmpty())
|
||||
{
|
||||
LOGGER.info("Loaded " + this.functions.size() + " custom command functions");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class QueuedCommand
|
||||
{
|
||||
private final FunctionManager functionManager;
|
||||
private final ICommandSender sender;
|
||||
private final FunctionObject.Entry entry;
|
||||
|
||||
public QueuedCommand(FunctionManager functionManagerIn, ICommandSender senderIn, FunctionObject.Entry entryIn)
|
||||
{
|
||||
this.functionManager = functionManagerIn;
|
||||
this.sender = senderIn;
|
||||
this.entry = entryIn;
|
||||
}
|
||||
|
||||
public void execute(ArrayDeque<FunctionManager.QueuedCommand> commandQueue, int maxCommandChainLength)
|
||||
{
|
||||
this.entry.execute(this.functionManager, this.sender, commandQueue, maxCommandChainLength);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return this.entry.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package net.minecraft.advancements;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public interface ICriterionInstance
|
||||
{
|
||||
ResourceLocation getId();
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package net.minecraft.advancements;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public interface ICriterionTrigger<T extends ICriterionInstance>
|
||||
{
|
||||
ResourceLocation getId();
|
||||
|
||||
void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<T> listener);
|
||||
|
||||
void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<T> listener);
|
||||
|
||||
void removeAllListeners(PlayerAdvancements playerAdvancementsIn);
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
T deserializeInstance(JsonObject json, JsonDeserializationContext context);
|
||||
|
||||
public static class Listener<T extends ICriterionInstance>
|
||||
{
|
||||
private final T criterionInstance;
|
||||
private final Advancement advancement;
|
||||
private final String criterionName;
|
||||
|
||||
public Listener(T criterionInstanceIn, Advancement advancementIn, String criterionNameIn)
|
||||
{
|
||||
this.criterionInstance = criterionInstanceIn;
|
||||
this.advancement = advancementIn;
|
||||
this.criterionName = criterionNameIn;
|
||||
}
|
||||
|
||||
public T getCriterionInstance()
|
||||
{
|
||||
return this.criterionInstance;
|
||||
}
|
||||
|
||||
public void grantCriterion(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
playerAdvancementsIn.grantCriterion(this.advancement, this.criterionName);
|
||||
}
|
||||
|
||||
public boolean equals(Object p_equals_1_)
|
||||
{
|
||||
if (this == p_equals_1_)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (p_equals_1_ != null && this.getClass() == p_equals_1_.getClass())
|
||||
{
|
||||
ICriterionTrigger.Listener<?> listener = (ICriterionTrigger.Listener)p_equals_1_;
|
||||
|
||||
if (!this.criterionInstance.equals(listener.criterionInstance))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return !this.advancement.equals(listener.advancement) ? false : this.criterionName.equals(listener.criterionName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
int i = this.criterionInstance.hashCode();
|
||||
i = 31 * i + this.advancement.hashCode();
|
||||
i = 31 * i + this.criterionName.hashCode();
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,468 @@
|
||||
package net.minecraft.advancements;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.io.Files;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.network.play.server.SPacketAdvancementInfo;
|
||||
import net.minecraft.network.play.server.SPacketSelectAdvancementsTab;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.text.TextComponentTranslation;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class PlayerAdvancements
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static final Gson GSON = (new GsonBuilder()).registerTypeAdapter(AdvancementProgress.class, new AdvancementProgress.Serializer()).registerTypeAdapter(ResourceLocation.class, new ResourceLocation.Serializer()).setPrettyPrinting().create();
|
||||
private static final TypeToken<Map<ResourceLocation, AdvancementProgress>> MAP_TOKEN = new TypeToken<Map<ResourceLocation, AdvancementProgress>>()
|
||||
{
|
||||
};
|
||||
private final MinecraftServer server;
|
||||
private final File progressFile;
|
||||
private final Map<Advancement, AdvancementProgress> progress = Maps.<Advancement, AdvancementProgress>newLinkedHashMap();
|
||||
private final Set<Advancement> visible = Sets.<Advancement>newLinkedHashSet();
|
||||
private final Set<Advancement> visibilityChanged = Sets.<Advancement>newLinkedHashSet();
|
||||
private final Set<Advancement> progressChanged = Sets.<Advancement>newLinkedHashSet();
|
||||
private EntityPlayerMP player;
|
||||
@Nullable
|
||||
private Advancement lastSelectedTab;
|
||||
private boolean isFirstPacket = true;
|
||||
|
||||
public PlayerAdvancements(MinecraftServer server, File p_i47422_2_, EntityPlayerMP player)
|
||||
{
|
||||
this.server = server;
|
||||
this.progressFile = p_i47422_2_;
|
||||
this.player = player;
|
||||
this.load();
|
||||
}
|
||||
|
||||
public void setPlayer(EntityPlayerMP player)
|
||||
{
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
for (ICriterionTrigger<?> icriteriontrigger : CriteriaTriggers.getAll())
|
||||
{
|
||||
icriteriontrigger.removeAllListeners(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void reload()
|
||||
{
|
||||
this.dispose();
|
||||
this.progress.clear();
|
||||
this.visible.clear();
|
||||
this.visibilityChanged.clear();
|
||||
this.progressChanged.clear();
|
||||
this.isFirstPacket = true;
|
||||
this.lastSelectedTab = null;
|
||||
this.load();
|
||||
}
|
||||
|
||||
private void registerListeners()
|
||||
{
|
||||
for (Advancement advancement : this.server.getAdvancementManager().getAdvancements())
|
||||
{
|
||||
this.registerListeners(advancement);
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureAllVisible()
|
||||
{
|
||||
List<Advancement> list = Lists.<Advancement>newArrayList();
|
||||
|
||||
for (Entry<Advancement, AdvancementProgress> entry : this.progress.entrySet())
|
||||
{
|
||||
if (((AdvancementProgress)entry.getValue()).isDone())
|
||||
{
|
||||
list.add(entry.getKey());
|
||||
this.progressChanged.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
for (Advancement advancement : list)
|
||||
{
|
||||
this.ensureVisibility(advancement);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForAutomaticTriggers()
|
||||
{
|
||||
for (Advancement advancement : this.server.getAdvancementManager().getAdvancements())
|
||||
{
|
||||
if (advancement.getCriteria().isEmpty())
|
||||
{
|
||||
this.grantCriterion(advancement, "");
|
||||
advancement.getRewards().apply(this.player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void load()
|
||||
{
|
||||
if (this.progressFile.isFile())
|
||||
{
|
||||
try
|
||||
{
|
||||
String s = Files.toString(this.progressFile, StandardCharsets.UTF_8);
|
||||
Map<ResourceLocation, AdvancementProgress> map = (Map)JsonUtils.gsonDeserialize(GSON, s, MAP_TOKEN.getType());
|
||||
|
||||
if (map == null)
|
||||
{
|
||||
throw new JsonParseException("Found null for advancements");
|
||||
}
|
||||
|
||||
Stream<Entry<ResourceLocation, AdvancementProgress>> stream = map.entrySet().stream().sorted(Comparator.comparing(Entry::getValue));
|
||||
|
||||
for (Entry<ResourceLocation, AdvancementProgress> entry : stream.collect(Collectors.toList()))
|
||||
{
|
||||
Advancement advancement = this.server.getAdvancementManager().getAdvancement(entry.getKey());
|
||||
|
||||
if (advancement == null)
|
||||
{
|
||||
LOGGER.warn("Ignored advancement '" + entry.getKey() + "' in progress file " + this.progressFile + " - it doesn't exist anymore?");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.startProgress(advancement, entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (JsonParseException jsonparseexception)
|
||||
{
|
||||
LOGGER.error("Couldn't parse player advancements in " + this.progressFile, (Throwable)jsonparseexception);
|
||||
}
|
||||
catch (IOException ioexception)
|
||||
{
|
||||
LOGGER.error("Couldn't access player advancements in " + this.progressFile, (Throwable)ioexception);
|
||||
}
|
||||
}
|
||||
|
||||
this.checkForAutomaticTriggers();
|
||||
this.ensureAllVisible();
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
public void save()
|
||||
{
|
||||
Map<ResourceLocation, AdvancementProgress> map = Maps.<ResourceLocation, AdvancementProgress>newHashMap();
|
||||
|
||||
for (Entry<Advancement, AdvancementProgress> entry : this.progress.entrySet())
|
||||
{
|
||||
AdvancementProgress advancementprogress = entry.getValue();
|
||||
|
||||
if (advancementprogress.hasProgress())
|
||||
{
|
||||
map.put(((Advancement)entry.getKey()).getId(), advancementprogress);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.progressFile.getParentFile() != null)
|
||||
{
|
||||
this.progressFile.getParentFile().mkdirs();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Files.write(GSON.toJson(map), this.progressFile, StandardCharsets.UTF_8);
|
||||
}
|
||||
catch (IOException ioexception)
|
||||
{
|
||||
LOGGER.error("Couldn't save player advancements to " + this.progressFile, (Throwable)ioexception);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean grantCriterion(Advancement p_192750_1_, String p_192750_2_)
|
||||
{
|
||||
// Forge: don't grant advancements for fake players
|
||||
if (this.player instanceof net.minecraftforge.common.util.FakePlayer) return false;
|
||||
|
||||
boolean flag = false;
|
||||
AdvancementProgress advancementprogress = this.getProgress(p_192750_1_);
|
||||
boolean flag1 = advancementprogress.isDone();
|
||||
|
||||
if (advancementprogress.grantCriterion(p_192750_2_))
|
||||
{
|
||||
this.unregisterListeners(p_192750_1_);
|
||||
this.progressChanged.add(p_192750_1_);
|
||||
flag = true;
|
||||
|
||||
if (!flag1 && advancementprogress.isDone())
|
||||
{
|
||||
p_192750_1_.getRewards().apply(this.player);
|
||||
|
||||
if (p_192750_1_.getDisplay() != null && p_192750_1_.getDisplay().shouldAnnounceToChat() && this.player.world.getGameRules().getBoolean("announceAdvancements"))
|
||||
{
|
||||
this.server.getPlayerList().sendMessage(new TextComponentTranslation("chat.type.advancement." + p_192750_1_.getDisplay().getFrame().getName(), new Object[] {this.player.getDisplayName(), p_192750_1_.getDisplayText()}));
|
||||
}
|
||||
|
||||
net.minecraftforge.common.ForgeHooks.onAdvancement(this.player, p_192750_1_);
|
||||
}
|
||||
}
|
||||
|
||||
if (advancementprogress.isDone())
|
||||
{
|
||||
this.ensureVisibility(p_192750_1_);
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
public boolean revokeCriterion(Advancement p_192744_1_, String p_192744_2_)
|
||||
{
|
||||
boolean flag = false;
|
||||
AdvancementProgress advancementprogress = this.getProgress(p_192744_1_);
|
||||
|
||||
if (advancementprogress.revokeCriterion(p_192744_2_))
|
||||
{
|
||||
this.registerListeners(p_192744_1_);
|
||||
this.progressChanged.add(p_192744_1_);
|
||||
flag = true;
|
||||
}
|
||||
|
||||
if (!advancementprogress.hasProgress())
|
||||
{
|
||||
this.ensureVisibility(p_192744_1_);
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
private void registerListeners(Advancement p_193764_1_)
|
||||
{
|
||||
AdvancementProgress advancementprogress = this.getProgress(p_193764_1_);
|
||||
|
||||
if (!advancementprogress.isDone())
|
||||
{
|
||||
for (Entry<String, Criterion> entry : p_193764_1_.getCriteria().entrySet())
|
||||
{
|
||||
CriterionProgress criterionprogress = advancementprogress.getCriterionProgress(entry.getKey());
|
||||
|
||||
if (criterionprogress != null && !criterionprogress.isObtained())
|
||||
{
|
||||
ICriterionInstance icriterioninstance = ((Criterion)entry.getValue()).getCriterionInstance();
|
||||
|
||||
if (icriterioninstance != null)
|
||||
{
|
||||
ICriterionTrigger<ICriterionInstance> icriteriontrigger = CriteriaTriggers.<ICriterionInstance>get(icriterioninstance.getId());
|
||||
|
||||
if (icriteriontrigger != null)
|
||||
{
|
||||
icriteriontrigger.addListener(this, new ICriterionTrigger.Listener(icriterioninstance, p_193764_1_, entry.getKey()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void unregisterListeners(Advancement p_193765_1_)
|
||||
{
|
||||
AdvancementProgress advancementprogress = this.getProgress(p_193765_1_);
|
||||
|
||||
for (Entry<String, Criterion> entry : p_193765_1_.getCriteria().entrySet())
|
||||
{
|
||||
CriterionProgress criterionprogress = advancementprogress.getCriterionProgress(entry.getKey());
|
||||
|
||||
if (criterionprogress != null && (criterionprogress.isObtained() || advancementprogress.isDone()))
|
||||
{
|
||||
ICriterionInstance icriterioninstance = ((Criterion)entry.getValue()).getCriterionInstance();
|
||||
|
||||
if (icriterioninstance != null)
|
||||
{
|
||||
ICriterionTrigger<ICriterionInstance> icriteriontrigger = CriteriaTriggers.<ICriterionInstance>get(icriterioninstance.getId());
|
||||
|
||||
if (icriteriontrigger != null)
|
||||
{
|
||||
icriteriontrigger.removeListener(this, new ICriterionTrigger.Listener(icriterioninstance, p_193765_1_, entry.getKey()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void flushDirty(EntityPlayerMP p_192741_1_)
|
||||
{
|
||||
if (!this.visibilityChanged.isEmpty() || !this.progressChanged.isEmpty())
|
||||
{
|
||||
Map<ResourceLocation, AdvancementProgress> map = Maps.<ResourceLocation, AdvancementProgress>newHashMap();
|
||||
Set<Advancement> set = Sets.<Advancement>newLinkedHashSet();
|
||||
Set<ResourceLocation> set1 = Sets.<ResourceLocation>newLinkedHashSet();
|
||||
|
||||
for (Advancement advancement : this.progressChanged)
|
||||
{
|
||||
if (this.visible.contains(advancement))
|
||||
{
|
||||
map.put(advancement.getId(), this.progress.get(advancement));
|
||||
}
|
||||
}
|
||||
|
||||
for (Advancement advancement1 : this.visibilityChanged)
|
||||
{
|
||||
if (this.visible.contains(advancement1))
|
||||
{
|
||||
set.add(advancement1);
|
||||
}
|
||||
else
|
||||
{
|
||||
set1.add(advancement1.getId());
|
||||
}
|
||||
}
|
||||
|
||||
if (!map.isEmpty() || !set.isEmpty() || !set1.isEmpty())
|
||||
{
|
||||
p_192741_1_.connection.sendPacket(new SPacketAdvancementInfo(this.isFirstPacket, set, set1, map));
|
||||
this.visibilityChanged.clear();
|
||||
this.progressChanged.clear();
|
||||
}
|
||||
}
|
||||
|
||||
this.isFirstPacket = false;
|
||||
}
|
||||
|
||||
public void setSelectedTab(@Nullable Advancement p_194220_1_)
|
||||
{
|
||||
Advancement advancement = this.lastSelectedTab;
|
||||
|
||||
if (p_194220_1_ != null && p_194220_1_.getParent() == null && p_194220_1_.getDisplay() != null)
|
||||
{
|
||||
this.lastSelectedTab = p_194220_1_;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.lastSelectedTab = null;
|
||||
}
|
||||
|
||||
if (advancement != this.lastSelectedTab)
|
||||
{
|
||||
this.player.connection.sendPacket(new SPacketSelectAdvancementsTab(this.lastSelectedTab == null ? null : this.lastSelectedTab.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
public AdvancementProgress getProgress(Advancement advancementIn)
|
||||
{
|
||||
AdvancementProgress advancementprogress = this.progress.get(advancementIn);
|
||||
|
||||
if (advancementprogress == null)
|
||||
{
|
||||
advancementprogress = new AdvancementProgress();
|
||||
this.startProgress(advancementIn, advancementprogress);
|
||||
}
|
||||
|
||||
return advancementprogress;
|
||||
}
|
||||
|
||||
private void startProgress(Advancement p_192743_1_, AdvancementProgress p_192743_2_)
|
||||
{
|
||||
p_192743_2_.update(p_192743_1_.getCriteria(), p_192743_1_.getRequirements());
|
||||
this.progress.put(p_192743_1_, p_192743_2_);
|
||||
}
|
||||
|
||||
private void ensureVisibility(Advancement p_192742_1_)
|
||||
{
|
||||
boolean flag = this.shouldBeVisible(p_192742_1_);
|
||||
boolean flag1 = this.visible.contains(p_192742_1_);
|
||||
|
||||
if (flag && !flag1)
|
||||
{
|
||||
this.visible.add(p_192742_1_);
|
||||
this.visibilityChanged.add(p_192742_1_);
|
||||
|
||||
if (this.progress.containsKey(p_192742_1_))
|
||||
{
|
||||
this.progressChanged.add(p_192742_1_);
|
||||
}
|
||||
}
|
||||
else if (!flag && flag1)
|
||||
{
|
||||
this.visible.remove(p_192742_1_);
|
||||
this.visibilityChanged.add(p_192742_1_);
|
||||
}
|
||||
|
||||
if (flag != flag1 && p_192742_1_.getParent() != null)
|
||||
{
|
||||
this.ensureVisibility(p_192742_1_.getParent());
|
||||
}
|
||||
|
||||
for (Advancement advancement : p_192742_1_.getChildren())
|
||||
{
|
||||
this.ensureVisibility(advancement);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldBeVisible(Advancement p_192738_1_)
|
||||
{
|
||||
for (int i = 0; p_192738_1_ != null && i <= 2; ++i)
|
||||
{
|
||||
if (i == 0 && this.hasCompletedChildrenOrSelf(p_192738_1_))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (p_192738_1_.getDisplay() == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AdvancementProgress advancementprogress = this.getProgress(p_192738_1_);
|
||||
|
||||
if (advancementprogress.isDone())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (p_192738_1_.getDisplay().isHidden())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
p_192738_1_ = p_192738_1_.getParent();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean hasCompletedChildrenOrSelf(Advancement p_192746_1_)
|
||||
{
|
||||
AdvancementProgress advancementprogress = this.getProgress(p_192746_1_);
|
||||
|
||||
if (advancementprogress.isDone())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Advancement advancement : p_192746_1_.getChildren())
|
||||
{
|
||||
if (this.hasCompletedChildrenOrSelf(advancement))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import net.minecraft.advancements.ICriterionInstance;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class AbstractCriterionInstance implements ICriterionInstance
|
||||
{
|
||||
private final ResourceLocation criterion;
|
||||
|
||||
public AbstractCriterionInstance(ResourceLocation criterionIn)
|
||||
{
|
||||
this.criterion = criterionIn;
|
||||
}
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return this.criterion;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "AbstractCriterionInstance{criterion=" + this.criterion + '}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.entity.EntityAgeable;
|
||||
import net.minecraft.entity.passive.EntityAnimal;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class BredAnimalsTrigger implements ICriterionTrigger<BredAnimalsTrigger.Instance>
|
||||
{
|
||||
private static final ResourceLocation ID = new ResourceLocation("bred_animals");
|
||||
private final Map<PlayerAdvancements, BredAnimalsTrigger.Listeners> listeners = Maps.<PlayerAdvancements, BredAnimalsTrigger.Listeners>newHashMap();
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<BredAnimalsTrigger.Instance> listener)
|
||||
{
|
||||
BredAnimalsTrigger.Listeners bredanimalstrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (bredanimalstrigger$listeners == null)
|
||||
{
|
||||
bredanimalstrigger$listeners = new BredAnimalsTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, bredanimalstrigger$listeners);
|
||||
}
|
||||
|
||||
bredanimalstrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<BredAnimalsTrigger.Instance> listener)
|
||||
{
|
||||
BredAnimalsTrigger.Listeners bredanimalstrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (bredanimalstrigger$listeners != null)
|
||||
{
|
||||
bredanimalstrigger$listeners.remove(listener);
|
||||
|
||||
if (bredanimalstrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public BredAnimalsTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
EntityPredicate entitypredicate = EntityPredicate.deserialize(json.get("parent"));
|
||||
EntityPredicate entitypredicate1 = EntityPredicate.deserialize(json.get("partner"));
|
||||
EntityPredicate entitypredicate2 = EntityPredicate.deserialize(json.get("child"));
|
||||
return new BredAnimalsTrigger.Instance(entitypredicate, entitypredicate1, entitypredicate2);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, EntityAnimal parent1, EntityAnimal parent2, EntityAgeable child)
|
||||
{
|
||||
BredAnimalsTrigger.Listeners bredanimalstrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (bredanimalstrigger$listeners != null)
|
||||
{
|
||||
bredanimalstrigger$listeners.trigger(player, parent1, parent2, child);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
private final EntityPredicate parent;
|
||||
private final EntityPredicate partner;
|
||||
private final EntityPredicate child;
|
||||
|
||||
public Instance(EntityPredicate parent, EntityPredicate partner, EntityPredicate child)
|
||||
{
|
||||
super(BredAnimalsTrigger.ID);
|
||||
this.parent = parent;
|
||||
this.partner = partner;
|
||||
this.child = child;
|
||||
}
|
||||
|
||||
public boolean test(EntityPlayerMP player, EntityAnimal parent1In, EntityAnimal parent2In, EntityAgeable childIn)
|
||||
{
|
||||
if (!this.child.test(player, childIn))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.parent.test(player, parent1In) && this.partner.test(player, parent2In) || this.parent.test(player, parent2In) && this.partner.test(player, parent1In);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<BredAnimalsTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<BredAnimalsTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<BredAnimalsTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<BredAnimalsTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, EntityAnimal parent1, EntityAnimal parent2, EntityAgeable child)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<BredAnimalsTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<BredAnimalsTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((BredAnimalsTrigger.Instance)listener.getCriterionInstance()).test(player, parent1, parent2, child))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<BredAnimalsTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<BredAnimalsTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.potion.PotionType;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class BrewedPotionTrigger implements ICriterionTrigger<BrewedPotionTrigger.Instance>
|
||||
{
|
||||
private static final ResourceLocation ID = new ResourceLocation("brewed_potion");
|
||||
private final Map<PlayerAdvancements, BrewedPotionTrigger.Listeners> listeners = Maps.<PlayerAdvancements, BrewedPotionTrigger.Listeners>newHashMap();
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<BrewedPotionTrigger.Instance> listener)
|
||||
{
|
||||
BrewedPotionTrigger.Listeners brewedpotiontrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (brewedpotiontrigger$listeners == null)
|
||||
{
|
||||
brewedpotiontrigger$listeners = new BrewedPotionTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, brewedpotiontrigger$listeners);
|
||||
}
|
||||
|
||||
brewedpotiontrigger$listeners.addListener(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<BrewedPotionTrigger.Instance> listener)
|
||||
{
|
||||
BrewedPotionTrigger.Listeners brewedpotiontrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (brewedpotiontrigger$listeners != null)
|
||||
{
|
||||
brewedpotiontrigger$listeners.removeListener(listener);
|
||||
|
||||
if (brewedpotiontrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public BrewedPotionTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
PotionType potiontype = null;
|
||||
|
||||
if (json.has("potion"))
|
||||
{
|
||||
ResourceLocation resourcelocation = new ResourceLocation(JsonUtils.getString(json, "potion"));
|
||||
|
||||
if (!PotionType.REGISTRY.containsKey(resourcelocation))
|
||||
{
|
||||
throw new JsonSyntaxException("Unknown potion '" + resourcelocation + "'");
|
||||
}
|
||||
|
||||
potiontype = PotionType.REGISTRY.getObject(resourcelocation);
|
||||
}
|
||||
|
||||
return new BrewedPotionTrigger.Instance(potiontype);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, PotionType potionIn)
|
||||
{
|
||||
BrewedPotionTrigger.Listeners brewedpotiontrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (brewedpotiontrigger$listeners != null)
|
||||
{
|
||||
brewedpotiontrigger$listeners.trigger(potionIn);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
private final PotionType potion;
|
||||
|
||||
public Instance(@Nullable PotionType potion)
|
||||
{
|
||||
super(BrewedPotionTrigger.ID);
|
||||
this.potion = potion;
|
||||
}
|
||||
|
||||
public boolean test(PotionType potion)
|
||||
{
|
||||
return this.potion == null || this.potion == potion;
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<BrewedPotionTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<BrewedPotionTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void addListener(ICriterionTrigger.Listener<BrewedPotionTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(ICriterionTrigger.Listener<BrewedPotionTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(PotionType potion)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<BrewedPotionTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<BrewedPotionTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((BrewedPotionTrigger.Instance)listener.getCriterionInstance()).test(potion))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<BrewedPotionTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<BrewedPotionTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.DimensionType;
|
||||
|
||||
public class ChangeDimensionTrigger implements ICriterionTrigger<ChangeDimensionTrigger.Instance>
|
||||
{
|
||||
private static final ResourceLocation ID = new ResourceLocation("changed_dimension");
|
||||
private final Map<PlayerAdvancements, ChangeDimensionTrigger.Listeners> listeners = Maps.<PlayerAdvancements, ChangeDimensionTrigger.Listeners>newHashMap();
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<ChangeDimensionTrigger.Instance> listener)
|
||||
{
|
||||
ChangeDimensionTrigger.Listeners changedimensiontrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (changedimensiontrigger$listeners == null)
|
||||
{
|
||||
changedimensiontrigger$listeners = new ChangeDimensionTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, changedimensiontrigger$listeners);
|
||||
}
|
||||
|
||||
changedimensiontrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<ChangeDimensionTrigger.Instance> listener)
|
||||
{
|
||||
ChangeDimensionTrigger.Listeners changedimensiontrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (changedimensiontrigger$listeners != null)
|
||||
{
|
||||
changedimensiontrigger$listeners.remove(listener);
|
||||
|
||||
if (changedimensiontrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public ChangeDimensionTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
DimensionType dimensiontype = json.has("from") ? DimensionType.byName(JsonUtils.getString(json, "from")) : null;
|
||||
DimensionType dimensiontype1 = json.has("to") ? DimensionType.byName(JsonUtils.getString(json, "to")) : null;
|
||||
return new ChangeDimensionTrigger.Instance(dimensiontype, dimensiontype1);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, DimensionType from, DimensionType to)
|
||||
{
|
||||
ChangeDimensionTrigger.Listeners changedimensiontrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (changedimensiontrigger$listeners != null)
|
||||
{
|
||||
changedimensiontrigger$listeners.trigger(from, to);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
@Nullable
|
||||
private final DimensionType from;
|
||||
@Nullable
|
||||
private final DimensionType to;
|
||||
|
||||
public Instance(@Nullable DimensionType from, @Nullable DimensionType to)
|
||||
{
|
||||
super(ChangeDimensionTrigger.ID);
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
public boolean test(DimensionType from, DimensionType to)
|
||||
{
|
||||
if (this.from != null && this.from != from)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.to == null || this.to == to;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<ChangeDimensionTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<ChangeDimensionTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<ChangeDimensionTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<ChangeDimensionTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(DimensionType from, DimensionType to)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<ChangeDimensionTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<ChangeDimensionTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((ChangeDimensionTrigger.Instance)listener.getCriterionInstance()).test(from, to))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<ChangeDimensionTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<ChangeDimensionTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.tileentity.TileEntityBeacon;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class ConstructBeaconTrigger implements ICriterionTrigger<ConstructBeaconTrigger.Instance>
|
||||
{
|
||||
private static final ResourceLocation ID = new ResourceLocation("construct_beacon");
|
||||
private final Map<PlayerAdvancements, ConstructBeaconTrigger.Listeners> listeners = Maps.<PlayerAdvancements, ConstructBeaconTrigger.Listeners>newHashMap();
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<ConstructBeaconTrigger.Instance> listener)
|
||||
{
|
||||
ConstructBeaconTrigger.Listeners constructbeacontrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (constructbeacontrigger$listeners == null)
|
||||
{
|
||||
constructbeacontrigger$listeners = new ConstructBeaconTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, constructbeacontrigger$listeners);
|
||||
}
|
||||
|
||||
constructbeacontrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<ConstructBeaconTrigger.Instance> listener)
|
||||
{
|
||||
ConstructBeaconTrigger.Listeners constructbeacontrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (constructbeacontrigger$listeners != null)
|
||||
{
|
||||
constructbeacontrigger$listeners.remove(listener);
|
||||
|
||||
if (constructbeacontrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public ConstructBeaconTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
MinMaxBounds minmaxbounds = MinMaxBounds.deserialize(json.get("level"));
|
||||
return new ConstructBeaconTrigger.Instance(minmaxbounds);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, TileEntityBeacon beacon)
|
||||
{
|
||||
ConstructBeaconTrigger.Listeners constructbeacontrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (constructbeacontrigger$listeners != null)
|
||||
{
|
||||
constructbeacontrigger$listeners.trigger(beacon);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
private final MinMaxBounds level;
|
||||
|
||||
public Instance(MinMaxBounds level)
|
||||
{
|
||||
super(ConstructBeaconTrigger.ID);
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
public boolean test(TileEntityBeacon beacon)
|
||||
{
|
||||
return this.level.test((float)beacon.getLevels());
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<ConstructBeaconTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<ConstructBeaconTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<ConstructBeaconTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<ConstructBeaconTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(TileEntityBeacon beacon)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<ConstructBeaconTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<ConstructBeaconTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((ConstructBeaconTrigger.Instance)listener.getCriterionInstance()).test(beacon))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<ConstructBeaconTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<ConstructBeaconTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class ConsumeItemTrigger implements ICriterionTrigger<ConsumeItemTrigger.Instance>
|
||||
{
|
||||
private static final ResourceLocation ID = new ResourceLocation("consume_item");
|
||||
private final Map<PlayerAdvancements, ConsumeItemTrigger.Listeners> listeners = Maps.<PlayerAdvancements, ConsumeItemTrigger.Listeners>newHashMap();
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<ConsumeItemTrigger.Instance> listener)
|
||||
{
|
||||
ConsumeItemTrigger.Listeners consumeitemtrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (consumeitemtrigger$listeners == null)
|
||||
{
|
||||
consumeitemtrigger$listeners = new ConsumeItemTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, consumeitemtrigger$listeners);
|
||||
}
|
||||
|
||||
consumeitemtrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<ConsumeItemTrigger.Instance> listener)
|
||||
{
|
||||
ConsumeItemTrigger.Listeners consumeitemtrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (consumeitemtrigger$listeners != null)
|
||||
{
|
||||
consumeitemtrigger$listeners.remove(listener);
|
||||
|
||||
if (consumeitemtrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public ConsumeItemTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
ItemPredicate itempredicate = ItemPredicate.deserialize(json.get("item"));
|
||||
return new ConsumeItemTrigger.Instance(itempredicate);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, ItemStack item)
|
||||
{
|
||||
ConsumeItemTrigger.Listeners consumeitemtrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (consumeitemtrigger$listeners != null)
|
||||
{
|
||||
consumeitemtrigger$listeners.trigger(item);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
private final ItemPredicate item;
|
||||
|
||||
public Instance(ItemPredicate item)
|
||||
{
|
||||
super(ConsumeItemTrigger.ID);
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
public boolean test(ItemStack item)
|
||||
{
|
||||
return this.item.test(item);
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<ConsumeItemTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<ConsumeItemTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<ConsumeItemTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<ConsumeItemTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(ItemStack item)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<ConsumeItemTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<ConsumeItemTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((ConsumeItemTrigger.Instance)listener.getCriterionInstance()).test(item))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<ConsumeItemTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<ConsumeItemTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.entity.monster.EntityZombie;
|
||||
import net.minecraft.entity.passive.EntityVillager;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class CuredZombieVillagerTrigger implements ICriterionTrigger<CuredZombieVillagerTrigger.Instance>
|
||||
{
|
||||
private static final ResourceLocation ID = new ResourceLocation("cured_zombie_villager");
|
||||
private final Map<PlayerAdvancements, CuredZombieVillagerTrigger.Listeners> listeners = Maps.<PlayerAdvancements, CuredZombieVillagerTrigger.Listeners>newHashMap();
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<CuredZombieVillagerTrigger.Instance> listener)
|
||||
{
|
||||
CuredZombieVillagerTrigger.Listeners curedzombievillagertrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (curedzombievillagertrigger$listeners == null)
|
||||
{
|
||||
curedzombievillagertrigger$listeners = new CuredZombieVillagerTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, curedzombievillagertrigger$listeners);
|
||||
}
|
||||
|
||||
curedzombievillagertrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<CuredZombieVillagerTrigger.Instance> listener)
|
||||
{
|
||||
CuredZombieVillagerTrigger.Listeners curedzombievillagertrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (curedzombievillagertrigger$listeners != null)
|
||||
{
|
||||
curedzombievillagertrigger$listeners.remove(listener);
|
||||
|
||||
if (curedzombievillagertrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public CuredZombieVillagerTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
EntityPredicate entitypredicate = EntityPredicate.deserialize(json.get("zombie"));
|
||||
EntityPredicate entitypredicate1 = EntityPredicate.deserialize(json.get("villager"));
|
||||
return new CuredZombieVillagerTrigger.Instance(entitypredicate, entitypredicate1);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, EntityZombie zombie, EntityVillager villager)
|
||||
{
|
||||
CuredZombieVillagerTrigger.Listeners curedzombievillagertrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (curedzombievillagertrigger$listeners != null)
|
||||
{
|
||||
curedzombievillagertrigger$listeners.trigger(player, zombie, villager);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
private final EntityPredicate zombie;
|
||||
private final EntityPredicate villager;
|
||||
|
||||
public Instance(EntityPredicate zombie, EntityPredicate villager)
|
||||
{
|
||||
super(CuredZombieVillagerTrigger.ID);
|
||||
this.zombie = zombie;
|
||||
this.villager = villager;
|
||||
}
|
||||
|
||||
public boolean test(EntityPlayerMP player, EntityZombie zombie, EntityVillager villager)
|
||||
{
|
||||
if (!this.zombie.test(player, zombie))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.villager.test(player, villager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<CuredZombieVillagerTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<CuredZombieVillagerTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<CuredZombieVillagerTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<CuredZombieVillagerTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, EntityZombie zombie, EntityVillager villager)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<CuredZombieVillagerTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<CuredZombieVillagerTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((CuredZombieVillagerTrigger.Instance)listener.getCriterionInstance()).test(player, zombie, villager))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<CuredZombieVillagerTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<CuredZombieVillagerTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
|
||||
public class DamagePredicate
|
||||
{
|
||||
public static DamagePredicate ANY = new DamagePredicate();
|
||||
private final MinMaxBounds dealt;
|
||||
private final MinMaxBounds taken;
|
||||
private final EntityPredicate sourceEntity;
|
||||
private final Boolean blocked;
|
||||
private final DamageSourcePredicate type;
|
||||
|
||||
public DamagePredicate()
|
||||
{
|
||||
this.dealt = MinMaxBounds.UNBOUNDED;
|
||||
this.taken = MinMaxBounds.UNBOUNDED;
|
||||
this.sourceEntity = EntityPredicate.ANY;
|
||||
this.blocked = null;
|
||||
this.type = DamageSourcePredicate.ANY;
|
||||
}
|
||||
|
||||
public DamagePredicate(MinMaxBounds dealt, MinMaxBounds taken, EntityPredicate sourceEntity, @Nullable Boolean blocked, DamageSourcePredicate type)
|
||||
{
|
||||
this.dealt = dealt;
|
||||
this.taken = taken;
|
||||
this.sourceEntity = sourceEntity;
|
||||
this.blocked = blocked;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public boolean test(EntityPlayerMP player, DamageSource source, float dealt, float taken, boolean blocked)
|
||||
{
|
||||
if (this == ANY)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (!this.dealt.test(dealt))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!this.taken.test(taken))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!this.sourceEntity.test(player, source.getTrueSource()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (this.blocked != null && this.blocked.booleanValue() != blocked)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.type.test(player, source);
|
||||
}
|
||||
}
|
||||
|
||||
public static DamagePredicate deserialize(@Nullable JsonElement element)
|
||||
{
|
||||
if (element != null && !element.isJsonNull())
|
||||
{
|
||||
JsonObject jsonobject = JsonUtils.getJsonObject(element, "damage");
|
||||
MinMaxBounds minmaxbounds = MinMaxBounds.deserialize(jsonobject.get("dealt"));
|
||||
MinMaxBounds minmaxbounds1 = MinMaxBounds.deserialize(jsonobject.get("taken"));
|
||||
Boolean obool = jsonobject.has("blocked") ? JsonUtils.getBoolean(jsonobject, "blocked") : null;
|
||||
EntityPredicate entitypredicate = EntityPredicate.deserialize(jsonobject.get("source_entity"));
|
||||
DamageSourcePredicate damagesourcepredicate = DamageSourcePredicate.deserialize(jsonobject.get("type"));
|
||||
return new DamagePredicate(minmaxbounds, minmaxbounds1, entitypredicate, obool, damagesourcepredicate);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ANY;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
|
||||
public class DamageSourcePredicate
|
||||
{
|
||||
public static DamageSourcePredicate ANY = new DamageSourcePredicate();
|
||||
private final Boolean isProjectile;
|
||||
private final Boolean isExplosion;
|
||||
private final Boolean bypassesArmor;
|
||||
private final Boolean bypassesInvulnerability;
|
||||
private final Boolean bypassesMagic;
|
||||
private final Boolean isFire;
|
||||
private final Boolean isMagic;
|
||||
private final EntityPredicate directEntity;
|
||||
private final EntityPredicate sourceEntity;
|
||||
|
||||
public DamageSourcePredicate()
|
||||
{
|
||||
this.isProjectile = null;
|
||||
this.isExplosion = null;
|
||||
this.bypassesArmor = null;
|
||||
this.bypassesInvulnerability = null;
|
||||
this.bypassesMagic = null;
|
||||
this.isFire = null;
|
||||
this.isMagic = null;
|
||||
this.directEntity = EntityPredicate.ANY;
|
||||
this.sourceEntity = EntityPredicate.ANY;
|
||||
}
|
||||
|
||||
public DamageSourcePredicate(@Nullable Boolean isProjectile, @Nullable Boolean isExplosion, @Nullable Boolean bypassesArmor, @Nullable Boolean bypassesInvulnerability, @Nullable Boolean bypassesMagic, @Nullable Boolean isFire, @Nullable Boolean isMagic, EntityPredicate directEntity, EntityPredicate sourceEntity)
|
||||
{
|
||||
this.isProjectile = isProjectile;
|
||||
this.isExplosion = isExplosion;
|
||||
this.bypassesArmor = bypassesArmor;
|
||||
this.bypassesInvulnerability = bypassesInvulnerability;
|
||||
this.bypassesMagic = bypassesMagic;
|
||||
this.isFire = isFire;
|
||||
this.isMagic = isMagic;
|
||||
this.directEntity = directEntity;
|
||||
this.sourceEntity = sourceEntity;
|
||||
}
|
||||
|
||||
public boolean test(EntityPlayerMP player, DamageSource source)
|
||||
{
|
||||
if (this == ANY)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (this.isProjectile != null && this.isProjectile.booleanValue() != source.isProjectile())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (this.isExplosion != null && this.isExplosion.booleanValue() != source.isExplosion())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (this.bypassesArmor != null && this.bypassesArmor.booleanValue() != source.isUnblockable())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (this.bypassesInvulnerability != null && this.bypassesInvulnerability.booleanValue() != source.canHarmInCreative())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (this.bypassesMagic != null && this.bypassesMagic.booleanValue() != source.isDamageAbsolute())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (this.isFire != null && this.isFire.booleanValue() != source.isFireDamage())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (this.isMagic != null && this.isMagic.booleanValue() != source.isMagicDamage())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!this.directEntity.test(player, source.getImmediateSource()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.sourceEntity.test(player, source.getTrueSource());
|
||||
}
|
||||
}
|
||||
|
||||
public static DamageSourcePredicate deserialize(@Nullable JsonElement element)
|
||||
{
|
||||
if (element != null && !element.isJsonNull())
|
||||
{
|
||||
JsonObject jsonobject = JsonUtils.getJsonObject(element, "damage type");
|
||||
Boolean obool = optionalBoolean(jsonobject, "is_projectile");
|
||||
Boolean obool1 = optionalBoolean(jsonobject, "is_explosion");
|
||||
Boolean obool2 = optionalBoolean(jsonobject, "bypasses_armor");
|
||||
Boolean obool3 = optionalBoolean(jsonobject, "bypasses_invulnerability");
|
||||
Boolean obool4 = optionalBoolean(jsonobject, "bypasses_magic");
|
||||
Boolean obool5 = optionalBoolean(jsonobject, "is_fire");
|
||||
Boolean obool6 = optionalBoolean(jsonobject, "is_magic");
|
||||
EntityPredicate entitypredicate = EntityPredicate.deserialize(jsonobject.get("direct_entity"));
|
||||
EntityPredicate entitypredicate1 = EntityPredicate.deserialize(jsonobject.get("source_entity"));
|
||||
return new DamageSourcePredicate(obool, obool1, obool2, obool3, obool4, obool5, obool6, entitypredicate, entitypredicate1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ANY;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Boolean optionalBoolean(JsonObject object, String memberName)
|
||||
{
|
||||
return object.has(memberName) ? JsonUtils.getBoolean(object, memberName) : null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
public class DistancePredicate
|
||||
{
|
||||
/** The predicate that matches any distance. */
|
||||
public static final DistancePredicate ANY = new DistancePredicate(MinMaxBounds.UNBOUNDED, MinMaxBounds.UNBOUNDED, MinMaxBounds.UNBOUNDED, MinMaxBounds.UNBOUNDED, MinMaxBounds.UNBOUNDED);
|
||||
private final MinMaxBounds x;
|
||||
private final MinMaxBounds y;
|
||||
private final MinMaxBounds z;
|
||||
private final MinMaxBounds horizontal;
|
||||
private final MinMaxBounds absolute;
|
||||
|
||||
public DistancePredicate(MinMaxBounds x, MinMaxBounds y, MinMaxBounds z, MinMaxBounds horizontal, MinMaxBounds absolute)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.horizontal = horizontal;
|
||||
this.absolute = absolute;
|
||||
}
|
||||
|
||||
public boolean test(double x1, double y1, double z1, double x2, double y2, double z2)
|
||||
{
|
||||
float f = (float)(x1 - x2);
|
||||
float f1 = (float)(y1 - y2);
|
||||
float f2 = (float)(z1 - z2);
|
||||
|
||||
if (this.x.test(MathHelper.abs(f)) && this.y.test(MathHelper.abs(f1)) && this.z.test(MathHelper.abs(f2)))
|
||||
{
|
||||
if (!this.horizontal.testSquare((double)(f * f + f2 * f2)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.absolute.testSquare((double)(f * f + f1 * f1 + f2 * f2));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static DistancePredicate deserialize(@Nullable JsonElement element)
|
||||
{
|
||||
if (element != null && !element.isJsonNull())
|
||||
{
|
||||
JsonObject jsonobject = JsonUtils.getJsonObject(element, "distance");
|
||||
MinMaxBounds minmaxbounds = MinMaxBounds.deserialize(jsonobject.get("x"));
|
||||
MinMaxBounds minmaxbounds1 = MinMaxBounds.deserialize(jsonobject.get("y"));
|
||||
MinMaxBounds minmaxbounds2 = MinMaxBounds.deserialize(jsonobject.get("z"));
|
||||
MinMaxBounds minmaxbounds3 = MinMaxBounds.deserialize(jsonobject.get("horizontal"));
|
||||
MinMaxBounds minmaxbounds4 = MinMaxBounds.deserialize(jsonobject.get("absolute"));
|
||||
return new DistancePredicate(minmaxbounds, minmaxbounds1, minmaxbounds2, minmaxbounds3, minmaxbounds4);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ANY;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class EffectsChangedTrigger implements ICriterionTrigger<EffectsChangedTrigger.Instance>
|
||||
{
|
||||
private static final ResourceLocation ID = new ResourceLocation("effects_changed");
|
||||
private final Map<PlayerAdvancements, EffectsChangedTrigger.Listeners> listeners = Maps.<PlayerAdvancements, EffectsChangedTrigger.Listeners>newHashMap();
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<EffectsChangedTrigger.Instance> listener)
|
||||
{
|
||||
EffectsChangedTrigger.Listeners effectschangedtrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (effectschangedtrigger$listeners == null)
|
||||
{
|
||||
effectschangedtrigger$listeners = new EffectsChangedTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, effectschangedtrigger$listeners);
|
||||
}
|
||||
|
||||
effectschangedtrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<EffectsChangedTrigger.Instance> listener)
|
||||
{
|
||||
EffectsChangedTrigger.Listeners effectschangedtrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (effectschangedtrigger$listeners != null)
|
||||
{
|
||||
effectschangedtrigger$listeners.remove(listener);
|
||||
|
||||
if (effectschangedtrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public EffectsChangedTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
MobEffectsPredicate mobeffectspredicate = MobEffectsPredicate.deserialize(json.get("effects"));
|
||||
return new EffectsChangedTrigger.Instance(mobeffectspredicate);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player)
|
||||
{
|
||||
EffectsChangedTrigger.Listeners effectschangedtrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (effectschangedtrigger$listeners != null)
|
||||
{
|
||||
effectschangedtrigger$listeners.trigger(player);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
private final MobEffectsPredicate effects;
|
||||
|
||||
public Instance(MobEffectsPredicate effects)
|
||||
{
|
||||
super(EffectsChangedTrigger.ID);
|
||||
this.effects = effects;
|
||||
}
|
||||
|
||||
public boolean test(EntityPlayerMP player)
|
||||
{
|
||||
return this.effects.test(player);
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<EffectsChangedTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<EffectsChangedTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<EffectsChangedTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<EffectsChangedTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<EffectsChangedTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<EffectsChangedTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((EffectsChangedTrigger.Instance)listener.getCriterionInstance()).test(player))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<EffectsChangedTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<EffectsChangedTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class EnchantedItemTrigger implements ICriterionTrigger<EnchantedItemTrigger.Instance>
|
||||
{
|
||||
private static final ResourceLocation ID = new ResourceLocation("enchanted_item");
|
||||
private final Map<PlayerAdvancements, EnchantedItemTrigger.Listeners> listeners = Maps.<PlayerAdvancements, EnchantedItemTrigger.Listeners>newHashMap();
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<EnchantedItemTrigger.Instance> listener)
|
||||
{
|
||||
EnchantedItemTrigger.Listeners enchanteditemtrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (enchanteditemtrigger$listeners == null)
|
||||
{
|
||||
enchanteditemtrigger$listeners = new EnchantedItemTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, enchanteditemtrigger$listeners);
|
||||
}
|
||||
|
||||
enchanteditemtrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<EnchantedItemTrigger.Instance> listener)
|
||||
{
|
||||
EnchantedItemTrigger.Listeners enchanteditemtrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (enchanteditemtrigger$listeners != null)
|
||||
{
|
||||
enchanteditemtrigger$listeners.remove(listener);
|
||||
|
||||
if (enchanteditemtrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public EnchantedItemTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
ItemPredicate itempredicate = ItemPredicate.deserialize(json.get("item"));
|
||||
MinMaxBounds minmaxbounds = MinMaxBounds.deserialize(json.get("levels"));
|
||||
return new EnchantedItemTrigger.Instance(itempredicate, minmaxbounds);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, ItemStack item, int levelsSpent)
|
||||
{
|
||||
EnchantedItemTrigger.Listeners enchanteditemtrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (enchanteditemtrigger$listeners != null)
|
||||
{
|
||||
enchanteditemtrigger$listeners.trigger(item, levelsSpent);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
private final ItemPredicate item;
|
||||
private final MinMaxBounds levels;
|
||||
|
||||
public Instance(ItemPredicate item, MinMaxBounds levels)
|
||||
{
|
||||
super(EnchantedItemTrigger.ID);
|
||||
this.item = item;
|
||||
this.levels = levels;
|
||||
}
|
||||
|
||||
public boolean test(ItemStack item, int levelsIn)
|
||||
{
|
||||
if (!this.item.test(item))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.levels.test((float)levelsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<EnchantedItemTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<EnchantedItemTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<EnchantedItemTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<EnchantedItemTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(ItemStack item, int levelsIn)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<EnchantedItemTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<EnchantedItemTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((EnchantedItemTrigger.Instance)listener.getCriterionInstance()).test(item, levelsIn))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<EnchantedItemTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<EnchantedItemTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.enchantment.Enchantment;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class EnchantmentPredicate
|
||||
{
|
||||
/** The predicate that matches any set of enchantments. */
|
||||
public static final EnchantmentPredicate ANY = new EnchantmentPredicate();
|
||||
private final Enchantment enchantment;
|
||||
private final MinMaxBounds levels;
|
||||
|
||||
public EnchantmentPredicate()
|
||||
{
|
||||
this.enchantment = null;
|
||||
this.levels = MinMaxBounds.UNBOUNDED;
|
||||
}
|
||||
|
||||
public EnchantmentPredicate(@Nullable Enchantment enchantment, MinMaxBounds levels)
|
||||
{
|
||||
this.enchantment = enchantment;
|
||||
this.levels = levels;
|
||||
}
|
||||
|
||||
public boolean test(Map<Enchantment, Integer> enchantmentsIn)
|
||||
{
|
||||
if (this.enchantment != null)
|
||||
{
|
||||
if (!enchantmentsIn.containsKey(this.enchantment))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int i = ((Integer)enchantmentsIn.get(this.enchantment)).intValue();
|
||||
|
||||
if (this.levels != null && !this.levels.test((float)i))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (this.levels != null)
|
||||
{
|
||||
for (Integer integer : enchantmentsIn.values())
|
||||
{
|
||||
if (this.levels.test((float)integer.intValue()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static EnchantmentPredicate deserialize(@Nullable JsonElement element)
|
||||
{
|
||||
if (element != null && !element.isJsonNull())
|
||||
{
|
||||
JsonObject jsonobject = JsonUtils.getJsonObject(element, "enchantment");
|
||||
Enchantment enchantment = null;
|
||||
|
||||
if (jsonobject.has("enchantment"))
|
||||
{
|
||||
ResourceLocation resourcelocation = new ResourceLocation(JsonUtils.getString(jsonobject, "enchantment"));
|
||||
enchantment = Enchantment.REGISTRY.getObject(resourcelocation);
|
||||
|
||||
if (enchantment == null)
|
||||
{
|
||||
throw new JsonSyntaxException("Unknown enchantment '" + resourcelocation + "'");
|
||||
}
|
||||
}
|
||||
|
||||
MinMaxBounds minmaxbounds = MinMaxBounds.deserialize(jsonobject.get("levels"));
|
||||
return new EnchantmentPredicate(enchantment, minmaxbounds);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ANY;
|
||||
}
|
||||
}
|
||||
|
||||
public static EnchantmentPredicate[] deserializeArray(@Nullable JsonElement element)
|
||||
{
|
||||
if (element != null && !element.isJsonNull())
|
||||
{
|
||||
JsonArray jsonarray = JsonUtils.getJsonArray(element, "enchantments");
|
||||
EnchantmentPredicate[] aenchantmentpredicate = new EnchantmentPredicate[jsonarray.size()];
|
||||
|
||||
for (int i = 0; i < aenchantmentpredicate.length; ++i)
|
||||
{
|
||||
aenchantmentpredicate[i] = deserialize(jsonarray.get(i));
|
||||
}
|
||||
|
||||
return aenchantmentpredicate;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new EnchantmentPredicate[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class EnterBlockTrigger implements ICriterionTrigger<EnterBlockTrigger.Instance>
|
||||
{
|
||||
private static final ResourceLocation ID = new ResourceLocation("enter_block");
|
||||
private final Map<PlayerAdvancements, EnterBlockTrigger.Listeners> listeners = Maps.<PlayerAdvancements, EnterBlockTrigger.Listeners>newHashMap();
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<EnterBlockTrigger.Instance> listener)
|
||||
{
|
||||
EnterBlockTrigger.Listeners enterblocktrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (enterblocktrigger$listeners == null)
|
||||
{
|
||||
enterblocktrigger$listeners = new EnterBlockTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, enterblocktrigger$listeners);
|
||||
}
|
||||
|
||||
enterblocktrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<EnterBlockTrigger.Instance> listener)
|
||||
{
|
||||
EnterBlockTrigger.Listeners enterblocktrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (enterblocktrigger$listeners != null)
|
||||
{
|
||||
enterblocktrigger$listeners.remove(listener);
|
||||
|
||||
if (enterblocktrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public EnterBlockTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
Block block = null;
|
||||
|
||||
if (json.has("block"))
|
||||
{
|
||||
ResourceLocation resourcelocation = new ResourceLocation(JsonUtils.getString(json, "block"));
|
||||
|
||||
if (!Block.REGISTRY.containsKey(resourcelocation))
|
||||
{
|
||||
throw new JsonSyntaxException("Unknown block type '" + resourcelocation + "'");
|
||||
}
|
||||
|
||||
block = Block.REGISTRY.getObject(resourcelocation);
|
||||
}
|
||||
|
||||
Map < IProperty<?>, Object > map = null;
|
||||
|
||||
if (json.has("state"))
|
||||
{
|
||||
if (block == null)
|
||||
{
|
||||
throw new JsonSyntaxException("Can't define block state without a specific block type");
|
||||
}
|
||||
|
||||
BlockStateContainer blockstatecontainer = block.getBlockState();
|
||||
|
||||
for (Entry<String, JsonElement> entry : JsonUtils.getJsonObject(json, "state").entrySet())
|
||||
{
|
||||
IProperty<?> iproperty = blockstatecontainer.getProperty(entry.getKey());
|
||||
|
||||
if (iproperty == null)
|
||||
{
|
||||
throw new JsonSyntaxException("Unknown block state property '" + (String)entry.getKey() + "' for block '" + Block.REGISTRY.getNameForObject(block) + "'");
|
||||
}
|
||||
|
||||
String s = JsonUtils.getString(entry.getValue(), entry.getKey());
|
||||
Optional<?> optional = iproperty.parseValue(s);
|
||||
|
||||
if (!optional.isPresent())
|
||||
{
|
||||
throw new JsonSyntaxException("Invalid block state value '" + s + "' for property '" + (String)entry.getKey() + "' on block '" + Block.REGISTRY.getNameForObject(block) + "'");
|
||||
}
|
||||
|
||||
if (map == null)
|
||||
{
|
||||
map = Maps. < IProperty<?>, Object > newHashMap();
|
||||
}
|
||||
|
||||
map.put(iproperty, optional.get());
|
||||
}
|
||||
}
|
||||
|
||||
return new EnterBlockTrigger.Instance(block, map);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, IBlockState state)
|
||||
{
|
||||
EnterBlockTrigger.Listeners enterblocktrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (enterblocktrigger$listeners != null)
|
||||
{
|
||||
enterblocktrigger$listeners.trigger(state);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
private final Block block;
|
||||
private final Map < IProperty<?>, Object > properties;
|
||||
|
||||
public Instance(@Nullable Block blockIn, @Nullable Map < IProperty<?>, Object > propertiesIn)
|
||||
{
|
||||
super(EnterBlockTrigger.ID);
|
||||
this.block = blockIn;
|
||||
this.properties = propertiesIn;
|
||||
}
|
||||
|
||||
public boolean test(IBlockState state)
|
||||
{
|
||||
if (this.block != null && state.getBlock() != this.block)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.properties != null)
|
||||
{
|
||||
for (Entry < IProperty<?>, Object > entry : this.properties.entrySet())
|
||||
{
|
||||
if (state.getValue(entry.getKey()) != entry.getValue())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<EnterBlockTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<EnterBlockTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<EnterBlockTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<EnterBlockTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(IBlockState state)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<EnterBlockTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<EnterBlockTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((EnterBlockTrigger.Instance)listener.getCriterionInstance()).test(state))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<EnterBlockTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<EnterBlockTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class EntityHurtPlayerTrigger implements ICriterionTrigger<EntityHurtPlayerTrigger.Instance>
|
||||
{
|
||||
private static final ResourceLocation ID = new ResourceLocation("entity_hurt_player");
|
||||
private final Map<PlayerAdvancements, EntityHurtPlayerTrigger.Listeners> listeners = Maps.<PlayerAdvancements, EntityHurtPlayerTrigger.Listeners>newHashMap();
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<EntityHurtPlayerTrigger.Instance> listener)
|
||||
{
|
||||
EntityHurtPlayerTrigger.Listeners entityhurtplayertrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (entityhurtplayertrigger$listeners == null)
|
||||
{
|
||||
entityhurtplayertrigger$listeners = new EntityHurtPlayerTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, entityhurtplayertrigger$listeners);
|
||||
}
|
||||
|
||||
entityhurtplayertrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<EntityHurtPlayerTrigger.Instance> listener)
|
||||
{
|
||||
EntityHurtPlayerTrigger.Listeners entityhurtplayertrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (entityhurtplayertrigger$listeners != null)
|
||||
{
|
||||
entityhurtplayertrigger$listeners.remove(listener);
|
||||
|
||||
if (entityhurtplayertrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public EntityHurtPlayerTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
DamagePredicate damagepredicate = DamagePredicate.deserialize(json.get("damage"));
|
||||
return new EntityHurtPlayerTrigger.Instance(damagepredicate);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, DamageSource source, float amountDealt, float amountTaken, boolean wasBlocked)
|
||||
{
|
||||
EntityHurtPlayerTrigger.Listeners entityhurtplayertrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (entityhurtplayertrigger$listeners != null)
|
||||
{
|
||||
entityhurtplayertrigger$listeners.trigger(player, source, amountDealt, amountTaken, wasBlocked);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
private final DamagePredicate damage;
|
||||
|
||||
public Instance(DamagePredicate damage)
|
||||
{
|
||||
super(EntityHurtPlayerTrigger.ID);
|
||||
this.damage = damage;
|
||||
}
|
||||
|
||||
public boolean test(EntityPlayerMP player, DamageSource source, float amountDealt, float amountTaken, boolean wasBlocked)
|
||||
{
|
||||
return this.damage.test(player, source, amountDealt, amountTaken, wasBlocked);
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<EntityHurtPlayerTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<EntityHurtPlayerTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements p_i47439_1_)
|
||||
{
|
||||
this.playerAdvancements = p_i47439_1_;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<EntityHurtPlayerTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<EntityHurtPlayerTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, DamageSource source, float amountDealt, float amountTaken, boolean wasBlocked)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<EntityHurtPlayerTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<EntityHurtPlayerTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((EntityHurtPlayerTrigger.Instance)listener.getCriterionInstance()).test(player, source, amountDealt, amountTaken, wasBlocked))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<EntityHurtPlayerTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<EntityHurtPlayerTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityList;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class EntityPredicate
|
||||
{
|
||||
/** The predicate that matches any entity. */
|
||||
public static final EntityPredicate ANY = new EntityPredicate((ResourceLocation)null, DistancePredicate.ANY, LocationPredicate.ANY, MobEffectsPredicate.ANY, NBTPredicate.ANY);
|
||||
private final ResourceLocation type;
|
||||
private final DistancePredicate distance;
|
||||
private final LocationPredicate location;
|
||||
private final MobEffectsPredicate effects;
|
||||
private final NBTPredicate nbt;
|
||||
|
||||
public EntityPredicate(@Nullable ResourceLocation type, DistancePredicate distance, LocationPredicate location, MobEffectsPredicate effects, NBTPredicate nbt)
|
||||
{
|
||||
this.type = type;
|
||||
this.distance = distance;
|
||||
this.location = location;
|
||||
this.effects = effects;
|
||||
this.nbt = nbt;
|
||||
}
|
||||
|
||||
public boolean test(EntityPlayerMP player, @Nullable Entity entity)
|
||||
{
|
||||
if (this == ANY)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (entity == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (this.type != null && !EntityList.isMatchingName(entity, this.type))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!this.distance.test(player.posX, player.posY, player.posZ, entity.posX, entity.posY, entity.posZ))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!this.location.test(player.getServerWorld(), entity.posX, entity.posY, entity.posZ))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!this.effects.test(entity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.nbt.test(entity);
|
||||
}
|
||||
}
|
||||
|
||||
public static EntityPredicate deserialize(@Nullable JsonElement element)
|
||||
{
|
||||
if (element != null && !element.isJsonNull())
|
||||
{
|
||||
JsonObject jsonobject = JsonUtils.getJsonObject(element, "entity");
|
||||
ResourceLocation resourcelocation = null;
|
||||
|
||||
if (jsonobject.has("type"))
|
||||
{
|
||||
resourcelocation = new ResourceLocation(JsonUtils.getString(jsonobject, "type"));
|
||||
|
||||
if (!EntityList.isRegistered(resourcelocation))
|
||||
{
|
||||
throw new JsonSyntaxException("Unknown entity type '" + resourcelocation + "', valid types are: " + EntityList.getValidTypeNames());
|
||||
}
|
||||
}
|
||||
|
||||
DistancePredicate distancepredicate = DistancePredicate.deserialize(jsonobject.get("distance"));
|
||||
LocationPredicate locationpredicate = LocationPredicate.deserialize(jsonobject.get("location"));
|
||||
MobEffectsPredicate mobeffectspredicate = MobEffectsPredicate.deserialize(jsonobject.get("effects"));
|
||||
NBTPredicate nbtpredicate = NBTPredicate.deserialize(jsonobject.get("nbt"));
|
||||
return new EntityPredicate(resourcelocation, distancepredicate, locationpredicate, mobeffectspredicate, nbtpredicate);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ANY;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class ImpossibleTrigger implements ICriterionTrigger<ImpossibleTrigger.Instance>
|
||||
{
|
||||
private static final ResourceLocation ID = new ResourceLocation("impossible");
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<ImpossibleTrigger.Instance> listener)
|
||||
{
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<ImpossibleTrigger.Instance> listener)
|
||||
{
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public ImpossibleTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
return new ImpossibleTrigger.Instance();
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
public Instance()
|
||||
{
|
||||
super(ImpossibleTrigger.ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class InventoryChangeTrigger implements ICriterionTrigger<InventoryChangeTrigger.Instance>
|
||||
{
|
||||
private static final ResourceLocation ID = new ResourceLocation("inventory_changed");
|
||||
private final Map<PlayerAdvancements, InventoryChangeTrigger.Listeners> listeners = Maps.<PlayerAdvancements, InventoryChangeTrigger.Listeners>newHashMap();
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<InventoryChangeTrigger.Instance> listener)
|
||||
{
|
||||
InventoryChangeTrigger.Listeners inventorychangetrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (inventorychangetrigger$listeners == null)
|
||||
{
|
||||
inventorychangetrigger$listeners = new InventoryChangeTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, inventorychangetrigger$listeners);
|
||||
}
|
||||
|
||||
inventorychangetrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<InventoryChangeTrigger.Instance> listener)
|
||||
{
|
||||
InventoryChangeTrigger.Listeners inventorychangetrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (inventorychangetrigger$listeners != null)
|
||||
{
|
||||
inventorychangetrigger$listeners.remove(listener);
|
||||
|
||||
if (inventorychangetrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public InventoryChangeTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
JsonObject jsonobject = JsonUtils.getJsonObject(json, "slots", new JsonObject());
|
||||
MinMaxBounds minmaxbounds = MinMaxBounds.deserialize(jsonobject.get("occupied"));
|
||||
MinMaxBounds minmaxbounds1 = MinMaxBounds.deserialize(jsonobject.get("full"));
|
||||
MinMaxBounds minmaxbounds2 = MinMaxBounds.deserialize(jsonobject.get("empty"));
|
||||
ItemPredicate[] aitempredicate = ItemPredicate.deserializeArray(json.get("items"));
|
||||
return new InventoryChangeTrigger.Instance(minmaxbounds, minmaxbounds1, minmaxbounds2, aitempredicate);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, InventoryPlayer inventory)
|
||||
{
|
||||
InventoryChangeTrigger.Listeners inventorychangetrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (inventorychangetrigger$listeners != null)
|
||||
{
|
||||
inventorychangetrigger$listeners.trigger(inventory);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
private final MinMaxBounds occupied;
|
||||
private final MinMaxBounds full;
|
||||
private final MinMaxBounds empty;
|
||||
private final ItemPredicate[] items;
|
||||
|
||||
public Instance(MinMaxBounds occupied, MinMaxBounds full, MinMaxBounds empty, ItemPredicate[] items)
|
||||
{
|
||||
super(InventoryChangeTrigger.ID);
|
||||
this.occupied = occupied;
|
||||
this.full = full;
|
||||
this.empty = empty;
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
public boolean test(InventoryPlayer inventory)
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int k = 0;
|
||||
List<ItemPredicate> list = Lists.newArrayList(this.items);
|
||||
|
||||
for (int l = 0; l < inventory.getSizeInventory(); ++l)
|
||||
{
|
||||
ItemStack itemstack = inventory.getStackInSlot(l);
|
||||
|
||||
if (itemstack.isEmpty())
|
||||
{
|
||||
++j;
|
||||
}
|
||||
else
|
||||
{
|
||||
++k;
|
||||
|
||||
if (itemstack.getCount() >= itemstack.getMaxStackSize())
|
||||
{
|
||||
++i;
|
||||
}
|
||||
|
||||
Iterator<ItemPredicate> iterator = list.iterator();
|
||||
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
ItemPredicate itempredicate = iterator.next();
|
||||
|
||||
if (itempredicate.test(itemstack))
|
||||
{
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.full.test((float)i))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!this.empty.test((float)j))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!this.occupied.test((float)k))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!list.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<InventoryChangeTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<InventoryChangeTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<InventoryChangeTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<InventoryChangeTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(InventoryPlayer inventory)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<InventoryChangeTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<InventoryChangeTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((InventoryChangeTrigger.Instance)listener.getCriterionInstance()).test(inventory))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<InventoryChangeTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<InventoryChangeTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class ItemDurabilityTrigger implements ICriterionTrigger<ItemDurabilityTrigger.Instance>
|
||||
{
|
||||
private static final ResourceLocation ID = new ResourceLocation("item_durability_changed");
|
||||
private final Map<PlayerAdvancements, ItemDurabilityTrigger.Listeners> listeners = Maps.<PlayerAdvancements, ItemDurabilityTrigger.Listeners>newHashMap();
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<ItemDurabilityTrigger.Instance> listener)
|
||||
{
|
||||
ItemDurabilityTrigger.Listeners itemdurabilitytrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (itemdurabilitytrigger$listeners == null)
|
||||
{
|
||||
itemdurabilitytrigger$listeners = new ItemDurabilityTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, itemdurabilitytrigger$listeners);
|
||||
}
|
||||
|
||||
itemdurabilitytrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<ItemDurabilityTrigger.Instance> listener)
|
||||
{
|
||||
ItemDurabilityTrigger.Listeners itemdurabilitytrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (itemdurabilitytrigger$listeners != null)
|
||||
{
|
||||
itemdurabilitytrigger$listeners.remove(listener);
|
||||
|
||||
if (itemdurabilitytrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public ItemDurabilityTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
ItemPredicate itempredicate = ItemPredicate.deserialize(json.get("item"));
|
||||
MinMaxBounds minmaxbounds = MinMaxBounds.deserialize(json.get("durability"));
|
||||
MinMaxBounds minmaxbounds1 = MinMaxBounds.deserialize(json.get("delta"));
|
||||
return new ItemDurabilityTrigger.Instance(itempredicate, minmaxbounds, minmaxbounds1);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, ItemStack itemIn, int newDurability)
|
||||
{
|
||||
ItemDurabilityTrigger.Listeners itemdurabilitytrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (itemdurabilitytrigger$listeners != null)
|
||||
{
|
||||
itemdurabilitytrigger$listeners.trigger(itemIn, newDurability);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
private final ItemPredicate item;
|
||||
private final MinMaxBounds durability;
|
||||
private final MinMaxBounds delta;
|
||||
|
||||
public Instance(ItemPredicate item, MinMaxBounds durability, MinMaxBounds delta)
|
||||
{
|
||||
super(ItemDurabilityTrigger.ID);
|
||||
this.item = item;
|
||||
this.durability = durability;
|
||||
this.delta = delta;
|
||||
}
|
||||
|
||||
public boolean test(ItemStack item, int p_193197_2_)
|
||||
{
|
||||
if (!this.item.test(item))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!this.durability.test((float)(item.getMaxDamage() - p_193197_2_)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.delta.test((float)(item.getItemDamage() - p_193197_2_));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<ItemDurabilityTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<ItemDurabilityTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<ItemDurabilityTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<ItemDurabilityTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(ItemStack item, int newDurability)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<ItemDurabilityTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<ItemDurabilityTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((ItemDurabilityTrigger.Instance)listener.getCriterionInstance()).test(item, newDurability))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<ItemDurabilityTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<ItemDurabilityTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.enchantment.Enchantment;
|
||||
import net.minecraft.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.potion.PotionType;
|
||||
import net.minecraft.potion.PotionUtils;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class ItemPredicate
|
||||
{
|
||||
public static final ItemPredicate ANY = new ItemPredicate();
|
||||
private final Item item;
|
||||
private final Integer data;
|
||||
private final MinMaxBounds count;
|
||||
private final MinMaxBounds durability;
|
||||
private final EnchantmentPredicate[] enchantments;
|
||||
private final PotionType potion;
|
||||
private final NBTPredicate nbt;
|
||||
|
||||
public ItemPredicate()
|
||||
{
|
||||
this.item = null;
|
||||
this.data = null;
|
||||
this.potion = null;
|
||||
this.count = MinMaxBounds.UNBOUNDED;
|
||||
this.durability = MinMaxBounds.UNBOUNDED;
|
||||
this.enchantments = new EnchantmentPredicate[0];
|
||||
this.nbt = NBTPredicate.ANY;
|
||||
}
|
||||
|
||||
public ItemPredicate(@Nullable Item item, @Nullable Integer data, MinMaxBounds count, MinMaxBounds durability, EnchantmentPredicate[] enchantments, @Nullable PotionType potion, NBTPredicate nbt)
|
||||
{
|
||||
this.item = item;
|
||||
this.data = data;
|
||||
this.count = count;
|
||||
this.durability = durability;
|
||||
this.enchantments = enchantments;
|
||||
this.potion = potion;
|
||||
this.nbt = nbt;
|
||||
}
|
||||
|
||||
public boolean test(ItemStack item)
|
||||
{
|
||||
if (this.item != null && item.getItem() != this.item)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (this.data != null && item.getMetadata() != this.data.intValue())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!this.count.test((float)item.getCount()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (this.durability != MinMaxBounds.UNBOUNDED && !item.isItemStackDamageable())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!this.durability.test((float)(item.getMaxDamage() - item.getItemDamage())))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!this.nbt.test(item))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Map<Enchantment, Integer> map = EnchantmentHelper.getEnchantments(item);
|
||||
|
||||
for (int i = 0; i < this.enchantments.length; ++i)
|
||||
{
|
||||
if (!this.enchantments[i].test(map))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
PotionType potiontype = PotionUtils.getPotionFromItem(item);
|
||||
|
||||
if (this.potion != null && this.potion != potiontype)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static ItemPredicate deserialize(@Nullable JsonElement element)
|
||||
{
|
||||
if (element != null && !element.isJsonNull())
|
||||
{
|
||||
JsonObject jsonobject = JsonUtils.getJsonObject(element, "item");
|
||||
if (jsonobject.has("type"))
|
||||
{
|
||||
final ResourceLocation rl = new ResourceLocation(JsonUtils.getString(jsonobject, "type"));
|
||||
final Map<ResourceLocation, java.util.function.Function<JsonObject, ItemPredicate>> map = net.minecraftforge.advancements.critereon.ItemPredicates.getPredicates();
|
||||
if (map.containsKey(rl)) return map.get(rl).apply(jsonobject);
|
||||
else throw new JsonSyntaxException("There is no ItemPredicate of type "+rl);
|
||||
}
|
||||
MinMaxBounds minmaxbounds = MinMaxBounds.deserialize(jsonobject.get("count"));
|
||||
MinMaxBounds minmaxbounds1 = MinMaxBounds.deserialize(jsonobject.get("durability"));
|
||||
Integer integer = jsonobject.has("data") ? JsonUtils.getInt(jsonobject, "data") : null;
|
||||
NBTPredicate nbtpredicate = NBTPredicate.deserialize(jsonobject.get("nbt"));
|
||||
Item item = null;
|
||||
|
||||
if (jsonobject.has("item"))
|
||||
{
|
||||
ResourceLocation resourcelocation = new ResourceLocation(JsonUtils.getString(jsonobject, "item"));
|
||||
item = Item.REGISTRY.getObject(resourcelocation);
|
||||
|
||||
if (item == null)
|
||||
{
|
||||
throw new JsonSyntaxException("Unknown item id '" + resourcelocation + "'");
|
||||
}
|
||||
}
|
||||
|
||||
EnchantmentPredicate[] aenchantmentpredicate = EnchantmentPredicate.deserializeArray(jsonobject.get("enchantments"));
|
||||
PotionType potiontype = null;
|
||||
|
||||
if (jsonobject.has("potion"))
|
||||
{
|
||||
ResourceLocation resourcelocation1 = new ResourceLocation(JsonUtils.getString(jsonobject, "potion"));
|
||||
|
||||
if (!PotionType.REGISTRY.containsKey(resourcelocation1))
|
||||
{
|
||||
throw new JsonSyntaxException("Unknown potion '" + resourcelocation1 + "'");
|
||||
}
|
||||
|
||||
potiontype = PotionType.REGISTRY.getObject(resourcelocation1);
|
||||
}
|
||||
|
||||
return new ItemPredicate(item, integer, minmaxbounds, minmaxbounds1, aenchantmentpredicate, potiontype, nbtpredicate);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ANY;
|
||||
}
|
||||
}
|
||||
|
||||
public static ItemPredicate[] deserializeArray(@Nullable JsonElement element)
|
||||
{
|
||||
if (element != null && !element.isJsonNull())
|
||||
{
|
||||
JsonArray jsonarray = JsonUtils.getJsonArray(element, "items");
|
||||
ItemPredicate[] aitempredicate = new ItemPredicate[jsonarray.size()];
|
||||
|
||||
for (int i = 0; i < aitempredicate.length; ++i)
|
||||
{
|
||||
aitempredicate[i] = deserialize(jsonarray.get(i));
|
||||
}
|
||||
|
||||
return aitempredicate;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new ItemPredicate[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class KilledTrigger implements ICriterionTrigger<KilledTrigger.Instance>
|
||||
{
|
||||
private final Map<PlayerAdvancements, KilledTrigger.Listeners> listeners = Maps.<PlayerAdvancements, KilledTrigger.Listeners>newHashMap();
|
||||
private final ResourceLocation id;
|
||||
|
||||
public KilledTrigger(ResourceLocation id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<KilledTrigger.Instance> listener)
|
||||
{
|
||||
KilledTrigger.Listeners killedtrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (killedtrigger$listeners == null)
|
||||
{
|
||||
killedtrigger$listeners = new KilledTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, killedtrigger$listeners);
|
||||
}
|
||||
|
||||
killedtrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<KilledTrigger.Instance> listener)
|
||||
{
|
||||
KilledTrigger.Listeners killedtrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (killedtrigger$listeners != null)
|
||||
{
|
||||
killedtrigger$listeners.remove(listener);
|
||||
|
||||
if (killedtrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public KilledTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
return new KilledTrigger.Instance(this.id, EntityPredicate.deserialize(json.get("entity")), DamageSourcePredicate.deserialize(json.get("killing_blow")));
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, Entity entity, DamageSource source)
|
||||
{
|
||||
KilledTrigger.Listeners killedtrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (killedtrigger$listeners != null)
|
||||
{
|
||||
killedtrigger$listeners.trigger(player, entity, source);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
private final EntityPredicate entity;
|
||||
private final DamageSourcePredicate killingBlow;
|
||||
|
||||
public Instance(ResourceLocation criterionIn, EntityPredicate entity, DamageSourcePredicate killingBlow)
|
||||
{
|
||||
super(criterionIn);
|
||||
this.entity = entity;
|
||||
this.killingBlow = killingBlow;
|
||||
}
|
||||
|
||||
public boolean test(EntityPlayerMP player, Entity entity, DamageSource source)
|
||||
{
|
||||
return !this.killingBlow.test(player, source) ? false : this.entity.test(player, entity);
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<KilledTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<KilledTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<KilledTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<KilledTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, Entity entity, DamageSource source)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<KilledTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<KilledTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((KilledTrigger.Instance)listener.getCriterionInstance()).test(player, entity, source))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<KilledTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<KilledTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
public class LevitationTrigger implements ICriterionTrigger<LevitationTrigger.Instance>
|
||||
{
|
||||
private static final ResourceLocation ID = new ResourceLocation("levitation");
|
||||
private final Map<PlayerAdvancements, LevitationTrigger.Listeners> listeners = Maps.<PlayerAdvancements, LevitationTrigger.Listeners>newHashMap();
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<LevitationTrigger.Instance> listener)
|
||||
{
|
||||
LevitationTrigger.Listeners levitationtrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (levitationtrigger$listeners == null)
|
||||
{
|
||||
levitationtrigger$listeners = new LevitationTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, levitationtrigger$listeners);
|
||||
}
|
||||
|
||||
levitationtrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<LevitationTrigger.Instance> listener)
|
||||
{
|
||||
LevitationTrigger.Listeners levitationtrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (levitationtrigger$listeners != null)
|
||||
{
|
||||
levitationtrigger$listeners.remove(listener);
|
||||
|
||||
if (levitationtrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public LevitationTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
DistancePredicate distancepredicate = DistancePredicate.deserialize(json.get("distance"));
|
||||
MinMaxBounds minmaxbounds = MinMaxBounds.deserialize(json.get("duration"));
|
||||
return new LevitationTrigger.Instance(distancepredicate, minmaxbounds);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, Vec3d startPos, int duration)
|
||||
{
|
||||
LevitationTrigger.Listeners levitationtrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (levitationtrigger$listeners != null)
|
||||
{
|
||||
levitationtrigger$listeners.trigger(player, startPos, duration);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
private final DistancePredicate distance;
|
||||
private final MinMaxBounds duration;
|
||||
|
||||
public Instance(DistancePredicate distance, MinMaxBounds duration)
|
||||
{
|
||||
super(LevitationTrigger.ID);
|
||||
this.distance = distance;
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public boolean test(EntityPlayerMP player, Vec3d startPos, int durationIn)
|
||||
{
|
||||
if (!this.distance.test(startPos.x, startPos.y, startPos.z, player.posX, player.posY, player.posZ))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.duration.test((float)durationIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<LevitationTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<LevitationTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<LevitationTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<LevitationTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, Vec3d startPos, int durationIn)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<LevitationTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<LevitationTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((LevitationTrigger.Instance)listener.getCriterionInstance()).test(player, startPos, durationIn))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<LevitationTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<LevitationTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
|
||||
public class LocationPredicate
|
||||
{
|
||||
public static LocationPredicate ANY = new LocationPredicate(MinMaxBounds.UNBOUNDED, MinMaxBounds.UNBOUNDED, MinMaxBounds.UNBOUNDED, (Biome)null, (String)null, (DimensionType)null);
|
||||
private final MinMaxBounds x;
|
||||
private final MinMaxBounds y;
|
||||
private final MinMaxBounds z;
|
||||
@Nullable
|
||||
final Biome biome;
|
||||
@Nullable
|
||||
private final String feature;
|
||||
@Nullable
|
||||
private final DimensionType dimension;
|
||||
|
||||
public LocationPredicate(MinMaxBounds x, MinMaxBounds y, MinMaxBounds z, @Nullable Biome biome, @Nullable String feature, @Nullable DimensionType dimension)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.biome = biome;
|
||||
this.feature = feature;
|
||||
this.dimension = dimension;
|
||||
}
|
||||
|
||||
public boolean test(WorldServer world, double x, double y, double z)
|
||||
{
|
||||
return this.test(world, (float)x, (float)y, (float)z);
|
||||
}
|
||||
|
||||
public boolean test(WorldServer world, float x, float y, float z)
|
||||
{
|
||||
if (!this.x.test(x))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!this.y.test(y))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!this.z.test(z))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (this.dimension != null && this.dimension != world.provider.getDimensionType())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
BlockPos blockpos = new BlockPos((double)x, (double)y, (double)z);
|
||||
|
||||
if (this.biome != null && this.biome != world.getBiome(blockpos))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.feature == null || world.getChunkProvider().isInsideStructure(world, this.feature, blockpos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static LocationPredicate deserialize(@Nullable JsonElement element)
|
||||
{
|
||||
if (element != null && !element.isJsonNull())
|
||||
{
|
||||
JsonObject jsonobject = JsonUtils.getJsonObject(element, "location");
|
||||
JsonObject jsonobject1 = JsonUtils.getJsonObject(jsonobject, "position", new JsonObject());
|
||||
MinMaxBounds minmaxbounds = MinMaxBounds.deserialize(jsonobject1.get("x"));
|
||||
MinMaxBounds minmaxbounds1 = MinMaxBounds.deserialize(jsonobject1.get("y"));
|
||||
MinMaxBounds minmaxbounds2 = MinMaxBounds.deserialize(jsonobject1.get("z"));
|
||||
DimensionType dimensiontype = jsonobject.has("dimension") ? DimensionType.byName(JsonUtils.getString(jsonobject, "dimension")) : null;
|
||||
String s = jsonobject.has("feature") ? JsonUtils.getString(jsonobject, "feature") : null;
|
||||
Biome biome = null;
|
||||
|
||||
if (jsonobject.has("biome"))
|
||||
{
|
||||
ResourceLocation resourcelocation = new ResourceLocation(JsonUtils.getString(jsonobject, "biome"));
|
||||
biome = Biome.REGISTRY.getObject(resourcelocation);
|
||||
|
||||
if (biome == null)
|
||||
{
|
||||
throw new JsonSyntaxException("Unknown biome '" + resourcelocation + "'");
|
||||
}
|
||||
}
|
||||
|
||||
return new LocationPredicate(minmaxbounds, minmaxbounds1, minmaxbounds2, biome, s, dimensiontype);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ANY;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
|
||||
public class MinMaxBounds
|
||||
{
|
||||
public static final MinMaxBounds UNBOUNDED = new MinMaxBounds((Float)null, (Float)null);
|
||||
private final Float min;
|
||||
private final Float max;
|
||||
|
||||
public MinMaxBounds(@Nullable Float min, @Nullable Float max)
|
||||
{
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
public boolean test(float value)
|
||||
{
|
||||
if (this.min != null && this.min.floatValue() > value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.max == null || this.max.floatValue() >= value;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean testSquare(double value)
|
||||
{
|
||||
if (this.min != null && (double)(this.min.floatValue() * this.min.floatValue()) > value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.max == null || (double)(this.max.floatValue() * this.max.floatValue()) >= value;
|
||||
}
|
||||
}
|
||||
|
||||
public static MinMaxBounds deserialize(@Nullable JsonElement element)
|
||||
{
|
||||
if (element != null && !element.isJsonNull())
|
||||
{
|
||||
if (JsonUtils.isNumber(element))
|
||||
{
|
||||
float f2 = JsonUtils.getFloat(element, "value");
|
||||
return new MinMaxBounds(f2, f2);
|
||||
}
|
||||
else
|
||||
{
|
||||
JsonObject jsonobject = JsonUtils.getJsonObject(element, "value");
|
||||
Float f = jsonobject.has("min") ? JsonUtils.getFloat(jsonobject, "min") : null;
|
||||
Float f1 = jsonobject.has("max") ? JsonUtils.getFloat(jsonobject, "max") : null;
|
||||
return new MinMaxBounds(f, f1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return UNBOUNDED;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.potion.Potion;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class MobEffectsPredicate
|
||||
{
|
||||
/** The predicate that matches any set of effects. */
|
||||
public static final MobEffectsPredicate ANY = new MobEffectsPredicate(Collections.emptyMap());
|
||||
private final Map<Potion, MobEffectsPredicate.InstancePredicate> effects;
|
||||
|
||||
public MobEffectsPredicate(Map<Potion, MobEffectsPredicate.InstancePredicate> effects)
|
||||
{
|
||||
this.effects = effects;
|
||||
}
|
||||
|
||||
public boolean test(Entity entityIn)
|
||||
{
|
||||
if (this == ANY)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return entityIn instanceof EntityLivingBase ? this.test(((EntityLivingBase)entityIn).getActivePotionMap()) : false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean test(EntityLivingBase entityIn)
|
||||
{
|
||||
return this == ANY ? true : this.test(entityIn.getActivePotionMap());
|
||||
}
|
||||
|
||||
public boolean test(Map<Potion, PotionEffect> potions)
|
||||
{
|
||||
if (this == ANY)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Entry<Potion, MobEffectsPredicate.InstancePredicate> entry : this.effects.entrySet())
|
||||
{
|
||||
PotionEffect potioneffect = potions.get(entry.getKey());
|
||||
|
||||
if (!((MobEffectsPredicate.InstancePredicate)entry.getValue()).test(potioneffect))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static MobEffectsPredicate deserialize(@Nullable JsonElement element)
|
||||
{
|
||||
if (element != null && !element.isJsonNull())
|
||||
{
|
||||
JsonObject jsonobject = JsonUtils.getJsonObject(element, "effects");
|
||||
Map<Potion, MobEffectsPredicate.InstancePredicate> map = Maps.<Potion, MobEffectsPredicate.InstancePredicate>newHashMap();
|
||||
|
||||
for (Entry<String, JsonElement> entry : jsonobject.entrySet())
|
||||
{
|
||||
ResourceLocation resourcelocation = new ResourceLocation(entry.getKey());
|
||||
Potion potion = Potion.REGISTRY.getObject(resourcelocation);
|
||||
|
||||
if (potion == null)
|
||||
{
|
||||
throw new JsonSyntaxException("Unknown effect '" + resourcelocation + "'");
|
||||
}
|
||||
|
||||
MobEffectsPredicate.InstancePredicate mobeffectspredicate$instancepredicate = MobEffectsPredicate.InstancePredicate.deserialize(JsonUtils.getJsonObject(entry.getValue(), entry.getKey()));
|
||||
map.put(potion, mobeffectspredicate$instancepredicate);
|
||||
}
|
||||
|
||||
return new MobEffectsPredicate(map);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ANY;
|
||||
}
|
||||
}
|
||||
|
||||
public static class InstancePredicate
|
||||
{
|
||||
private final MinMaxBounds amplifier;
|
||||
private final MinMaxBounds duration;
|
||||
@Nullable
|
||||
private final Boolean ambient;
|
||||
@Nullable
|
||||
private final Boolean visible;
|
||||
|
||||
public InstancePredicate(MinMaxBounds amplifier, MinMaxBounds duration, @Nullable Boolean ambient, @Nullable Boolean visible)
|
||||
{
|
||||
this.amplifier = amplifier;
|
||||
this.duration = duration;
|
||||
this.ambient = ambient;
|
||||
this.visible = visible;
|
||||
}
|
||||
|
||||
public boolean test(@Nullable PotionEffect effect)
|
||||
{
|
||||
if (effect == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!this.amplifier.test((float)effect.getAmplifier()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!this.duration.test((float)effect.getDuration()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (this.ambient != null && this.ambient.booleanValue() != effect.getIsAmbient())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.visible == null || this.visible.booleanValue() == effect.doesShowParticles();
|
||||
}
|
||||
}
|
||||
|
||||
public static MobEffectsPredicate.InstancePredicate deserialize(JsonObject object)
|
||||
{
|
||||
MinMaxBounds minmaxbounds = MinMaxBounds.deserialize(object.get("amplifier"));
|
||||
MinMaxBounds minmaxbounds1 = MinMaxBounds.deserialize(object.get("duration"));
|
||||
Boolean obool = object.has("ambient") ? JsonUtils.getBoolean(object, "ambient") : null;
|
||||
Boolean obool1 = object.has("visible") ? JsonUtils.getBoolean(object, "visible") : null;
|
||||
return new MobEffectsPredicate.InstancePredicate(minmaxbounds, minmaxbounds1, obool, obool1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.command.CommandBase;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.JsonToNBT;
|
||||
import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTException;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
|
||||
public class NBTPredicate
|
||||
{
|
||||
/** The predicate that matches any NBT tag. */
|
||||
public static final NBTPredicate ANY = new NBTPredicate((NBTTagCompound)null);
|
||||
@Nullable
|
||||
private final NBTTagCompound tag;
|
||||
|
||||
public NBTPredicate(@Nullable NBTTagCompound tag)
|
||||
{
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
public boolean test(ItemStack item)
|
||||
{
|
||||
return this == ANY ? true : this.test(item.getTagCompound());
|
||||
}
|
||||
|
||||
public boolean test(Entity entityIn)
|
||||
{
|
||||
return this == ANY ? true : this.test(CommandBase.entityToNBT(entityIn));
|
||||
}
|
||||
|
||||
public boolean test(@Nullable NBTBase nbt)
|
||||
{
|
||||
if (nbt == null)
|
||||
{
|
||||
return this == ANY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.tag == null || NBTUtil.areNBTEquals(this.tag, nbt, true);
|
||||
}
|
||||
}
|
||||
|
||||
public static NBTPredicate deserialize(@Nullable JsonElement json)
|
||||
{
|
||||
if (json != null && !json.isJsonNull())
|
||||
{
|
||||
NBTTagCompound nbttagcompound;
|
||||
|
||||
try
|
||||
{
|
||||
nbttagcompound = JsonToNBT.getTagFromJson(JsonUtils.getString(json, "nbt"));
|
||||
}
|
||||
catch (NBTException nbtexception)
|
||||
{
|
||||
throw new JsonSyntaxException("Invalid nbt tag: " + nbtexception.getMessage());
|
||||
}
|
||||
|
||||
return new NBTPredicate(nbttagcompound);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ANY;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.WorldServer;
|
||||
|
||||
public class NetherTravelTrigger implements ICriterionTrigger<NetherTravelTrigger.Instance>
|
||||
{
|
||||
private static final ResourceLocation ID = new ResourceLocation("nether_travel");
|
||||
private final Map<PlayerAdvancements, NetherTravelTrigger.Listeners> listeners = Maps.<PlayerAdvancements, NetherTravelTrigger.Listeners>newHashMap();
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<NetherTravelTrigger.Instance> listener)
|
||||
{
|
||||
NetherTravelTrigger.Listeners nethertraveltrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (nethertraveltrigger$listeners == null)
|
||||
{
|
||||
nethertraveltrigger$listeners = new NetherTravelTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, nethertraveltrigger$listeners);
|
||||
}
|
||||
|
||||
nethertraveltrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<NetherTravelTrigger.Instance> listener)
|
||||
{
|
||||
NetherTravelTrigger.Listeners nethertraveltrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (nethertraveltrigger$listeners != null)
|
||||
{
|
||||
nethertraveltrigger$listeners.remove(listener);
|
||||
|
||||
if (nethertraveltrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public NetherTravelTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
LocationPredicate locationpredicate = LocationPredicate.deserialize(json.get("entered"));
|
||||
LocationPredicate locationpredicate1 = LocationPredicate.deserialize(json.get("exited"));
|
||||
DistancePredicate distancepredicate = DistancePredicate.deserialize(json.get("distance"));
|
||||
return new NetherTravelTrigger.Instance(locationpredicate, locationpredicate1, distancepredicate);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, Vec3d enteredNetherPosition)
|
||||
{
|
||||
NetherTravelTrigger.Listeners nethertraveltrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (nethertraveltrigger$listeners != null)
|
||||
{
|
||||
nethertraveltrigger$listeners.trigger(player.getServerWorld(), enteredNetherPosition, player.posX, player.posY, player.posZ);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
private final LocationPredicate entered;
|
||||
private final LocationPredicate exited;
|
||||
private final DistancePredicate distance;
|
||||
|
||||
public Instance(LocationPredicate enteredIn, LocationPredicate exitedIn, DistancePredicate distanceIn)
|
||||
{
|
||||
super(NetherTravelTrigger.ID);
|
||||
this.entered = enteredIn;
|
||||
this.exited = exitedIn;
|
||||
this.distance = distanceIn;
|
||||
}
|
||||
|
||||
public boolean test(WorldServer world, Vec3d enteredNetherPosition, double x, double y, double z)
|
||||
{
|
||||
if (!this.entered.test(world, enteredNetherPosition.x, enteredNetherPosition.y, enteredNetherPosition.z))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!this.exited.test(world, x, y, z))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.distance.test(enteredNetherPosition.x, enteredNetherPosition.y, enteredNetherPosition.z, x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<NetherTravelTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<NetherTravelTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<NetherTravelTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<NetherTravelTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(WorldServer world, Vec3d enteredNetherPosition, double x, double y, double z)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<NetherTravelTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<NetherTravelTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((NetherTravelTrigger.Instance)listener.getCriterionInstance()).test(world, enteredNetherPosition, x, y, z))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<NetherTravelTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<NetherTravelTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.WorldServer;
|
||||
|
||||
public class PlacedBlockTrigger implements ICriterionTrigger<PlacedBlockTrigger.Instance>
|
||||
{
|
||||
private static final ResourceLocation ID = new ResourceLocation("placed_block");
|
||||
private final Map<PlayerAdvancements, PlacedBlockTrigger.Listeners> listeners = Maps.<PlayerAdvancements, PlacedBlockTrigger.Listeners>newHashMap();
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<PlacedBlockTrigger.Instance> listener)
|
||||
{
|
||||
PlacedBlockTrigger.Listeners placedblocktrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (placedblocktrigger$listeners == null)
|
||||
{
|
||||
placedblocktrigger$listeners = new PlacedBlockTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, placedblocktrigger$listeners);
|
||||
}
|
||||
|
||||
placedblocktrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<PlacedBlockTrigger.Instance> listener)
|
||||
{
|
||||
PlacedBlockTrigger.Listeners placedblocktrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (placedblocktrigger$listeners != null)
|
||||
{
|
||||
placedblocktrigger$listeners.remove(listener);
|
||||
|
||||
if (placedblocktrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public PlacedBlockTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
Block block = null;
|
||||
|
||||
if (json.has("block"))
|
||||
{
|
||||
ResourceLocation resourcelocation = new ResourceLocation(JsonUtils.getString(json, "block"));
|
||||
|
||||
if (!Block.REGISTRY.containsKey(resourcelocation))
|
||||
{
|
||||
throw new JsonSyntaxException("Unknown block type '" + resourcelocation + "'");
|
||||
}
|
||||
|
||||
block = Block.REGISTRY.getObject(resourcelocation);
|
||||
}
|
||||
|
||||
Map < IProperty<?>, Object > map = null;
|
||||
|
||||
if (json.has("state"))
|
||||
{
|
||||
if (block == null)
|
||||
{
|
||||
throw new JsonSyntaxException("Can't define block state without a specific block type");
|
||||
}
|
||||
|
||||
BlockStateContainer blockstatecontainer = block.getBlockState();
|
||||
|
||||
for (Entry<String, JsonElement> entry : JsonUtils.getJsonObject(json, "state").entrySet())
|
||||
{
|
||||
IProperty<?> iproperty = blockstatecontainer.getProperty(entry.getKey());
|
||||
|
||||
if (iproperty == null)
|
||||
{
|
||||
throw new JsonSyntaxException("Unknown block state property '" + (String)entry.getKey() + "' for block '" + Block.REGISTRY.getNameForObject(block) + "'");
|
||||
}
|
||||
|
||||
String s = JsonUtils.getString(entry.getValue(), entry.getKey());
|
||||
Optional<?> optional = iproperty.parseValue(s);
|
||||
|
||||
if (!optional.isPresent())
|
||||
{
|
||||
throw new JsonSyntaxException("Invalid block state value '" + s + "' for property '" + (String)entry.getKey() + "' on block '" + Block.REGISTRY.getNameForObject(block) + "'");
|
||||
}
|
||||
|
||||
if (map == null)
|
||||
{
|
||||
map = Maps. < IProperty<?>, Object > newHashMap();
|
||||
}
|
||||
|
||||
map.put(iproperty, optional.get());
|
||||
}
|
||||
}
|
||||
|
||||
LocationPredicate locationpredicate = LocationPredicate.deserialize(json.get("location"));
|
||||
ItemPredicate itempredicate = ItemPredicate.deserialize(json.get("item"));
|
||||
return new PlacedBlockTrigger.Instance(block, map, locationpredicate, itempredicate);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, BlockPos pos, ItemStack item)
|
||||
{
|
||||
IBlockState iblockstate = player.world.getBlockState(pos);
|
||||
PlacedBlockTrigger.Listeners placedblocktrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (placedblocktrigger$listeners != null)
|
||||
{
|
||||
placedblocktrigger$listeners.trigger(iblockstate, pos, player.getServerWorld(), item);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
private final Block block;
|
||||
private final Map < IProperty<?>, Object > properties;
|
||||
private final LocationPredicate location;
|
||||
private final ItemPredicate item;
|
||||
|
||||
public Instance(@Nullable Block block, @Nullable Map < IProperty<?>, Object > propertiesIn, LocationPredicate locationIn, ItemPredicate itemIn)
|
||||
{
|
||||
super(PlacedBlockTrigger.ID);
|
||||
this.block = block;
|
||||
this.properties = propertiesIn;
|
||||
this.location = locationIn;
|
||||
this.item = itemIn;
|
||||
}
|
||||
|
||||
public boolean test(IBlockState state, BlockPos pos, WorldServer world, ItemStack item)
|
||||
{
|
||||
if (this.block != null && state.getBlock() != this.block)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.properties != null)
|
||||
{
|
||||
for (Entry < IProperty<?>, Object > entry : this.properties.entrySet())
|
||||
{
|
||||
if (state.getValue(entry.getKey()) != entry.getValue())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.location.test(world, (float)pos.getX(), (float)pos.getY(), (float)pos.getZ()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.item.test(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<PlacedBlockTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<PlacedBlockTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<PlacedBlockTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<PlacedBlockTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(IBlockState state, BlockPos pos, WorldServer world, ItemStack item)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<PlacedBlockTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<PlacedBlockTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((PlacedBlockTrigger.Instance)listener.getCriterionInstance()).test(state, pos, world, item))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<PlacedBlockTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<PlacedBlockTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class PlayerHurtEntityTrigger implements ICriterionTrigger<PlayerHurtEntityTrigger.Instance>
|
||||
{
|
||||
private static final ResourceLocation ID = new ResourceLocation("player_hurt_entity");
|
||||
private final Map<PlayerAdvancements, PlayerHurtEntityTrigger.Listeners> listeners = Maps.<PlayerAdvancements, PlayerHurtEntityTrigger.Listeners>newHashMap();
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<PlayerHurtEntityTrigger.Instance> listener)
|
||||
{
|
||||
PlayerHurtEntityTrigger.Listeners playerhurtentitytrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (playerhurtentitytrigger$listeners == null)
|
||||
{
|
||||
playerhurtentitytrigger$listeners = new PlayerHurtEntityTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, playerhurtentitytrigger$listeners);
|
||||
}
|
||||
|
||||
playerhurtentitytrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<PlayerHurtEntityTrigger.Instance> listener)
|
||||
{
|
||||
PlayerHurtEntityTrigger.Listeners playerhurtentitytrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (playerhurtentitytrigger$listeners != null)
|
||||
{
|
||||
playerhurtentitytrigger$listeners.remove(listener);
|
||||
|
||||
if (playerhurtentitytrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public PlayerHurtEntityTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
DamagePredicate damagepredicate = DamagePredicate.deserialize(json.get("damage"));
|
||||
EntityPredicate entitypredicate = EntityPredicate.deserialize(json.get("entity"));
|
||||
return new PlayerHurtEntityTrigger.Instance(damagepredicate, entitypredicate);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, Entity entityIn, DamageSource source, float amountDealt, float amountTaken, boolean blocked)
|
||||
{
|
||||
PlayerHurtEntityTrigger.Listeners playerhurtentitytrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (playerhurtentitytrigger$listeners != null)
|
||||
{
|
||||
playerhurtentitytrigger$listeners.trigger(player, entityIn, source, amountDealt, amountTaken, blocked);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
private final DamagePredicate damage;
|
||||
private final EntityPredicate entity;
|
||||
|
||||
public Instance(DamagePredicate damage, EntityPredicate entity)
|
||||
{
|
||||
super(PlayerHurtEntityTrigger.ID);
|
||||
this.damage = damage;
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
public boolean test(EntityPlayerMP player, Entity entity, DamageSource source, float dealt, float taken, boolean blocked)
|
||||
{
|
||||
if (!this.damage.test(player, source, dealt, taken, blocked))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.entity.test(player, entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<PlayerHurtEntityTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<PlayerHurtEntityTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<PlayerHurtEntityTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<PlayerHurtEntityTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, Entity entity, DamageSource source, float dealt, float taken, boolean blocked)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<PlayerHurtEntityTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<PlayerHurtEntityTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((PlayerHurtEntityTrigger.Instance)listener.getCriterionInstance()).test(player, entity, source, dealt, taken, blocked))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<PlayerHurtEntityTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<PlayerHurtEntityTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.WorldServer;
|
||||
|
||||
public class PositionTrigger implements ICriterionTrigger<PositionTrigger.Instance>
|
||||
{
|
||||
private final ResourceLocation id;
|
||||
private final Map<PlayerAdvancements, PositionTrigger.Listeners> listeners = Maps.<PlayerAdvancements, PositionTrigger.Listeners>newHashMap();
|
||||
|
||||
public PositionTrigger(ResourceLocation id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<PositionTrigger.Instance> listener)
|
||||
{
|
||||
PositionTrigger.Listeners positiontrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (positiontrigger$listeners == null)
|
||||
{
|
||||
positiontrigger$listeners = new PositionTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, positiontrigger$listeners);
|
||||
}
|
||||
|
||||
positiontrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<PositionTrigger.Instance> listener)
|
||||
{
|
||||
PositionTrigger.Listeners positiontrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (positiontrigger$listeners != null)
|
||||
{
|
||||
positiontrigger$listeners.remove(listener);
|
||||
|
||||
if (positiontrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public PositionTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
LocationPredicate locationpredicate = LocationPredicate.deserialize(json);
|
||||
return new PositionTrigger.Instance(this.id, locationpredicate);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player)
|
||||
{
|
||||
PositionTrigger.Listeners positiontrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (positiontrigger$listeners != null)
|
||||
{
|
||||
positiontrigger$listeners.trigger(player.getServerWorld(), player.posX, player.posY, player.posZ);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
private final LocationPredicate location;
|
||||
|
||||
public Instance(ResourceLocation criterionIn, LocationPredicate location)
|
||||
{
|
||||
super(criterionIn);
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public boolean test(WorldServer world, double x, double y, double z)
|
||||
{
|
||||
return this.location.test(world, x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<PositionTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<PositionTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<PositionTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<PositionTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(WorldServer world, double x, double y, double z)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<PositionTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<PositionTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((PositionTrigger.Instance)listener.getCriterionInstance()).test(world, x, y, z))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<PositionTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<PositionTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.crafting.CraftingManager;
|
||||
import net.minecraft.item.crafting.IRecipe;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class RecipeUnlockedTrigger implements ICriterionTrigger<RecipeUnlockedTrigger.Instance>
|
||||
{
|
||||
private static final ResourceLocation ID = new ResourceLocation("recipe_unlocked");
|
||||
private final Map<PlayerAdvancements, RecipeUnlockedTrigger.Listeners> listeners = Maps.<PlayerAdvancements, RecipeUnlockedTrigger.Listeners>newHashMap();
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<RecipeUnlockedTrigger.Instance> listener)
|
||||
{
|
||||
RecipeUnlockedTrigger.Listeners recipeunlockedtrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (recipeunlockedtrigger$listeners == null)
|
||||
{
|
||||
recipeunlockedtrigger$listeners = new RecipeUnlockedTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, recipeunlockedtrigger$listeners);
|
||||
}
|
||||
|
||||
recipeunlockedtrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<RecipeUnlockedTrigger.Instance> listener)
|
||||
{
|
||||
RecipeUnlockedTrigger.Listeners recipeunlockedtrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (recipeunlockedtrigger$listeners != null)
|
||||
{
|
||||
recipeunlockedtrigger$listeners.remove(listener);
|
||||
|
||||
if (recipeunlockedtrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public RecipeUnlockedTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
ResourceLocation resourcelocation = new ResourceLocation(JsonUtils.getString(json, "recipe"));
|
||||
IRecipe irecipe = CraftingManager.getRecipe(resourcelocation);
|
||||
|
||||
if (irecipe == null)
|
||||
{
|
||||
throw new JsonSyntaxException("Unknown recipe '" + resourcelocation + "'");
|
||||
}
|
||||
else
|
||||
{
|
||||
return new RecipeUnlockedTrigger.Instance(irecipe);
|
||||
}
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, IRecipe recipe)
|
||||
{
|
||||
RecipeUnlockedTrigger.Listeners recipeunlockedtrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (recipeunlockedtrigger$listeners != null)
|
||||
{
|
||||
recipeunlockedtrigger$listeners.trigger(recipe);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
private final IRecipe recipe;
|
||||
|
||||
public Instance(IRecipe recipe)
|
||||
{
|
||||
super(RecipeUnlockedTrigger.ID);
|
||||
this.recipe = recipe;
|
||||
}
|
||||
|
||||
public boolean test(IRecipe recipe)
|
||||
{
|
||||
return this.recipe == recipe;
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<RecipeUnlockedTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<RecipeUnlockedTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<RecipeUnlockedTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<RecipeUnlockedTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(IRecipe recipe)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<RecipeUnlockedTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<RecipeUnlockedTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((RecipeUnlockedTrigger.Instance)listener.getCriterionInstance()).test(recipe))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<RecipeUnlockedTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<RecipeUnlockedTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class SummonedEntityTrigger implements ICriterionTrigger<SummonedEntityTrigger.Instance>
|
||||
{
|
||||
private static final ResourceLocation ID = new ResourceLocation("summoned_entity");
|
||||
private final Map<PlayerAdvancements, SummonedEntityTrigger.Listeners> listeners = Maps.<PlayerAdvancements, SummonedEntityTrigger.Listeners>newHashMap();
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<SummonedEntityTrigger.Instance> listener)
|
||||
{
|
||||
SummonedEntityTrigger.Listeners summonedentitytrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (summonedentitytrigger$listeners == null)
|
||||
{
|
||||
summonedentitytrigger$listeners = new SummonedEntityTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, summonedentitytrigger$listeners);
|
||||
}
|
||||
|
||||
summonedentitytrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<SummonedEntityTrigger.Instance> listener)
|
||||
{
|
||||
SummonedEntityTrigger.Listeners summonedentitytrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (summonedentitytrigger$listeners != null)
|
||||
{
|
||||
summonedentitytrigger$listeners.remove(listener);
|
||||
|
||||
if (summonedentitytrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public SummonedEntityTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
EntityPredicate entitypredicate = EntityPredicate.deserialize(json.get("entity"));
|
||||
return new SummonedEntityTrigger.Instance(entitypredicate);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, Entity entity)
|
||||
{
|
||||
SummonedEntityTrigger.Listeners summonedentitytrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (summonedentitytrigger$listeners != null)
|
||||
{
|
||||
summonedentitytrigger$listeners.trigger(player, entity);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
private final EntityPredicate entity;
|
||||
|
||||
public Instance(EntityPredicate entity)
|
||||
{
|
||||
super(SummonedEntityTrigger.ID);
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
public boolean test(EntityPlayerMP player, Entity entity)
|
||||
{
|
||||
return this.entity.test(player, entity);
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<SummonedEntityTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<SummonedEntityTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<SummonedEntityTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<SummonedEntityTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, Entity entity)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<SummonedEntityTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<SummonedEntityTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((SummonedEntityTrigger.Instance)listener.getCriterionInstance()).test(player, entity))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<SummonedEntityTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<SummonedEntityTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.entity.passive.EntityAnimal;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class TameAnimalTrigger implements ICriterionTrigger<TameAnimalTrigger.Instance>
|
||||
{
|
||||
private static final ResourceLocation ID = new ResourceLocation("tame_animal");
|
||||
private final Map<PlayerAdvancements, TameAnimalTrigger.Listeners> listeners = Maps.<PlayerAdvancements, TameAnimalTrigger.Listeners>newHashMap();
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<TameAnimalTrigger.Instance> listener)
|
||||
{
|
||||
TameAnimalTrigger.Listeners tameanimaltrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (tameanimaltrigger$listeners == null)
|
||||
{
|
||||
tameanimaltrigger$listeners = new TameAnimalTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, tameanimaltrigger$listeners);
|
||||
}
|
||||
|
||||
tameanimaltrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<TameAnimalTrigger.Instance> listener)
|
||||
{
|
||||
TameAnimalTrigger.Listeners tameanimaltrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (tameanimaltrigger$listeners != null)
|
||||
{
|
||||
tameanimaltrigger$listeners.remove(listener);
|
||||
|
||||
if (tameanimaltrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public TameAnimalTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
EntityPredicate entitypredicate = EntityPredicate.deserialize(json.get("entity"));
|
||||
return new TameAnimalTrigger.Instance(entitypredicate);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, EntityAnimal entity)
|
||||
{
|
||||
TameAnimalTrigger.Listeners tameanimaltrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (tameanimaltrigger$listeners != null)
|
||||
{
|
||||
tameanimaltrigger$listeners.trigger(player, entity);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
private final EntityPredicate entity;
|
||||
|
||||
public Instance(EntityPredicate entity)
|
||||
{
|
||||
super(TameAnimalTrigger.ID);
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
public boolean test(EntityPlayerMP player, EntityAnimal entity)
|
||||
{
|
||||
return this.entity.test(player, entity);
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<TameAnimalTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<TameAnimalTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<TameAnimalTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<TameAnimalTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, EntityAnimal entity)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<TameAnimalTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<TameAnimalTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((TameAnimalTrigger.Instance)listener.getCriterionInstance()).test(player, entity))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<TameAnimalTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<TameAnimalTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class TickTrigger implements ICriterionTrigger<TickTrigger.Instance>
|
||||
{
|
||||
public static final ResourceLocation ID = new ResourceLocation("tick");
|
||||
private final Map<PlayerAdvancements, TickTrigger.Listeners> listeners = Maps.<PlayerAdvancements, TickTrigger.Listeners>newHashMap();
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<TickTrigger.Instance> listener)
|
||||
{
|
||||
TickTrigger.Listeners ticktrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (ticktrigger$listeners == null)
|
||||
{
|
||||
ticktrigger$listeners = new TickTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, ticktrigger$listeners);
|
||||
}
|
||||
|
||||
ticktrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<TickTrigger.Instance> listener)
|
||||
{
|
||||
TickTrigger.Listeners ticktrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (ticktrigger$listeners != null)
|
||||
{
|
||||
ticktrigger$listeners.remove(listener);
|
||||
|
||||
if (ticktrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public TickTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
return new TickTrigger.Instance();
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player)
|
||||
{
|
||||
TickTrigger.Listeners ticktrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (ticktrigger$listeners != null)
|
||||
{
|
||||
ticktrigger$listeners.trigger();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
public Instance()
|
||||
{
|
||||
super(TickTrigger.ID);
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<TickTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<TickTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<TickTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<TickTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger()
|
||||
{
|
||||
for (ICriterionTrigger.Listener<TickTrigger.Instance> listener : Lists.newArrayList(this.listeners))
|
||||
{
|
||||
listener.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public class UsedEnderEyeTrigger implements ICriterionTrigger<UsedEnderEyeTrigger.Instance>
|
||||
{
|
||||
private static final ResourceLocation ID = new ResourceLocation("used_ender_eye");
|
||||
private final Map<PlayerAdvancements, UsedEnderEyeTrigger.Listeners> listeners = Maps.<PlayerAdvancements, UsedEnderEyeTrigger.Listeners>newHashMap();
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<UsedEnderEyeTrigger.Instance> listener)
|
||||
{
|
||||
UsedEnderEyeTrigger.Listeners usedendereyetrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (usedendereyetrigger$listeners == null)
|
||||
{
|
||||
usedendereyetrigger$listeners = new UsedEnderEyeTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, usedendereyetrigger$listeners);
|
||||
}
|
||||
|
||||
usedendereyetrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<UsedEnderEyeTrigger.Instance> listener)
|
||||
{
|
||||
UsedEnderEyeTrigger.Listeners usedendereyetrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (usedendereyetrigger$listeners != null)
|
||||
{
|
||||
usedendereyetrigger$listeners.remove(listener);
|
||||
|
||||
if (usedendereyetrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public UsedEnderEyeTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
MinMaxBounds minmaxbounds = MinMaxBounds.deserialize(json.get("distance"));
|
||||
return new UsedEnderEyeTrigger.Instance(minmaxbounds);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, BlockPos pos)
|
||||
{
|
||||
UsedEnderEyeTrigger.Listeners usedendereyetrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (usedendereyetrigger$listeners != null)
|
||||
{
|
||||
double d0 = player.posX - (double)pos.getX();
|
||||
double d1 = player.posZ - (double)pos.getZ();
|
||||
usedendereyetrigger$listeners.trigger(d0 * d0 + d1 * d1);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
private final MinMaxBounds distance;
|
||||
|
||||
public Instance(MinMaxBounds distance)
|
||||
{
|
||||
super(UsedEnderEyeTrigger.ID);
|
||||
this.distance = distance;
|
||||
}
|
||||
|
||||
public boolean test(double distanceSq)
|
||||
{
|
||||
return this.distance.testSquare(distanceSq);
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<UsedEnderEyeTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<UsedEnderEyeTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<UsedEnderEyeTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<UsedEnderEyeTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(double distanceSq)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<UsedEnderEyeTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<UsedEnderEyeTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((UsedEnderEyeTrigger.Instance)listener.getCriterionInstance()).test(distanceSq))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<UsedEnderEyeTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<UsedEnderEyeTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class UsedTotemTrigger implements ICriterionTrigger<UsedTotemTrigger.Instance>
|
||||
{
|
||||
private static final ResourceLocation ID = new ResourceLocation("used_totem");
|
||||
private final Map<PlayerAdvancements, UsedTotemTrigger.Listeners> listeners = Maps.<PlayerAdvancements, UsedTotemTrigger.Listeners>newHashMap();
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<UsedTotemTrigger.Instance> listener)
|
||||
{
|
||||
UsedTotemTrigger.Listeners usedtotemtrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (usedtotemtrigger$listeners == null)
|
||||
{
|
||||
usedtotemtrigger$listeners = new UsedTotemTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, usedtotemtrigger$listeners);
|
||||
}
|
||||
|
||||
usedtotemtrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<UsedTotemTrigger.Instance> listener)
|
||||
{
|
||||
UsedTotemTrigger.Listeners usedtotemtrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (usedtotemtrigger$listeners != null)
|
||||
{
|
||||
usedtotemtrigger$listeners.remove(listener);
|
||||
|
||||
if (usedtotemtrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public UsedTotemTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
ItemPredicate itempredicate = ItemPredicate.deserialize(json.get("item"));
|
||||
return new UsedTotemTrigger.Instance(itempredicate);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, ItemStack item)
|
||||
{
|
||||
UsedTotemTrigger.Listeners usedtotemtrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (usedtotemtrigger$listeners != null)
|
||||
{
|
||||
usedtotemtrigger$listeners.trigger(item);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
private final ItemPredicate item;
|
||||
|
||||
public Instance(ItemPredicate item)
|
||||
{
|
||||
super(UsedTotemTrigger.ID);
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
public boolean test(ItemStack item)
|
||||
{
|
||||
return this.item.test(item);
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<UsedTotemTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<UsedTotemTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<UsedTotemTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<UsedTotemTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(ItemStack item)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<UsedTotemTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<UsedTotemTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((UsedTotemTrigger.Instance)listener.getCriterionInstance()).test(item))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<UsedTotemTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<UsedTotemTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.minecraft.advancements.ICriterionTrigger;
|
||||
import net.minecraft.advancements.PlayerAdvancements;
|
||||
import net.minecraft.entity.passive.EntityVillager;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class VillagerTradeTrigger implements ICriterionTrigger<VillagerTradeTrigger.Instance>
|
||||
{
|
||||
private static final ResourceLocation ID = new ResourceLocation("villager_trade");
|
||||
private final Map<PlayerAdvancements, VillagerTradeTrigger.Listeners> listeners = Maps.<PlayerAdvancements, VillagerTradeTrigger.Listeners>newHashMap();
|
||||
|
||||
public ResourceLocation getId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void addListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<VillagerTradeTrigger.Instance> listener)
|
||||
{
|
||||
VillagerTradeTrigger.Listeners villagertradetrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (villagertradetrigger$listeners == null)
|
||||
{
|
||||
villagertradetrigger$listeners = new VillagerTradeTrigger.Listeners(playerAdvancementsIn);
|
||||
this.listeners.put(playerAdvancementsIn, villagertradetrigger$listeners);
|
||||
}
|
||||
|
||||
villagertradetrigger$listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(PlayerAdvancements playerAdvancementsIn, ICriterionTrigger.Listener<VillagerTradeTrigger.Instance> listener)
|
||||
{
|
||||
VillagerTradeTrigger.Listeners villagertradetrigger$listeners = this.listeners.get(playerAdvancementsIn);
|
||||
|
||||
if (villagertradetrigger$listeners != null)
|
||||
{
|
||||
villagertradetrigger$listeners.remove(listener);
|
||||
|
||||
if (villagertradetrigger$listeners.isEmpty())
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.listeners.remove(playerAdvancementsIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a ICriterionInstance of this trigger from the data in the JSON.
|
||||
*/
|
||||
public VillagerTradeTrigger.Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
|
||||
{
|
||||
EntityPredicate entitypredicate = EntityPredicate.deserialize(json.get("villager"));
|
||||
ItemPredicate itempredicate = ItemPredicate.deserialize(json.get("item"));
|
||||
return new VillagerTradeTrigger.Instance(entitypredicate, itempredicate);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, EntityVillager villager, ItemStack item)
|
||||
{
|
||||
VillagerTradeTrigger.Listeners villagertradetrigger$listeners = this.listeners.get(player.getAdvancements());
|
||||
|
||||
if (villagertradetrigger$listeners != null)
|
||||
{
|
||||
villagertradetrigger$listeners.trigger(player, villager, item);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Instance extends AbstractCriterionInstance
|
||||
{
|
||||
private final EntityPredicate villager;
|
||||
private final ItemPredicate item;
|
||||
|
||||
public Instance(EntityPredicate villager, ItemPredicate item)
|
||||
{
|
||||
super(VillagerTradeTrigger.ID);
|
||||
this.villager = villager;
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
public boolean test(EntityPlayerMP player, EntityVillager villager, ItemStack item)
|
||||
{
|
||||
if (!this.villager.test(player, villager))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.item.test(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class Listeners
|
||||
{
|
||||
private final PlayerAdvancements playerAdvancements;
|
||||
private final Set<ICriterionTrigger.Listener<VillagerTradeTrigger.Instance>> listeners = Sets.<ICriterionTrigger.Listener<VillagerTradeTrigger.Instance>>newHashSet();
|
||||
|
||||
public Listeners(PlayerAdvancements playerAdvancementsIn)
|
||||
{
|
||||
this.playerAdvancements = playerAdvancementsIn;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void add(ICriterionTrigger.Listener<VillagerTradeTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void remove(ICriterionTrigger.Listener<VillagerTradeTrigger.Instance> listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void trigger(EntityPlayerMP player, EntityVillager villager, ItemStack item)
|
||||
{
|
||||
List<ICriterionTrigger.Listener<VillagerTradeTrigger.Instance>> list = null;
|
||||
|
||||
for (ICriterionTrigger.Listener<VillagerTradeTrigger.Instance> listener : this.listeners)
|
||||
{
|
||||
if (((VillagerTradeTrigger.Instance)listener.getCriterionInstance()).test(player, villager, item))
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = Lists.<ICriterionTrigger.Listener<VillagerTradeTrigger.Instance>>newArrayList();
|
||||
}
|
||||
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
for (ICriterionTrigger.Listener<VillagerTradeTrigger.Instance> listener1 : list)
|
||||
{
|
||||
listener1.grantCriterion(this.playerAdvancements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// Auto generated package-info by MCP
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
package net.minecraft.advancements.critereon;
|
||||
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
@@ -0,0 +1,7 @@
|
||||
// Auto generated package-info by MCP
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
package net.minecraft.advancements;
|
||||
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
2867
build/tmp/recompileMc/sources/net/minecraft/block/Block.java
Normal file
2867
build/tmp/recompileMc/sources/net/minecraft/block/Block.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,82 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.BlockFaceShape;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.EnumBlockRenderType;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class BlockAir extends Block
|
||||
{
|
||||
protected BlockAir()
|
||||
{
|
||||
super(Material.AIR);
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of render function called. MODEL for mixed tesr and static model, MODELBLOCK_ANIMATED for TESR-only,
|
||||
* LIQUID for vanilla liquids, INVISIBLE to skip all rendering
|
||||
*/
|
||||
public EnumBlockRenderType getRenderType(IBlockState state)
|
||||
{
|
||||
return EnumBlockRenderType.INVISIBLE;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public AxisAlignedBB getCollisionBoundingBox(IBlockState blockState, IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
return NULL_AABB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine ambient occlusion and culling when rebuilding chunks for render
|
||||
*/
|
||||
public boolean isOpaqueCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean canCollideCheck(IBlockState state, boolean hitIfLiquid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns this Block's drops into the World as EntityItems.
|
||||
*/
|
||||
public void dropBlockAsItemWithChance(World worldIn, BlockPos pos, IBlockState state, float chance, int fortune)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this Block can be replaced directly by other blocks (true for e.g. tall grass)
|
||||
*/
|
||||
public boolean isReplaceable(IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isFullCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the geometry of the queried face at the given position and state. This is used to decide whether things like
|
||||
* buttons are allowed to be placed on the face, or how glass panes connect to the face, among other things.
|
||||
* <p>
|
||||
* Common values are {@code SOLID}, which is the default, and {@code UNDEFINED}, which represents something that
|
||||
* does not fit the other descriptions and will generally cause other things not to connect to the face.
|
||||
*
|
||||
* @return an approximation of the form of the given face
|
||||
*/
|
||||
public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face)
|
||||
{
|
||||
return BlockFaceShape.UNDEFINED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.properties.PropertyDirection;
|
||||
import net.minecraft.block.properties.PropertyInteger;
|
||||
import net.minecraft.block.state.BlockFaceShape;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.item.EntityFallingBlock;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.inventory.Container;
|
||||
import net.minecraft.inventory.ContainerRepair;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.util.Rotation;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.TextComponentTranslation;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.IInteractionObject;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class BlockAnvil extends BlockFalling
|
||||
{
|
||||
public static final PropertyDirection FACING = BlockHorizontal.FACING;
|
||||
public static final PropertyInteger DAMAGE = PropertyInteger.create("damage", 0, 2);
|
||||
protected static final AxisAlignedBB X_AXIS_AABB = new AxisAlignedBB(0.0D, 0.0D, 0.125D, 1.0D, 1.0D, 0.875D);
|
||||
protected static final AxisAlignedBB Z_AXIS_AABB = new AxisAlignedBB(0.125D, 0.0D, 0.0D, 0.875D, 1.0D, 1.0D);
|
||||
protected static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
protected BlockAnvil()
|
||||
{
|
||||
super(Material.ANVIL);
|
||||
this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH).withProperty(DAMAGE, Integer.valueOf(0)));
|
||||
this.setLightOpacity(0);
|
||||
this.setCreativeTab(CreativeTabs.DECORATIONS);
|
||||
}
|
||||
|
||||
public boolean isFullCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the geometry of the queried face at the given position and state. This is used to decide whether things like
|
||||
* buttons are allowed to be placed on the face, or how glass panes connect to the face, among other things.
|
||||
* <p>
|
||||
* Common values are {@code SOLID}, which is the default, and {@code UNDEFINED}, which represents something that
|
||||
* does not fit the other descriptions and will generally cause other things not to connect to the face.
|
||||
*
|
||||
* @return an approximation of the form of the given face
|
||||
*/
|
||||
public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face)
|
||||
{
|
||||
return BlockFaceShape.UNDEFINED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine ambient occlusion and culling when rebuilding chunks for render
|
||||
*/
|
||||
public boolean isOpaqueCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by ItemBlocks just before a block is actually set in the world, to allow for adjustments to the
|
||||
* IBlockstate
|
||||
*/
|
||||
public IBlockState getStateForPlacement(World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer)
|
||||
{
|
||||
EnumFacing enumfacing = placer.getHorizontalFacing().rotateY();
|
||||
|
||||
try
|
||||
{
|
||||
return super.getStateForPlacement(worldIn, pos, facing, hitX, hitY, hitZ, meta, placer).withProperty(FACING, enumfacing).withProperty(DAMAGE, Integer.valueOf(meta >> 2));
|
||||
}
|
||||
catch (IllegalArgumentException var11)
|
||||
{
|
||||
if (!worldIn.isRemote)
|
||||
{
|
||||
LOGGER.warn(String.format("Invalid damage property for anvil at %s. Found %d, must be in [0, 1, 2]", pos, meta >> 2));
|
||||
|
||||
if (placer instanceof EntityPlayer)
|
||||
{
|
||||
placer.sendMessage(new TextComponentTranslation("Invalid damage property. Please pick in [0, 1, 2]", new Object[0]));
|
||||
}
|
||||
}
|
||||
|
||||
return super.getStateForPlacement(worldIn, pos, facing, hitX, hitY, hitZ, 0, placer).withProperty(FACING, enumfacing).withProperty(DAMAGE, Integer.valueOf(0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the block is right clicked by a player.
|
||||
*/
|
||||
public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
|
||||
{
|
||||
if (!worldIn.isRemote)
|
||||
{
|
||||
playerIn.displayGui(new BlockAnvil.Anvil(worldIn, pos));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the metadata of the item this Block can drop. This method is called when the block gets destroyed. It
|
||||
* returns the metadata of the dropped item based on the old metadata of the block.
|
||||
*/
|
||||
public int damageDropped(IBlockState state)
|
||||
{
|
||||
return ((Integer)state.getValue(DAMAGE)).intValue();
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
|
||||
{
|
||||
EnumFacing enumfacing = (EnumFacing)state.getValue(FACING);
|
||||
return enumfacing.getAxis() == EnumFacing.Axis.X ? X_AXIS_AABB : Z_AXIS_AABB;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a list of blocks with the same ID, but different meta (eg: wood returns 4 blocks)
|
||||
*/
|
||||
public void getSubBlocks(CreativeTabs itemIn, NonNullList<ItemStack> items)
|
||||
{
|
||||
items.add(new ItemStack(this));
|
||||
items.add(new ItemStack(this, 1, 1));
|
||||
items.add(new ItemStack(this, 1, 2));
|
||||
}
|
||||
|
||||
protected void onStartFalling(EntityFallingBlock fallingEntity)
|
||||
{
|
||||
fallingEntity.setHurtEntities(true);
|
||||
}
|
||||
|
||||
public void onEndFalling(World worldIn, BlockPos pos, IBlockState p_176502_3_, IBlockState p_176502_4_)
|
||||
{
|
||||
worldIn.playEvent(1031, pos, 0);
|
||||
}
|
||||
|
||||
public void onBroken(World worldIn, BlockPos pos)
|
||||
{
|
||||
worldIn.playEvent(1029, pos, 0);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public boolean shouldSideBeRendered(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given metadata into a BlockState for this Block
|
||||
*/
|
||||
public IBlockState getStateFromMeta(int meta)
|
||||
{
|
||||
return this.getDefaultState().withProperty(FACING, EnumFacing.getHorizontal(meta & 3)).withProperty(DAMAGE, Integer.valueOf((meta & 15) >> 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the BlockState into the correct metadata value
|
||||
*/
|
||||
public int getMetaFromState(IBlockState state)
|
||||
{
|
||||
int i = 0;
|
||||
i = i | ((EnumFacing)state.getValue(FACING)).getHorizontalIndex();
|
||||
i = i | ((Integer)state.getValue(DAMAGE)).intValue() << 2;
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blockstate with the given rotation from the passed blockstate. If inapplicable, returns the passed
|
||||
* blockstate.
|
||||
*/
|
||||
public IBlockState withRotation(IBlockState state, Rotation rot)
|
||||
{
|
||||
return state.getBlock() != this ? state : state.withProperty(FACING, rot.rotate((EnumFacing)state.getValue(FACING)));
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {FACING, DAMAGE});
|
||||
}
|
||||
|
||||
public static class Anvil implements IInteractionObject
|
||||
{
|
||||
private final World world;
|
||||
private final BlockPos position;
|
||||
|
||||
public Anvil(World worldIn, BlockPos pos)
|
||||
{
|
||||
this.world = worldIn;
|
||||
this.position = pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of this object. For players this returns their username
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return "anvil";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this thing is named
|
||||
*/
|
||||
public boolean hasCustomName()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the formatted ChatComponent that will be used for the sender's username in chat
|
||||
*/
|
||||
public ITextComponent getDisplayName()
|
||||
{
|
||||
return new TextComponentTranslation(Blocks.ANVIL.getUnlocalizedName() + ".name", new Object[0]);
|
||||
}
|
||||
|
||||
public Container createContainer(InventoryPlayer playerInventory, EntityPlayer playerIn)
|
||||
{
|
||||
return new ContainerRepair(playerInventory, this.world, this.position, playerIn);
|
||||
}
|
||||
|
||||
public String getGuiID()
|
||||
{
|
||||
return "minecraft:anvil";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.Random;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.properties.PropertyDirection;
|
||||
import net.minecraft.block.properties.PropertyInteger;
|
||||
import net.minecraft.block.state.BlockFaceShape;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityBanner;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.Mirror;
|
||||
import net.minecraft.util.Rotation;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.translation.I18n;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class BlockBanner extends BlockContainer
|
||||
{
|
||||
public static final PropertyDirection FACING = BlockHorizontal.FACING;
|
||||
public static final PropertyInteger ROTATION = PropertyInteger.create("rotation", 0, 15);
|
||||
protected static final AxisAlignedBB STANDING_AABB = new AxisAlignedBB(0.25D, 0.0D, 0.25D, 0.75D, 1.0D, 0.75D);
|
||||
|
||||
protected BlockBanner()
|
||||
{
|
||||
super(Material.WOOD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the localized name of this block. Used for the statistics page.
|
||||
*/
|
||||
public String getLocalizedName()
|
||||
{
|
||||
return I18n.translateToLocal("item.banner.white.name");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public AxisAlignedBB getCollisionBoundingBox(IBlockState blockState, IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
return NULL_AABB;
|
||||
}
|
||||
|
||||
public boolean isFullCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if an entity can path through this block
|
||||
*/
|
||||
public boolean isPassable(IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine ambient occlusion and culling when rebuilding chunks for render
|
||||
*/
|
||||
public boolean isOpaqueCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if an entity can be spawned inside the block (used to get the player's bed spawn location)
|
||||
*/
|
||||
public boolean canSpawnInBlock()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new instance of a block's tile entity class. Called on placing the block.
|
||||
*/
|
||||
public TileEntity createNewTileEntity(World worldIn, int meta)
|
||||
{
|
||||
return new TileEntityBanner();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Item that this Block should drop when harvested.
|
||||
*/
|
||||
public Item getItemDropped(IBlockState state, Random rand, int fortune)
|
||||
{
|
||||
return Items.BANNER;
|
||||
}
|
||||
|
||||
private ItemStack getTileDataItemStack(World worldIn, BlockPos pos)
|
||||
{
|
||||
TileEntity tileentity = worldIn.getTileEntity(pos);
|
||||
return tileentity instanceof TileEntityBanner ? ((TileEntityBanner)tileentity).getItem() : ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
ItemStack itemstack = this.getTileDataItemStack(worldIn, pos);
|
||||
return itemstack.isEmpty() ? new ItemStack(Items.BANNER) : itemstack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns this Block's drops into the World as EntityItems.
|
||||
*/
|
||||
public void dropBlockAsItemWithChance(World worldIn, BlockPos pos, IBlockState state, float chance, int fortune)
|
||||
{
|
||||
{
|
||||
super.dropBlockAsItemWithChance(worldIn, pos, state, chance, fortune);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this block can be placed exactly at the given position.
|
||||
*/
|
||||
public boolean canPlaceBlockAt(World worldIn, BlockPos pos)
|
||||
{
|
||||
return !this.hasInvalidNeighbor(worldIn, pos) && super.canPlaceBlockAt(worldIn, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns the block's drops in the world. By the time this is called the Block has possibly been set to air via
|
||||
* Block.removedByPlayer
|
||||
*/
|
||||
public void harvestBlock(World worldIn, EntityPlayer player, BlockPos pos, IBlockState state, @Nullable TileEntity te, ItemStack stack)
|
||||
{
|
||||
if (te instanceof TileEntityBanner)
|
||||
{
|
||||
TileEntityBanner tileentitybanner = (TileEntityBanner)te;
|
||||
ItemStack itemstack = tileentitybanner.getItem();
|
||||
spawnAsEntity(worldIn, pos, itemstack);
|
||||
}
|
||||
else
|
||||
{
|
||||
super.harvestBlock(worldIn, player, pos, state, (TileEntity)null, stack);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the geometry of the queried face at the given position and state. This is used to decide whether things like
|
||||
* buttons are allowed to be placed on the face, or how glass panes connect to the face, among other things.
|
||||
* <p>
|
||||
* Common values are {@code SOLID}, which is the default, and {@code UNDEFINED}, which represents something that
|
||||
* does not fit the other descriptions and will generally cause other things not to connect to the face.
|
||||
*
|
||||
* @return an approximation of the form of the given face
|
||||
*/
|
||||
public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face)
|
||||
{
|
||||
return BlockFaceShape.UNDEFINED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getDrops(net.minecraft.util.NonNullList<ItemStack> drops, IBlockAccess world, BlockPos pos, IBlockState state, int fortune)
|
||||
{
|
||||
TileEntity te = world.getTileEntity(pos);
|
||||
|
||||
if (te instanceof TileEntityBanner)
|
||||
{
|
||||
TileEntityBanner tileentitybanner = (TileEntityBanner)te;
|
||||
ItemStack itemstack = tileentitybanner.getItem();
|
||||
drops.add(itemstack);
|
||||
}
|
||||
else
|
||||
{
|
||||
drops.add(new ItemStack(Items.BANNER, 1, 0));
|
||||
}
|
||||
}
|
||||
|
||||
public static class BlockBannerHanging extends BlockBanner
|
||||
{
|
||||
protected static final AxisAlignedBB NORTH_AABB = new AxisAlignedBB(0.0D, 0.0D, 0.875D, 1.0D, 0.78125D, 1.0D);
|
||||
protected static final AxisAlignedBB SOUTH_AABB = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.78125D, 0.125D);
|
||||
protected static final AxisAlignedBB WEST_AABB = new AxisAlignedBB(0.875D, 0.0D, 0.0D, 1.0D, 0.78125D, 1.0D);
|
||||
protected static final AxisAlignedBB EAST_AABB = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 0.125D, 0.78125D, 1.0D);
|
||||
|
||||
public BlockBannerHanging()
|
||||
{
|
||||
this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blockstate with the given rotation from the passed blockstate. If inapplicable, returns the
|
||||
* passed blockstate.
|
||||
*/
|
||||
public IBlockState withRotation(IBlockState state, Rotation rot)
|
||||
{
|
||||
return state.withProperty(FACING, rot.rotate((EnumFacing)state.getValue(FACING)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blockstate with the given mirror of the passed blockstate. If inapplicable, returns the
|
||||
* passed blockstate.
|
||||
*/
|
||||
public IBlockState withMirror(IBlockState state, Mirror mirrorIn)
|
||||
{
|
||||
return state.withRotation(mirrorIn.toRotation((EnumFacing)state.getValue(FACING)));
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
|
||||
{
|
||||
switch ((EnumFacing)state.getValue(FACING))
|
||||
{
|
||||
case NORTH:
|
||||
default:
|
||||
return NORTH_AABB;
|
||||
case SOUTH:
|
||||
return SOUTH_AABB;
|
||||
case WEST:
|
||||
return WEST_AABB;
|
||||
case EAST:
|
||||
return EAST_AABB;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a neighboring block was changed and marks that this state should perform any checks during a
|
||||
* neighbor change. Cases may include when redstone power is updated, cactus blocks popping off due to a
|
||||
* neighboring solid block, etc.
|
||||
*/
|
||||
public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos)
|
||||
{
|
||||
EnumFacing enumfacing = (EnumFacing)state.getValue(FACING);
|
||||
|
||||
if (!worldIn.getBlockState(pos.offset(enumfacing.getOpposite())).getMaterial().isSolid())
|
||||
{
|
||||
this.dropBlockAsItem(worldIn, pos, state, 0);
|
||||
worldIn.setBlockToAir(pos);
|
||||
}
|
||||
|
||||
super.neighborChanged(state, worldIn, pos, blockIn, fromPos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given metadata into a BlockState for this Block
|
||||
*/
|
||||
public IBlockState getStateFromMeta(int meta)
|
||||
{
|
||||
EnumFacing enumfacing = EnumFacing.getFront(meta);
|
||||
|
||||
if (enumfacing.getAxis() == EnumFacing.Axis.Y)
|
||||
{
|
||||
enumfacing = EnumFacing.NORTH;
|
||||
}
|
||||
|
||||
return this.getDefaultState().withProperty(FACING, enumfacing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the BlockState into the correct metadata value
|
||||
*/
|
||||
public int getMetaFromState(IBlockState state)
|
||||
{
|
||||
return ((EnumFacing)state.getValue(FACING)).getIndex();
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {FACING});
|
||||
}
|
||||
}
|
||||
|
||||
public static class BlockBannerStanding extends BlockBanner
|
||||
{
|
||||
public BlockBannerStanding()
|
||||
{
|
||||
this.setDefaultState(this.blockState.getBaseState().withProperty(ROTATION, Integer.valueOf(0)));
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
|
||||
{
|
||||
return STANDING_AABB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blockstate with the given rotation from the passed blockstate. If inapplicable, returns the
|
||||
* passed blockstate.
|
||||
*/
|
||||
public IBlockState withRotation(IBlockState state, Rotation rot)
|
||||
{
|
||||
return state.withProperty(ROTATION, Integer.valueOf(rot.rotate(((Integer)state.getValue(ROTATION)).intValue(), 16)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blockstate with the given mirror of the passed blockstate. If inapplicable, returns the
|
||||
* passed blockstate.
|
||||
*/
|
||||
public IBlockState withMirror(IBlockState state, Mirror mirrorIn)
|
||||
{
|
||||
return state.withProperty(ROTATION, Integer.valueOf(mirrorIn.mirrorRotation(((Integer)state.getValue(ROTATION)).intValue(), 16)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a neighboring block was changed and marks that this state should perform any checks during a
|
||||
* neighbor change. Cases may include when redstone power is updated, cactus blocks popping off due to a
|
||||
* neighboring solid block, etc.
|
||||
*/
|
||||
public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos)
|
||||
{
|
||||
if (!worldIn.getBlockState(pos.down()).getMaterial().isSolid())
|
||||
{
|
||||
this.dropBlockAsItem(worldIn, pos, state, 0);
|
||||
worldIn.setBlockToAir(pos);
|
||||
}
|
||||
|
||||
super.neighborChanged(state, worldIn, pos, blockIn, fromPos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given metadata into a BlockState for this Block
|
||||
*/
|
||||
public IBlockState getStateFromMeta(int meta)
|
||||
{
|
||||
return this.getDefaultState().withProperty(ROTATION, Integer.valueOf(meta));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the BlockState into the correct metadata value
|
||||
*/
|
||||
public int getMetaFromState(IBlockState state)
|
||||
{
|
||||
return ((Integer)state.getValue(ROTATION)).intValue();
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {ROTATION});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.EnumBlockRenderType;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class BlockBarrier extends Block
|
||||
{
|
||||
protected BlockBarrier()
|
||||
{
|
||||
super(Material.BARRIER);
|
||||
this.setBlockUnbreakable();
|
||||
this.setResistance(6000001.0F);
|
||||
this.disableStats();
|
||||
this.translucent = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of render function called. MODEL for mixed tesr and static model, MODELBLOCK_ANIMATED for TESR-only,
|
||||
* LIQUID for vanilla liquids, INVISIBLE to skip all rendering
|
||||
*/
|
||||
public EnumBlockRenderType getRenderType(IBlockState state)
|
||||
{
|
||||
return EnumBlockRenderType.INVISIBLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine ambient occlusion and culling when rebuilding chunks for render
|
||||
*/
|
||||
public boolean isOpaqueCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public float getAmbientOcclusionLightValue(IBlockState state)
|
||||
{
|
||||
return 1.0F;
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns this Block's drops into the World as EntityItems.
|
||||
*/
|
||||
public void dropBlockAsItemWithChance(World worldIn, BlockPos pos, IBlockState state, float chance, int fortune)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.Random;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.material.EnumPushReaction;
|
||||
import net.minecraft.block.material.MapColor;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.BlockFaceShape;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public abstract class BlockBasePressurePlate extends Block
|
||||
{
|
||||
/** The bounding box for the pressure plate pressed state */
|
||||
protected static final AxisAlignedBB PRESSED_AABB = new AxisAlignedBB(0.0625D, 0.0D, 0.0625D, 0.9375D, 0.03125D, 0.9375D);
|
||||
protected static final AxisAlignedBB UNPRESSED_AABB = new AxisAlignedBB(0.0625D, 0.0D, 0.0625D, 0.9375D, 0.0625D, 0.9375D);
|
||||
/** This bounding box is used to check for entities in a certain area and then determine the pressed state. */
|
||||
protected static final AxisAlignedBB PRESSURE_AABB = new AxisAlignedBB(0.125D, 0.0D, 0.125D, 0.875D, 0.25D, 0.875D);
|
||||
|
||||
protected BlockBasePressurePlate(Material materialIn)
|
||||
{
|
||||
this(materialIn, materialIn.getMaterialMapColor());
|
||||
}
|
||||
|
||||
protected BlockBasePressurePlate(Material materialIn, MapColor mapColorIn)
|
||||
{
|
||||
super(materialIn, mapColorIn);
|
||||
this.setCreativeTab(CreativeTabs.REDSTONE);
|
||||
this.setTickRandomly(true);
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
|
||||
{
|
||||
boolean flag = this.getRedstoneStrength(state) > 0;
|
||||
return flag ? PRESSED_AABB : UNPRESSED_AABB;
|
||||
}
|
||||
|
||||
/**
|
||||
* How many world ticks before ticking
|
||||
*/
|
||||
public int tickRate(World worldIn)
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public AxisAlignedBB getCollisionBoundingBox(IBlockState blockState, IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
return NULL_AABB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine ambient occlusion and culling when rebuilding chunks for render
|
||||
*/
|
||||
public boolean isOpaqueCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isFullCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if an entity can path through this block
|
||||
*/
|
||||
public boolean isPassable(IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if an entity can be spawned inside the block (used to get the player's bed spawn location)
|
||||
*/
|
||||
public boolean canSpawnInBlock()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this block can be placed exactly at the given position.
|
||||
*/
|
||||
public boolean canPlaceBlockAt(World worldIn, BlockPos pos)
|
||||
{
|
||||
return this.canBePlacedOn(worldIn, pos.down());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a neighboring block was changed and marks that this state should perform any checks during a neighbor
|
||||
* change. Cases may include when redstone power is updated, cactus blocks popping off due to a neighboring solid
|
||||
* block, etc.
|
||||
*/
|
||||
public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos)
|
||||
{
|
||||
if (!this.canBePlacedOn(worldIn, pos.down()))
|
||||
{
|
||||
this.dropBlockAsItem(worldIn, pos, state, 0);
|
||||
worldIn.setBlockToAir(pos);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canBePlacedOn(World worldIn, BlockPos pos)
|
||||
{
|
||||
return worldIn.getBlockState(pos).isTopSolid() || worldIn.getBlockState(pos).getBlock() instanceof BlockFence;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called randomly when setTickRandomly is set to true (used by e.g. crops to grow, etc.)
|
||||
*/
|
||||
public void randomTick(World worldIn, BlockPos pos, IBlockState state, Random random)
|
||||
{
|
||||
}
|
||||
|
||||
public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand)
|
||||
{
|
||||
if (!worldIn.isRemote)
|
||||
{
|
||||
int i = this.getRedstoneStrength(state);
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
this.updateState(worldIn, pos, state, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called When an Entity Collided with the Block
|
||||
*/
|
||||
public void onEntityCollidedWithBlock(World worldIn, BlockPos pos, IBlockState state, Entity entityIn)
|
||||
{
|
||||
if (!worldIn.isRemote)
|
||||
{
|
||||
int i = this.getRedstoneStrength(state);
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
this.updateState(worldIn, pos, state, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the pressure plate when stepped on
|
||||
*/
|
||||
protected void updateState(World worldIn, BlockPos pos, IBlockState state, int oldRedstoneStrength)
|
||||
{
|
||||
int i = this.computeRedstoneStrength(worldIn, pos);
|
||||
boolean flag = oldRedstoneStrength > 0;
|
||||
boolean flag1 = i > 0;
|
||||
|
||||
if (oldRedstoneStrength != i)
|
||||
{
|
||||
state = this.setRedstoneStrength(state, i);
|
||||
worldIn.setBlockState(pos, state, 2);
|
||||
this.updateNeighbors(worldIn, pos);
|
||||
worldIn.markBlockRangeForRenderUpdate(pos, pos);
|
||||
}
|
||||
|
||||
if (!flag1 && flag)
|
||||
{
|
||||
this.playClickOffSound(worldIn, pos);
|
||||
}
|
||||
else if (flag1 && !flag)
|
||||
{
|
||||
this.playClickOnSound(worldIn, pos);
|
||||
}
|
||||
|
||||
if (flag1)
|
||||
{
|
||||
worldIn.scheduleUpdate(new BlockPos(pos), this, this.tickRate(worldIn));
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void playClickOnSound(World worldIn, BlockPos color);
|
||||
|
||||
protected abstract void playClickOffSound(World worldIn, BlockPos pos);
|
||||
|
||||
/**
|
||||
* Called serverside after this block is replaced with another in Chunk, but before the Tile Entity is updated
|
||||
*/
|
||||
public void breakBlock(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
if (this.getRedstoneStrength(state) > 0)
|
||||
{
|
||||
this.updateNeighbors(worldIn, pos);
|
||||
}
|
||||
|
||||
super.breakBlock(worldIn, pos, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify block and block below of changes
|
||||
*/
|
||||
protected void updateNeighbors(World worldIn, BlockPos pos)
|
||||
{
|
||||
worldIn.notifyNeighborsOfStateChange(pos, this, false);
|
||||
worldIn.notifyNeighborsOfStateChange(pos.down(), this, false);
|
||||
}
|
||||
|
||||
public int getWeakPower(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side)
|
||||
{
|
||||
return this.getRedstoneStrength(blockState);
|
||||
}
|
||||
|
||||
public int getStrongPower(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side)
|
||||
{
|
||||
return side == EnumFacing.UP ? this.getRedstoneStrength(blockState) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can this block provide power. Only wire currently seems to have this change based on its state.
|
||||
*/
|
||||
public boolean canProvidePower(IBlockState state)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public EnumPushReaction getMobilityFlag(IBlockState state)
|
||||
{
|
||||
return EnumPushReaction.DESTROY;
|
||||
}
|
||||
|
||||
protected abstract int computeRedstoneStrength(World worldIn, BlockPos pos);
|
||||
|
||||
protected abstract int getRedstoneStrength(IBlockState state);
|
||||
|
||||
protected abstract IBlockState setRedstoneStrength(IBlockState state, int strength);
|
||||
|
||||
/**
|
||||
* Get the geometry of the queried face at the given position and state. This is used to decide whether things like
|
||||
* buttons are allowed to be placed on the face, or how glass panes connect to the face, among other things.
|
||||
* <p>
|
||||
* Common values are {@code SOLID}, which is the default, and {@code UNDEFINED}, which represents something that
|
||||
* does not fit the other descriptions and will generally cause other things not to connect to the face.
|
||||
*
|
||||
* @return an approximation of the form of the given face
|
||||
*/
|
||||
public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face)
|
||||
{
|
||||
return BlockFaceShape.UNDEFINED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import net.minecraft.block.material.MapColor;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.stats.StatList;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityBeacon;
|
||||
import net.minecraft.util.BlockRenderLayer;
|
||||
import net.minecraft.util.EnumBlockRenderType;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.HttpUtil;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class BlockBeacon extends BlockContainer
|
||||
{
|
||||
public BlockBeacon()
|
||||
{
|
||||
super(Material.GLASS, MapColor.DIAMOND);
|
||||
this.setHardness(3.0F);
|
||||
this.setCreativeTab(CreativeTabs.MISC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new instance of a block's tile entity class. Called on placing the block.
|
||||
*/
|
||||
public TileEntity createNewTileEntity(World worldIn, int meta)
|
||||
{
|
||||
return new TileEntityBeacon();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the block is right clicked by a player.
|
||||
*/
|
||||
public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
|
||||
{
|
||||
if (worldIn.isRemote)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
TileEntity tileentity = worldIn.getTileEntity(pos);
|
||||
|
||||
if (tileentity instanceof TileEntityBeacon)
|
||||
{
|
||||
playerIn.displayGUIChest((TileEntityBeacon)tileentity);
|
||||
playerIn.addStat(StatList.BEACON_INTERACTION);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine ambient occlusion and culling when rebuilding chunks for render
|
||||
*/
|
||||
public boolean isOpaqueCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isFullCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of render function called. MODEL for mixed tesr and static model, MODELBLOCK_ANIMATED for TESR-only,
|
||||
* LIQUID for vanilla liquids, INVISIBLE to skip all rendering
|
||||
*/
|
||||
public EnumBlockRenderType getRenderType(IBlockState state)
|
||||
{
|
||||
return EnumBlockRenderType.MODEL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by ItemBlocks after a block is set in the world, to allow post-place logic
|
||||
*/
|
||||
public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
|
||||
{
|
||||
super.onBlockPlacedBy(worldIn, pos, state, placer, stack);
|
||||
|
||||
if (stack.hasDisplayName())
|
||||
{
|
||||
TileEntity tileentity = worldIn.getTileEntity(pos);
|
||||
|
||||
if (tileentity instanceof TileEntityBeacon)
|
||||
{
|
||||
((TileEntityBeacon)tileentity).setName(stack.getDisplayName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a neighboring block was changed and marks that this state should perform any checks during a neighbor
|
||||
* change. Cases may include when redstone power is updated, cactus blocks popping off due to a neighboring solid
|
||||
* block, etc.
|
||||
*/
|
||||
public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos)
|
||||
{
|
||||
TileEntity tileentity = worldIn.getTileEntity(pos);
|
||||
|
||||
if (tileentity instanceof TileEntityBeacon)
|
||||
{
|
||||
((TileEntityBeacon)tileentity).updateBeacon();
|
||||
worldIn.addBlockEvent(pos, this, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public BlockRenderLayer getBlockLayer()
|
||||
{
|
||||
return BlockRenderLayer.CUTOUT;
|
||||
}
|
||||
|
||||
public static void updateColorAsync(final World worldIn, final BlockPos glassPos)
|
||||
{
|
||||
HttpUtil.DOWNLOADER_EXECUTOR.submit(new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
Chunk chunk = worldIn.getChunkFromBlockCoords(glassPos);
|
||||
|
||||
for (int i = glassPos.getY() - 1; i >= 0; --i)
|
||||
{
|
||||
final BlockPos blockpos = new BlockPos(glassPos.getX(), i, glassPos.getZ());
|
||||
|
||||
if (!chunk.canSeeSky(blockpos))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
IBlockState iblockstate = worldIn.getBlockState(blockpos);
|
||||
|
||||
if (iblockstate.getBlock() == Blocks.BEACON)
|
||||
{
|
||||
((WorldServer)worldIn).addScheduledTask(new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
TileEntity tileentity = worldIn.getTileEntity(blockpos);
|
||||
|
||||
if (tileentity instanceof TileEntityBeacon)
|
||||
{
|
||||
((TileEntityBeacon)tileentity).updateBeacon();
|
||||
worldIn.addBlockEvent(blockpos, Blocks.BEACON, 1, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
513
build/tmp/recompileMc/sources/net/minecraft/block/BlockBed.java
Normal file
513
build/tmp/recompileMc/sources/net/minecraft/block/BlockBed.java
Normal file
@@ -0,0 +1,513 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.Random;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.material.EnumPushReaction;
|
||||
import net.minecraft.block.material.MapColor;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.properties.PropertyBool;
|
||||
import net.minecraft.block.properties.PropertyEnum;
|
||||
import net.minecraft.block.state.BlockFaceShape;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Biomes;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.EnumDyeColor;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityBed;
|
||||
import net.minecraft.util.BlockRenderLayer;
|
||||
import net.minecraft.util.EnumBlockRenderType;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.IStringSerializable;
|
||||
import net.minecraft.util.Mirror;
|
||||
import net.minecraft.util.Rotation;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.TextComponentTranslation;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class BlockBed extends BlockHorizontal implements ITileEntityProvider
|
||||
{
|
||||
public static final PropertyEnum<BlockBed.EnumPartType> PART = PropertyEnum.<BlockBed.EnumPartType>create("part", BlockBed.EnumPartType.class);
|
||||
public static final PropertyBool OCCUPIED = PropertyBool.create("occupied");
|
||||
protected static final AxisAlignedBB BED_AABB = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.5625D, 1.0D);
|
||||
|
||||
public BlockBed()
|
||||
{
|
||||
super(Material.CLOTH);
|
||||
this.setDefaultState(this.blockState.getBaseState().withProperty(PART, BlockBed.EnumPartType.FOOT).withProperty(OCCUPIED, Boolean.valueOf(false)));
|
||||
this.hasTileEntity = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MapColor for this Block and the given BlockState
|
||||
*/
|
||||
public MapColor getMapColor(IBlockState state, IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
if (state.getValue(PART) == BlockBed.EnumPartType.FOOT)
|
||||
{
|
||||
TileEntity tileentity = worldIn.getTileEntity(pos);
|
||||
|
||||
if (tileentity instanceof TileEntityBed)
|
||||
{
|
||||
EnumDyeColor enumdyecolor = ((TileEntityBed)tileentity).getColor();
|
||||
return MapColor.getBlockColor(enumdyecolor);
|
||||
}
|
||||
}
|
||||
|
||||
return MapColor.CLOTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the block is right clicked by a player.
|
||||
*/
|
||||
public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
|
||||
{
|
||||
if (worldIn.isRemote)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (state.getValue(PART) != BlockBed.EnumPartType.HEAD)
|
||||
{
|
||||
pos = pos.offset((EnumFacing)state.getValue(FACING));
|
||||
state = worldIn.getBlockState(pos);
|
||||
|
||||
if (state.getBlock() != this)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
net.minecraft.world.WorldProvider.WorldSleepResult sleepResult = worldIn.provider.canSleepAt(playerIn, pos);
|
||||
if (sleepResult != net.minecraft.world.WorldProvider.WorldSleepResult.BED_EXPLODES)
|
||||
{
|
||||
if (sleepResult == net.minecraft.world.WorldProvider.WorldSleepResult.DENY) return true;
|
||||
if (((Boolean)state.getValue(OCCUPIED)).booleanValue())
|
||||
{
|
||||
EntityPlayer entityplayer = this.getPlayerInBed(worldIn, pos);
|
||||
|
||||
if (entityplayer != null)
|
||||
{
|
||||
playerIn.sendStatusMessage(new TextComponentTranslation("tile.bed.occupied", new Object[0]), true);
|
||||
return true;
|
||||
}
|
||||
|
||||
state = state.withProperty(OCCUPIED, Boolean.valueOf(false));
|
||||
worldIn.setBlockState(pos, state, 4);
|
||||
}
|
||||
|
||||
EntityPlayer.SleepResult entityplayer$sleepresult = playerIn.trySleep(pos);
|
||||
|
||||
if (entityplayer$sleepresult == EntityPlayer.SleepResult.OK)
|
||||
{
|
||||
state = state.withProperty(OCCUPIED, Boolean.valueOf(true));
|
||||
worldIn.setBlockState(pos, state, 4);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (entityplayer$sleepresult == EntityPlayer.SleepResult.NOT_POSSIBLE_NOW)
|
||||
{
|
||||
playerIn.sendStatusMessage(new TextComponentTranslation("tile.bed.noSleep", new Object[0]), true);
|
||||
}
|
||||
else if (entityplayer$sleepresult == EntityPlayer.SleepResult.NOT_SAFE)
|
||||
{
|
||||
playerIn.sendStatusMessage(new TextComponentTranslation("tile.bed.notSafe", new Object[0]), true);
|
||||
}
|
||||
else if (entityplayer$sleepresult == EntityPlayer.SleepResult.TOO_FAR_AWAY)
|
||||
{
|
||||
playerIn.sendStatusMessage(new TextComponentTranslation("tile.bed.tooFarAway", new Object[0]), true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
worldIn.setBlockToAir(pos);
|
||||
BlockPos blockpos = pos.offset(((EnumFacing)state.getValue(FACING)).getOpposite());
|
||||
|
||||
if (worldIn.getBlockState(blockpos).getBlock() == this)
|
||||
{
|
||||
worldIn.setBlockToAir(blockpos);
|
||||
}
|
||||
|
||||
worldIn.newExplosion((Entity)null, (double)pos.getX() + 0.5D, (double)pos.getY() + 0.5D, (double)pos.getZ() + 0.5D, 5.0F, true, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private EntityPlayer getPlayerInBed(World worldIn, BlockPos pos)
|
||||
{
|
||||
for (EntityPlayer entityplayer : worldIn.playerEntities)
|
||||
{
|
||||
if (entityplayer.isPlayerSleeping() && entityplayer.bedLocation.equals(pos))
|
||||
{
|
||||
return entityplayer;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isFullCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine ambient occlusion and culling when rebuilding chunks for render
|
||||
*/
|
||||
public boolean isOpaqueCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Block's chance to react to a living entity falling on it.
|
||||
*/
|
||||
public void onFallenUpon(World worldIn, BlockPos pos, Entity entityIn, float fallDistance)
|
||||
{
|
||||
super.onFallenUpon(worldIn, pos, entityIn, fallDistance * 0.5F);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an Entity lands on this Block. This method *must* update motionY because the entity will not do that
|
||||
* on its own
|
||||
*/
|
||||
public void onLanded(World worldIn, Entity entityIn)
|
||||
{
|
||||
if (entityIn.isSneaking())
|
||||
{
|
||||
super.onLanded(worldIn, entityIn);
|
||||
}
|
||||
else if (entityIn.motionY < 0.0D)
|
||||
{
|
||||
entityIn.motionY = -entityIn.motionY * 0.6600000262260437D;
|
||||
|
||||
if (!(entityIn instanceof EntityLivingBase))
|
||||
{
|
||||
entityIn.motionY *= 0.8D;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a neighboring block was changed and marks that this state should perform any checks during a neighbor
|
||||
* change. Cases may include when redstone power is updated, cactus blocks popping off due to a neighboring solid
|
||||
* block, etc.
|
||||
*/
|
||||
public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos)
|
||||
{
|
||||
EnumFacing enumfacing = (EnumFacing)state.getValue(FACING);
|
||||
|
||||
if (state.getValue(PART) == BlockBed.EnumPartType.FOOT)
|
||||
{
|
||||
if (worldIn.getBlockState(pos.offset(enumfacing)).getBlock() != this)
|
||||
{
|
||||
worldIn.setBlockToAir(pos);
|
||||
}
|
||||
}
|
||||
else if (worldIn.getBlockState(pos.offset(enumfacing.getOpposite())).getBlock() != this)
|
||||
{
|
||||
if (!worldIn.isRemote)
|
||||
{
|
||||
this.dropBlockAsItem(worldIn, pos, state, 0);
|
||||
}
|
||||
|
||||
worldIn.setBlockToAir(pos);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Item that this Block should drop when harvested.
|
||||
*/
|
||||
public Item getItemDropped(IBlockState state, Random rand, int fortune)
|
||||
{
|
||||
return state.getValue(PART) == BlockBed.EnumPartType.FOOT ? Items.AIR : Items.BED;
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
|
||||
{
|
||||
return BED_AABB;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public boolean hasCustomBreakingProgress(IBlockState state)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a safe BlockPos to disembark the bed
|
||||
*/
|
||||
@Nullable
|
||||
public static BlockPos getSafeExitLocation(World worldIn, BlockPos pos, int tries)
|
||||
{
|
||||
EnumFacing enumfacing = (EnumFacing)worldIn.getBlockState(pos).getValue(FACING);
|
||||
int i = pos.getX();
|
||||
int j = pos.getY();
|
||||
int k = pos.getZ();
|
||||
|
||||
for (int l = 0; l <= 1; ++l)
|
||||
{
|
||||
int i1 = i - enumfacing.getFrontOffsetX() * l - 1;
|
||||
int j1 = k - enumfacing.getFrontOffsetZ() * l - 1;
|
||||
int k1 = i1 + 2;
|
||||
int l1 = j1 + 2;
|
||||
|
||||
for (int i2 = i1; i2 <= k1; ++i2)
|
||||
{
|
||||
for (int j2 = j1; j2 <= l1; ++j2)
|
||||
{
|
||||
BlockPos blockpos = new BlockPos(i2, j, j2);
|
||||
|
||||
if (hasRoomForPlayer(worldIn, blockpos))
|
||||
{
|
||||
if (tries <= 0)
|
||||
{
|
||||
return blockpos;
|
||||
}
|
||||
|
||||
--tries;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static boolean hasRoomForPlayer(World worldIn, BlockPos pos)
|
||||
{
|
||||
return worldIn.getBlockState(pos.down()).isTopSolid() && !worldIn.getBlockState(pos).getMaterial().isSolid() && !worldIn.getBlockState(pos.up()).getMaterial().isSolid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns this Block's drops into the World as EntityItems.
|
||||
*/
|
||||
public void dropBlockAsItemWithChance(World worldIn, BlockPos pos, IBlockState state, float chance, int fortune)
|
||||
{
|
||||
if (state.getValue(PART) == BlockBed.EnumPartType.HEAD)
|
||||
{
|
||||
TileEntity tileentity = worldIn.getTileEntity(pos);
|
||||
EnumDyeColor enumdyecolor = tileentity instanceof TileEntityBed ? ((TileEntityBed)tileentity).getColor() : EnumDyeColor.RED;
|
||||
spawnAsEntity(worldIn, pos, new ItemStack(Items.BED, 1, enumdyecolor.getMetadata()));
|
||||
}
|
||||
}
|
||||
|
||||
public EnumPushReaction getMobilityFlag(IBlockState state)
|
||||
{
|
||||
return EnumPushReaction.DESTROY;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public BlockRenderLayer getBlockLayer()
|
||||
{
|
||||
return BlockRenderLayer.CUTOUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of render function called. MODEL for mixed tesr and static model, MODELBLOCK_ANIMATED for TESR-only,
|
||||
* LIQUID for vanilla liquids, INVISIBLE to skip all rendering
|
||||
*/
|
||||
public EnumBlockRenderType getRenderType(IBlockState state)
|
||||
{
|
||||
return EnumBlockRenderType.ENTITYBLOCK_ANIMATED;
|
||||
}
|
||||
|
||||
public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
BlockPos blockpos = pos;
|
||||
|
||||
if (state.getValue(PART) == BlockBed.EnumPartType.FOOT)
|
||||
{
|
||||
blockpos = pos.offset((EnumFacing)state.getValue(FACING));
|
||||
}
|
||||
|
||||
TileEntity tileentity = worldIn.getTileEntity(blockpos);
|
||||
EnumDyeColor enumdyecolor = tileentity instanceof TileEntityBed ? ((TileEntityBed)tileentity).getColor() : EnumDyeColor.RED;
|
||||
return new ItemStack(Items.BED, 1, enumdyecolor.getMetadata());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before the Block is set to air in the world. Called regardless of if the player's tool can actually
|
||||
* collect this block
|
||||
*/
|
||||
public void onBlockHarvested(World worldIn, BlockPos pos, IBlockState state, EntityPlayer player)
|
||||
{
|
||||
if (player.capabilities.isCreativeMode && state.getValue(PART) == BlockBed.EnumPartType.FOOT)
|
||||
{
|
||||
BlockPos blockpos = pos.offset((EnumFacing)state.getValue(FACING));
|
||||
|
||||
if (worldIn.getBlockState(blockpos).getBlock() == this)
|
||||
{
|
||||
worldIn.setBlockToAir(blockpos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns the block's drops in the world. By the time this is called the Block has possibly been set to air via
|
||||
* Block.removedByPlayer
|
||||
*/
|
||||
public void harvestBlock(World worldIn, EntityPlayer player, BlockPos pos, IBlockState state, TileEntity te, ItemStack stack)
|
||||
{
|
||||
if (state.getValue(PART) == BlockBed.EnumPartType.HEAD && te instanceof TileEntityBed)
|
||||
{
|
||||
TileEntityBed tileentitybed = (TileEntityBed)te;
|
||||
ItemStack itemstack = tileentitybed.getItemStack();
|
||||
spawnAsEntity(worldIn, pos, itemstack);
|
||||
}
|
||||
else
|
||||
{
|
||||
super.harvestBlock(worldIn, player, pos, state, (TileEntity)null, stack);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called serverside after this block is replaced with another in Chunk, but before the Tile Entity is updated
|
||||
*/
|
||||
public void breakBlock(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
super.breakBlock(worldIn, pos, state);
|
||||
worldIn.removeTileEntity(pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given metadata into a BlockState for this Block
|
||||
*/
|
||||
public IBlockState getStateFromMeta(int meta)
|
||||
{
|
||||
EnumFacing enumfacing = EnumFacing.getHorizontal(meta);
|
||||
return (meta & 8) > 0 ? this.getDefaultState().withProperty(PART, BlockBed.EnumPartType.HEAD).withProperty(FACING, enumfacing).withProperty(OCCUPIED, Boolean.valueOf((meta & 4) > 0)) : this.getDefaultState().withProperty(PART, BlockBed.EnumPartType.FOOT).withProperty(FACING, enumfacing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the actual Block state of this Block at the given position. This applies properties not visible in the
|
||||
* metadata, such as fence connections.
|
||||
*/
|
||||
public IBlockState getActualState(IBlockState state, IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
if (state.getValue(PART) == BlockBed.EnumPartType.FOOT)
|
||||
{
|
||||
IBlockState iblockstate = worldIn.getBlockState(pos.offset((EnumFacing)state.getValue(FACING)));
|
||||
|
||||
if (iblockstate.getBlock() == this)
|
||||
{
|
||||
state = state.withProperty(OCCUPIED, iblockstate.getValue(OCCUPIED));
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blockstate with the given rotation from the passed blockstate. If inapplicable, returns the passed
|
||||
* blockstate.
|
||||
*/
|
||||
public IBlockState withRotation(IBlockState state, Rotation rot)
|
||||
{
|
||||
return state.withProperty(FACING, rot.rotate((EnumFacing)state.getValue(FACING)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blockstate with the given mirror of the passed blockstate. If inapplicable, returns the passed
|
||||
* blockstate.
|
||||
*/
|
||||
public IBlockState withMirror(IBlockState state, Mirror mirrorIn)
|
||||
{
|
||||
return state.withRotation(mirrorIn.toRotation((EnumFacing)state.getValue(FACING)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the BlockState into the correct metadata value
|
||||
*/
|
||||
public int getMetaFromState(IBlockState state)
|
||||
{
|
||||
int i = 0;
|
||||
i = i | ((EnumFacing)state.getValue(FACING)).getHorizontalIndex();
|
||||
|
||||
if (state.getValue(PART) == BlockBed.EnumPartType.HEAD)
|
||||
{
|
||||
i |= 8;
|
||||
|
||||
if (((Boolean)state.getValue(OCCUPIED)).booleanValue())
|
||||
{
|
||||
i |= 4;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the geometry of the queried face at the given position and state. This is used to decide whether things like
|
||||
* buttons are allowed to be placed on the face, or how glass panes connect to the face, among other things.
|
||||
* <p>
|
||||
* Common values are {@code SOLID}, which is the default, and {@code UNDEFINED}, which represents something that
|
||||
* does not fit the other descriptions and will generally cause other things not to connect to the face.
|
||||
*
|
||||
* @return an approximation of the form of the given face
|
||||
*/
|
||||
public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face)
|
||||
{
|
||||
return BlockFaceShape.UNDEFINED;
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {FACING, PART, OCCUPIED});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new instance of a block's tile entity class. Called on placing the block.
|
||||
*/
|
||||
public TileEntity createNewTileEntity(World worldIn, int meta)
|
||||
{
|
||||
return new TileEntityBed();
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public static boolean isHeadPiece(int metadata)
|
||||
{
|
||||
return (metadata & 8) != 0;
|
||||
}
|
||||
|
||||
public static enum EnumPartType implements IStringSerializable
|
||||
{
|
||||
HEAD("head"),
|
||||
FOOT("foot");
|
||||
|
||||
private final String name;
|
||||
|
||||
private EnumPartType(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.Random;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.properties.PropertyInteger;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class BlockBeetroot extends BlockCrops
|
||||
{
|
||||
public static final PropertyInteger BEETROOT_AGE = PropertyInteger.create("age", 0, 3);
|
||||
private static final AxisAlignedBB[] BEETROOT_AABB = new AxisAlignedBB[] {new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.125D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.25D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.375D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.5D, 1.0D)};
|
||||
|
||||
protected PropertyInteger getAgeProperty()
|
||||
{
|
||||
return BEETROOT_AGE;
|
||||
}
|
||||
|
||||
public int getMaxAge()
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
protected Item getSeed()
|
||||
{
|
||||
return Items.BEETROOT_SEEDS;
|
||||
}
|
||||
|
||||
protected Item getCrop()
|
||||
{
|
||||
return Items.BEETROOT;
|
||||
}
|
||||
|
||||
public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand)
|
||||
{
|
||||
if (rand.nextInt(3) == 0)
|
||||
{
|
||||
this.checkAndDropBlock(worldIn, pos, state);
|
||||
}
|
||||
else
|
||||
{
|
||||
super.updateTick(worldIn, pos, state, rand);
|
||||
}
|
||||
}
|
||||
|
||||
protected int getBonemealAgeIncrease(World worldIn)
|
||||
{
|
||||
return super.getBonemealAgeIncrease(worldIn) / 3;
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {BEETROOT_AGE});
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
|
||||
{
|
||||
return BEETROOT_AABB[((Integer)state.getValue(this.getAgeProperty())).intValue()];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import net.minecraft.block.material.MapColor;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
|
||||
public class BlockBone extends BlockRotatedPillar
|
||||
{
|
||||
public BlockBone()
|
||||
{
|
||||
super(Material.ROCK, MapColor.SAND);
|
||||
this.setCreativeTab(CreativeTabs.BUILDING_BLOCKS);
|
||||
this.setHardness(2.0F);
|
||||
this.setSoundType(SoundType.STONE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.Random;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.Item;
|
||||
|
||||
public class BlockBookshelf extends Block
|
||||
{
|
||||
public BlockBookshelf()
|
||||
{
|
||||
super(Material.WOOD);
|
||||
this.setCreativeTab(CreativeTabs.BUILDING_BLOCKS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the quantity of items to drop on block destruction.
|
||||
*/
|
||||
public int quantityDropped(Random random)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Item that this Block should drop when harvested.
|
||||
*/
|
||||
public Item getItemDropped(IBlockState state, Random rand, int fortune)
|
||||
{
|
||||
return Items.BOOK;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import net.minecraft.block.material.MapColor;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class BlockBreakable extends Block
|
||||
{
|
||||
private final boolean ignoreSimilarity;
|
||||
|
||||
protected BlockBreakable(Material materialIn, boolean ignoreSimilarityIn)
|
||||
{
|
||||
this(materialIn, ignoreSimilarityIn, materialIn.getMaterialMapColor());
|
||||
}
|
||||
|
||||
protected BlockBreakable(Material materialIn, boolean ignoreSimilarityIn, MapColor mapColorIn)
|
||||
{
|
||||
super(materialIn, mapColorIn);
|
||||
this.ignoreSimilarity = ignoreSimilarityIn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine ambient occlusion and culling when rebuilding chunks for render
|
||||
*/
|
||||
public boolean isOpaqueCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public boolean shouldSideBeRendered(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side)
|
||||
{
|
||||
IBlockState iblockstate = blockAccess.getBlockState(pos.offset(side));
|
||||
Block block = iblockstate.getBlock();
|
||||
|
||||
if (this == Blocks.GLASS || this == Blocks.STAINED_GLASS)
|
||||
{
|
||||
if (blockState != iblockstate)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (block == this)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return !this.ignoreSimilarity && block == this ? false : super.shouldSideBeRendered(blockState, blockAccess, pos, side);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.properties.PropertyBool;
|
||||
import net.minecraft.block.state.BlockFaceShape;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.inventory.Container;
|
||||
import net.minecraft.inventory.InventoryHelper;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.stats.StatList;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityBrewingStand;
|
||||
import net.minecraft.util.BlockRenderLayer;
|
||||
import net.minecraft.util.EnumBlockRenderType;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.EnumParticleTypes;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.translation.I18n;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class BlockBrewingStand extends BlockContainer
|
||||
{
|
||||
public static final PropertyBool[] HAS_BOTTLE = new PropertyBool[] {PropertyBool.create("has_bottle_0"), PropertyBool.create("has_bottle_1"), PropertyBool.create("has_bottle_2")};
|
||||
protected static final AxisAlignedBB BASE_AABB = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.125D, 1.0D);
|
||||
protected static final AxisAlignedBB STICK_AABB = new AxisAlignedBB(0.4375D, 0.0D, 0.4375D, 0.5625D, 0.875D, 0.5625D);
|
||||
|
||||
public BlockBrewingStand()
|
||||
{
|
||||
super(Material.IRON);
|
||||
this.setDefaultState(this.blockState.getBaseState().withProperty(HAS_BOTTLE[0], Boolean.valueOf(false)).withProperty(HAS_BOTTLE[1], Boolean.valueOf(false)).withProperty(HAS_BOTTLE[2], Boolean.valueOf(false)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the localized name of this block. Used for the statistics page.
|
||||
*/
|
||||
public String getLocalizedName()
|
||||
{
|
||||
return I18n.translateToLocal("item.brewingStand.name");
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine ambient occlusion and culling when rebuilding chunks for render
|
||||
*/
|
||||
public boolean isOpaqueCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of render function called. MODEL for mixed tesr and static model, MODELBLOCK_ANIMATED for TESR-only,
|
||||
* LIQUID for vanilla liquids, INVISIBLE to skip all rendering
|
||||
*/
|
||||
public EnumBlockRenderType getRenderType(IBlockState state)
|
||||
{
|
||||
return EnumBlockRenderType.MODEL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new instance of a block's tile entity class. Called on placing the block.
|
||||
*/
|
||||
public TileEntity createNewTileEntity(World worldIn, int meta)
|
||||
{
|
||||
return new TileEntityBrewingStand();
|
||||
}
|
||||
|
||||
public boolean isFullCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void addCollisionBoxToList(IBlockState state, World worldIn, BlockPos pos, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, @Nullable Entity entityIn, boolean isActualState)
|
||||
{
|
||||
addCollisionBoxToList(pos, entityBox, collidingBoxes, STICK_AABB);
|
||||
addCollisionBoxToList(pos, entityBox, collidingBoxes, BASE_AABB);
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
|
||||
{
|
||||
return BASE_AABB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the block is right clicked by a player.
|
||||
*/
|
||||
public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
|
||||
{
|
||||
if (worldIn.isRemote)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
TileEntity tileentity = worldIn.getTileEntity(pos);
|
||||
|
||||
if (tileentity instanceof TileEntityBrewingStand)
|
||||
{
|
||||
playerIn.displayGUIChest((TileEntityBrewingStand)tileentity);
|
||||
playerIn.addStat(StatList.BREWINGSTAND_INTERACTION);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by ItemBlocks after a block is set in the world, to allow post-place logic
|
||||
*/
|
||||
public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
|
||||
{
|
||||
if (stack.hasDisplayName())
|
||||
{
|
||||
TileEntity tileentity = worldIn.getTileEntity(pos);
|
||||
|
||||
if (tileentity instanceof TileEntityBrewingStand)
|
||||
{
|
||||
((TileEntityBrewingStand)tileentity).setName(stack.getDisplayName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void randomDisplayTick(IBlockState stateIn, World worldIn, BlockPos pos, Random rand)
|
||||
{
|
||||
double d0 = (double)((float)pos.getX() + 0.4F + rand.nextFloat() * 0.2F);
|
||||
double d1 = (double)((float)pos.getY() + 0.7F + rand.nextFloat() * 0.3F);
|
||||
double d2 = (double)((float)pos.getZ() + 0.4F + rand.nextFloat() * 0.2F);
|
||||
worldIn.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, d0, d1, d2, 0.0D, 0.0D, 0.0D);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called serverside after this block is replaced with another in Chunk, but before the Tile Entity is updated
|
||||
*/
|
||||
public void breakBlock(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
TileEntity tileentity = worldIn.getTileEntity(pos);
|
||||
|
||||
if (tileentity instanceof TileEntityBrewingStand)
|
||||
{
|
||||
InventoryHelper.dropInventoryItems(worldIn, pos, (TileEntityBrewingStand)tileentity);
|
||||
}
|
||||
|
||||
super.breakBlock(worldIn, pos, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Item that this Block should drop when harvested.
|
||||
*/
|
||||
public Item getItemDropped(IBlockState state, Random rand, int fortune)
|
||||
{
|
||||
return Items.BREWING_STAND;
|
||||
}
|
||||
|
||||
public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
return new ItemStack(Items.BREWING_STAND);
|
||||
}
|
||||
|
||||
public boolean hasComparatorInputOverride(IBlockState state)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getComparatorInputOverride(IBlockState blockState, World worldIn, BlockPos pos)
|
||||
{
|
||||
return Container.calcRedstone(worldIn.getTileEntity(pos));
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public BlockRenderLayer getBlockLayer()
|
||||
{
|
||||
return BlockRenderLayer.CUTOUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given metadata into a BlockState for this Block
|
||||
*/
|
||||
public IBlockState getStateFromMeta(int meta)
|
||||
{
|
||||
IBlockState iblockstate = this.getDefaultState();
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
iblockstate = iblockstate.withProperty(HAS_BOTTLE[i], Boolean.valueOf((meta & 1 << i) > 0));
|
||||
}
|
||||
|
||||
return iblockstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the BlockState into the correct metadata value
|
||||
*/
|
||||
public int getMetaFromState(IBlockState state)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (int j = 0; j < 3; ++j)
|
||||
{
|
||||
if (((Boolean)state.getValue(HAS_BOTTLE[j])).booleanValue())
|
||||
{
|
||||
i |= 1 << j;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {HAS_BOTTLE[0], HAS_BOTTLE[1], HAS_BOTTLE[2]});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the geometry of the queried face at the given position and state. This is used to decide whether things like
|
||||
* buttons are allowed to be placed on the face, or how glass panes connect to the face, among other things.
|
||||
* <p>
|
||||
* Common values are {@code SOLID}, which is the default, and {@code UNDEFINED}, which represents something that
|
||||
* does not fit the other descriptions and will generally cause other things not to connect to the face.
|
||||
*
|
||||
* @return an approximation of the form of the given face
|
||||
*/
|
||||
public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face)
|
||||
{
|
||||
return BlockFaceShape.UNDEFINED;
|
||||
}
|
||||
}
|
||||
166
build/tmp/recompileMc/sources/net/minecraft/block/BlockBush.java
Normal file
166
build/tmp/recompileMc/sources/net/minecraft/block/BlockBush.java
Normal file
@@ -0,0 +1,166 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.Random;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.material.MapColor;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.BlockFaceShape;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.BlockRenderLayer;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class BlockBush extends Block implements net.minecraftforge.common.IPlantable
|
||||
{
|
||||
protected static final AxisAlignedBB BUSH_AABB = new AxisAlignedBB(0.30000001192092896D, 0.0D, 0.30000001192092896D, 0.699999988079071D, 0.6000000238418579D, 0.699999988079071D);
|
||||
|
||||
protected BlockBush()
|
||||
{
|
||||
this(Material.PLANTS);
|
||||
}
|
||||
|
||||
protected BlockBush(Material materialIn)
|
||||
{
|
||||
this(materialIn, materialIn.getMaterialMapColor());
|
||||
}
|
||||
|
||||
protected BlockBush(Material materialIn, MapColor mapColorIn)
|
||||
{
|
||||
super(materialIn, mapColorIn);
|
||||
this.setTickRandomly(true);
|
||||
this.setCreativeTab(CreativeTabs.DECORATIONS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this block can be placed exactly at the given position.
|
||||
*/
|
||||
public boolean canPlaceBlockAt(World worldIn, BlockPos pos)
|
||||
{
|
||||
IBlockState soil = worldIn.getBlockState(pos.down());
|
||||
return super.canPlaceBlockAt(worldIn, pos) && soil.getBlock().canSustainPlant(soil, worldIn, pos.down(), net.minecraft.util.EnumFacing.UP, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the block can sustain a Bush
|
||||
*/
|
||||
protected boolean canSustainBush(IBlockState state)
|
||||
{
|
||||
return state.getBlock() == Blocks.GRASS || state.getBlock() == Blocks.DIRT || state.getBlock() == Blocks.FARMLAND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a neighboring block was changed and marks that this state should perform any checks during a neighbor
|
||||
* change. Cases may include when redstone power is updated, cactus blocks popping off due to a neighboring solid
|
||||
* block, etc.
|
||||
*/
|
||||
public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos)
|
||||
{
|
||||
super.neighborChanged(state, worldIn, pos, blockIn, fromPos);
|
||||
this.checkAndDropBlock(worldIn, pos, state);
|
||||
}
|
||||
|
||||
public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand)
|
||||
{
|
||||
this.checkAndDropBlock(worldIn, pos, state);
|
||||
}
|
||||
|
||||
protected void checkAndDropBlock(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
if (!this.canBlockStay(worldIn, pos, state))
|
||||
{
|
||||
this.dropBlockAsItem(worldIn, pos, state, 0);
|
||||
worldIn.setBlockState(pos, Blocks.AIR.getDefaultState(), 3);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canBlockStay(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
if (state.getBlock() == this) //Forge: This function is called during world gen and placement, before this block is set, so if we are not 'here' then assume it's the pre-check.
|
||||
{
|
||||
IBlockState soil = worldIn.getBlockState(pos.down());
|
||||
return soil.getBlock().canSustainPlant(soil, worldIn, pos.down(), net.minecraft.util.EnumFacing.UP, this);
|
||||
}
|
||||
return this.canSustainBush(worldIn.getBlockState(pos.down()));
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
|
||||
{
|
||||
return BUSH_AABB;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public AxisAlignedBB getCollisionBoundingBox(IBlockState blockState, IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
return NULL_AABB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine ambient occlusion and culling when rebuilding chunks for render
|
||||
*/
|
||||
public boolean isOpaqueCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isFullCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.minecraftforge.common.EnumPlantType getPlantType(net.minecraft.world.IBlockAccess world, BlockPos pos)
|
||||
{
|
||||
if (this == Blocks.WHEAT) return net.minecraftforge.common.EnumPlantType.Crop;
|
||||
if (this == Blocks.CARROTS) return net.minecraftforge.common.EnumPlantType.Crop;
|
||||
if (this == Blocks.POTATOES) return net.minecraftforge.common.EnumPlantType.Crop;
|
||||
if (this == Blocks.BEETROOTS) return net.minecraftforge.common.EnumPlantType.Crop;
|
||||
if (this == Blocks.MELON_STEM) return net.minecraftforge.common.EnumPlantType.Crop;
|
||||
if (this == Blocks.PUMPKIN_STEM) return net.minecraftforge.common.EnumPlantType.Crop;
|
||||
if (this == Blocks.DEADBUSH) return net.minecraftforge.common.EnumPlantType.Desert;
|
||||
if (this == Blocks.WATERLILY) return net.minecraftforge.common.EnumPlantType.Water;
|
||||
if (this == Blocks.RED_MUSHROOM) return net.minecraftforge.common.EnumPlantType.Cave;
|
||||
if (this == Blocks.BROWN_MUSHROOM) return net.minecraftforge.common.EnumPlantType.Cave;
|
||||
if (this == Blocks.NETHER_WART) return net.minecraftforge.common.EnumPlantType.Nether;
|
||||
if (this == Blocks.SAPLING) return net.minecraftforge.common.EnumPlantType.Plains;
|
||||
if (this == Blocks.TALLGRASS) return net.minecraftforge.common.EnumPlantType.Plains;
|
||||
if (this == Blocks.DOUBLE_PLANT) return net.minecraftforge.common.EnumPlantType.Plains;
|
||||
if (this == Blocks.RED_FLOWER) return net.minecraftforge.common.EnumPlantType.Plains;
|
||||
if (this == Blocks.YELLOW_FLOWER) return net.minecraftforge.common.EnumPlantType.Plains;
|
||||
return net.minecraftforge.common.EnumPlantType.Plains;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlockState getPlant(net.minecraft.world.IBlockAccess world, BlockPos pos)
|
||||
{
|
||||
IBlockState state = world.getBlockState(pos);
|
||||
if (state.getBlock() != this) return getDefaultState();
|
||||
return state;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public BlockRenderLayer getBlockLayer()
|
||||
{
|
||||
return BlockRenderLayer.CUTOUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the geometry of the queried face at the given position and state. This is used to decide whether things like
|
||||
* buttons are allowed to be placed on the face, or how glass panes connect to the face, among other things.
|
||||
* <p>
|
||||
* Common values are {@code SOLID}, which is the default, and {@code UNDEFINED}, which represents something that
|
||||
* does not fit the other descriptions and will generally cause other things not to connect to the face.
|
||||
*
|
||||
* @return an approximation of the form of the given face
|
||||
*/
|
||||
public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face)
|
||||
{
|
||||
return BlockFaceShape.UNDEFINED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,430 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.properties.PropertyBool;
|
||||
import net.minecraft.block.state.BlockFaceShape;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.projectile.EntityArrow;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.Mirror;
|
||||
import net.minecraft.util.Rotation;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public abstract class BlockButton extends BlockDirectional
|
||||
{
|
||||
public static final PropertyBool POWERED = PropertyBool.create("powered");
|
||||
protected static final AxisAlignedBB AABB_DOWN_OFF = new AxisAlignedBB(0.3125D, 0.875D, 0.375D, 0.6875D, 1.0D, 0.625D);
|
||||
protected static final AxisAlignedBB AABB_UP_OFF = new AxisAlignedBB(0.3125D, 0.0D, 0.375D, 0.6875D, 0.125D, 0.625D);
|
||||
protected static final AxisAlignedBB AABB_NORTH_OFF = new AxisAlignedBB(0.3125D, 0.375D, 0.875D, 0.6875D, 0.625D, 1.0D);
|
||||
protected static final AxisAlignedBB AABB_SOUTH_OFF = new AxisAlignedBB(0.3125D, 0.375D, 0.0D, 0.6875D, 0.625D, 0.125D);
|
||||
protected static final AxisAlignedBB AABB_WEST_OFF = new AxisAlignedBB(0.875D, 0.375D, 0.3125D, 1.0D, 0.625D, 0.6875D);
|
||||
protected static final AxisAlignedBB AABB_EAST_OFF = new AxisAlignedBB(0.0D, 0.375D, 0.3125D, 0.125D, 0.625D, 0.6875D);
|
||||
protected static final AxisAlignedBB AABB_DOWN_ON = new AxisAlignedBB(0.3125D, 0.9375D, 0.375D, 0.6875D, 1.0D, 0.625D);
|
||||
protected static final AxisAlignedBB AABB_UP_ON = new AxisAlignedBB(0.3125D, 0.0D, 0.375D, 0.6875D, 0.0625D, 0.625D);
|
||||
protected static final AxisAlignedBB AABB_NORTH_ON = new AxisAlignedBB(0.3125D, 0.375D, 0.9375D, 0.6875D, 0.625D, 1.0D);
|
||||
protected static final AxisAlignedBB AABB_SOUTH_ON = new AxisAlignedBB(0.3125D, 0.375D, 0.0D, 0.6875D, 0.625D, 0.0625D);
|
||||
protected static final AxisAlignedBB AABB_WEST_ON = new AxisAlignedBB(0.9375D, 0.375D, 0.3125D, 1.0D, 0.625D, 0.6875D);
|
||||
protected static final AxisAlignedBB AABB_EAST_ON = new AxisAlignedBB(0.0D, 0.375D, 0.3125D, 0.0625D, 0.625D, 0.6875D);
|
||||
private final boolean wooden;
|
||||
|
||||
protected BlockButton(boolean wooden)
|
||||
{
|
||||
super(Material.CIRCUITS);
|
||||
this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH).withProperty(POWERED, Boolean.valueOf(false)));
|
||||
this.setTickRandomly(true);
|
||||
this.setCreativeTab(CreativeTabs.REDSTONE);
|
||||
this.wooden = wooden;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public AxisAlignedBB getCollisionBoundingBox(IBlockState blockState, IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
return NULL_AABB;
|
||||
}
|
||||
|
||||
/**
|
||||
* How many world ticks before ticking
|
||||
*/
|
||||
public int tickRate(World worldIn)
|
||||
{
|
||||
return this.wooden ? 30 : 20;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine ambient occlusion and culling when rebuilding chunks for render
|
||||
*/
|
||||
public boolean isOpaqueCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isFullCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether this Block can be placed at pos, while aiming at the specified side of an adjacent block
|
||||
*/
|
||||
public boolean canPlaceBlockOnSide(World worldIn, BlockPos pos, EnumFacing side)
|
||||
{
|
||||
return canPlaceBlock(worldIn, pos, side);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this block can be placed exactly at the given position.
|
||||
*/
|
||||
public boolean canPlaceBlockAt(World worldIn, BlockPos pos)
|
||||
{
|
||||
for (EnumFacing enumfacing : EnumFacing.values())
|
||||
{
|
||||
if (canPlaceBlock(worldIn, pos, enumfacing))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether this block can be placed on the block in the given direction.
|
||||
*/
|
||||
protected static boolean canPlaceBlock(World worldIn, BlockPos pos, EnumFacing direction)
|
||||
{
|
||||
BlockPos blockpos = pos.offset(direction.getOpposite());
|
||||
IBlockState iblockstate = worldIn.getBlockState(blockpos);
|
||||
boolean flag = iblockstate.getBlockFaceShape(worldIn, blockpos, direction) == BlockFaceShape.SOLID;
|
||||
Block block = iblockstate.getBlock();
|
||||
|
||||
if (direction == EnumFacing.UP)
|
||||
{
|
||||
return iblockstate.isTopSolid() || !isExceptionBlockForAttaching(block) && flag;
|
||||
}
|
||||
else
|
||||
{
|
||||
return !isExceptBlockForAttachWithPiston(block) && flag;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by ItemBlocks just before a block is actually set in the world, to allow for adjustments to the
|
||||
* IBlockstate
|
||||
*/
|
||||
public IBlockState getStateForPlacement(World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer)
|
||||
{
|
||||
return canPlaceBlock(worldIn, pos, facing) ? this.getDefaultState().withProperty(FACING, facing).withProperty(POWERED, Boolean.valueOf(false)) : this.getDefaultState().withProperty(FACING, EnumFacing.DOWN).withProperty(POWERED, Boolean.valueOf(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a neighboring block was changed and marks that this state should perform any checks during a neighbor
|
||||
* change. Cases may include when redstone power is updated, cactus blocks popping off due to a neighboring solid
|
||||
* block, etc.
|
||||
*/
|
||||
public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos)
|
||||
{
|
||||
if (this.checkForDrop(worldIn, pos, state) && !canPlaceBlock(worldIn, pos, (EnumFacing)state.getValue(FACING)))
|
||||
{
|
||||
this.dropBlockAsItem(worldIn, pos, state, 0);
|
||||
worldIn.setBlockToAir(pos);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkForDrop(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
if (this.canPlaceBlockAt(worldIn, pos))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.dropBlockAsItem(worldIn, pos, state, 0);
|
||||
worldIn.setBlockToAir(pos);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
|
||||
{
|
||||
EnumFacing enumfacing = (EnumFacing)state.getValue(FACING);
|
||||
boolean flag = ((Boolean)state.getValue(POWERED)).booleanValue();
|
||||
|
||||
switch (enumfacing)
|
||||
{
|
||||
case EAST:
|
||||
return flag ? AABB_EAST_ON : AABB_EAST_OFF;
|
||||
case WEST:
|
||||
return flag ? AABB_WEST_ON : AABB_WEST_OFF;
|
||||
case SOUTH:
|
||||
return flag ? AABB_SOUTH_ON : AABB_SOUTH_OFF;
|
||||
case NORTH:
|
||||
default:
|
||||
return flag ? AABB_NORTH_ON : AABB_NORTH_OFF;
|
||||
case UP:
|
||||
return flag ? AABB_UP_ON : AABB_UP_OFF;
|
||||
case DOWN:
|
||||
return flag ? AABB_DOWN_ON : AABB_DOWN_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the block is right clicked by a player.
|
||||
*/
|
||||
public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
|
||||
{
|
||||
if (((Boolean)state.getValue(POWERED)).booleanValue())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
worldIn.setBlockState(pos, state.withProperty(POWERED, Boolean.valueOf(true)), 3);
|
||||
worldIn.markBlockRangeForRenderUpdate(pos, pos);
|
||||
this.playClickSound(playerIn, worldIn, pos);
|
||||
this.notifyNeighbors(worldIn, pos, (EnumFacing)state.getValue(FACING));
|
||||
worldIn.scheduleUpdate(pos, this, this.tickRate(worldIn));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void playClickSound(@Nullable EntityPlayer player, World worldIn, BlockPos pos);
|
||||
|
||||
protected abstract void playReleaseSound(World worldIn, BlockPos pos);
|
||||
|
||||
/**
|
||||
* Called serverside after this block is replaced with another in Chunk, but before the Tile Entity is updated
|
||||
*/
|
||||
public void breakBlock(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
if (((Boolean)state.getValue(POWERED)).booleanValue())
|
||||
{
|
||||
this.notifyNeighbors(worldIn, pos, (EnumFacing)state.getValue(FACING));
|
||||
}
|
||||
|
||||
super.breakBlock(worldIn, pos, state);
|
||||
}
|
||||
|
||||
public int getWeakPower(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side)
|
||||
{
|
||||
return ((Boolean)blockState.getValue(POWERED)).booleanValue() ? 15 : 0;
|
||||
}
|
||||
|
||||
public int getStrongPower(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side)
|
||||
{
|
||||
if (!((Boolean)blockState.getValue(POWERED)).booleanValue())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return blockState.getValue(FACING) == side ? 15 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Can this block provide power. Only wire currently seems to have this change based on its state.
|
||||
*/
|
||||
public boolean canProvidePower(IBlockState state)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called randomly when setTickRandomly is set to true (used by e.g. crops to grow, etc.)
|
||||
*/
|
||||
public void randomTick(World worldIn, BlockPos pos, IBlockState state, Random random)
|
||||
{
|
||||
}
|
||||
|
||||
public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand)
|
||||
{
|
||||
if (!worldIn.isRemote)
|
||||
{
|
||||
if (((Boolean)state.getValue(POWERED)).booleanValue())
|
||||
{
|
||||
if (this.wooden)
|
||||
{
|
||||
this.checkPressed(state, worldIn, pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
worldIn.setBlockState(pos, state.withProperty(POWERED, Boolean.valueOf(false)));
|
||||
this.notifyNeighbors(worldIn, pos, (EnumFacing)state.getValue(FACING));
|
||||
this.playReleaseSound(worldIn, pos);
|
||||
worldIn.markBlockRangeForRenderUpdate(pos, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called When an Entity Collided with the Block
|
||||
*/
|
||||
public void onEntityCollidedWithBlock(World worldIn, BlockPos pos, IBlockState state, Entity entityIn)
|
||||
{
|
||||
if (!worldIn.isRemote)
|
||||
{
|
||||
if (this.wooden)
|
||||
{
|
||||
if (!((Boolean)state.getValue(POWERED)).booleanValue())
|
||||
{
|
||||
this.checkPressed(state, worldIn, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkPressed(IBlockState state, World worldIn, BlockPos pos)
|
||||
{
|
||||
List <? extends Entity > list = worldIn.<Entity>getEntitiesWithinAABB(EntityArrow.class, state.getBoundingBox(worldIn, pos).offset(pos));
|
||||
boolean flag = !list.isEmpty();
|
||||
boolean flag1 = ((Boolean)state.getValue(POWERED)).booleanValue();
|
||||
|
||||
if (flag && !flag1)
|
||||
{
|
||||
worldIn.setBlockState(pos, state.withProperty(POWERED, Boolean.valueOf(true)));
|
||||
this.notifyNeighbors(worldIn, pos, (EnumFacing)state.getValue(FACING));
|
||||
worldIn.markBlockRangeForRenderUpdate(pos, pos);
|
||||
this.playClickSound((EntityPlayer)null, worldIn, pos);
|
||||
}
|
||||
|
||||
if (!flag && flag1)
|
||||
{
|
||||
worldIn.setBlockState(pos, state.withProperty(POWERED, Boolean.valueOf(false)));
|
||||
this.notifyNeighbors(worldIn, pos, (EnumFacing)state.getValue(FACING));
|
||||
worldIn.markBlockRangeForRenderUpdate(pos, pos);
|
||||
this.playReleaseSound(worldIn, pos);
|
||||
}
|
||||
|
||||
if (flag)
|
||||
{
|
||||
worldIn.scheduleUpdate(new BlockPos(pos), this, this.tickRate(worldIn));
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyNeighbors(World worldIn, BlockPos pos, EnumFacing facing)
|
||||
{
|
||||
worldIn.notifyNeighborsOfStateChange(pos, this, false);
|
||||
worldIn.notifyNeighborsOfStateChange(pos.offset(facing.getOpposite()), this, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given metadata into a BlockState for this Block
|
||||
*/
|
||||
public IBlockState getStateFromMeta(int meta)
|
||||
{
|
||||
EnumFacing enumfacing;
|
||||
|
||||
switch (meta & 7)
|
||||
{
|
||||
case 0:
|
||||
enumfacing = EnumFacing.DOWN;
|
||||
break;
|
||||
case 1:
|
||||
enumfacing = EnumFacing.EAST;
|
||||
break;
|
||||
case 2:
|
||||
enumfacing = EnumFacing.WEST;
|
||||
break;
|
||||
case 3:
|
||||
enumfacing = EnumFacing.SOUTH;
|
||||
break;
|
||||
case 4:
|
||||
enumfacing = EnumFacing.NORTH;
|
||||
break;
|
||||
case 5:
|
||||
default:
|
||||
enumfacing = EnumFacing.UP;
|
||||
}
|
||||
|
||||
return this.getDefaultState().withProperty(FACING, enumfacing).withProperty(POWERED, Boolean.valueOf((meta & 8) > 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the BlockState into the correct metadata value
|
||||
*/
|
||||
public int getMetaFromState(IBlockState state)
|
||||
{
|
||||
int i;
|
||||
|
||||
switch ((EnumFacing)state.getValue(FACING))
|
||||
{
|
||||
case EAST:
|
||||
i = 1;
|
||||
break;
|
||||
case WEST:
|
||||
i = 2;
|
||||
break;
|
||||
case SOUTH:
|
||||
i = 3;
|
||||
break;
|
||||
case NORTH:
|
||||
i = 4;
|
||||
break;
|
||||
case UP:
|
||||
default:
|
||||
i = 5;
|
||||
break;
|
||||
case DOWN:
|
||||
i = 0;
|
||||
}
|
||||
|
||||
if (((Boolean)state.getValue(POWERED)).booleanValue())
|
||||
{
|
||||
i |= 8;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blockstate with the given rotation from the passed blockstate. If inapplicable, returns the passed
|
||||
* blockstate.
|
||||
*/
|
||||
public IBlockState withRotation(IBlockState state, Rotation rot)
|
||||
{
|
||||
return state.withProperty(FACING, rot.rotate((EnumFacing)state.getValue(FACING)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blockstate with the given mirror of the passed blockstate. If inapplicable, returns the passed
|
||||
* blockstate.
|
||||
*/
|
||||
public IBlockState withMirror(IBlockState state, Mirror mirrorIn)
|
||||
{
|
||||
return state.withRotation(mirrorIn.toRotation((EnumFacing)state.getValue(FACING)));
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {FACING, POWERED});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the geometry of the queried face at the given position and state. This is used to decide whether things like
|
||||
* buttons are allowed to be placed on the face, or how glass panes connect to the face, among other things.
|
||||
* <p>
|
||||
* Common values are {@code SOLID}, which is the default, and {@code UNDEFINED}, which represents something that
|
||||
* does not fit the other descriptions and will generally cause other things not to connect to the face.
|
||||
*
|
||||
* @return an approximation of the form of the given face
|
||||
*/
|
||||
public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face)
|
||||
{
|
||||
return BlockFaceShape.UNDEFINED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.SoundEvents;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class BlockButtonStone extends BlockButton
|
||||
{
|
||||
protected BlockButtonStone()
|
||||
{
|
||||
super(false);
|
||||
}
|
||||
|
||||
protected void playClickSound(@Nullable EntityPlayer player, World worldIn, BlockPos pos)
|
||||
{
|
||||
worldIn.playSound(player, pos, SoundEvents.BLOCK_STONE_BUTTON_CLICK_ON, SoundCategory.BLOCKS, 0.3F, 0.6F);
|
||||
}
|
||||
|
||||
protected void playReleaseSound(World worldIn, BlockPos pos)
|
||||
{
|
||||
worldIn.playSound((EntityPlayer)null, pos, SoundEvents.BLOCK_STONE_BUTTON_CLICK_OFF, SoundCategory.BLOCKS, 0.3F, 0.5F);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.SoundEvents;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class BlockButtonWood extends BlockButton
|
||||
{
|
||||
protected BlockButtonWood()
|
||||
{
|
||||
super(true);
|
||||
}
|
||||
|
||||
protected void playClickSound(@Nullable EntityPlayer player, World worldIn, BlockPos pos)
|
||||
{
|
||||
worldIn.playSound(player, pos, SoundEvents.BLOCK_WOOD_BUTTON_CLICK_ON, SoundCategory.BLOCKS, 0.3F, 0.6F);
|
||||
}
|
||||
|
||||
protected void playReleaseSound(World worldIn, BlockPos pos)
|
||||
{
|
||||
worldIn.playSound((EntityPlayer)null, pos, SoundEvents.BLOCK_WOOD_BUTTON_CLICK_OFF, SoundCategory.BLOCKS, 0.3F, 0.5F);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.Random;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.properties.PropertyInteger;
|
||||
import net.minecraft.block.state.BlockFaceShape;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.BlockRenderLayer;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class BlockCactus extends Block implements net.minecraftforge.common.IPlantable
|
||||
{
|
||||
public static final PropertyInteger AGE = PropertyInteger.create("age", 0, 15);
|
||||
protected static final AxisAlignedBB CACTUS_COLLISION_AABB = new AxisAlignedBB(0.0625D, 0.0D, 0.0625D, 0.9375D, 0.9375D, 0.9375D);
|
||||
protected static final AxisAlignedBB CACTUS_AABB = new AxisAlignedBB(0.0625D, 0.0D, 0.0625D, 0.9375D, 1.0D, 0.9375D);
|
||||
|
||||
protected BlockCactus()
|
||||
{
|
||||
super(Material.CACTUS);
|
||||
this.setDefaultState(this.blockState.getBaseState().withProperty(AGE, Integer.valueOf(0)));
|
||||
this.setTickRandomly(true);
|
||||
this.setCreativeTab(CreativeTabs.DECORATIONS);
|
||||
}
|
||||
|
||||
public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand)
|
||||
{
|
||||
if (!worldIn.isAreaLoaded(pos, 1)) return; // Forge: prevent growing cactus from loading unloaded chunks with block update
|
||||
BlockPos blockpos = pos.up();
|
||||
|
||||
if (worldIn.isAirBlock(blockpos))
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; worldIn.getBlockState(pos.down(i)).getBlock() == this; ++i)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
if (i < 3)
|
||||
{
|
||||
int j = ((Integer)state.getValue(AGE)).intValue();
|
||||
|
||||
if(net.minecraftforge.common.ForgeHooks.onCropsGrowPre(worldIn, blockpos, state, true))
|
||||
{
|
||||
if (j == 15)
|
||||
{
|
||||
worldIn.setBlockState(blockpos, this.getDefaultState());
|
||||
IBlockState iblockstate = state.withProperty(AGE, Integer.valueOf(0));
|
||||
worldIn.setBlockState(pos, iblockstate, 4);
|
||||
iblockstate.neighborChanged(worldIn, blockpos, this, pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
worldIn.setBlockState(pos, state.withProperty(AGE, Integer.valueOf(j + 1)), 4);
|
||||
}
|
||||
net.minecraftforge.common.ForgeHooks.onCropsGrowPost(worldIn, pos, state, worldIn.getBlockState(pos));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AxisAlignedBB getCollisionBoundingBox(IBlockState blockState, IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
return CACTUS_COLLISION_AABB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an AABB (in world coords!) that should be highlighted when the player is targeting this Block
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
public AxisAlignedBB getSelectedBoundingBox(IBlockState state, World worldIn, BlockPos pos)
|
||||
{
|
||||
return CACTUS_AABB.offset(pos);
|
||||
}
|
||||
|
||||
public boolean isFullCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine ambient occlusion and culling when rebuilding chunks for render
|
||||
*/
|
||||
public boolean isOpaqueCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this block can be placed exactly at the given position.
|
||||
*/
|
||||
public boolean canPlaceBlockAt(World worldIn, BlockPos pos)
|
||||
{
|
||||
return super.canPlaceBlockAt(worldIn, pos) ? this.canBlockStay(worldIn, pos) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a neighboring block was changed and marks that this state should perform any checks during a neighbor
|
||||
* change. Cases may include when redstone power is updated, cactus blocks popping off due to a neighboring solid
|
||||
* block, etc.
|
||||
*/
|
||||
public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos)
|
||||
{
|
||||
if (!this.canBlockStay(worldIn, pos))
|
||||
{
|
||||
worldIn.destroyBlock(pos, true);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canBlockStay(World worldIn, BlockPos pos)
|
||||
{
|
||||
for (EnumFacing enumfacing : EnumFacing.Plane.HORIZONTAL)
|
||||
{
|
||||
Material material = worldIn.getBlockState(pos.offset(enumfacing)).getMaterial();
|
||||
|
||||
if (material.isSolid() || material == Material.LAVA)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
IBlockState state = worldIn.getBlockState(pos.down());
|
||||
return state.getBlock().canSustainPlant(state, worldIn, pos.down(), EnumFacing.UP, this) && !worldIn.getBlockState(pos.up()).getMaterial().isLiquid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called When an Entity Collided with the Block
|
||||
*/
|
||||
public void onEntityCollidedWithBlock(World worldIn, BlockPos pos, IBlockState state, Entity entityIn)
|
||||
{
|
||||
entityIn.attackEntityFrom(DamageSource.CACTUS, 1.0F);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given metadata into a BlockState for this Block
|
||||
*/
|
||||
public IBlockState getStateFromMeta(int meta)
|
||||
{
|
||||
return this.getDefaultState().withProperty(AGE, Integer.valueOf(meta));
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public BlockRenderLayer getBlockLayer()
|
||||
{
|
||||
return BlockRenderLayer.CUTOUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the BlockState into the correct metadata value
|
||||
*/
|
||||
public int getMetaFromState(IBlockState state)
|
||||
{
|
||||
return ((Integer)state.getValue(AGE)).intValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.minecraftforge.common.EnumPlantType getPlantType(net.minecraft.world.IBlockAccess world, BlockPos pos)
|
||||
{
|
||||
return net.minecraftforge.common.EnumPlantType.Desert;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlockState getPlant(net.minecraft.world.IBlockAccess world, BlockPos pos)
|
||||
{
|
||||
return getDefaultState();
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {AGE});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the geometry of the queried face at the given position and state. This is used to decide whether things like
|
||||
* buttons are allowed to be placed on the face, or how glass panes connect to the face, among other things.
|
||||
* <p>
|
||||
* Common values are {@code SOLID}, which is the default, and {@code UNDEFINED}, which represents something that
|
||||
* does not fit the other descriptions and will generally cause other things not to connect to the face.
|
||||
*
|
||||
* @return an approximation of the form of the given face
|
||||
*/
|
||||
public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face)
|
||||
{
|
||||
return BlockFaceShape.UNDEFINED;
|
||||
}
|
||||
}
|
||||
193
build/tmp/recompileMc/sources/net/minecraft/block/BlockCake.java
Normal file
193
build/tmp/recompileMc/sources/net/minecraft/block/BlockCake.java
Normal file
@@ -0,0 +1,193 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.Random;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.properties.PropertyInteger;
|
||||
import net.minecraft.block.state.BlockFaceShape;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.stats.StatList;
|
||||
import net.minecraft.util.BlockRenderLayer;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class BlockCake extends Block
|
||||
{
|
||||
public static final PropertyInteger BITES = PropertyInteger.create("bites", 0, 6);
|
||||
protected static final AxisAlignedBB[] CAKE_AABB = new AxisAlignedBB[] {new AxisAlignedBB(0.0625D, 0.0D, 0.0625D, 0.9375D, 0.5D, 0.9375D), new AxisAlignedBB(0.1875D, 0.0D, 0.0625D, 0.9375D, 0.5D, 0.9375D), new AxisAlignedBB(0.3125D, 0.0D, 0.0625D, 0.9375D, 0.5D, 0.9375D), new AxisAlignedBB(0.4375D, 0.0D, 0.0625D, 0.9375D, 0.5D, 0.9375D), new AxisAlignedBB(0.5625D, 0.0D, 0.0625D, 0.9375D, 0.5D, 0.9375D), new AxisAlignedBB(0.6875D, 0.0D, 0.0625D, 0.9375D, 0.5D, 0.9375D), new AxisAlignedBB(0.8125D, 0.0D, 0.0625D, 0.9375D, 0.5D, 0.9375D)};
|
||||
|
||||
protected BlockCake()
|
||||
{
|
||||
super(Material.CAKE);
|
||||
this.setDefaultState(this.blockState.getBaseState().withProperty(BITES, Integer.valueOf(0)));
|
||||
this.setTickRandomly(true);
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
|
||||
{
|
||||
return CAKE_AABB[((Integer)state.getValue(BITES)).intValue()];
|
||||
}
|
||||
|
||||
public boolean isFullCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine ambient occlusion and culling when rebuilding chunks for render
|
||||
*/
|
||||
public boolean isOpaqueCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the block is right clicked by a player.
|
||||
*/
|
||||
public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
|
||||
{
|
||||
if (!worldIn.isRemote)
|
||||
{
|
||||
return this.eatCake(worldIn, pos, state, playerIn);
|
||||
}
|
||||
else
|
||||
{
|
||||
ItemStack itemstack = playerIn.getHeldItem(hand);
|
||||
return this.eatCake(worldIn, pos, state, playerIn) || itemstack.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean eatCake(World worldIn, BlockPos pos, IBlockState state, EntityPlayer player)
|
||||
{
|
||||
if (!player.canEat(false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
player.addStat(StatList.CAKE_SLICES_EATEN);
|
||||
player.getFoodStats().addStats(2, 0.1F);
|
||||
int i = ((Integer)state.getValue(BITES)).intValue();
|
||||
|
||||
if (i < 6)
|
||||
{
|
||||
worldIn.setBlockState(pos, state.withProperty(BITES, Integer.valueOf(i + 1)), 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
worldIn.setBlockToAir(pos);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this block can be placed exactly at the given position.
|
||||
*/
|
||||
public boolean canPlaceBlockAt(World worldIn, BlockPos pos)
|
||||
{
|
||||
return super.canPlaceBlockAt(worldIn, pos) ? this.canBlockStay(worldIn, pos) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a neighboring block was changed and marks that this state should perform any checks during a neighbor
|
||||
* change. Cases may include when redstone power is updated, cactus blocks popping off due to a neighboring solid
|
||||
* block, etc.
|
||||
*/
|
||||
public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos)
|
||||
{
|
||||
if (!this.canBlockStay(worldIn, pos))
|
||||
{
|
||||
worldIn.setBlockToAir(pos);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canBlockStay(World worldIn, BlockPos pos)
|
||||
{
|
||||
return worldIn.getBlockState(pos.down()).getMaterial().isSolid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the quantity of items to drop on block destruction.
|
||||
*/
|
||||
public int quantityDropped(Random random)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Item that this Block should drop when harvested.
|
||||
*/
|
||||
public Item getItemDropped(IBlockState state, Random rand, int fortune)
|
||||
{
|
||||
return Items.AIR;
|
||||
}
|
||||
|
||||
public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
return new ItemStack(Items.CAKE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given metadata into a BlockState for this Block
|
||||
*/
|
||||
public IBlockState getStateFromMeta(int meta)
|
||||
{
|
||||
return this.getDefaultState().withProperty(BITES, Integer.valueOf(meta));
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public BlockRenderLayer getBlockLayer()
|
||||
{
|
||||
return BlockRenderLayer.CUTOUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the BlockState into the correct metadata value
|
||||
*/
|
||||
public int getMetaFromState(IBlockState state)
|
||||
{
|
||||
return ((Integer)state.getValue(BITES)).intValue();
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {BITES});
|
||||
}
|
||||
|
||||
public int getComparatorInputOverride(IBlockState blockState, World worldIn, BlockPos pos)
|
||||
{
|
||||
return (7 - ((Integer)blockState.getValue(BITES)).intValue()) * 2;
|
||||
}
|
||||
|
||||
public boolean hasComparatorInputOverride(IBlockState state)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the geometry of the queried face at the given position and state. This is used to decide whether things like
|
||||
* buttons are allowed to be placed on the face, or how glass panes connect to the face, among other things.
|
||||
* <p>
|
||||
* Common values are {@code SOLID}, which is the default, and {@code UNDEFINED}, which represents something that
|
||||
* does not fit the other descriptions and will generally cause other things not to connect to the face.
|
||||
*
|
||||
* @return an approximation of the form of the given face
|
||||
*/
|
||||
public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face)
|
||||
{
|
||||
return BlockFaceShape.UNDEFINED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import net.minecraft.block.material.MapColor;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.properties.PropertyEnum;
|
||||
import net.minecraft.block.state.BlockFaceShape;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.item.EnumDyeColor;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class BlockCarpet extends Block
|
||||
{
|
||||
public static final PropertyEnum<EnumDyeColor> COLOR = PropertyEnum.<EnumDyeColor>create("color", EnumDyeColor.class);
|
||||
protected static final AxisAlignedBB CARPET_AABB = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.0625D, 1.0D);
|
||||
|
||||
protected BlockCarpet()
|
||||
{
|
||||
super(Material.CARPET);
|
||||
this.setDefaultState(this.blockState.getBaseState().withProperty(COLOR, EnumDyeColor.WHITE));
|
||||
this.setTickRandomly(true);
|
||||
this.setCreativeTab(CreativeTabs.DECORATIONS);
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
|
||||
{
|
||||
return CARPET_AABB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MapColor for this Block and the given BlockState
|
||||
*/
|
||||
public MapColor getMapColor(IBlockState state, IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
return MapColor.getBlockColor((EnumDyeColor)state.getValue(COLOR));
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine ambient occlusion and culling when rebuilding chunks for render
|
||||
*/
|
||||
public boolean isOpaqueCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isFullCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this block can be placed exactly at the given position.
|
||||
*/
|
||||
public boolean canPlaceBlockAt(World worldIn, BlockPos pos)
|
||||
{
|
||||
return super.canPlaceBlockAt(worldIn, pos) && this.canBlockStay(worldIn, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a neighboring block was changed and marks that this state should perform any checks during a neighbor
|
||||
* change. Cases may include when redstone power is updated, cactus blocks popping off due to a neighboring solid
|
||||
* block, etc.
|
||||
*/
|
||||
public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos)
|
||||
{
|
||||
this.checkForDrop(worldIn, pos, state);
|
||||
}
|
||||
|
||||
private boolean checkForDrop(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
if (!this.canBlockStay(worldIn, pos))
|
||||
{
|
||||
this.dropBlockAsItem(worldIn, pos, state, 0);
|
||||
worldIn.setBlockToAir(pos);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canBlockStay(World worldIn, BlockPos pos)
|
||||
{
|
||||
return !worldIn.isAirBlock(pos.down());
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public boolean shouldSideBeRendered(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side)
|
||||
{
|
||||
if (side == EnumFacing.UP)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return blockAccess.getBlockState(pos.offset(side)).getBlock() == this ? true : super.shouldSideBeRendered(blockState, blockAccess, pos, side);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the metadata of the item this Block can drop. This method is called when the block gets destroyed. It
|
||||
* returns the metadata of the dropped item based on the old metadata of the block.
|
||||
*/
|
||||
public int damageDropped(IBlockState state)
|
||||
{
|
||||
return ((EnumDyeColor)state.getValue(COLOR)).getMetadata();
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a list of blocks with the same ID, but different meta (eg: wood returns 4 blocks)
|
||||
*/
|
||||
public void getSubBlocks(CreativeTabs itemIn, NonNullList<ItemStack> items)
|
||||
{
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
items.add(new ItemStack(this, 1, i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given metadata into a BlockState for this Block
|
||||
*/
|
||||
public IBlockState getStateFromMeta(int meta)
|
||||
{
|
||||
return this.getDefaultState().withProperty(COLOR, EnumDyeColor.byMetadata(meta));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the BlockState into the correct metadata value
|
||||
*/
|
||||
public int getMetaFromState(IBlockState state)
|
||||
{
|
||||
return ((EnumDyeColor)state.getValue(COLOR)).getMetadata();
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {COLOR});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the geometry of the queried face at the given position and state. This is used to decide whether things like
|
||||
* buttons are allowed to be placed on the face, or how glass panes connect to the face, among other things.
|
||||
* <p>
|
||||
* Common values are {@code SOLID}, which is the default, and {@code UNDEFINED}, which represents something that
|
||||
* does not fit the other descriptions and will generally cause other things not to connect to the face.
|
||||
*
|
||||
* @return an approximation of the form of the given face
|
||||
*/
|
||||
public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face)
|
||||
{
|
||||
return face == EnumFacing.DOWN ? BlockFaceShape.SOLID : BlockFaceShape.UNDEFINED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
|
||||
public class BlockCarrot extends BlockCrops
|
||||
{
|
||||
private static final AxisAlignedBB[] CARROT_AABB = new AxisAlignedBB[] {new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.125D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.1875D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.25D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.3125D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.375D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.4375D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.5D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.5625D, 1.0D)};
|
||||
|
||||
protected Item getSeed()
|
||||
{
|
||||
return Items.CARROT;
|
||||
}
|
||||
|
||||
protected Item getCrop()
|
||||
{
|
||||
return Items.CARROT;
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
|
||||
{
|
||||
return CARROT_AABB[((Integer)state.getValue(this.getAgeProperty())).intValue()];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,354 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.material.MapColor;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.properties.PropertyInteger;
|
||||
import net.minecraft.block.state.BlockFaceShape;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.init.PotionTypes;
|
||||
import net.minecraft.init.SoundEvents;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemArmor;
|
||||
import net.minecraft.item.ItemBanner;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.potion.PotionUtils;
|
||||
import net.minecraft.stats.StatList;
|
||||
import net.minecraft.tileentity.TileEntityBanner;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class BlockCauldron extends Block
|
||||
{
|
||||
public static final PropertyInteger LEVEL = PropertyInteger.create("level", 0, 3);
|
||||
protected static final AxisAlignedBB AABB_LEGS = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.3125D, 1.0D);
|
||||
protected static final AxisAlignedBB AABB_WALL_NORTH = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 1.0D, 0.125D);
|
||||
protected static final AxisAlignedBB AABB_WALL_SOUTH = new AxisAlignedBB(0.0D, 0.0D, 0.875D, 1.0D, 1.0D, 1.0D);
|
||||
protected static final AxisAlignedBB AABB_WALL_EAST = new AxisAlignedBB(0.875D, 0.0D, 0.0D, 1.0D, 1.0D, 1.0D);
|
||||
protected static final AxisAlignedBB AABB_WALL_WEST = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 0.125D, 1.0D, 1.0D);
|
||||
|
||||
public BlockCauldron()
|
||||
{
|
||||
super(Material.IRON, MapColor.STONE);
|
||||
this.setDefaultState(this.blockState.getBaseState().withProperty(LEVEL, Integer.valueOf(0)));
|
||||
}
|
||||
|
||||
public void addCollisionBoxToList(IBlockState state, World worldIn, BlockPos pos, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, @Nullable Entity entityIn, boolean isActualState)
|
||||
{
|
||||
addCollisionBoxToList(pos, entityBox, collidingBoxes, AABB_LEGS);
|
||||
addCollisionBoxToList(pos, entityBox, collidingBoxes, AABB_WALL_WEST);
|
||||
addCollisionBoxToList(pos, entityBox, collidingBoxes, AABB_WALL_NORTH);
|
||||
addCollisionBoxToList(pos, entityBox, collidingBoxes, AABB_WALL_EAST);
|
||||
addCollisionBoxToList(pos, entityBox, collidingBoxes, AABB_WALL_SOUTH);
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
|
||||
{
|
||||
return FULL_BLOCK_AABB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine ambient occlusion and culling when rebuilding chunks for render
|
||||
*/
|
||||
public boolean isOpaqueCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isFullCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called When an Entity Collided with the Block
|
||||
*/
|
||||
public void onEntityCollidedWithBlock(World worldIn, BlockPos pos, IBlockState state, Entity entityIn)
|
||||
{
|
||||
int i = ((Integer)state.getValue(LEVEL)).intValue();
|
||||
float f = (float)pos.getY() + (6.0F + (float)(3 * i)) / 16.0F;
|
||||
|
||||
if (!worldIn.isRemote && entityIn.isBurning() && i > 0 && entityIn.getEntityBoundingBox().minY <= (double)f)
|
||||
{
|
||||
entityIn.extinguish();
|
||||
this.setWaterLevel(worldIn, pos, state, i - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the block is right clicked by a player.
|
||||
*/
|
||||
public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
|
||||
{
|
||||
ItemStack itemstack = playerIn.getHeldItem(hand);
|
||||
|
||||
if (itemstack.isEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = ((Integer)state.getValue(LEVEL)).intValue();
|
||||
Item item = itemstack.getItem();
|
||||
|
||||
if (item == Items.WATER_BUCKET)
|
||||
{
|
||||
if (i < 3 && !worldIn.isRemote)
|
||||
{
|
||||
if (!playerIn.capabilities.isCreativeMode)
|
||||
{
|
||||
playerIn.setHeldItem(hand, new ItemStack(Items.BUCKET));
|
||||
}
|
||||
|
||||
playerIn.addStat(StatList.CAULDRON_FILLED);
|
||||
this.setWaterLevel(worldIn, pos, state, 3);
|
||||
worldIn.playSound((EntityPlayer)null, pos, SoundEvents.ITEM_BUCKET_EMPTY, SoundCategory.BLOCKS, 1.0F, 1.0F);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (item == Items.BUCKET)
|
||||
{
|
||||
if (i == 3 && !worldIn.isRemote)
|
||||
{
|
||||
if (!playerIn.capabilities.isCreativeMode)
|
||||
{
|
||||
itemstack.shrink(1);
|
||||
|
||||
if (itemstack.isEmpty())
|
||||
{
|
||||
playerIn.setHeldItem(hand, new ItemStack(Items.WATER_BUCKET));
|
||||
}
|
||||
else if (!playerIn.inventory.addItemStackToInventory(new ItemStack(Items.WATER_BUCKET)))
|
||||
{
|
||||
playerIn.dropItem(new ItemStack(Items.WATER_BUCKET), false);
|
||||
}
|
||||
}
|
||||
|
||||
playerIn.addStat(StatList.CAULDRON_USED);
|
||||
this.setWaterLevel(worldIn, pos, state, 0);
|
||||
worldIn.playSound((EntityPlayer)null, pos, SoundEvents.ITEM_BUCKET_FILL, SoundCategory.BLOCKS, 1.0F, 1.0F);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (item == Items.GLASS_BOTTLE)
|
||||
{
|
||||
if (i > 0 && !worldIn.isRemote)
|
||||
{
|
||||
if (!playerIn.capabilities.isCreativeMode)
|
||||
{
|
||||
ItemStack itemstack3 = PotionUtils.addPotionToItemStack(new ItemStack(Items.POTIONITEM), PotionTypes.WATER);
|
||||
playerIn.addStat(StatList.CAULDRON_USED);
|
||||
itemstack.shrink(1);
|
||||
|
||||
if (itemstack.isEmpty())
|
||||
{
|
||||
playerIn.setHeldItem(hand, itemstack3);
|
||||
}
|
||||
else if (!playerIn.inventory.addItemStackToInventory(itemstack3))
|
||||
{
|
||||
playerIn.dropItem(itemstack3, false);
|
||||
}
|
||||
else if (playerIn instanceof EntityPlayerMP)
|
||||
{
|
||||
((EntityPlayerMP)playerIn).sendContainerToPlayer(playerIn.inventoryContainer);
|
||||
}
|
||||
}
|
||||
|
||||
worldIn.playSound((EntityPlayer)null, pos, SoundEvents.ITEM_BOTTLE_FILL, SoundCategory.BLOCKS, 1.0F, 1.0F);
|
||||
this.setWaterLevel(worldIn, pos, state, i - 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (item == Items.POTIONITEM && PotionUtils.getPotionFromItem(itemstack) == PotionTypes.WATER)
|
||||
{
|
||||
if (i < 3 && !worldIn.isRemote)
|
||||
{
|
||||
if (!playerIn.capabilities.isCreativeMode)
|
||||
{
|
||||
ItemStack itemstack2 = new ItemStack(Items.GLASS_BOTTLE);
|
||||
playerIn.addStat(StatList.CAULDRON_USED);
|
||||
playerIn.setHeldItem(hand, itemstack2);
|
||||
|
||||
if (playerIn instanceof EntityPlayerMP)
|
||||
{
|
||||
((EntityPlayerMP)playerIn).sendContainerToPlayer(playerIn.inventoryContainer);
|
||||
}
|
||||
}
|
||||
|
||||
worldIn.playSound((EntityPlayer)null, pos, SoundEvents.ITEM_BOTTLE_EMPTY, SoundCategory.BLOCKS, 1.0F, 1.0F);
|
||||
this.setWaterLevel(worldIn, pos, state, i + 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i > 0 && item instanceof ItemArmor)
|
||||
{
|
||||
ItemArmor itemarmor = (ItemArmor)item;
|
||||
|
||||
if (itemarmor.getArmorMaterial() == ItemArmor.ArmorMaterial.LEATHER && itemarmor.hasColor(itemstack) && !worldIn.isRemote)
|
||||
{
|
||||
itemarmor.removeColor(itemstack);
|
||||
this.setWaterLevel(worldIn, pos, state, i - 1);
|
||||
playerIn.addStat(StatList.ARMOR_CLEANED);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (i > 0 && item instanceof ItemBanner)
|
||||
{
|
||||
if (TileEntityBanner.getPatterns(itemstack) > 0 && !worldIn.isRemote)
|
||||
{
|
||||
ItemStack itemstack1 = itemstack.copy();
|
||||
itemstack1.setCount(1);
|
||||
TileEntityBanner.removeBannerData(itemstack1);
|
||||
playerIn.addStat(StatList.BANNER_CLEANED);
|
||||
|
||||
if (!playerIn.capabilities.isCreativeMode)
|
||||
{
|
||||
itemstack.shrink(1);
|
||||
this.setWaterLevel(worldIn, pos, state, i - 1);
|
||||
}
|
||||
|
||||
if (itemstack.isEmpty())
|
||||
{
|
||||
playerIn.setHeldItem(hand, itemstack1);
|
||||
}
|
||||
else if (!playerIn.inventory.addItemStackToInventory(itemstack1))
|
||||
{
|
||||
playerIn.dropItem(itemstack1, false);
|
||||
}
|
||||
else if (playerIn instanceof EntityPlayerMP)
|
||||
{
|
||||
((EntityPlayerMP)playerIn).sendContainerToPlayer(playerIn.inventoryContainer);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setWaterLevel(World worldIn, BlockPos pos, IBlockState state, int level)
|
||||
{
|
||||
worldIn.setBlockState(pos, state.withProperty(LEVEL, Integer.valueOf(MathHelper.clamp(level, 0, 3))), 2);
|
||||
worldIn.updateComparatorOutputLevel(pos, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called similar to random ticks, but only when it is raining.
|
||||
*/
|
||||
public void fillWithRain(World worldIn, BlockPos pos)
|
||||
{
|
||||
if (worldIn.rand.nextInt(20) == 1)
|
||||
{
|
||||
float f = worldIn.getBiome(pos).getTemperature(pos);
|
||||
|
||||
if (worldIn.getBiomeProvider().getTemperatureAtHeight(f, pos.getY()) >= 0.15F)
|
||||
{
|
||||
IBlockState iblockstate = worldIn.getBlockState(pos);
|
||||
|
||||
if (((Integer)iblockstate.getValue(LEVEL)).intValue() < 3)
|
||||
{
|
||||
worldIn.setBlockState(pos, iblockstate.cycleProperty(LEVEL), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Item that this Block should drop when harvested.
|
||||
*/
|
||||
public Item getItemDropped(IBlockState state, Random rand, int fortune)
|
||||
{
|
||||
return Items.CAULDRON;
|
||||
}
|
||||
|
||||
public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
return new ItemStack(Items.CAULDRON);
|
||||
}
|
||||
|
||||
public boolean hasComparatorInputOverride(IBlockState state)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getComparatorInputOverride(IBlockState blockState, World worldIn, BlockPos pos)
|
||||
{
|
||||
return ((Integer)blockState.getValue(LEVEL)).intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given metadata into a BlockState for this Block
|
||||
*/
|
||||
public IBlockState getStateFromMeta(int meta)
|
||||
{
|
||||
return this.getDefaultState().withProperty(LEVEL, Integer.valueOf(meta));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the BlockState into the correct metadata value
|
||||
*/
|
||||
public int getMetaFromState(IBlockState state)
|
||||
{
|
||||
return ((Integer)state.getValue(LEVEL)).intValue();
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {LEVEL});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if an entity can path through this block
|
||||
*/
|
||||
public boolean isPassable(IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the geometry of the queried face at the given position and state. This is used to decide whether things like
|
||||
* buttons are allowed to be placed on the face, or how glass panes connect to the face, among other things.
|
||||
* <p>
|
||||
* Common values are {@code SOLID}, which is the default, and {@code UNDEFINED}, which represents something that
|
||||
* does not fit the other descriptions and will generally cause other things not to connect to the face.
|
||||
*
|
||||
* @return an approximation of the form of the given face
|
||||
*/
|
||||
public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face)
|
||||
{
|
||||
if (face == EnumFacing.UP)
|
||||
{
|
||||
return BlockFaceShape.BOWL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return face == EnumFacing.DOWN ? BlockFaceShape.UNDEFINED : BlockFaceShape.SOLID;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,678 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.properties.PropertyDirection;
|
||||
import net.minecraft.block.state.BlockFaceShape;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.passive.EntityOcelot;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.inventory.Container;
|
||||
import net.minecraft.inventory.IInventory;
|
||||
import net.minecraft.inventory.InventoryHelper;
|
||||
import net.minecraft.inventory.InventoryLargeChest;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.stats.StatList;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityChest;
|
||||
import net.minecraft.util.EnumBlockRenderType;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.Mirror;
|
||||
import net.minecraft.util.Rotation;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.ILockableContainer;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class BlockChest extends BlockContainer
|
||||
{
|
||||
public static final PropertyDirection FACING = BlockHorizontal.FACING;
|
||||
protected static final AxisAlignedBB NORTH_CHEST_AABB = new AxisAlignedBB(0.0625D, 0.0D, 0.0D, 0.9375D, 0.875D, 0.9375D);
|
||||
protected static final AxisAlignedBB SOUTH_CHEST_AABB = new AxisAlignedBB(0.0625D, 0.0D, 0.0625D, 0.9375D, 0.875D, 1.0D);
|
||||
protected static final AxisAlignedBB WEST_CHEST_AABB = new AxisAlignedBB(0.0D, 0.0D, 0.0625D, 0.9375D, 0.875D, 0.9375D);
|
||||
protected static final AxisAlignedBB EAST_CHEST_AABB = new AxisAlignedBB(0.0625D, 0.0D, 0.0625D, 1.0D, 0.875D, 0.9375D);
|
||||
protected static final AxisAlignedBB NOT_CONNECTED_AABB = new AxisAlignedBB(0.0625D, 0.0D, 0.0625D, 0.9375D, 0.875D, 0.9375D);
|
||||
/** 0 : Normal chest, 1 : Trapped chest */
|
||||
public final BlockChest.Type chestType;
|
||||
|
||||
protected BlockChest(BlockChest.Type chestTypeIn)
|
||||
{
|
||||
super(Material.WOOD);
|
||||
this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH));
|
||||
this.chestType = chestTypeIn;
|
||||
this.setCreativeTab(chestTypeIn == BlockChest.Type.TRAP ? CreativeTabs.REDSTONE : CreativeTabs.DECORATIONS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine ambient occlusion and culling when rebuilding chunks for render
|
||||
*/
|
||||
public boolean isOpaqueCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isFullCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public boolean hasCustomBreakingProgress(IBlockState state)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of render function called. MODEL for mixed tesr and static model, MODELBLOCK_ANIMATED for TESR-only,
|
||||
* LIQUID for vanilla liquids, INVISIBLE to skip all rendering
|
||||
*/
|
||||
public EnumBlockRenderType getRenderType(IBlockState state)
|
||||
{
|
||||
return EnumBlockRenderType.ENTITYBLOCK_ANIMATED;
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
|
||||
{
|
||||
if (source.getBlockState(pos.north()).getBlock() == this)
|
||||
{
|
||||
return NORTH_CHEST_AABB;
|
||||
}
|
||||
else if (source.getBlockState(pos.south()).getBlock() == this)
|
||||
{
|
||||
return SOUTH_CHEST_AABB;
|
||||
}
|
||||
else if (source.getBlockState(pos.west()).getBlock() == this)
|
||||
{
|
||||
return WEST_CHEST_AABB;
|
||||
}
|
||||
else
|
||||
{
|
||||
return source.getBlockState(pos.east()).getBlock() == this ? EAST_CHEST_AABB : NOT_CONNECTED_AABB;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the block is set in the Chunk data, but before the Tile Entity is set
|
||||
*/
|
||||
public void onBlockAdded(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
this.checkForSurroundingChests(worldIn, pos, state);
|
||||
|
||||
for (EnumFacing enumfacing : EnumFacing.Plane.HORIZONTAL)
|
||||
{
|
||||
BlockPos blockpos = pos.offset(enumfacing);
|
||||
IBlockState iblockstate = worldIn.getBlockState(blockpos);
|
||||
|
||||
if (iblockstate.getBlock() == this)
|
||||
{
|
||||
this.checkForSurroundingChests(worldIn, blockpos, iblockstate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by ItemBlocks just before a block is actually set in the world, to allow for adjustments to the
|
||||
* IBlockstate
|
||||
*/
|
||||
public IBlockState getStateForPlacement(World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer)
|
||||
{
|
||||
return this.getDefaultState().withProperty(FACING, placer.getHorizontalFacing());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by ItemBlocks after a block is set in the world, to allow post-place logic
|
||||
*/
|
||||
public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
|
||||
{
|
||||
EnumFacing enumfacing = EnumFacing.getHorizontal(MathHelper.floor((double)(placer.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3).getOpposite();
|
||||
state = state.withProperty(FACING, enumfacing);
|
||||
BlockPos blockpos = pos.north();
|
||||
BlockPos blockpos1 = pos.south();
|
||||
BlockPos blockpos2 = pos.west();
|
||||
BlockPos blockpos3 = pos.east();
|
||||
boolean flag = this == worldIn.getBlockState(blockpos).getBlock();
|
||||
boolean flag1 = this == worldIn.getBlockState(blockpos1).getBlock();
|
||||
boolean flag2 = this == worldIn.getBlockState(blockpos2).getBlock();
|
||||
boolean flag3 = this == worldIn.getBlockState(blockpos3).getBlock();
|
||||
|
||||
if (!flag && !flag1 && !flag2 && !flag3)
|
||||
{
|
||||
worldIn.setBlockState(pos, state, 3);
|
||||
}
|
||||
else if (enumfacing.getAxis() != EnumFacing.Axis.X || !flag && !flag1)
|
||||
{
|
||||
if (enumfacing.getAxis() == EnumFacing.Axis.Z && (flag2 || flag3))
|
||||
{
|
||||
if (flag2)
|
||||
{
|
||||
worldIn.setBlockState(blockpos2, state, 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
worldIn.setBlockState(blockpos3, state, 3);
|
||||
}
|
||||
|
||||
worldIn.setBlockState(pos, state, 3);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
worldIn.setBlockState(blockpos, state, 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
worldIn.setBlockState(blockpos1, state, 3);
|
||||
}
|
||||
|
||||
worldIn.setBlockState(pos, state, 3);
|
||||
}
|
||||
|
||||
if (stack.hasDisplayName())
|
||||
{
|
||||
TileEntity tileentity = worldIn.getTileEntity(pos);
|
||||
|
||||
if (tileentity instanceof TileEntityChest)
|
||||
{
|
||||
((TileEntityChest)tileentity).setCustomName(stack.getDisplayName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IBlockState checkForSurroundingChests(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
if (worldIn.isRemote)
|
||||
{
|
||||
return state;
|
||||
}
|
||||
else
|
||||
{
|
||||
IBlockState iblockstate = worldIn.getBlockState(pos.north());
|
||||
IBlockState iblockstate1 = worldIn.getBlockState(pos.south());
|
||||
IBlockState iblockstate2 = worldIn.getBlockState(pos.west());
|
||||
IBlockState iblockstate3 = worldIn.getBlockState(pos.east());
|
||||
EnumFacing enumfacing = (EnumFacing)state.getValue(FACING);
|
||||
|
||||
if (iblockstate.getBlock() != this && iblockstate1.getBlock() != this)
|
||||
{
|
||||
boolean flag = iblockstate.isFullBlock();
|
||||
boolean flag1 = iblockstate1.isFullBlock();
|
||||
|
||||
if (iblockstate2.getBlock() == this || iblockstate3.getBlock() == this)
|
||||
{
|
||||
BlockPos blockpos1 = iblockstate2.getBlock() == this ? pos.west() : pos.east();
|
||||
IBlockState iblockstate7 = worldIn.getBlockState(blockpos1.north());
|
||||
IBlockState iblockstate6 = worldIn.getBlockState(blockpos1.south());
|
||||
enumfacing = EnumFacing.SOUTH;
|
||||
EnumFacing enumfacing2;
|
||||
|
||||
if (iblockstate2.getBlock() == this)
|
||||
{
|
||||
enumfacing2 = (EnumFacing)iblockstate2.getValue(FACING);
|
||||
}
|
||||
else
|
||||
{
|
||||
enumfacing2 = (EnumFacing)iblockstate3.getValue(FACING);
|
||||
}
|
||||
|
||||
if (enumfacing2 == EnumFacing.NORTH)
|
||||
{
|
||||
enumfacing = EnumFacing.NORTH;
|
||||
}
|
||||
|
||||
if ((flag || iblockstate7.isFullBlock()) && !flag1 && !iblockstate6.isFullBlock())
|
||||
{
|
||||
enumfacing = EnumFacing.SOUTH;
|
||||
}
|
||||
|
||||
if ((flag1 || iblockstate6.isFullBlock()) && !flag && !iblockstate7.isFullBlock())
|
||||
{
|
||||
enumfacing = EnumFacing.NORTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BlockPos blockpos = iblockstate.getBlock() == this ? pos.north() : pos.south();
|
||||
IBlockState iblockstate4 = worldIn.getBlockState(blockpos.west());
|
||||
IBlockState iblockstate5 = worldIn.getBlockState(blockpos.east());
|
||||
enumfacing = EnumFacing.EAST;
|
||||
EnumFacing enumfacing1;
|
||||
|
||||
if (iblockstate.getBlock() == this)
|
||||
{
|
||||
enumfacing1 = (EnumFacing)iblockstate.getValue(FACING);
|
||||
}
|
||||
else
|
||||
{
|
||||
enumfacing1 = (EnumFacing)iblockstate1.getValue(FACING);
|
||||
}
|
||||
|
||||
if (enumfacing1 == EnumFacing.WEST)
|
||||
{
|
||||
enumfacing = EnumFacing.WEST;
|
||||
}
|
||||
|
||||
if ((iblockstate2.isFullBlock() || iblockstate4.isFullBlock()) && !iblockstate3.isFullBlock() && !iblockstate5.isFullBlock())
|
||||
{
|
||||
enumfacing = EnumFacing.EAST;
|
||||
}
|
||||
|
||||
if ((iblockstate3.isFullBlock() || iblockstate5.isFullBlock()) && !iblockstate2.isFullBlock() && !iblockstate4.isFullBlock())
|
||||
{
|
||||
enumfacing = EnumFacing.WEST;
|
||||
}
|
||||
}
|
||||
|
||||
state = state.withProperty(FACING, enumfacing);
|
||||
worldIn.setBlockState(pos, state, 3);
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
public IBlockState correctFacing(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
EnumFacing enumfacing = null;
|
||||
|
||||
for (EnumFacing enumfacing1 : EnumFacing.Plane.HORIZONTAL)
|
||||
{
|
||||
IBlockState iblockstate = worldIn.getBlockState(pos.offset(enumfacing1));
|
||||
|
||||
if (iblockstate.getBlock() == this)
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
if (iblockstate.isFullBlock())
|
||||
{
|
||||
if (enumfacing != null)
|
||||
{
|
||||
enumfacing = null;
|
||||
break;
|
||||
}
|
||||
|
||||
enumfacing = enumfacing1;
|
||||
}
|
||||
}
|
||||
|
||||
if (enumfacing != null)
|
||||
{
|
||||
return state.withProperty(FACING, enumfacing.getOpposite());
|
||||
}
|
||||
else
|
||||
{
|
||||
EnumFacing enumfacing2 = (EnumFacing)state.getValue(FACING);
|
||||
|
||||
if (worldIn.getBlockState(pos.offset(enumfacing2)).isFullBlock())
|
||||
{
|
||||
enumfacing2 = enumfacing2.getOpposite();
|
||||
}
|
||||
|
||||
if (worldIn.getBlockState(pos.offset(enumfacing2)).isFullBlock())
|
||||
{
|
||||
enumfacing2 = enumfacing2.rotateY();
|
||||
}
|
||||
|
||||
if (worldIn.getBlockState(pos.offset(enumfacing2)).isFullBlock())
|
||||
{
|
||||
enumfacing2 = enumfacing2.getOpposite();
|
||||
}
|
||||
|
||||
return state.withProperty(FACING, enumfacing2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this block can be placed exactly at the given position.
|
||||
*/
|
||||
public boolean canPlaceBlockAt(World worldIn, BlockPos pos)
|
||||
{
|
||||
int i = 0;
|
||||
BlockPos blockpos = pos.west();
|
||||
BlockPos blockpos1 = pos.east();
|
||||
BlockPos blockpos2 = pos.north();
|
||||
BlockPos blockpos3 = pos.south();
|
||||
|
||||
if (worldIn.getBlockState(blockpos).getBlock() == this)
|
||||
{
|
||||
if (this.isDoubleChest(worldIn, blockpos))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
if (worldIn.getBlockState(blockpos1).getBlock() == this)
|
||||
{
|
||||
if (this.isDoubleChest(worldIn, blockpos1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
if (worldIn.getBlockState(blockpos2).getBlock() == this)
|
||||
{
|
||||
if (this.isDoubleChest(worldIn, blockpos2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
if (worldIn.getBlockState(blockpos3).getBlock() == this)
|
||||
{
|
||||
if (this.isDoubleChest(worldIn, blockpos3))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
return i <= 1;
|
||||
}
|
||||
|
||||
private boolean isDoubleChest(World worldIn, BlockPos pos)
|
||||
{
|
||||
if (worldIn.getBlockState(pos).getBlock() != this)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (EnumFacing enumfacing : EnumFacing.Plane.HORIZONTAL)
|
||||
{
|
||||
if (worldIn.getBlockState(pos.offset(enumfacing)).getBlock() == this)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a neighboring block was changed and marks that this state should perform any checks during a neighbor
|
||||
* change. Cases may include when redstone power is updated, cactus blocks popping off due to a neighboring solid
|
||||
* block, etc.
|
||||
*/
|
||||
public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos)
|
||||
{
|
||||
super.neighborChanged(state, worldIn, pos, blockIn, fromPos);
|
||||
TileEntity tileentity = worldIn.getTileEntity(pos);
|
||||
|
||||
if (tileentity instanceof TileEntityChest)
|
||||
{
|
||||
tileentity.updateContainingBlockInfo();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called serverside after this block is replaced with another in Chunk, but before the Tile Entity is updated
|
||||
*/
|
||||
public void breakBlock(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
TileEntity tileentity = worldIn.getTileEntity(pos);
|
||||
|
||||
if (tileentity instanceof IInventory)
|
||||
{
|
||||
InventoryHelper.dropInventoryItems(worldIn, pos, (IInventory)tileentity);
|
||||
worldIn.updateComparatorOutputLevel(pos, this);
|
||||
}
|
||||
|
||||
super.breakBlock(worldIn, pos, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the block is right clicked by a player.
|
||||
*/
|
||||
public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
|
||||
{
|
||||
if (worldIn.isRemote)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ILockableContainer ilockablecontainer = this.getLockableContainer(worldIn, pos);
|
||||
|
||||
if (ilockablecontainer != null)
|
||||
{
|
||||
playerIn.displayGUIChest(ilockablecontainer);
|
||||
|
||||
if (this.chestType == BlockChest.Type.BASIC)
|
||||
{
|
||||
playerIn.addStat(StatList.CHEST_OPENED);
|
||||
}
|
||||
else if (this.chestType == BlockChest.Type.TRAP)
|
||||
{
|
||||
playerIn.addStat(StatList.TRAPPED_CHEST_TRIGGERED);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ILockableContainer getLockableContainer(World worldIn, BlockPos pos)
|
||||
{
|
||||
return this.getContainer(worldIn, pos, false);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ILockableContainer getContainer(World worldIn, BlockPos pos, boolean allowBlocking)
|
||||
{
|
||||
TileEntity tileentity = worldIn.getTileEntity(pos);
|
||||
|
||||
if (!(tileentity instanceof TileEntityChest))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
ILockableContainer ilockablecontainer = (TileEntityChest)tileentity;
|
||||
|
||||
if (!allowBlocking && this.isBlocked(worldIn, pos))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (EnumFacing enumfacing : EnumFacing.Plane.HORIZONTAL)
|
||||
{
|
||||
BlockPos blockpos = pos.offset(enumfacing);
|
||||
Block block = worldIn.getBlockState(blockpos).getBlock();
|
||||
|
||||
if (block == this)
|
||||
{
|
||||
if (!allowBlocking && this.isBlocked(worldIn, blockpos)) // Forge: fix MC-99321
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
TileEntity tileentity1 = worldIn.getTileEntity(blockpos);
|
||||
|
||||
if (tileentity1 instanceof TileEntityChest)
|
||||
{
|
||||
if (enumfacing != EnumFacing.WEST && enumfacing != EnumFacing.NORTH)
|
||||
{
|
||||
ilockablecontainer = new InventoryLargeChest("container.chestDouble", ilockablecontainer, (TileEntityChest)tileentity1);
|
||||
}
|
||||
else
|
||||
{
|
||||
ilockablecontainer = new InventoryLargeChest("container.chestDouble", (TileEntityChest)tileentity1, ilockablecontainer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ilockablecontainer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new instance of a block's tile entity class. Called on placing the block.
|
||||
*/
|
||||
public TileEntity createNewTileEntity(World worldIn, int meta)
|
||||
{
|
||||
return new TileEntityChest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Can this block provide power. Only wire currently seems to have this change based on its state.
|
||||
*/
|
||||
public boolean canProvidePower(IBlockState state)
|
||||
{
|
||||
return this.chestType == BlockChest.Type.TRAP;
|
||||
}
|
||||
|
||||
public int getWeakPower(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side)
|
||||
{
|
||||
if (!blockState.canProvidePower())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = 0;
|
||||
TileEntity tileentity = blockAccess.getTileEntity(pos);
|
||||
|
||||
if (tileentity instanceof TileEntityChest)
|
||||
{
|
||||
i = ((TileEntityChest)tileentity).numPlayersUsing;
|
||||
}
|
||||
|
||||
return MathHelper.clamp(i, 0, 15);
|
||||
}
|
||||
}
|
||||
|
||||
public int getStrongPower(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side)
|
||||
{
|
||||
return side == EnumFacing.UP ? blockState.getWeakPower(blockAccess, pos, side) : 0;
|
||||
}
|
||||
|
||||
private boolean isBlocked(World worldIn, BlockPos pos)
|
||||
{
|
||||
return this.isBelowSolidBlock(worldIn, pos) || this.isOcelotSittingOnChest(worldIn, pos);
|
||||
}
|
||||
|
||||
private boolean isBelowSolidBlock(World worldIn, BlockPos pos)
|
||||
{
|
||||
return worldIn.getBlockState(pos.up()).doesSideBlockChestOpening(worldIn, pos.up(), EnumFacing.DOWN);
|
||||
}
|
||||
|
||||
private boolean isOcelotSittingOnChest(World worldIn, BlockPos pos)
|
||||
{
|
||||
for (Entity entity : worldIn.getEntitiesWithinAABB(EntityOcelot.class, new AxisAlignedBB((double)pos.getX(), (double)(pos.getY() + 1), (double)pos.getZ(), (double)(pos.getX() + 1), (double)(pos.getY() + 2), (double)(pos.getZ() + 1))))
|
||||
{
|
||||
EntityOcelot entityocelot = (EntityOcelot)entity;
|
||||
|
||||
if (entityocelot.isSitting())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasComparatorInputOverride(IBlockState state)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getComparatorInputOverride(IBlockState blockState, World worldIn, BlockPos pos)
|
||||
{
|
||||
return Container.calcRedstoneFromInventory(this.getLockableContainer(worldIn, pos));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given metadata into a BlockState for this Block
|
||||
*/
|
||||
public IBlockState getStateFromMeta(int meta)
|
||||
{
|
||||
EnumFacing enumfacing = EnumFacing.getFront(meta);
|
||||
|
||||
if (enumfacing.getAxis() == EnumFacing.Axis.Y)
|
||||
{
|
||||
enumfacing = EnumFacing.NORTH;
|
||||
}
|
||||
|
||||
return this.getDefaultState().withProperty(FACING, enumfacing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the BlockState into the correct metadata value
|
||||
*/
|
||||
public int getMetaFromState(IBlockState state)
|
||||
{
|
||||
return ((EnumFacing)state.getValue(FACING)).getIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blockstate with the given rotation from the passed blockstate. If inapplicable, returns the passed
|
||||
* blockstate.
|
||||
*/
|
||||
public IBlockState withRotation(IBlockState state, Rotation rot)
|
||||
{
|
||||
return state.withProperty(FACING, rot.rotate((EnumFacing)state.getValue(FACING)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blockstate with the given mirror of the passed blockstate. If inapplicable, returns the passed
|
||||
* blockstate.
|
||||
*/
|
||||
public IBlockState withMirror(IBlockState state, Mirror mirrorIn)
|
||||
{
|
||||
return state.withRotation(mirrorIn.toRotation((EnumFacing)state.getValue(FACING)));
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {FACING});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the geometry of the queried face at the given position and state. This is used to decide whether things like
|
||||
* buttons are allowed to be placed on the face, or how glass panes connect to the face, among other things.
|
||||
* <p>
|
||||
* Common values are {@code SOLID}, which is the default, and {@code UNDEFINED}, which represents something that
|
||||
* does not fit the other descriptions and will generally cause other things not to connect to the face.
|
||||
*
|
||||
* @return an approximation of the form of the given face
|
||||
*/
|
||||
public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face)
|
||||
{
|
||||
return BlockFaceShape.UNDEFINED;
|
||||
}
|
||||
|
||||
public static enum Type
|
||||
{
|
||||
BASIC,
|
||||
TRAP;
|
||||
}
|
||||
|
||||
/* ======================================== FORGE START =====================================*/
|
||||
public boolean rotateBlock(World world, BlockPos pos, EnumFacing axis)
|
||||
{
|
||||
return !isDoubleChest(world, pos) && super.rotateBlock(world, pos, axis);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,367 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.Random;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.material.MapColor;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.properties.PropertyInteger;
|
||||
import net.minecraft.block.state.BlockFaceShape;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.BlockRenderLayer;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class BlockChorusFlower extends Block
|
||||
{
|
||||
public static final PropertyInteger AGE = PropertyInteger.create("age", 0, 5);
|
||||
|
||||
protected BlockChorusFlower()
|
||||
{
|
||||
super(Material.PLANTS, MapColor.PURPLE);
|
||||
this.setDefaultState(this.blockState.getBaseState().withProperty(AGE, Integer.valueOf(0)));
|
||||
this.setCreativeTab(CreativeTabs.DECORATIONS);
|
||||
this.setTickRandomly(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Item that this Block should drop when harvested.
|
||||
*/
|
||||
public Item getItemDropped(IBlockState state, Random rand, int fortune)
|
||||
{
|
||||
return Items.AIR;
|
||||
}
|
||||
|
||||
public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand)
|
||||
{
|
||||
if (!this.canSurvive(worldIn, pos))
|
||||
{
|
||||
worldIn.destroyBlock(pos, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
BlockPos blockpos = pos.up();
|
||||
|
||||
if (worldIn.isAirBlock(blockpos) && blockpos.getY() < 256)
|
||||
{
|
||||
int i = ((Integer)state.getValue(AGE)).intValue();
|
||||
|
||||
if (i < 5 && net.minecraftforge.common.ForgeHooks.onCropsGrowPre(worldIn, blockpos, state, rand.nextInt(1) == 0))
|
||||
{
|
||||
boolean flag = false;
|
||||
boolean flag1 = false;
|
||||
IBlockState iblockstate = worldIn.getBlockState(pos.down());
|
||||
Block block = iblockstate.getBlock();
|
||||
|
||||
if (block == Blocks.END_STONE)
|
||||
{
|
||||
flag = true;
|
||||
}
|
||||
else if (block == Blocks.CHORUS_PLANT)
|
||||
{
|
||||
int j = 1;
|
||||
|
||||
for (int k = 0; k < 4; ++k)
|
||||
{
|
||||
Block block1 = worldIn.getBlockState(pos.down(j + 1)).getBlock();
|
||||
|
||||
if (block1 != Blocks.CHORUS_PLANT)
|
||||
{
|
||||
if (block1 == Blocks.END_STONE)
|
||||
{
|
||||
flag1 = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
++j;
|
||||
}
|
||||
|
||||
int i1 = 4;
|
||||
|
||||
if (flag1)
|
||||
{
|
||||
++i1;
|
||||
}
|
||||
|
||||
if (j < 2 || rand.nextInt(i1) >= j)
|
||||
{
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
else if (iblockstate.getMaterial() == Material.AIR)
|
||||
{
|
||||
flag = true;
|
||||
}
|
||||
|
||||
if (flag && areAllNeighborsEmpty(worldIn, blockpos, (EnumFacing)null) && worldIn.isAirBlock(pos.up(2)))
|
||||
{
|
||||
worldIn.setBlockState(pos, Blocks.CHORUS_PLANT.getDefaultState(), 2);
|
||||
this.placeGrownFlower(worldIn, blockpos, i);
|
||||
}
|
||||
else if (i < 4)
|
||||
{
|
||||
int l = rand.nextInt(4);
|
||||
boolean flag2 = false;
|
||||
|
||||
if (flag1)
|
||||
{
|
||||
++l;
|
||||
}
|
||||
|
||||
for (int j1 = 0; j1 < l; ++j1)
|
||||
{
|
||||
EnumFacing enumfacing = EnumFacing.Plane.HORIZONTAL.random(rand);
|
||||
BlockPos blockpos1 = pos.offset(enumfacing);
|
||||
|
||||
if (worldIn.isAirBlock(blockpos1) && worldIn.isAirBlock(blockpos1.down()) && areAllNeighborsEmpty(worldIn, blockpos1, enumfacing.getOpposite()))
|
||||
{
|
||||
this.placeGrownFlower(worldIn, blockpos1, i + 1);
|
||||
flag2 = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag2)
|
||||
{
|
||||
worldIn.setBlockState(pos, Blocks.CHORUS_PLANT.getDefaultState(), 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.placeDeadFlower(worldIn, pos);
|
||||
}
|
||||
}
|
||||
else if (i == 4)
|
||||
{
|
||||
this.placeDeadFlower(worldIn, pos);
|
||||
}
|
||||
net.minecraftforge.common.ForgeHooks.onCropsGrowPost(worldIn, pos, state, worldIn.getBlockState(pos));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void placeGrownFlower(World worldIn, BlockPos pos, int age)
|
||||
{
|
||||
worldIn.setBlockState(pos, this.getDefaultState().withProperty(AGE, Integer.valueOf(age)), 2);
|
||||
worldIn.playEvent(1033, pos, 0);
|
||||
}
|
||||
|
||||
private void placeDeadFlower(World worldIn, BlockPos pos)
|
||||
{
|
||||
worldIn.setBlockState(pos, this.getDefaultState().withProperty(AGE, Integer.valueOf(5)), 2);
|
||||
worldIn.playEvent(1034, pos, 0);
|
||||
}
|
||||
|
||||
private static boolean areAllNeighborsEmpty(World worldIn, BlockPos pos, EnumFacing excludingSide)
|
||||
{
|
||||
for (EnumFacing enumfacing : EnumFacing.Plane.HORIZONTAL)
|
||||
{
|
||||
if (enumfacing != excludingSide && !worldIn.isAirBlock(pos.offset(enumfacing)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isFullCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine ambient occlusion and culling when rebuilding chunks for render
|
||||
*/
|
||||
public boolean isOpaqueCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this block can be placed exactly at the given position.
|
||||
*/
|
||||
public boolean canPlaceBlockAt(World worldIn, BlockPos pos)
|
||||
{
|
||||
return super.canPlaceBlockAt(worldIn, pos) && this.canSurvive(worldIn, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a neighboring block was changed and marks that this state should perform any checks during a neighbor
|
||||
* change. Cases may include when redstone power is updated, cactus blocks popping off due to a neighboring solid
|
||||
* block, etc.
|
||||
*/
|
||||
public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos)
|
||||
{
|
||||
if (!this.canSurvive(worldIn, pos))
|
||||
{
|
||||
worldIn.scheduleUpdate(pos, this, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canSurvive(World worldIn, BlockPos pos)
|
||||
{
|
||||
IBlockState iblockstate = worldIn.getBlockState(pos.down());
|
||||
Block block = iblockstate.getBlock();
|
||||
|
||||
if (block != Blocks.CHORUS_PLANT && block != Blocks.END_STONE)
|
||||
{
|
||||
if (iblockstate.getMaterial() == Material.AIR)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (EnumFacing enumfacing : EnumFacing.Plane.HORIZONTAL)
|
||||
{
|
||||
IBlockState iblockstate1 = worldIn.getBlockState(pos.offset(enumfacing));
|
||||
Block block1 = iblockstate1.getBlock();
|
||||
|
||||
if (block1 == Blocks.CHORUS_PLANT)
|
||||
{
|
||||
++i;
|
||||
}
|
||||
else if (iblockstate1.getMaterial() != Material.AIR)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return i == 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns the block's drops in the world. By the time this is called the Block has possibly been set to air via
|
||||
* Block.removedByPlayer
|
||||
*/
|
||||
public void harvestBlock(World worldIn, EntityPlayer player, BlockPos pos, IBlockState state, @Nullable TileEntity te, ItemStack stack)
|
||||
{
|
||||
super.harvestBlock(worldIn, player, pos, state, te, stack);
|
||||
spawnAsEntity(worldIn, pos, new ItemStack(Item.getItemFromBlock(this)));
|
||||
}
|
||||
|
||||
protected ItemStack getSilkTouchDrop(IBlockState state)
|
||||
{
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public BlockRenderLayer getBlockLayer()
|
||||
{
|
||||
return BlockRenderLayer.CUTOUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given metadata into a BlockState for this Block
|
||||
*/
|
||||
public IBlockState getStateFromMeta(int meta)
|
||||
{
|
||||
return this.getDefaultState().withProperty(AGE, Integer.valueOf(meta));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the BlockState into the correct metadata value
|
||||
*/
|
||||
public int getMetaFromState(IBlockState state)
|
||||
{
|
||||
return ((Integer)state.getValue(AGE)).intValue();
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {AGE});
|
||||
}
|
||||
|
||||
public static void generatePlant(World worldIn, BlockPos pos, Random rand, int p_185603_3_)
|
||||
{
|
||||
worldIn.setBlockState(pos, Blocks.CHORUS_PLANT.getDefaultState(), 2);
|
||||
growTreeRecursive(worldIn, pos, rand, pos, p_185603_3_, 0);
|
||||
}
|
||||
|
||||
private static void growTreeRecursive(World worldIn, BlockPos p_185601_1_, Random rand, BlockPos p_185601_3_, int p_185601_4_, int p_185601_5_)
|
||||
{
|
||||
int i = rand.nextInt(4) + 1;
|
||||
|
||||
if (p_185601_5_ == 0)
|
||||
{
|
||||
++i;
|
||||
}
|
||||
|
||||
for (int j = 0; j < i; ++j)
|
||||
{
|
||||
BlockPos blockpos = p_185601_1_.up(j + 1);
|
||||
|
||||
if (!areAllNeighborsEmpty(worldIn, blockpos, (EnumFacing)null))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
worldIn.setBlockState(blockpos, Blocks.CHORUS_PLANT.getDefaultState(), 2);
|
||||
}
|
||||
|
||||
boolean flag = false;
|
||||
|
||||
if (p_185601_5_ < 4)
|
||||
{
|
||||
int l = rand.nextInt(4);
|
||||
|
||||
if (p_185601_5_ == 0)
|
||||
{
|
||||
++l;
|
||||
}
|
||||
|
||||
for (int k = 0; k < l; ++k)
|
||||
{
|
||||
EnumFacing enumfacing = EnumFacing.Plane.HORIZONTAL.random(rand);
|
||||
BlockPos blockpos1 = p_185601_1_.up(i).offset(enumfacing);
|
||||
|
||||
if (Math.abs(blockpos1.getX() - p_185601_3_.getX()) < p_185601_4_ && Math.abs(blockpos1.getZ() - p_185601_3_.getZ()) < p_185601_4_ && worldIn.isAirBlock(blockpos1) && worldIn.isAirBlock(blockpos1.down()) && areAllNeighborsEmpty(worldIn, blockpos1, enumfacing.getOpposite()))
|
||||
{
|
||||
flag = true;
|
||||
worldIn.setBlockState(blockpos1, Blocks.CHORUS_PLANT.getDefaultState(), 2);
|
||||
growTreeRecursive(worldIn, blockpos1, rand, p_185601_3_, p_185601_4_, p_185601_5_ + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!flag)
|
||||
{
|
||||
worldIn.setBlockState(p_185601_1_.up(i), Blocks.CHORUS_FLOWER.getDefaultState().withProperty(AGE, Integer.valueOf(5)), 2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the geometry of the queried face at the given position and state. This is used to decide whether things like
|
||||
* buttons are allowed to be placed on the face, or how glass panes connect to the face, among other things.
|
||||
* <p>
|
||||
* Common values are {@code SOLID}, which is the default, and {@code UNDEFINED}, which represents something that
|
||||
* does not fit the other descriptions and will generally cause other things not to connect to the face.
|
||||
*
|
||||
* @return an approximation of the form of the given face
|
||||
*/
|
||||
public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face)
|
||||
{
|
||||
return BlockFaceShape.UNDEFINED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.material.MapColor;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.properties.PropertyBool;
|
||||
import net.minecraft.block.state.BlockFaceShape;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.util.BlockRenderLayer;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class BlockChorusPlant extends Block
|
||||
{
|
||||
public static final PropertyBool NORTH = PropertyBool.create("north");
|
||||
public static final PropertyBool EAST = PropertyBool.create("east");
|
||||
public static final PropertyBool SOUTH = PropertyBool.create("south");
|
||||
public static final PropertyBool WEST = PropertyBool.create("west");
|
||||
public static final PropertyBool UP = PropertyBool.create("up");
|
||||
public static final PropertyBool DOWN = PropertyBool.create("down");
|
||||
|
||||
protected BlockChorusPlant()
|
||||
{
|
||||
super(Material.PLANTS, MapColor.PURPLE);
|
||||
this.setCreativeTab(CreativeTabs.DECORATIONS);
|
||||
this.setDefaultState(this.blockState.getBaseState().withProperty(NORTH, Boolean.valueOf(false)).withProperty(EAST, Boolean.valueOf(false)).withProperty(SOUTH, Boolean.valueOf(false)).withProperty(WEST, Boolean.valueOf(false)).withProperty(UP, Boolean.valueOf(false)).withProperty(DOWN, Boolean.valueOf(false)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the actual Block state of this Block at the given position. This applies properties not visible in the
|
||||
* metadata, such as fence connections.
|
||||
*/
|
||||
public IBlockState getActualState(IBlockState state, IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
Block block = worldIn.getBlockState(pos.down()).getBlock();
|
||||
Block block1 = worldIn.getBlockState(pos.up()).getBlock();
|
||||
Block block2 = worldIn.getBlockState(pos.north()).getBlock();
|
||||
Block block3 = worldIn.getBlockState(pos.east()).getBlock();
|
||||
Block block4 = worldIn.getBlockState(pos.south()).getBlock();
|
||||
Block block5 = worldIn.getBlockState(pos.west()).getBlock();
|
||||
return state.withProperty(DOWN, Boolean.valueOf(block == this || block == Blocks.CHORUS_FLOWER || block == Blocks.END_STONE)).withProperty(UP, Boolean.valueOf(block1 == this || block1 == Blocks.CHORUS_FLOWER)).withProperty(NORTH, Boolean.valueOf(block2 == this || block2 == Blocks.CHORUS_FLOWER)).withProperty(EAST, Boolean.valueOf(block3 == this || block3 == Blocks.CHORUS_FLOWER)).withProperty(SOUTH, Boolean.valueOf(block4 == this || block4 == Blocks.CHORUS_FLOWER)).withProperty(WEST, Boolean.valueOf(block5 == this || block5 == Blocks.CHORUS_FLOWER));
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
|
||||
{
|
||||
state = state.getActualState(source, pos);
|
||||
float f = 0.1875F;
|
||||
float f1 = ((Boolean)state.getValue(WEST)).booleanValue() ? 0.0F : 0.1875F;
|
||||
float f2 = ((Boolean)state.getValue(DOWN)).booleanValue() ? 0.0F : 0.1875F;
|
||||
float f3 = ((Boolean)state.getValue(NORTH)).booleanValue() ? 0.0F : 0.1875F;
|
||||
float f4 = ((Boolean)state.getValue(EAST)).booleanValue() ? 1.0F : 0.8125F;
|
||||
float f5 = ((Boolean)state.getValue(UP)).booleanValue() ? 1.0F : 0.8125F;
|
||||
float f6 = ((Boolean)state.getValue(SOUTH)).booleanValue() ? 1.0F : 0.8125F;
|
||||
return new AxisAlignedBB((double)f1, (double)f2, (double)f3, (double)f4, (double)f5, (double)f6);
|
||||
}
|
||||
|
||||
public void addCollisionBoxToList(IBlockState state, World worldIn, BlockPos pos, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, @Nullable Entity entityIn, boolean isActualState)
|
||||
{
|
||||
if (!isActualState)
|
||||
{
|
||||
state = state.getActualState(worldIn, pos);
|
||||
}
|
||||
|
||||
float f = 0.1875F;
|
||||
float f1 = 0.8125F;
|
||||
addCollisionBoxToList(pos, entityBox, collidingBoxes, new AxisAlignedBB(0.1875D, 0.1875D, 0.1875D, 0.8125D, 0.8125D, 0.8125D));
|
||||
|
||||
if (((Boolean)state.getValue(WEST)).booleanValue())
|
||||
{
|
||||
addCollisionBoxToList(pos, entityBox, collidingBoxes, new AxisAlignedBB(0.0D, 0.1875D, 0.1875D, 0.1875D, 0.8125D, 0.8125D));
|
||||
}
|
||||
|
||||
if (((Boolean)state.getValue(EAST)).booleanValue())
|
||||
{
|
||||
addCollisionBoxToList(pos, entityBox, collidingBoxes, new AxisAlignedBB(0.8125D, 0.1875D, 0.1875D, 1.0D, 0.8125D, 0.8125D));
|
||||
}
|
||||
|
||||
if (((Boolean)state.getValue(UP)).booleanValue())
|
||||
{
|
||||
addCollisionBoxToList(pos, entityBox, collidingBoxes, new AxisAlignedBB(0.1875D, 0.8125D, 0.1875D, 0.8125D, 1.0D, 0.8125D));
|
||||
}
|
||||
|
||||
if (((Boolean)state.getValue(DOWN)).booleanValue())
|
||||
{
|
||||
addCollisionBoxToList(pos, entityBox, collidingBoxes, new AxisAlignedBB(0.1875D, 0.0D, 0.1875D, 0.8125D, 0.1875D, 0.8125D));
|
||||
}
|
||||
|
||||
if (((Boolean)state.getValue(NORTH)).booleanValue())
|
||||
{
|
||||
addCollisionBoxToList(pos, entityBox, collidingBoxes, new AxisAlignedBB(0.1875D, 0.1875D, 0.0D, 0.8125D, 0.8125D, 0.1875D));
|
||||
}
|
||||
|
||||
if (((Boolean)state.getValue(SOUTH)).booleanValue())
|
||||
{
|
||||
addCollisionBoxToList(pos, entityBox, collidingBoxes, new AxisAlignedBB(0.1875D, 0.1875D, 0.8125D, 0.8125D, 0.8125D, 1.0D));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the BlockState into the correct metadata value
|
||||
*/
|
||||
public int getMetaFromState(IBlockState state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand)
|
||||
{
|
||||
if (!this.canSurviveAt(worldIn, pos))
|
||||
{
|
||||
worldIn.destroyBlock(pos, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Item that this Block should drop when harvested.
|
||||
*/
|
||||
public Item getItemDropped(IBlockState state, Random rand, int fortune)
|
||||
{
|
||||
return Items.CHORUS_FRUIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the quantity of items to drop on block destruction.
|
||||
*/
|
||||
public int quantityDropped(Random random)
|
||||
{
|
||||
return random.nextInt(2);
|
||||
}
|
||||
|
||||
public boolean isFullCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine ambient occlusion and culling when rebuilding chunks for render
|
||||
*/
|
||||
public boolean isOpaqueCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this block can be placed exactly at the given position.
|
||||
*/
|
||||
public boolean canPlaceBlockAt(World worldIn, BlockPos pos)
|
||||
{
|
||||
return super.canPlaceBlockAt(worldIn, pos) ? this.canSurviveAt(worldIn, pos) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a neighboring block was changed and marks that this state should perform any checks during a neighbor
|
||||
* change. Cases may include when redstone power is updated, cactus blocks popping off due to a neighboring solid
|
||||
* block, etc.
|
||||
*/
|
||||
public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos)
|
||||
{
|
||||
if (!this.canSurviveAt(worldIn, pos))
|
||||
{
|
||||
worldIn.scheduleUpdate(pos, this, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canSurviveAt(World wordIn, BlockPos pos)
|
||||
{
|
||||
boolean flag = wordIn.isAirBlock(pos.up());
|
||||
boolean flag1 = wordIn.isAirBlock(pos.down());
|
||||
|
||||
for (EnumFacing enumfacing : EnumFacing.Plane.HORIZONTAL)
|
||||
{
|
||||
BlockPos blockpos = pos.offset(enumfacing);
|
||||
Block block = wordIn.getBlockState(blockpos).getBlock();
|
||||
|
||||
if (block == this)
|
||||
{
|
||||
if (!flag && !flag1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Block block1 = wordIn.getBlockState(blockpos.down()).getBlock();
|
||||
|
||||
if (block1 == this || block1 == Blocks.END_STONE)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Block block2 = wordIn.getBlockState(pos.down()).getBlock();
|
||||
return block2 == this || block2 == Blocks.END_STONE;
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {NORTH, EAST, SOUTH, WEST, UP, DOWN});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if an entity can path through this block
|
||||
*/
|
||||
public boolean isPassable(IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public BlockRenderLayer getBlockLayer()
|
||||
{
|
||||
return BlockRenderLayer.CUTOUT;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public boolean shouldSideBeRendered(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side)
|
||||
{
|
||||
Block block = blockAccess.getBlockState(pos.offset(side)).getBlock();
|
||||
return block != this && block != Blocks.CHORUS_FLOWER && (side != EnumFacing.DOWN || block != Blocks.END_STONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the geometry of the queried face at the given position and state. This is used to decide whether things like
|
||||
* buttons are allowed to be placed on the face, or how glass panes connect to the face, among other things.
|
||||
* <p>
|
||||
* Common values are {@code SOLID}, which is the default, and {@code UNDEFINED}, which represents something that
|
||||
* does not fit the other descriptions and will generally cause other things not to connect to the face.
|
||||
*
|
||||
* @return an approximation of the form of the given face
|
||||
*/
|
||||
public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face)
|
||||
{
|
||||
return BlockFaceShape.UNDEFINED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.Random;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.Item;
|
||||
|
||||
public class BlockClay extends Block
|
||||
{
|
||||
public BlockClay()
|
||||
{
|
||||
super(Material.CLAY);
|
||||
this.setCreativeTab(CreativeTabs.BUILDING_BLOCKS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Item that this Block should drop when harvested.
|
||||
*/
|
||||
public Item getItemDropped(IBlockState state, Random rand, int fortune)
|
||||
{
|
||||
return Items.CLAY_BALL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the quantity of items to drop on block destruction.
|
||||
*/
|
||||
public int quantityDropped(Random random)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.Random;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.properties.PropertyInteger;
|
||||
import net.minecraft.block.state.BlockFaceShape;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.EnumDyeColor;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.BlockRenderLayer;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.Mirror;
|
||||
import net.minecraft.util.Rotation;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class BlockCocoa extends BlockHorizontal implements IGrowable
|
||||
{
|
||||
public static final PropertyInteger AGE = PropertyInteger.create("age", 0, 2);
|
||||
protected static final AxisAlignedBB[] COCOA_EAST_AABB = new AxisAlignedBB[] {new AxisAlignedBB(0.6875D, 0.4375D, 0.375D, 0.9375D, 0.75D, 0.625D), new AxisAlignedBB(0.5625D, 0.3125D, 0.3125D, 0.9375D, 0.75D, 0.6875D), new AxisAlignedBB(0.4375D, 0.1875D, 0.25D, 0.9375D, 0.75D, 0.75D)};
|
||||
protected static final AxisAlignedBB[] COCOA_WEST_AABB = new AxisAlignedBB[] {new AxisAlignedBB(0.0625D, 0.4375D, 0.375D, 0.3125D, 0.75D, 0.625D), new AxisAlignedBB(0.0625D, 0.3125D, 0.3125D, 0.4375D, 0.75D, 0.6875D), new AxisAlignedBB(0.0625D, 0.1875D, 0.25D, 0.5625D, 0.75D, 0.75D)};
|
||||
protected static final AxisAlignedBB[] COCOA_NORTH_AABB = new AxisAlignedBB[] {new AxisAlignedBB(0.375D, 0.4375D, 0.0625D, 0.625D, 0.75D, 0.3125D), new AxisAlignedBB(0.3125D, 0.3125D, 0.0625D, 0.6875D, 0.75D, 0.4375D), new AxisAlignedBB(0.25D, 0.1875D, 0.0625D, 0.75D, 0.75D, 0.5625D)};
|
||||
protected static final AxisAlignedBB[] COCOA_SOUTH_AABB = new AxisAlignedBB[] {new AxisAlignedBB(0.375D, 0.4375D, 0.6875D, 0.625D, 0.75D, 0.9375D), new AxisAlignedBB(0.3125D, 0.3125D, 0.5625D, 0.6875D, 0.75D, 0.9375D), new AxisAlignedBB(0.25D, 0.1875D, 0.4375D, 0.75D, 0.75D, 0.9375D)};
|
||||
|
||||
public BlockCocoa()
|
||||
{
|
||||
super(Material.PLANTS);
|
||||
this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH).withProperty(AGE, Integer.valueOf(0)));
|
||||
this.setTickRandomly(true);
|
||||
}
|
||||
|
||||
public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand)
|
||||
{
|
||||
if (!this.canBlockStay(worldIn, pos, state))
|
||||
{
|
||||
this.dropBlock(worldIn, pos, state);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = ((Integer)state.getValue(AGE)).intValue();
|
||||
|
||||
if (i < 2 && net.minecraftforge.common.ForgeHooks.onCropsGrowPre(worldIn, pos, state, rand.nextInt(5) == 0))
|
||||
{
|
||||
worldIn.setBlockState(pos, state.withProperty(AGE, Integer.valueOf(i + 1)), 2);
|
||||
net.minecraftforge.common.ForgeHooks.onCropsGrowPost(worldIn, pos, state, worldIn.getBlockState(pos));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canBlockStay(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
pos = pos.offset((EnumFacing)state.getValue(FACING));
|
||||
IBlockState iblockstate = worldIn.getBlockState(pos);
|
||||
return iblockstate.getBlock() == Blocks.LOG && iblockstate.getValue(BlockOldLog.VARIANT) == BlockPlanks.EnumType.JUNGLE;
|
||||
}
|
||||
|
||||
public boolean isFullCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine ambient occlusion and culling when rebuilding chunks for render
|
||||
*/
|
||||
public boolean isOpaqueCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
|
||||
{
|
||||
int i = ((Integer)state.getValue(AGE)).intValue();
|
||||
|
||||
switch ((EnumFacing)state.getValue(FACING))
|
||||
{
|
||||
case SOUTH:
|
||||
return COCOA_SOUTH_AABB[i];
|
||||
case NORTH:
|
||||
default:
|
||||
return COCOA_NORTH_AABB[i];
|
||||
case WEST:
|
||||
return COCOA_WEST_AABB[i];
|
||||
case EAST:
|
||||
return COCOA_EAST_AABB[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blockstate with the given rotation from the passed blockstate. If inapplicable, returns the passed
|
||||
* blockstate.
|
||||
*/
|
||||
public IBlockState withRotation(IBlockState state, Rotation rot)
|
||||
{
|
||||
return state.withProperty(FACING, rot.rotate((EnumFacing)state.getValue(FACING)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blockstate with the given mirror of the passed blockstate. If inapplicable, returns the passed
|
||||
* blockstate.
|
||||
*/
|
||||
public IBlockState withMirror(IBlockState state, Mirror mirrorIn)
|
||||
{
|
||||
return state.withRotation(mirrorIn.toRotation((EnumFacing)state.getValue(FACING)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by ItemBlocks after a block is set in the world, to allow post-place logic
|
||||
*/
|
||||
public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
|
||||
{
|
||||
EnumFacing enumfacing = EnumFacing.fromAngle((double)placer.rotationYaw);
|
||||
worldIn.setBlockState(pos, state.withProperty(FACING, enumfacing), 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by ItemBlocks just before a block is actually set in the world, to allow for adjustments to the
|
||||
* IBlockstate
|
||||
*/
|
||||
public IBlockState getStateForPlacement(World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer)
|
||||
{
|
||||
if (!facing.getAxis().isHorizontal())
|
||||
{
|
||||
facing = EnumFacing.NORTH;
|
||||
}
|
||||
|
||||
return this.getDefaultState().withProperty(FACING, facing.getOpposite()).withProperty(AGE, Integer.valueOf(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a neighboring block was changed and marks that this state should perform any checks during a neighbor
|
||||
* change. Cases may include when redstone power is updated, cactus blocks popping off due to a neighboring solid
|
||||
* block, etc.
|
||||
*/
|
||||
public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos)
|
||||
{
|
||||
if (!this.canBlockStay(worldIn, pos, state))
|
||||
{
|
||||
this.dropBlock(worldIn, pos, state);
|
||||
}
|
||||
}
|
||||
|
||||
private void dropBlock(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
worldIn.setBlockState(pos, Blocks.AIR.getDefaultState(), 3);
|
||||
this.dropBlockAsItem(worldIn, pos, state, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns this Block's drops into the World as EntityItems.
|
||||
*/
|
||||
public void dropBlockAsItemWithChance(World worldIn, BlockPos pos, IBlockState state, float chance, int fortune)
|
||||
{
|
||||
super.dropBlockAsItemWithChance(worldIn, pos, state, chance, fortune);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getDrops(net.minecraft.util.NonNullList<ItemStack> drops, IBlockAccess world, BlockPos pos, IBlockState state, int fortune)
|
||||
{
|
||||
super.getDrops(drops, world, pos, state, fortune);
|
||||
int i = ((Integer)state.getValue(AGE)).intValue();
|
||||
int j = 1;
|
||||
|
||||
if (i >= 2)
|
||||
{
|
||||
j = 3;
|
||||
}
|
||||
|
||||
for (int k = 0; k < j; ++k)
|
||||
{
|
||||
drops.add(new ItemStack(Items.DYE, 1, EnumDyeColor.BROWN.getDyeDamage()));
|
||||
}
|
||||
}
|
||||
|
||||
public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
return new ItemStack(Items.DYE, 1, EnumDyeColor.BROWN.getDyeDamage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this IGrowable can grow
|
||||
*/
|
||||
public boolean canGrow(World worldIn, BlockPos pos, IBlockState state, boolean isClient)
|
||||
{
|
||||
return ((Integer)state.getValue(AGE)).intValue() < 2;
|
||||
}
|
||||
|
||||
public boolean canUseBonemeal(World worldIn, Random rand, BlockPos pos, IBlockState state)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void grow(World worldIn, Random rand, BlockPos pos, IBlockState state)
|
||||
{
|
||||
worldIn.setBlockState(pos, state.withProperty(AGE, Integer.valueOf(((Integer)state.getValue(AGE)).intValue() + 1)), 2);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public BlockRenderLayer getBlockLayer()
|
||||
{
|
||||
return BlockRenderLayer.CUTOUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given metadata into a BlockState for this Block
|
||||
*/
|
||||
public IBlockState getStateFromMeta(int meta)
|
||||
{
|
||||
return this.getDefaultState().withProperty(FACING, EnumFacing.getHorizontal(meta)).withProperty(AGE, Integer.valueOf((meta & 15) >> 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the BlockState into the correct metadata value
|
||||
*/
|
||||
public int getMetaFromState(IBlockState state)
|
||||
{
|
||||
int i = 0;
|
||||
i = i | ((EnumFacing)state.getValue(FACING)).getHorizontalIndex();
|
||||
i = i | ((Integer)state.getValue(AGE)).intValue() << 2;
|
||||
return i;
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {FACING, AGE});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the geometry of the queried face at the given position and state. This is used to decide whether things like
|
||||
* buttons are allowed to be placed on the face, or how glass panes connect to the face, among other things.
|
||||
* <p>
|
||||
* Common values are {@code SOLID}, which is the default, and {@code UNDEFINED}, which represents something that
|
||||
* does not fit the other descriptions and will generally cause other things not to connect to the face.
|
||||
*
|
||||
* @return an approximation of the form of the given face
|
||||
*/
|
||||
public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face)
|
||||
{
|
||||
return BlockFaceShape.UNDEFINED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import net.minecraft.block.material.MapColor;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.properties.PropertyEnum;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.item.EnumDyeColor;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
|
||||
public class BlockColored extends Block
|
||||
{
|
||||
public static final PropertyEnum<EnumDyeColor> COLOR = PropertyEnum.<EnumDyeColor>create("color", EnumDyeColor.class);
|
||||
|
||||
public BlockColored(Material materialIn)
|
||||
{
|
||||
super(materialIn);
|
||||
this.setDefaultState(this.blockState.getBaseState().withProperty(COLOR, EnumDyeColor.WHITE));
|
||||
this.setCreativeTab(CreativeTabs.BUILDING_BLOCKS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the metadata of the item this Block can drop. This method is called when the block gets destroyed. It
|
||||
* returns the metadata of the dropped item based on the old metadata of the block.
|
||||
*/
|
||||
public int damageDropped(IBlockState state)
|
||||
{
|
||||
return ((EnumDyeColor)state.getValue(COLOR)).getMetadata();
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a list of blocks with the same ID, but different meta (eg: wood returns 4 blocks)
|
||||
*/
|
||||
public void getSubBlocks(CreativeTabs itemIn, NonNullList<ItemStack> items)
|
||||
{
|
||||
for (EnumDyeColor enumdyecolor : EnumDyeColor.values())
|
||||
{
|
||||
items.add(new ItemStack(this, 1, enumdyecolor.getMetadata()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MapColor for this Block and the given BlockState
|
||||
*/
|
||||
public MapColor getMapColor(IBlockState state, IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
return MapColor.getBlockColor((EnumDyeColor)state.getValue(COLOR));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given metadata into a BlockState for this Block
|
||||
*/
|
||||
public IBlockState getStateFromMeta(int meta)
|
||||
{
|
||||
return this.getDefaultState().withProperty(COLOR, EnumDyeColor.byMetadata(meta));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the BlockState into the correct metadata value
|
||||
*/
|
||||
public int getMetaFromState(IBlockState state)
|
||||
{
|
||||
return ((EnumDyeColor)state.getValue(COLOR)).getMetadata();
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {COLOR});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,342 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.Random;
|
||||
import net.minecraft.block.material.MapColor;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.properties.PropertyBool;
|
||||
import net.minecraft.block.properties.PropertyDirection;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.tileentity.CommandBlockBaseLogic;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityCommandBlock;
|
||||
import net.minecraft.util.EnumBlockRenderType;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.Mirror;
|
||||
import net.minecraft.util.Rotation;
|
||||
import net.minecraft.util.StringUtils;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.GameRules;
|
||||
import net.minecraft.world.World;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class BlockCommandBlock extends BlockContainer
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
public static final PropertyDirection FACING = BlockDirectional.FACING;
|
||||
public static final PropertyBool CONDITIONAL = PropertyBool.create("conditional");
|
||||
|
||||
public BlockCommandBlock(MapColor color)
|
||||
{
|
||||
super(Material.IRON, color);
|
||||
this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH).withProperty(CONDITIONAL, Boolean.valueOf(false)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new instance of a block's tile entity class. Called on placing the block.
|
||||
*/
|
||||
public TileEntity createNewTileEntity(World worldIn, int meta)
|
||||
{
|
||||
TileEntityCommandBlock tileentitycommandblock = new TileEntityCommandBlock();
|
||||
tileentitycommandblock.setAuto(this == Blocks.CHAIN_COMMAND_BLOCK);
|
||||
return tileentitycommandblock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a neighboring block was changed and marks that this state should perform any checks during a neighbor
|
||||
* change. Cases may include when redstone power is updated, cactus blocks popping off due to a neighboring solid
|
||||
* block, etc.
|
||||
*/
|
||||
public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos)
|
||||
{
|
||||
if (!worldIn.isRemote)
|
||||
{
|
||||
TileEntity tileentity = worldIn.getTileEntity(pos);
|
||||
|
||||
if (tileentity instanceof TileEntityCommandBlock)
|
||||
{
|
||||
TileEntityCommandBlock tileentitycommandblock = (TileEntityCommandBlock)tileentity;
|
||||
boolean flag = worldIn.isBlockPowered(pos);
|
||||
boolean flag1 = tileentitycommandblock.isPowered();
|
||||
tileentitycommandblock.setPowered(flag);
|
||||
|
||||
if (!flag1 && !tileentitycommandblock.isAuto() && tileentitycommandblock.getMode() != TileEntityCommandBlock.Mode.SEQUENCE)
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
tileentitycommandblock.setConditionMet();
|
||||
worldIn.scheduleUpdate(pos, this, this.tickRate(worldIn));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand)
|
||||
{
|
||||
if (!worldIn.isRemote)
|
||||
{
|
||||
TileEntity tileentity = worldIn.getTileEntity(pos);
|
||||
|
||||
if (tileentity instanceof TileEntityCommandBlock)
|
||||
{
|
||||
TileEntityCommandBlock tileentitycommandblock = (TileEntityCommandBlock)tileentity;
|
||||
CommandBlockBaseLogic commandblockbaselogic = tileentitycommandblock.getCommandBlockLogic();
|
||||
boolean flag = !StringUtils.isNullOrEmpty(commandblockbaselogic.getCommand());
|
||||
TileEntityCommandBlock.Mode tileentitycommandblock$mode = tileentitycommandblock.getMode();
|
||||
boolean flag1 = tileentitycommandblock.isConditionMet();
|
||||
|
||||
if (tileentitycommandblock$mode == TileEntityCommandBlock.Mode.AUTO)
|
||||
{
|
||||
tileentitycommandblock.setConditionMet();
|
||||
|
||||
if (flag1)
|
||||
{
|
||||
this.execute(state, worldIn, pos, commandblockbaselogic, flag);
|
||||
}
|
||||
else if (tileentitycommandblock.isConditional())
|
||||
{
|
||||
commandblockbaselogic.setSuccessCount(0);
|
||||
}
|
||||
|
||||
if (tileentitycommandblock.isPowered() || tileentitycommandblock.isAuto())
|
||||
{
|
||||
worldIn.scheduleUpdate(pos, this, this.tickRate(worldIn));
|
||||
}
|
||||
}
|
||||
else if (tileentitycommandblock$mode == TileEntityCommandBlock.Mode.REDSTONE)
|
||||
{
|
||||
if (flag1)
|
||||
{
|
||||
this.execute(state, worldIn, pos, commandblockbaselogic, flag);
|
||||
}
|
||||
else if (tileentitycommandblock.isConditional())
|
||||
{
|
||||
commandblockbaselogic.setSuccessCount(0);
|
||||
}
|
||||
}
|
||||
|
||||
worldIn.updateComparatorOutputLevel(pos, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void execute(IBlockState p_193387_1_, World p_193387_2_, BlockPos p_193387_3_, CommandBlockBaseLogic p_193387_4_, boolean p_193387_5_)
|
||||
{
|
||||
if (p_193387_5_)
|
||||
{
|
||||
p_193387_4_.trigger(p_193387_2_);
|
||||
}
|
||||
else
|
||||
{
|
||||
p_193387_4_.setSuccessCount(0);
|
||||
}
|
||||
|
||||
executeChain(p_193387_2_, p_193387_3_, (EnumFacing)p_193387_1_.getValue(FACING));
|
||||
}
|
||||
|
||||
/**
|
||||
* How many world ticks before ticking
|
||||
*/
|
||||
public int tickRate(World worldIn)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the block is right clicked by a player.
|
||||
*/
|
||||
public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
|
||||
{
|
||||
TileEntity tileentity = worldIn.getTileEntity(pos);
|
||||
|
||||
if (tileentity instanceof TileEntityCommandBlock && playerIn.canUseCommandBlock())
|
||||
{
|
||||
playerIn.displayGuiCommandBlock((TileEntityCommandBlock)tileentity);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasComparatorInputOverride(IBlockState state)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getComparatorInputOverride(IBlockState blockState, World worldIn, BlockPos pos)
|
||||
{
|
||||
TileEntity tileentity = worldIn.getTileEntity(pos);
|
||||
return tileentity instanceof TileEntityCommandBlock ? ((TileEntityCommandBlock)tileentity).getCommandBlockLogic().getSuccessCount() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by ItemBlocks after a block is set in the world, to allow post-place logic
|
||||
*/
|
||||
public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
|
||||
{
|
||||
TileEntity tileentity = worldIn.getTileEntity(pos);
|
||||
|
||||
if (tileentity instanceof TileEntityCommandBlock)
|
||||
{
|
||||
TileEntityCommandBlock tileentitycommandblock = (TileEntityCommandBlock)tileentity;
|
||||
CommandBlockBaseLogic commandblockbaselogic = tileentitycommandblock.getCommandBlockLogic();
|
||||
|
||||
if (stack.hasDisplayName())
|
||||
{
|
||||
commandblockbaselogic.setName(stack.getDisplayName());
|
||||
}
|
||||
|
||||
if (!worldIn.isRemote)
|
||||
{
|
||||
NBTTagCompound nbttagcompound = stack.getTagCompound();
|
||||
|
||||
if (nbttagcompound == null || !nbttagcompound.hasKey("BlockEntityTag", 10))
|
||||
{
|
||||
commandblockbaselogic.setTrackOutput(worldIn.getGameRules().getBoolean("sendCommandFeedback"));
|
||||
tileentitycommandblock.setAuto(this == Blocks.CHAIN_COMMAND_BLOCK);
|
||||
}
|
||||
|
||||
if (tileentitycommandblock.getMode() == TileEntityCommandBlock.Mode.SEQUENCE)
|
||||
{
|
||||
boolean flag = worldIn.isBlockPowered(pos);
|
||||
tileentitycommandblock.setPowered(flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the quantity of items to drop on block destruction.
|
||||
*/
|
||||
public int quantityDropped(Random random)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of render function called. MODEL for mixed tesr and static model, MODELBLOCK_ANIMATED for TESR-only,
|
||||
* LIQUID for vanilla liquids, INVISIBLE to skip all rendering
|
||||
*/
|
||||
public EnumBlockRenderType getRenderType(IBlockState state)
|
||||
{
|
||||
return EnumBlockRenderType.MODEL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given metadata into a BlockState for this Block
|
||||
*/
|
||||
public IBlockState getStateFromMeta(int meta)
|
||||
{
|
||||
return this.getDefaultState().withProperty(FACING, EnumFacing.getFront(meta & 7)).withProperty(CONDITIONAL, Boolean.valueOf((meta & 8) != 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the BlockState into the correct metadata value
|
||||
*/
|
||||
public int getMetaFromState(IBlockState state)
|
||||
{
|
||||
return ((EnumFacing)state.getValue(FACING)).getIndex() | (((Boolean)state.getValue(CONDITIONAL)).booleanValue() ? 8 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blockstate with the given rotation from the passed blockstate. If inapplicable, returns the passed
|
||||
* blockstate.
|
||||
*/
|
||||
public IBlockState withRotation(IBlockState state, Rotation rot)
|
||||
{
|
||||
return state.withProperty(FACING, rot.rotate((EnumFacing)state.getValue(FACING)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blockstate with the given mirror of the passed blockstate. If inapplicable, returns the passed
|
||||
* blockstate.
|
||||
*/
|
||||
public IBlockState withMirror(IBlockState state, Mirror mirrorIn)
|
||||
{
|
||||
return state.withRotation(mirrorIn.toRotation((EnumFacing)state.getValue(FACING)));
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {FACING, CONDITIONAL});
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by ItemBlocks just before a block is actually set in the world, to allow for adjustments to the
|
||||
* IBlockstate
|
||||
*/
|
||||
public IBlockState getStateForPlacement(World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer)
|
||||
{
|
||||
return this.getDefaultState().withProperty(FACING, EnumFacing.getDirectionFromEntityLiving(pos, placer)).withProperty(CONDITIONAL, Boolean.valueOf(false));
|
||||
}
|
||||
|
||||
private static void executeChain(World p_193386_0_, BlockPos p_193386_1_, EnumFacing p_193386_2_)
|
||||
{
|
||||
BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos(p_193386_1_);
|
||||
GameRules gamerules = p_193386_0_.getGameRules();
|
||||
int i;
|
||||
IBlockState iblockstate;
|
||||
|
||||
for (i = gamerules.getInt("maxCommandChainLength"); i-- > 0; p_193386_2_ = (EnumFacing)iblockstate.getValue(FACING))
|
||||
{
|
||||
blockpos$mutableblockpos.move(p_193386_2_);
|
||||
iblockstate = p_193386_0_.getBlockState(blockpos$mutableblockpos);
|
||||
Block block = iblockstate.getBlock();
|
||||
|
||||
if (block != Blocks.CHAIN_COMMAND_BLOCK)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
TileEntity tileentity = p_193386_0_.getTileEntity(blockpos$mutableblockpos);
|
||||
|
||||
if (!(tileentity instanceof TileEntityCommandBlock))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
TileEntityCommandBlock tileentitycommandblock = (TileEntityCommandBlock)tileentity;
|
||||
|
||||
if (tileentitycommandblock.getMode() != TileEntityCommandBlock.Mode.SEQUENCE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (tileentitycommandblock.isPowered() || tileentitycommandblock.isAuto())
|
||||
{
|
||||
CommandBlockBaseLogic commandblockbaselogic = tileentitycommandblock.getCommandBlockLogic();
|
||||
|
||||
if (tileentitycommandblock.setConditionMet())
|
||||
{
|
||||
if (!commandblockbaselogic.trigger(p_193386_0_))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
p_193386_0_.updateComparatorOutputLevel(blockpos$mutableblockpos, block);
|
||||
}
|
||||
else if (tileentitycommandblock.isConditional())
|
||||
{
|
||||
commandblockbaselogic.setSuccessCount(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i <= 0)
|
||||
{
|
||||
int j = Math.max(gamerules.getInt("maxCommandChainLength"), 0);
|
||||
LOGGER.warn("Commandblock chain tried to execure more than " + j + " steps!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import net.minecraft.block.material.MapColor;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
|
||||
public class BlockCompressedPowered extends Block
|
||||
{
|
||||
public BlockCompressedPowered(Material materialIn, MapColor color)
|
||||
{
|
||||
super(materialIn, color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Can this block provide power. Only wire currently seems to have this change based on its state.
|
||||
*/
|
||||
public boolean canProvidePower(IBlockState state)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getWeakPower(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side)
|
||||
{
|
||||
return 15;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import net.minecraft.block.material.MapColor;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.properties.PropertyEnum;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.EnumDyeColor;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class BlockConcretePowder extends BlockFalling
|
||||
{
|
||||
public static final PropertyEnum<EnumDyeColor> COLOR = PropertyEnum.<EnumDyeColor>create("color", EnumDyeColor.class);
|
||||
|
||||
public BlockConcretePowder()
|
||||
{
|
||||
super(Material.SAND);
|
||||
this.setDefaultState(this.blockState.getBaseState().withProperty(COLOR, EnumDyeColor.WHITE));
|
||||
this.setCreativeTab(CreativeTabs.BUILDING_BLOCKS);
|
||||
}
|
||||
|
||||
public void onEndFalling(World worldIn, BlockPos pos, IBlockState p_176502_3_, IBlockState p_176502_4_)
|
||||
{
|
||||
if (p_176502_4_.getMaterial().isLiquid())
|
||||
{
|
||||
worldIn.setBlockState(pos, Blocks.CONCRETE.getDefaultState().withProperty(BlockColored.COLOR, p_176502_3_.getValue(COLOR)), 3);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean tryTouchWater(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
boolean flag = false;
|
||||
|
||||
for (EnumFacing enumfacing : EnumFacing.values())
|
||||
{
|
||||
if (enumfacing != EnumFacing.DOWN)
|
||||
{
|
||||
BlockPos blockpos = pos.offset(enumfacing);
|
||||
|
||||
if (worldIn.getBlockState(blockpos).getMaterial() == Material.WATER)
|
||||
{
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flag)
|
||||
{
|
||||
worldIn.setBlockState(pos, Blocks.CONCRETE.getDefaultState().withProperty(BlockColored.COLOR, state.getValue(COLOR)), 3);
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a neighboring block was changed and marks that this state should perform any checks during a neighbor
|
||||
* change. Cases may include when redstone power is updated, cactus blocks popping off due to a neighboring solid
|
||||
* block, etc.
|
||||
*/
|
||||
public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos)
|
||||
{
|
||||
if (!this.tryTouchWater(worldIn, pos, state))
|
||||
{
|
||||
super.neighborChanged(state, worldIn, pos, blockIn, fromPos);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the block is set in the Chunk data, but before the Tile Entity is set
|
||||
*/
|
||||
public void onBlockAdded(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
if (!this.tryTouchWater(worldIn, pos, state))
|
||||
{
|
||||
super.onBlockAdded(worldIn, pos, state);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the metadata of the item this Block can drop. This method is called when the block gets destroyed. It
|
||||
* returns the metadata of the dropped item based on the old metadata of the block.
|
||||
*/
|
||||
public int damageDropped(IBlockState state)
|
||||
{
|
||||
return ((EnumDyeColor)state.getValue(COLOR)).getMetadata();
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a list of blocks with the same ID, but different meta (eg: wood returns 4 blocks)
|
||||
*/
|
||||
public void getSubBlocks(CreativeTabs itemIn, NonNullList<ItemStack> items)
|
||||
{
|
||||
for (EnumDyeColor enumdyecolor : EnumDyeColor.values())
|
||||
{
|
||||
items.add(new ItemStack(this, 1, enumdyecolor.getMetadata()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MapColor for this Block and the given BlockState
|
||||
*/
|
||||
public MapColor getMapColor(IBlockState state, IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
return MapColor.getBlockColor((EnumDyeColor)state.getValue(COLOR));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given metadata into a BlockState for this Block
|
||||
*/
|
||||
public IBlockState getStateFromMeta(int meta)
|
||||
{
|
||||
return this.getDefaultState().withProperty(COLOR, EnumDyeColor.byMetadata(meta));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the BlockState into the correct metadata value
|
||||
*/
|
||||
public int getMetaFromState(IBlockState state)
|
||||
{
|
||||
return ((EnumDyeColor)state.getValue(COLOR)).getMetadata();
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {COLOR});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.material.MapColor;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Enchantments;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.stats.StatList;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.EnumBlockRenderType;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IWorldNameable;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public abstract class BlockContainer extends Block implements ITileEntityProvider
|
||||
{
|
||||
protected BlockContainer(Material materialIn)
|
||||
{
|
||||
this(materialIn, materialIn.getMaterialMapColor());
|
||||
}
|
||||
|
||||
protected BlockContainer(Material materialIn, MapColor color)
|
||||
{
|
||||
super(materialIn, color);
|
||||
this.hasTileEntity = true;
|
||||
}
|
||||
|
||||
protected boolean isInvalidNeighbor(World worldIn, BlockPos pos, EnumFacing facing)
|
||||
{
|
||||
return worldIn.getBlockState(pos.offset(facing)).getMaterial() == Material.CACTUS;
|
||||
}
|
||||
|
||||
protected boolean hasInvalidNeighbor(World worldIn, BlockPos pos)
|
||||
{
|
||||
return this.isInvalidNeighbor(worldIn, pos, EnumFacing.NORTH) || this.isInvalidNeighbor(worldIn, pos, EnumFacing.SOUTH) || this.isInvalidNeighbor(worldIn, pos, EnumFacing.WEST) || this.isInvalidNeighbor(worldIn, pos, EnumFacing.EAST);
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of render function called. MODEL for mixed tesr and static model, MODELBLOCK_ANIMATED for TESR-only,
|
||||
* LIQUID for vanilla liquids, INVISIBLE to skip all rendering
|
||||
*/
|
||||
public EnumBlockRenderType getRenderType(IBlockState state)
|
||||
{
|
||||
return EnumBlockRenderType.INVISIBLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called serverside after this block is replaced with another in Chunk, but before the Tile Entity is updated
|
||||
*/
|
||||
public void breakBlock(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
super.breakBlock(worldIn, pos, state);
|
||||
worldIn.removeTileEntity(pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns the block's drops in the world. By the time this is called the Block has possibly been set to air via
|
||||
* Block.removedByPlayer
|
||||
*/
|
||||
public void harvestBlock(World worldIn, EntityPlayer player, BlockPos pos, IBlockState state, @Nullable TileEntity te, ItemStack stack)
|
||||
{
|
||||
if (te instanceof IWorldNameable && ((IWorldNameable)te).hasCustomName())
|
||||
{
|
||||
player.addStat(StatList.getBlockStats(this));
|
||||
player.addExhaustion(0.005F);
|
||||
|
||||
if (worldIn.isRemote)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int i = EnchantmentHelper.getEnchantmentLevel(Enchantments.FORTUNE, stack);
|
||||
Item item = this.getItemDropped(state, worldIn.rand, i);
|
||||
|
||||
if (item == Items.AIR)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack itemstack = new ItemStack(item, this.quantityDropped(worldIn.rand));
|
||||
itemstack.setStackDisplayName(((IWorldNameable)te).getName());
|
||||
spawnAsEntity(worldIn, pos, itemstack);
|
||||
}
|
||||
else
|
||||
{
|
||||
super.harvestBlock(worldIn, player, pos, state, (TileEntity)null, stack);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on server when World#addBlockEvent is called. If server returns true, then also called on the client. On
|
||||
* the Server, this may perform additional changes to the world, like pistons replacing the block with an extended
|
||||
* base. On the client, the update may involve replacing tile entities or effects such as sounds or particles
|
||||
*/
|
||||
public boolean eventReceived(IBlockState state, World worldIn, BlockPos pos, int id, int param)
|
||||
{
|
||||
super.eventReceived(state, worldIn, pos, id, param);
|
||||
TileEntity tileentity = worldIn.getTileEntity(pos);
|
||||
return tileentity == null ? false : tileentity.receiveClientEvent(id, param);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,281 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.Random;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.properties.PropertyInteger;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class BlockCrops extends BlockBush implements IGrowable
|
||||
{
|
||||
public static final PropertyInteger AGE = PropertyInteger.create("age", 0, 7);
|
||||
private static final AxisAlignedBB[] CROPS_AABB = new AxisAlignedBB[] {new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.125D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.25D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.375D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.5D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.625D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.75D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.875D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 1.0D, 1.0D)};
|
||||
|
||||
protected BlockCrops()
|
||||
{
|
||||
this.setDefaultState(this.blockState.getBaseState().withProperty(this.getAgeProperty(), Integer.valueOf(0)));
|
||||
this.setTickRandomly(true);
|
||||
this.setCreativeTab((CreativeTabs)null);
|
||||
this.setHardness(0.0F);
|
||||
this.setSoundType(SoundType.PLANT);
|
||||
this.disableStats();
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
|
||||
{
|
||||
return CROPS_AABB[((Integer)state.getValue(this.getAgeProperty())).intValue()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the block can sustain a Bush
|
||||
*/
|
||||
protected boolean canSustainBush(IBlockState state)
|
||||
{
|
||||
return state.getBlock() == Blocks.FARMLAND;
|
||||
}
|
||||
|
||||
protected PropertyInteger getAgeProperty()
|
||||
{
|
||||
return AGE;
|
||||
}
|
||||
|
||||
public int getMaxAge()
|
||||
{
|
||||
return 7;
|
||||
}
|
||||
|
||||
protected int getAge(IBlockState state)
|
||||
{
|
||||
return ((Integer)state.getValue(this.getAgeProperty())).intValue();
|
||||
}
|
||||
|
||||
public IBlockState withAge(int age)
|
||||
{
|
||||
return this.getDefaultState().withProperty(this.getAgeProperty(), Integer.valueOf(age));
|
||||
}
|
||||
|
||||
public boolean isMaxAge(IBlockState state)
|
||||
{
|
||||
return ((Integer)state.getValue(this.getAgeProperty())).intValue() >= this.getMaxAge();
|
||||
}
|
||||
|
||||
public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand)
|
||||
{
|
||||
super.updateTick(worldIn, pos, state, rand);
|
||||
|
||||
if (!worldIn.isAreaLoaded(pos, 1)) return; // Forge: prevent loading unloaded chunks when checking neighbor's light
|
||||
if (worldIn.getLightFromNeighbors(pos.up()) >= 9)
|
||||
{
|
||||
int i = this.getAge(state);
|
||||
|
||||
if (i < this.getMaxAge())
|
||||
{
|
||||
float f = getGrowthChance(this, worldIn, pos);
|
||||
|
||||
if(net.minecraftforge.common.ForgeHooks.onCropsGrowPre(worldIn, pos, state, rand.nextInt((int)(25.0F / f) + 1) == 0))
|
||||
{
|
||||
worldIn.setBlockState(pos, this.withAge(i + 1), 2);
|
||||
net.minecraftforge.common.ForgeHooks.onCropsGrowPost(worldIn, pos, state, worldIn.getBlockState(pos));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void grow(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
int i = this.getAge(state) + this.getBonemealAgeIncrease(worldIn);
|
||||
int j = this.getMaxAge();
|
||||
|
||||
if (i > j)
|
||||
{
|
||||
i = j;
|
||||
}
|
||||
|
||||
worldIn.setBlockState(pos, this.withAge(i), 2);
|
||||
}
|
||||
|
||||
protected int getBonemealAgeIncrease(World worldIn)
|
||||
{
|
||||
return MathHelper.getInt(worldIn.rand, 2, 5);
|
||||
}
|
||||
|
||||
protected static float getGrowthChance(Block blockIn, World worldIn, BlockPos pos)
|
||||
{
|
||||
float f = 1.0F;
|
||||
BlockPos blockpos = pos.down();
|
||||
|
||||
for (int i = -1; i <= 1; ++i)
|
||||
{
|
||||
for (int j = -1; j <= 1; ++j)
|
||||
{
|
||||
float f1 = 0.0F;
|
||||
IBlockState iblockstate = worldIn.getBlockState(blockpos.add(i, 0, j));
|
||||
|
||||
if (iblockstate.getBlock().canSustainPlant(iblockstate, worldIn, blockpos.add(i, 0, j), net.minecraft.util.EnumFacing.UP, (net.minecraftforge.common.IPlantable)blockIn))
|
||||
{
|
||||
f1 = 1.0F;
|
||||
|
||||
if (iblockstate.getBlock().isFertile(worldIn, blockpos.add(i, 0, j)))
|
||||
{
|
||||
f1 = 3.0F;
|
||||
}
|
||||
}
|
||||
|
||||
if (i != 0 || j != 0)
|
||||
{
|
||||
f1 /= 4.0F;
|
||||
}
|
||||
|
||||
f += f1;
|
||||
}
|
||||
}
|
||||
|
||||
BlockPos blockpos1 = pos.north();
|
||||
BlockPos blockpos2 = pos.south();
|
||||
BlockPos blockpos3 = pos.west();
|
||||
BlockPos blockpos4 = pos.east();
|
||||
boolean flag = blockIn == worldIn.getBlockState(blockpos3).getBlock() || blockIn == worldIn.getBlockState(blockpos4).getBlock();
|
||||
boolean flag1 = blockIn == worldIn.getBlockState(blockpos1).getBlock() || blockIn == worldIn.getBlockState(blockpos2).getBlock();
|
||||
|
||||
if (flag && flag1)
|
||||
{
|
||||
f /= 2.0F;
|
||||
}
|
||||
else
|
||||
{
|
||||
boolean flag2 = blockIn == worldIn.getBlockState(blockpos3.north()).getBlock() || blockIn == worldIn.getBlockState(blockpos4.north()).getBlock() || blockIn == worldIn.getBlockState(blockpos4.south()).getBlock() || blockIn == worldIn.getBlockState(blockpos3.south()).getBlock();
|
||||
|
||||
if (flag2)
|
||||
{
|
||||
f /= 2.0F;
|
||||
}
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
public boolean canBlockStay(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
IBlockState soil = worldIn.getBlockState(pos.down());
|
||||
return (worldIn.getLight(pos) >= 8 || worldIn.canSeeSky(pos)) && soil.getBlock().canSustainPlant(soil, worldIn, pos.down(), net.minecraft.util.EnumFacing.UP, this);
|
||||
}
|
||||
|
||||
protected Item getSeed()
|
||||
{
|
||||
return Items.WHEAT_SEEDS;
|
||||
}
|
||||
|
||||
protected Item getCrop()
|
||||
{
|
||||
return Items.WHEAT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getDrops(net.minecraft.util.NonNullList<ItemStack> drops, net.minecraft.world.IBlockAccess world, BlockPos pos, IBlockState state, int fortune)
|
||||
{
|
||||
super.getDrops(drops, world, pos, state, 0);
|
||||
int age = getAge(state);
|
||||
Random rand = world instanceof World ? ((World)world).rand : new Random();
|
||||
|
||||
if (age >= getMaxAge())
|
||||
{
|
||||
int k = 3 + fortune;
|
||||
|
||||
for (int i = 0; i < 3 + fortune; ++i)
|
||||
{
|
||||
if (rand.nextInt(2 * getMaxAge()) <= age)
|
||||
{
|
||||
drops.add(new ItemStack(this.getSeed(), 1, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns this Block's drops into the World as EntityItems.
|
||||
*/
|
||||
public void dropBlockAsItemWithChance(World worldIn, BlockPos pos, IBlockState state, float chance, int fortune)
|
||||
{
|
||||
super.dropBlockAsItemWithChance(worldIn, pos, state, chance, fortune);
|
||||
|
||||
if (false && !worldIn.isRemote) // Forge: NOP all this.
|
||||
{
|
||||
int i = this.getAge(state);
|
||||
|
||||
if (i >= this.getMaxAge())
|
||||
{
|
||||
int j = 3 + fortune;
|
||||
|
||||
for (int k = 0; k < j; ++k)
|
||||
{
|
||||
if (worldIn.rand.nextInt(2 * this.getMaxAge()) <= i)
|
||||
{
|
||||
spawnAsEntity(worldIn, pos, new ItemStack(this.getSeed()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Item that this Block should drop when harvested.
|
||||
*/
|
||||
public Item getItemDropped(IBlockState state, Random rand, int fortune)
|
||||
{
|
||||
return this.isMaxAge(state) ? this.getCrop() : this.getSeed();
|
||||
}
|
||||
|
||||
public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
return new ItemStack(this.getSeed());
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this IGrowable can grow
|
||||
*/
|
||||
public boolean canGrow(World worldIn, BlockPos pos, IBlockState state, boolean isClient)
|
||||
{
|
||||
return !this.isMaxAge(state);
|
||||
}
|
||||
|
||||
public boolean canUseBonemeal(World worldIn, Random rand, BlockPos pos, IBlockState state)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void grow(World worldIn, Random rand, BlockPos pos, IBlockState state)
|
||||
{
|
||||
this.grow(worldIn, pos, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given metadata into a BlockState for this Block
|
||||
*/
|
||||
public IBlockState getStateFromMeta(int meta)
|
||||
{
|
||||
return this.withAge(meta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the BlockState into the correct metadata value
|
||||
*/
|
||||
public int getMetaFromState(IBlockState state)
|
||||
{
|
||||
return this.getAge(state);
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {AGE});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.Random;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.properties.PropertyInteger;
|
||||
import net.minecraft.block.state.BlockFaceShape;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityDaylightDetector;
|
||||
import net.minecraft.util.EnumBlockRenderType;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.EnumSkyBlock;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class BlockDaylightDetector extends BlockContainer
|
||||
{
|
||||
public static final PropertyInteger POWER = PropertyInteger.create("power", 0, 15);
|
||||
protected static final AxisAlignedBB DAYLIGHT_DETECTOR_AABB = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.375D, 1.0D);
|
||||
private final boolean inverted;
|
||||
|
||||
public BlockDaylightDetector(boolean inverted)
|
||||
{
|
||||
super(Material.WOOD);
|
||||
this.inverted = inverted;
|
||||
this.setDefaultState(this.blockState.getBaseState().withProperty(POWER, Integer.valueOf(0)));
|
||||
this.setCreativeTab(CreativeTabs.REDSTONE);
|
||||
this.setHardness(0.2F);
|
||||
this.setSoundType(SoundType.WOOD);
|
||||
this.setUnlocalizedName("daylightDetector");
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
|
||||
{
|
||||
return DAYLIGHT_DETECTOR_AABB;
|
||||
}
|
||||
|
||||
public int getWeakPower(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side)
|
||||
{
|
||||
return ((Integer)blockState.getValue(POWER)).intValue();
|
||||
}
|
||||
|
||||
public void updatePower(World worldIn, BlockPos pos)
|
||||
{
|
||||
if (worldIn.provider.hasSkyLight())
|
||||
{
|
||||
IBlockState iblockstate = worldIn.getBlockState(pos);
|
||||
int i = worldIn.getLightFor(EnumSkyBlock.SKY, pos) - worldIn.getSkylightSubtracted();
|
||||
float f = worldIn.getCelestialAngleRadians(1.0F);
|
||||
|
||||
if (this.inverted)
|
||||
{
|
||||
i = 15 - i;
|
||||
}
|
||||
|
||||
if (i > 0 && !this.inverted)
|
||||
{
|
||||
float f1 = f < (float)Math.PI ? 0.0F : ((float)Math.PI * 2F);
|
||||
f = f + (f1 - f) * 0.2F;
|
||||
i = Math.round((float)i * MathHelper.cos(f));
|
||||
}
|
||||
|
||||
i = MathHelper.clamp(i, 0, 15);
|
||||
|
||||
if (((Integer)iblockstate.getValue(POWER)).intValue() != i)
|
||||
{
|
||||
worldIn.setBlockState(pos, iblockstate.withProperty(POWER, Integer.valueOf(i)), 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the block is right clicked by a player.
|
||||
*/
|
||||
public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
|
||||
{
|
||||
if (playerIn.isAllowEdit())
|
||||
{
|
||||
if (worldIn.isRemote)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.inverted)
|
||||
{
|
||||
worldIn.setBlockState(pos, Blocks.DAYLIGHT_DETECTOR.getDefaultState().withProperty(POWER, state.getValue(POWER)), 4);
|
||||
Blocks.DAYLIGHT_DETECTOR.updatePower(worldIn, pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
worldIn.setBlockState(pos, Blocks.DAYLIGHT_DETECTOR_INVERTED.getDefaultState().withProperty(POWER, state.getValue(POWER)), 4);
|
||||
Blocks.DAYLIGHT_DETECTOR_INVERTED.updatePower(worldIn, pos);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return super.onBlockActivated(worldIn, pos, state, playerIn, hand, facing, hitX, hitY, hitZ);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Item that this Block should drop when harvested.
|
||||
*/
|
||||
public Item getItemDropped(IBlockState state, Random rand, int fortune)
|
||||
{
|
||||
return Item.getItemFromBlock(Blocks.DAYLIGHT_DETECTOR);
|
||||
}
|
||||
|
||||
public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
return new ItemStack(Blocks.DAYLIGHT_DETECTOR);
|
||||
}
|
||||
|
||||
public boolean isFullCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine ambient occlusion and culling when rebuilding chunks for render
|
||||
*/
|
||||
public boolean isOpaqueCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of render function called. MODEL for mixed tesr and static model, MODELBLOCK_ANIMATED for TESR-only,
|
||||
* LIQUID for vanilla liquids, INVISIBLE to skip all rendering
|
||||
*/
|
||||
public EnumBlockRenderType getRenderType(IBlockState state)
|
||||
{
|
||||
return EnumBlockRenderType.MODEL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can this block provide power. Only wire currently seems to have this change based on its state.
|
||||
*/
|
||||
public boolean canProvidePower(IBlockState state)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new instance of a block's tile entity class. Called on placing the block.
|
||||
*/
|
||||
public TileEntity createNewTileEntity(World worldIn, int meta)
|
||||
{
|
||||
return new TileEntityDaylightDetector();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given metadata into a BlockState for this Block
|
||||
*/
|
||||
public IBlockState getStateFromMeta(int meta)
|
||||
{
|
||||
return this.getDefaultState().withProperty(POWER, Integer.valueOf(meta));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the BlockState into the correct metadata value
|
||||
*/
|
||||
public int getMetaFromState(IBlockState state)
|
||||
{
|
||||
return ((Integer)state.getValue(POWER)).intValue();
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {POWER});
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a list of blocks with the same ID, but different meta (eg: wood returns 4 blocks)
|
||||
*/
|
||||
public void getSubBlocks(CreativeTabs itemIn, NonNullList<ItemStack> items)
|
||||
{
|
||||
if (!this.inverted)
|
||||
{
|
||||
super.getSubBlocks(itemIn, items);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the geometry of the queried face at the given position and state. This is used to decide whether things like
|
||||
* buttons are allowed to be placed on the face, or how glass panes connect to the face, among other things.
|
||||
* <p>
|
||||
* Common values are {@code SOLID}, which is the default, and {@code UNDEFINED}, which represents something that
|
||||
* does not fit the other descriptions and will generally cause other things not to connect to the face.
|
||||
*
|
||||
* @return an approximation of the form of the given face
|
||||
*/
|
||||
public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face)
|
||||
{
|
||||
return face == EnumFacing.DOWN ? BlockFaceShape.SOLID : BlockFaceShape.UNDEFINED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.Random;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.material.MapColor;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.stats.StatList;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class BlockDeadBush extends BlockBush implements net.minecraftforge.common.IShearable
|
||||
{
|
||||
protected static final AxisAlignedBB DEAD_BUSH_AABB = new AxisAlignedBB(0.09999999403953552D, 0.0D, 0.09999999403953552D, 0.8999999761581421D, 0.800000011920929D, 0.8999999761581421D);
|
||||
|
||||
protected BlockDeadBush()
|
||||
{
|
||||
super(Material.VINE);
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
|
||||
{
|
||||
return DEAD_BUSH_AABB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MapColor for this Block and the given BlockState
|
||||
*/
|
||||
public MapColor getMapColor(IBlockState state, IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
return MapColor.WOOD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the block can sustain a Bush
|
||||
*/
|
||||
protected boolean canSustainBush(IBlockState state)
|
||||
{
|
||||
return state.getBlock() == Blocks.SAND || state.getBlock() == Blocks.HARDENED_CLAY || state.getBlock() == Blocks.STAINED_HARDENED_CLAY || state.getBlock() == Blocks.DIRT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this Block can be replaced directly by other blocks (true for e.g. tall grass)
|
||||
*/
|
||||
public boolean isReplaceable(IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the quantity of items to drop on block destruction.
|
||||
*/
|
||||
public int quantityDropped(Random random)
|
||||
{
|
||||
return random.nextInt(3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Item that this Block should drop when harvested.
|
||||
*/
|
||||
public Item getItemDropped(IBlockState state, Random rand, int fortune)
|
||||
{
|
||||
return Items.STICK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns the block's drops in the world. By the time this is called the Block has possibly been set to air via
|
||||
* Block.removedByPlayer
|
||||
*/
|
||||
public void harvestBlock(World worldIn, EntityPlayer player, BlockPos pos, IBlockState state, @Nullable TileEntity te, ItemStack stack)
|
||||
{
|
||||
if (!worldIn.isRemote && stack.getItem() == Items.SHEARS)
|
||||
{
|
||||
player.addStat(StatList.getBlockStats(this));
|
||||
spawnAsEntity(worldIn, pos, new ItemStack(Blocks.DEADBUSH, 1, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
super.harvestBlock(worldIn, player, pos, state, te, stack);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public boolean isShearable(ItemStack item, net.minecraft.world.IBlockAccess world, BlockPos pos){ return true; }
|
||||
@Override
|
||||
public java.util.List<ItemStack> onSheared(ItemStack item, net.minecraft.world.IBlockAccess world, BlockPos pos, int fortune)
|
||||
{
|
||||
return java.util.Arrays.asList(new ItemStack(Blocks.DEADBUSH));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.PropertyDirection;
|
||||
|
||||
public abstract class BlockDirectional extends Block
|
||||
{
|
||||
public static final PropertyDirection FACING = PropertyDirection.create("facing");
|
||||
|
||||
protected BlockDirectional(Material materialIn)
|
||||
{
|
||||
super(materialIn);
|
||||
}
|
||||
}
|
||||
174
build/tmp/recompileMc/sources/net/minecraft/block/BlockDirt.java
Normal file
174
build/tmp/recompileMc/sources/net/minecraft/block/BlockDirt.java
Normal file
@@ -0,0 +1,174 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import net.minecraft.block.material.MapColor;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.properties.PropertyBool;
|
||||
import net.minecraft.block.properties.PropertyEnum;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.IStringSerializable;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class BlockDirt extends Block
|
||||
{
|
||||
public static final PropertyEnum<BlockDirt.DirtType> VARIANT = PropertyEnum.<BlockDirt.DirtType>create("variant", BlockDirt.DirtType.class);
|
||||
public static final PropertyBool SNOWY = PropertyBool.create("snowy");
|
||||
|
||||
protected BlockDirt()
|
||||
{
|
||||
super(Material.GROUND);
|
||||
this.setDefaultState(this.blockState.getBaseState().withProperty(VARIANT, BlockDirt.DirtType.DIRT).withProperty(SNOWY, Boolean.valueOf(false)));
|
||||
this.setCreativeTab(CreativeTabs.BUILDING_BLOCKS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MapColor for this Block and the given BlockState
|
||||
*/
|
||||
public MapColor getMapColor(IBlockState state, IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
return ((BlockDirt.DirtType)state.getValue(VARIANT)).getColor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the actual Block state of this Block at the given position. This applies properties not visible in the
|
||||
* metadata, such as fence connections.
|
||||
*/
|
||||
public IBlockState getActualState(IBlockState state, IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
if (state.getValue(VARIANT) == BlockDirt.DirtType.PODZOL)
|
||||
{
|
||||
Block block = worldIn.getBlockState(pos.up()).getBlock();
|
||||
state = state.withProperty(SNOWY, Boolean.valueOf(block == Blocks.SNOW || block == Blocks.SNOW_LAYER));
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a list of blocks with the same ID, but different meta (eg: wood returns 4 blocks)
|
||||
*/
|
||||
public void getSubBlocks(CreativeTabs itemIn, NonNullList<ItemStack> items)
|
||||
{
|
||||
items.add(new ItemStack(this, 1, BlockDirt.DirtType.DIRT.getMetadata()));
|
||||
items.add(new ItemStack(this, 1, BlockDirt.DirtType.COARSE_DIRT.getMetadata()));
|
||||
items.add(new ItemStack(this, 1, BlockDirt.DirtType.PODZOL.getMetadata()));
|
||||
}
|
||||
|
||||
public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
return new ItemStack(this, 1, ((BlockDirt.DirtType)state.getValue(VARIANT)).getMetadata());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given metadata into a BlockState for this Block
|
||||
*/
|
||||
public IBlockState getStateFromMeta(int meta)
|
||||
{
|
||||
return this.getDefaultState().withProperty(VARIANT, BlockDirt.DirtType.byMetadata(meta));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the BlockState into the correct metadata value
|
||||
*/
|
||||
public int getMetaFromState(IBlockState state)
|
||||
{
|
||||
return ((BlockDirt.DirtType)state.getValue(VARIANT)).getMetadata();
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {VARIANT, SNOWY});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the metadata of the item this Block can drop. This method is called when the block gets destroyed. It
|
||||
* returns the metadata of the dropped item based on the old metadata of the block.
|
||||
*/
|
||||
public int damageDropped(IBlockState state)
|
||||
{
|
||||
BlockDirt.DirtType blockdirt$dirttype = (BlockDirt.DirtType)state.getValue(VARIANT);
|
||||
|
||||
if (blockdirt$dirttype == BlockDirt.DirtType.PODZOL)
|
||||
{
|
||||
blockdirt$dirttype = BlockDirt.DirtType.DIRT;
|
||||
}
|
||||
|
||||
return blockdirt$dirttype.getMetadata();
|
||||
}
|
||||
|
||||
public static enum DirtType implements IStringSerializable
|
||||
{
|
||||
DIRT(0, "dirt", "default", MapColor.DIRT),
|
||||
COARSE_DIRT(1, "coarse_dirt", "coarse", MapColor.DIRT),
|
||||
PODZOL(2, "podzol", MapColor.OBSIDIAN);
|
||||
|
||||
private static final BlockDirt.DirtType[] METADATA_LOOKUP = new BlockDirt.DirtType[values().length];
|
||||
private final int metadata;
|
||||
private final String name;
|
||||
private final String unlocalizedName;
|
||||
private final MapColor color;
|
||||
|
||||
private DirtType(int metadataIn, String nameIn, MapColor color)
|
||||
{
|
||||
this(metadataIn, nameIn, nameIn, color);
|
||||
}
|
||||
|
||||
private DirtType(int metadataIn, String nameIn, String unlocalizedNameIn, MapColor color)
|
||||
{
|
||||
this.metadata = metadataIn;
|
||||
this.name = nameIn;
|
||||
this.unlocalizedName = unlocalizedNameIn;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public int getMetadata()
|
||||
{
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
public String getUnlocalizedName()
|
||||
{
|
||||
return this.unlocalizedName;
|
||||
}
|
||||
|
||||
public MapColor getColor()
|
||||
{
|
||||
return this.color;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public static BlockDirt.DirtType byMetadata(int metadata)
|
||||
{
|
||||
if (metadata < 0 || metadata >= METADATA_LOOKUP.length)
|
||||
{
|
||||
metadata = 0;
|
||||
}
|
||||
|
||||
return METADATA_LOOKUP[metadata];
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
static
|
||||
{
|
||||
for (BlockDirt.DirtType blockdirt$dirttype : values())
|
||||
{
|
||||
METADATA_LOOKUP[blockdirt$dirttype.getMetadata()] = blockdirt$dirttype;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,321 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.Random;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.properties.PropertyBool;
|
||||
import net.minecraft.block.properties.PropertyDirection;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.dispenser.BehaviorDefaultDispenseItem;
|
||||
import net.minecraft.dispenser.IBehaviorDispenseItem;
|
||||
import net.minecraft.dispenser.IBlockSource;
|
||||
import net.minecraft.dispenser.IPosition;
|
||||
import net.minecraft.dispenser.PositionImpl;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.inventory.Container;
|
||||
import net.minecraft.inventory.InventoryHelper;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.stats.StatList;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityDispenser;
|
||||
import net.minecraft.tileentity.TileEntityDropper;
|
||||
import net.minecraft.util.EnumBlockRenderType;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.Mirror;
|
||||
import net.minecraft.util.Rotation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.registry.RegistryDefaulted;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class BlockDispenser extends BlockContainer
|
||||
{
|
||||
public static final PropertyDirection FACING = BlockDirectional.FACING;
|
||||
public static final PropertyBool TRIGGERED = PropertyBool.create("triggered");
|
||||
/** Registry for all dispense behaviors. */
|
||||
public static final RegistryDefaulted<Item, IBehaviorDispenseItem> DISPENSE_BEHAVIOR_REGISTRY = new RegistryDefaulted<Item, IBehaviorDispenseItem>(new BehaviorDefaultDispenseItem());
|
||||
protected Random rand = new Random();
|
||||
|
||||
protected BlockDispenser()
|
||||
{
|
||||
super(Material.ROCK);
|
||||
this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH).withProperty(TRIGGERED, Boolean.valueOf(false)));
|
||||
this.setCreativeTab(CreativeTabs.REDSTONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* How many world ticks before ticking
|
||||
*/
|
||||
public int tickRate(World worldIn)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the block is set in the Chunk data, but before the Tile Entity is set
|
||||
*/
|
||||
public void onBlockAdded(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
super.onBlockAdded(worldIn, pos, state);
|
||||
this.setDefaultDirection(worldIn, pos, state);
|
||||
}
|
||||
|
||||
private void setDefaultDirection(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
if (!worldIn.isRemote)
|
||||
{
|
||||
EnumFacing enumfacing = (EnumFacing)state.getValue(FACING);
|
||||
boolean flag = worldIn.getBlockState(pos.north()).isFullBlock();
|
||||
boolean flag1 = worldIn.getBlockState(pos.south()).isFullBlock();
|
||||
|
||||
if (enumfacing == EnumFacing.NORTH && flag && !flag1)
|
||||
{
|
||||
enumfacing = EnumFacing.SOUTH;
|
||||
}
|
||||
else if (enumfacing == EnumFacing.SOUTH && flag1 && !flag)
|
||||
{
|
||||
enumfacing = EnumFacing.NORTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
boolean flag2 = worldIn.getBlockState(pos.west()).isFullBlock();
|
||||
boolean flag3 = worldIn.getBlockState(pos.east()).isFullBlock();
|
||||
|
||||
if (enumfacing == EnumFacing.WEST && flag2 && !flag3)
|
||||
{
|
||||
enumfacing = EnumFacing.EAST;
|
||||
}
|
||||
else if (enumfacing == EnumFacing.EAST && flag3 && !flag2)
|
||||
{
|
||||
enumfacing = EnumFacing.WEST;
|
||||
}
|
||||
}
|
||||
|
||||
worldIn.setBlockState(pos, state.withProperty(FACING, enumfacing).withProperty(TRIGGERED, Boolean.valueOf(false)), 2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the block is right clicked by a player.
|
||||
*/
|
||||
public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
|
||||
{
|
||||
if (worldIn.isRemote)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
TileEntity tileentity = worldIn.getTileEntity(pos);
|
||||
|
||||
if (tileentity instanceof TileEntityDispenser)
|
||||
{
|
||||
playerIn.displayGUIChest((TileEntityDispenser)tileentity);
|
||||
|
||||
if (tileentity instanceof TileEntityDropper)
|
||||
{
|
||||
playerIn.addStat(StatList.DROPPER_INSPECTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
playerIn.addStat(StatList.DISPENSER_INSPECTED);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
protected void dispense(World worldIn, BlockPos pos)
|
||||
{
|
||||
BlockSourceImpl blocksourceimpl = new BlockSourceImpl(worldIn, pos);
|
||||
TileEntityDispenser tileentitydispenser = (TileEntityDispenser)blocksourceimpl.getBlockTileEntity();
|
||||
|
||||
if (tileentitydispenser != null)
|
||||
{
|
||||
int i = tileentitydispenser.getDispenseSlot();
|
||||
|
||||
if (i < 0)
|
||||
{
|
||||
worldIn.playEvent(1001, pos, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ItemStack itemstack = tileentitydispenser.getStackInSlot(i);
|
||||
IBehaviorDispenseItem ibehaviordispenseitem = this.getBehavior(itemstack);
|
||||
|
||||
if (ibehaviordispenseitem != IBehaviorDispenseItem.DEFAULT_BEHAVIOR)
|
||||
{
|
||||
tileentitydispenser.setInventorySlotContents(i, ibehaviordispenseitem.dispense(blocksourceimpl, itemstack));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected IBehaviorDispenseItem getBehavior(ItemStack stack)
|
||||
{
|
||||
return DISPENSE_BEHAVIOR_REGISTRY.getObject(stack.getItem());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a neighboring block was changed and marks that this state should perform any checks during a neighbor
|
||||
* change. Cases may include when redstone power is updated, cactus blocks popping off due to a neighboring solid
|
||||
* block, etc.
|
||||
*/
|
||||
public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos)
|
||||
{
|
||||
boolean flag = worldIn.isBlockPowered(pos) || worldIn.isBlockPowered(pos.up());
|
||||
boolean flag1 = ((Boolean)state.getValue(TRIGGERED)).booleanValue();
|
||||
|
||||
if (flag && !flag1)
|
||||
{
|
||||
worldIn.scheduleUpdate(pos, this, this.tickRate(worldIn));
|
||||
worldIn.setBlockState(pos, state.withProperty(TRIGGERED, Boolean.valueOf(true)), 4);
|
||||
}
|
||||
else if (!flag && flag1)
|
||||
{
|
||||
worldIn.setBlockState(pos, state.withProperty(TRIGGERED, Boolean.valueOf(false)), 4);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand)
|
||||
{
|
||||
if (!worldIn.isRemote)
|
||||
{
|
||||
this.dispense(worldIn, pos);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new instance of a block's tile entity class. Called on placing the block.
|
||||
*/
|
||||
public TileEntity createNewTileEntity(World worldIn, int meta)
|
||||
{
|
||||
return new TileEntityDispenser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by ItemBlocks just before a block is actually set in the world, to allow for adjustments to the
|
||||
* IBlockstate
|
||||
*/
|
||||
public IBlockState getStateForPlacement(World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer)
|
||||
{
|
||||
return this.getDefaultState().withProperty(FACING, EnumFacing.getDirectionFromEntityLiving(pos, placer)).withProperty(TRIGGERED, Boolean.valueOf(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by ItemBlocks after a block is set in the world, to allow post-place logic
|
||||
*/
|
||||
public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
|
||||
{
|
||||
worldIn.setBlockState(pos, state.withProperty(FACING, EnumFacing.getDirectionFromEntityLiving(pos, placer)), 2);
|
||||
|
||||
if (stack.hasDisplayName())
|
||||
{
|
||||
TileEntity tileentity = worldIn.getTileEntity(pos);
|
||||
|
||||
if (tileentity instanceof TileEntityDispenser)
|
||||
{
|
||||
((TileEntityDispenser)tileentity).setCustomName(stack.getDisplayName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called serverside after this block is replaced with another in Chunk, but before the Tile Entity is updated
|
||||
*/
|
||||
public void breakBlock(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
TileEntity tileentity = worldIn.getTileEntity(pos);
|
||||
|
||||
if (tileentity instanceof TileEntityDispenser)
|
||||
{
|
||||
InventoryHelper.dropInventoryItems(worldIn, pos, (TileEntityDispenser)tileentity);
|
||||
worldIn.updateComparatorOutputLevel(pos, this);
|
||||
}
|
||||
|
||||
super.breakBlock(worldIn, pos, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the position where the dispenser at the given Coordinates should dispense to.
|
||||
*/
|
||||
public static IPosition getDispensePosition(IBlockSource coords)
|
||||
{
|
||||
EnumFacing enumfacing = (EnumFacing)coords.getBlockState().getValue(FACING);
|
||||
double d0 = coords.getX() + 0.7D * (double)enumfacing.getFrontOffsetX();
|
||||
double d1 = coords.getY() + 0.7D * (double)enumfacing.getFrontOffsetY();
|
||||
double d2 = coords.getZ() + 0.7D * (double)enumfacing.getFrontOffsetZ();
|
||||
return new PositionImpl(d0, d1, d2);
|
||||
}
|
||||
|
||||
public boolean hasComparatorInputOverride(IBlockState state)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getComparatorInputOverride(IBlockState blockState, World worldIn, BlockPos pos)
|
||||
{
|
||||
return Container.calcRedstone(worldIn.getTileEntity(pos));
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of render function called. MODEL for mixed tesr and static model, MODELBLOCK_ANIMATED for TESR-only,
|
||||
* LIQUID for vanilla liquids, INVISIBLE to skip all rendering
|
||||
*/
|
||||
public EnumBlockRenderType getRenderType(IBlockState state)
|
||||
{
|
||||
return EnumBlockRenderType.MODEL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given metadata into a BlockState for this Block
|
||||
*/
|
||||
public IBlockState getStateFromMeta(int meta)
|
||||
{
|
||||
return this.getDefaultState().withProperty(FACING, EnumFacing.getFront(meta & 7)).withProperty(TRIGGERED, Boolean.valueOf((meta & 8) > 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the BlockState into the correct metadata value
|
||||
*/
|
||||
public int getMetaFromState(IBlockState state)
|
||||
{
|
||||
int i = 0;
|
||||
i = i | ((EnumFacing)state.getValue(FACING)).getIndex();
|
||||
|
||||
if (((Boolean)state.getValue(TRIGGERED)).booleanValue())
|
||||
{
|
||||
i |= 8;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blockstate with the given rotation from the passed blockstate. If inapplicable, returns the passed
|
||||
* blockstate.
|
||||
*/
|
||||
public IBlockState withRotation(IBlockState state, Rotation rot)
|
||||
{
|
||||
return state.withProperty(FACING, rot.rotate((EnumFacing)state.getValue(FACING)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blockstate with the given mirror of the passed blockstate. If inapplicable, returns the passed
|
||||
* blockstate.
|
||||
*/
|
||||
public IBlockState withMirror(IBlockState state, Mirror mirrorIn)
|
||||
{
|
||||
return state.withRotation(mirrorIn.toRotation((EnumFacing)state.getValue(FACING)));
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {FACING, TRIGGERED});
|
||||
}
|
||||
}
|
||||
540
build/tmp/recompileMc/sources/net/minecraft/block/BlockDoor.java
Normal file
540
build/tmp/recompileMc/sources/net/minecraft/block/BlockDoor.java
Normal file
@@ -0,0 +1,540 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.Random;
|
||||
import net.minecraft.block.material.EnumPushReaction;
|
||||
import net.minecraft.block.material.MapColor;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.properties.PropertyBool;
|
||||
import net.minecraft.block.properties.PropertyDirection;
|
||||
import net.minecraft.block.properties.PropertyEnum;
|
||||
import net.minecraft.block.state.BlockFaceShape;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.BlockRenderLayer;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.IStringSerializable;
|
||||
import net.minecraft.util.Mirror;
|
||||
import net.minecraft.util.Rotation;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.translation.I18n;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class BlockDoor extends Block
|
||||
{
|
||||
public static final PropertyDirection FACING = BlockHorizontal.FACING;
|
||||
public static final PropertyBool OPEN = PropertyBool.create("open");
|
||||
public static final PropertyEnum<BlockDoor.EnumHingePosition> HINGE = PropertyEnum.<BlockDoor.EnumHingePosition>create("hinge", BlockDoor.EnumHingePosition.class);
|
||||
public static final PropertyBool POWERED = PropertyBool.create("powered");
|
||||
public static final PropertyEnum<BlockDoor.EnumDoorHalf> HALF = PropertyEnum.<BlockDoor.EnumDoorHalf>create("half", BlockDoor.EnumDoorHalf.class);
|
||||
protected static final AxisAlignedBB SOUTH_AABB = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 1.0D, 0.1875D);
|
||||
protected static final AxisAlignedBB NORTH_AABB = new AxisAlignedBB(0.0D, 0.0D, 0.8125D, 1.0D, 1.0D, 1.0D);
|
||||
protected static final AxisAlignedBB WEST_AABB = new AxisAlignedBB(0.8125D, 0.0D, 0.0D, 1.0D, 1.0D, 1.0D);
|
||||
protected static final AxisAlignedBB EAST_AABB = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 0.1875D, 1.0D, 1.0D);
|
||||
|
||||
protected BlockDoor(Material materialIn)
|
||||
{
|
||||
super(materialIn);
|
||||
this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH).withProperty(OPEN, Boolean.valueOf(false)).withProperty(HINGE, BlockDoor.EnumHingePosition.LEFT).withProperty(POWERED, Boolean.valueOf(false)).withProperty(HALF, BlockDoor.EnumDoorHalf.LOWER));
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
|
||||
{
|
||||
state = state.getActualState(source, pos);
|
||||
EnumFacing enumfacing = (EnumFacing)state.getValue(FACING);
|
||||
boolean flag = !((Boolean)state.getValue(OPEN)).booleanValue();
|
||||
boolean flag1 = state.getValue(HINGE) == BlockDoor.EnumHingePosition.RIGHT;
|
||||
|
||||
switch (enumfacing)
|
||||
{
|
||||
case EAST:
|
||||
default:
|
||||
return flag ? EAST_AABB : (flag1 ? NORTH_AABB : SOUTH_AABB);
|
||||
case SOUTH:
|
||||
return flag ? SOUTH_AABB : (flag1 ? EAST_AABB : WEST_AABB);
|
||||
case WEST:
|
||||
return flag ? WEST_AABB : (flag1 ? SOUTH_AABB : NORTH_AABB);
|
||||
case NORTH:
|
||||
return flag ? NORTH_AABB : (flag1 ? WEST_AABB : EAST_AABB);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the localized name of this block. Used for the statistics page.
|
||||
*/
|
||||
public String getLocalizedName()
|
||||
{
|
||||
return I18n.translateToLocal((this.getUnlocalizedName() + ".name").replaceAll("tile", "item"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine ambient occlusion and culling when rebuilding chunks for render
|
||||
*/
|
||||
public boolean isOpaqueCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if an entity can path through this block
|
||||
*/
|
||||
public boolean isPassable(IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
return isOpen(combineMetadata(worldIn, pos));
|
||||
}
|
||||
|
||||
public boolean isFullCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private int getCloseSound()
|
||||
{
|
||||
return this.blockMaterial == Material.IRON ? 1011 : 1012;
|
||||
}
|
||||
|
||||
private int getOpenSound()
|
||||
{
|
||||
return this.blockMaterial == Material.IRON ? 1005 : 1006;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MapColor for this Block and the given BlockState
|
||||
*/
|
||||
public MapColor getMapColor(IBlockState state, IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
if (state.getBlock() == Blocks.IRON_DOOR)
|
||||
{
|
||||
return MapColor.IRON;
|
||||
}
|
||||
else if (state.getBlock() == Blocks.OAK_DOOR)
|
||||
{
|
||||
return BlockPlanks.EnumType.OAK.getMapColor();
|
||||
}
|
||||
else if (state.getBlock() == Blocks.SPRUCE_DOOR)
|
||||
{
|
||||
return BlockPlanks.EnumType.SPRUCE.getMapColor();
|
||||
}
|
||||
else if (state.getBlock() == Blocks.BIRCH_DOOR)
|
||||
{
|
||||
return BlockPlanks.EnumType.BIRCH.getMapColor();
|
||||
}
|
||||
else if (state.getBlock() == Blocks.JUNGLE_DOOR)
|
||||
{
|
||||
return BlockPlanks.EnumType.JUNGLE.getMapColor();
|
||||
}
|
||||
else if (state.getBlock() == Blocks.ACACIA_DOOR)
|
||||
{
|
||||
return BlockPlanks.EnumType.ACACIA.getMapColor();
|
||||
}
|
||||
else
|
||||
{
|
||||
return state.getBlock() == Blocks.DARK_OAK_DOOR ? BlockPlanks.EnumType.DARK_OAK.getMapColor() : super.getMapColor(state, worldIn, pos);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the block is right clicked by a player.
|
||||
*/
|
||||
public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
|
||||
{
|
||||
if (this.blockMaterial == Material.IRON)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
BlockPos blockpos = state.getValue(HALF) == BlockDoor.EnumDoorHalf.LOWER ? pos : pos.down();
|
||||
IBlockState iblockstate = pos.equals(blockpos) ? state : worldIn.getBlockState(blockpos);
|
||||
|
||||
if (iblockstate.getBlock() != this)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = iblockstate.cycleProperty(OPEN);
|
||||
worldIn.setBlockState(blockpos, state, 10);
|
||||
worldIn.markBlockRangeForRenderUpdate(blockpos, pos);
|
||||
worldIn.playEvent(playerIn, ((Boolean)state.getValue(OPEN)).booleanValue() ? this.getOpenSound() : this.getCloseSound(), pos, 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void toggleDoor(World worldIn, BlockPos pos, boolean open)
|
||||
{
|
||||
IBlockState iblockstate = worldIn.getBlockState(pos);
|
||||
|
||||
if (iblockstate.getBlock() == this)
|
||||
{
|
||||
BlockPos blockpos = iblockstate.getValue(HALF) == BlockDoor.EnumDoorHalf.LOWER ? pos : pos.down();
|
||||
IBlockState iblockstate1 = pos == blockpos ? iblockstate : worldIn.getBlockState(blockpos);
|
||||
|
||||
if (iblockstate1.getBlock() == this && ((Boolean)iblockstate1.getValue(OPEN)).booleanValue() != open)
|
||||
{
|
||||
worldIn.setBlockState(blockpos, iblockstate1.withProperty(OPEN, Boolean.valueOf(open)), 10);
|
||||
worldIn.markBlockRangeForRenderUpdate(blockpos, pos);
|
||||
worldIn.playEvent((EntityPlayer)null, open ? this.getOpenSound() : this.getCloseSound(), pos, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a neighboring block was changed and marks that this state should perform any checks during a neighbor
|
||||
* change. Cases may include when redstone power is updated, cactus blocks popping off due to a neighboring solid
|
||||
* block, etc.
|
||||
*/
|
||||
public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos)
|
||||
{
|
||||
if (state.getValue(HALF) == BlockDoor.EnumDoorHalf.UPPER)
|
||||
{
|
||||
BlockPos blockpos = pos.down();
|
||||
IBlockState iblockstate = worldIn.getBlockState(blockpos);
|
||||
|
||||
if (iblockstate.getBlock() != this)
|
||||
{
|
||||
worldIn.setBlockToAir(pos);
|
||||
}
|
||||
else if (blockIn != this)
|
||||
{
|
||||
iblockstate.neighborChanged(worldIn, blockpos, blockIn, fromPos);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
boolean flag1 = false;
|
||||
BlockPos blockpos1 = pos.up();
|
||||
IBlockState iblockstate1 = worldIn.getBlockState(blockpos1);
|
||||
|
||||
if (iblockstate1.getBlock() != this)
|
||||
{
|
||||
worldIn.setBlockToAir(pos);
|
||||
flag1 = true;
|
||||
}
|
||||
|
||||
if (!worldIn.getBlockState(pos.down()).isSideSolid(worldIn, pos.down(), EnumFacing.UP))
|
||||
{
|
||||
worldIn.setBlockToAir(pos);
|
||||
flag1 = true;
|
||||
|
||||
if (iblockstate1.getBlock() == this)
|
||||
{
|
||||
worldIn.setBlockToAir(blockpos1);
|
||||
}
|
||||
}
|
||||
|
||||
if (flag1)
|
||||
{
|
||||
if (!worldIn.isRemote)
|
||||
{
|
||||
this.dropBlockAsItem(worldIn, pos, state, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
boolean flag = worldIn.isBlockPowered(pos) || worldIn.isBlockPowered(blockpos1);
|
||||
|
||||
if (blockIn != this && (flag || blockIn.getDefaultState().canProvidePower()) && flag != ((Boolean)iblockstate1.getValue(POWERED)).booleanValue())
|
||||
{
|
||||
worldIn.setBlockState(blockpos1, iblockstate1.withProperty(POWERED, Boolean.valueOf(flag)), 2);
|
||||
|
||||
if (flag != ((Boolean)state.getValue(OPEN)).booleanValue())
|
||||
{
|
||||
worldIn.setBlockState(pos, state.withProperty(OPEN, Boolean.valueOf(flag)), 2);
|
||||
worldIn.markBlockRangeForRenderUpdate(pos, pos);
|
||||
worldIn.playEvent((EntityPlayer)null, flag ? this.getOpenSound() : this.getCloseSound(), pos, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Item that this Block should drop when harvested.
|
||||
*/
|
||||
public Item getItemDropped(IBlockState state, Random rand, int fortune)
|
||||
{
|
||||
return state.getValue(HALF) == BlockDoor.EnumDoorHalf.UPPER ? Items.AIR : this.getItem();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this block can be placed exactly at the given position.
|
||||
*/
|
||||
public boolean canPlaceBlockAt(World worldIn, BlockPos pos)
|
||||
{
|
||||
if (pos.getY() >= worldIn.getHeight() - 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
IBlockState state = worldIn.getBlockState(pos.down());
|
||||
return (state.isTopSolid() || state.getBlockFaceShape(worldIn, pos.down(), EnumFacing.UP) == BlockFaceShape.SOLID) && super.canPlaceBlockAt(worldIn, pos) && super.canPlaceBlockAt(worldIn, pos.up());
|
||||
}
|
||||
}
|
||||
|
||||
public EnumPushReaction getMobilityFlag(IBlockState state)
|
||||
{
|
||||
return EnumPushReaction.DESTROY;
|
||||
}
|
||||
|
||||
public static int combineMetadata(IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
IBlockState iblockstate = worldIn.getBlockState(pos);
|
||||
int i = iblockstate.getBlock().getMetaFromState(iblockstate);
|
||||
boolean flag = isTop(i);
|
||||
IBlockState iblockstate1 = worldIn.getBlockState(pos.down());
|
||||
int j = iblockstate1.getBlock().getMetaFromState(iblockstate1);
|
||||
int k = flag ? j : i;
|
||||
IBlockState iblockstate2 = worldIn.getBlockState(pos.up());
|
||||
int l = iblockstate2.getBlock().getMetaFromState(iblockstate2);
|
||||
int i1 = flag ? i : l;
|
||||
boolean flag1 = (i1 & 1) != 0;
|
||||
boolean flag2 = (i1 & 2) != 0;
|
||||
return removeHalfBit(k) | (flag ? 8 : 0) | (flag1 ? 16 : 0) | (flag2 ? 32 : 0);
|
||||
}
|
||||
|
||||
public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
return new ItemStack(this.getItem());
|
||||
}
|
||||
|
||||
private Item getItem()
|
||||
{
|
||||
if (this == Blocks.IRON_DOOR)
|
||||
{
|
||||
return Items.IRON_DOOR;
|
||||
}
|
||||
else if (this == Blocks.SPRUCE_DOOR)
|
||||
{
|
||||
return Items.SPRUCE_DOOR;
|
||||
}
|
||||
else if (this == Blocks.BIRCH_DOOR)
|
||||
{
|
||||
return Items.BIRCH_DOOR;
|
||||
}
|
||||
else if (this == Blocks.JUNGLE_DOOR)
|
||||
{
|
||||
return Items.JUNGLE_DOOR;
|
||||
}
|
||||
else if (this == Blocks.ACACIA_DOOR)
|
||||
{
|
||||
return Items.ACACIA_DOOR;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this == Blocks.DARK_OAK_DOOR ? Items.DARK_OAK_DOOR : Items.OAK_DOOR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before the Block is set to air in the world. Called regardless of if the player's tool can actually
|
||||
* collect this block
|
||||
*/
|
||||
public void onBlockHarvested(World worldIn, BlockPos pos, IBlockState state, EntityPlayer player)
|
||||
{
|
||||
BlockPos blockpos = pos.down();
|
||||
BlockPos blockpos1 = pos.up();
|
||||
|
||||
if (player.capabilities.isCreativeMode && state.getValue(HALF) == BlockDoor.EnumDoorHalf.UPPER && worldIn.getBlockState(blockpos).getBlock() == this)
|
||||
{
|
||||
worldIn.setBlockToAir(blockpos);
|
||||
}
|
||||
|
||||
if (state.getValue(HALF) == BlockDoor.EnumDoorHalf.LOWER && worldIn.getBlockState(blockpos1).getBlock() == this)
|
||||
{
|
||||
if (player.capabilities.isCreativeMode)
|
||||
{
|
||||
worldIn.setBlockToAir(pos);
|
||||
}
|
||||
|
||||
worldIn.setBlockToAir(blockpos1);
|
||||
}
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public BlockRenderLayer getBlockLayer()
|
||||
{
|
||||
return BlockRenderLayer.CUTOUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the actual Block state of this Block at the given position. This applies properties not visible in the
|
||||
* metadata, such as fence connections.
|
||||
*/
|
||||
public IBlockState getActualState(IBlockState state, IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
if (state.getValue(HALF) == BlockDoor.EnumDoorHalf.LOWER)
|
||||
{
|
||||
IBlockState iblockstate = worldIn.getBlockState(pos.up());
|
||||
|
||||
if (iblockstate.getBlock() == this)
|
||||
{
|
||||
state = state.withProperty(HINGE, iblockstate.getValue(HINGE)).withProperty(POWERED, iblockstate.getValue(POWERED));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IBlockState iblockstate1 = worldIn.getBlockState(pos.down());
|
||||
|
||||
if (iblockstate1.getBlock() == this)
|
||||
{
|
||||
state = state.withProperty(FACING, iblockstate1.getValue(FACING)).withProperty(OPEN, iblockstate1.getValue(OPEN));
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blockstate with the given rotation from the passed blockstate. If inapplicable, returns the passed
|
||||
* blockstate.
|
||||
*/
|
||||
public IBlockState withRotation(IBlockState state, Rotation rot)
|
||||
{
|
||||
return state.getValue(HALF) != BlockDoor.EnumDoorHalf.LOWER ? state : state.withProperty(FACING, rot.rotate((EnumFacing)state.getValue(FACING)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blockstate with the given mirror of the passed blockstate. If inapplicable, returns the passed
|
||||
* blockstate.
|
||||
*/
|
||||
public IBlockState withMirror(IBlockState state, Mirror mirrorIn)
|
||||
{
|
||||
return mirrorIn == Mirror.NONE ? state : state.withRotation(mirrorIn.toRotation((EnumFacing)state.getValue(FACING))).cycleProperty(HINGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given metadata into a BlockState for this Block
|
||||
*/
|
||||
public IBlockState getStateFromMeta(int meta)
|
||||
{
|
||||
return (meta & 8) > 0 ? this.getDefaultState().withProperty(HALF, BlockDoor.EnumDoorHalf.UPPER).withProperty(HINGE, (meta & 1) > 0 ? BlockDoor.EnumHingePosition.RIGHT : BlockDoor.EnumHingePosition.LEFT).withProperty(POWERED, Boolean.valueOf((meta & 2) > 0)) : this.getDefaultState().withProperty(HALF, BlockDoor.EnumDoorHalf.LOWER).withProperty(FACING, EnumFacing.getHorizontal(meta & 3).rotateYCCW()).withProperty(OPEN, Boolean.valueOf((meta & 4) > 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the BlockState into the correct metadata value
|
||||
*/
|
||||
public int getMetaFromState(IBlockState state)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (state.getValue(HALF) == BlockDoor.EnumDoorHalf.UPPER)
|
||||
{
|
||||
i = i | 8;
|
||||
|
||||
if (state.getValue(HINGE) == BlockDoor.EnumHingePosition.RIGHT)
|
||||
{
|
||||
i |= 1;
|
||||
}
|
||||
|
||||
if (((Boolean)state.getValue(POWERED)).booleanValue())
|
||||
{
|
||||
i |= 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
i = i | ((EnumFacing)state.getValue(FACING)).rotateY().getHorizontalIndex();
|
||||
|
||||
if (((Boolean)state.getValue(OPEN)).booleanValue())
|
||||
{
|
||||
i |= 4;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
protected static int removeHalfBit(int meta)
|
||||
{
|
||||
return meta & 7;
|
||||
}
|
||||
|
||||
public static boolean isOpen(IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
return isOpen(combineMetadata(worldIn, pos));
|
||||
}
|
||||
|
||||
public static EnumFacing getFacing(IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
return getFacing(combineMetadata(worldIn, pos));
|
||||
}
|
||||
|
||||
public static EnumFacing getFacing(int combinedMeta)
|
||||
{
|
||||
return EnumFacing.getHorizontal(combinedMeta & 3).rotateYCCW();
|
||||
}
|
||||
|
||||
protected static boolean isOpen(int combinedMeta)
|
||||
{
|
||||
return (combinedMeta & 4) != 0;
|
||||
}
|
||||
|
||||
protected static boolean isTop(int meta)
|
||||
{
|
||||
return (meta & 8) != 0;
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {HALF, FACING, OPEN, HINGE, POWERED});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the geometry of the queried face at the given position and state. This is used to decide whether things like
|
||||
* buttons are allowed to be placed on the face, or how glass panes connect to the face, among other things.
|
||||
* <p>
|
||||
* Common values are {@code SOLID}, which is the default, and {@code UNDEFINED}, which represents something that
|
||||
* does not fit the other descriptions and will generally cause other things not to connect to the face.
|
||||
*
|
||||
* @return an approximation of the form of the given face
|
||||
*/
|
||||
public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face)
|
||||
{
|
||||
return BlockFaceShape.UNDEFINED;
|
||||
}
|
||||
|
||||
public static enum EnumDoorHalf implements IStringSerializable
|
||||
{
|
||||
UPPER,
|
||||
LOWER;
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return this.getName();
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return this == UPPER ? "upper" : "lower";
|
||||
}
|
||||
}
|
||||
|
||||
public static enum EnumHingePosition implements IStringSerializable
|
||||
{
|
||||
LEFT,
|
||||
RIGHT;
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return this.getName();
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return this == LEFT ? "left" : "right";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,429 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.Random;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.properties.PropertyEnum;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.stats.StatList;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.IStringSerializable;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class BlockDoublePlant extends BlockBush implements IGrowable, net.minecraftforge.common.IShearable
|
||||
{
|
||||
public static final PropertyEnum<BlockDoublePlant.EnumPlantType> VARIANT = PropertyEnum.<BlockDoublePlant.EnumPlantType>create("variant", BlockDoublePlant.EnumPlantType.class);
|
||||
public static final PropertyEnum<BlockDoublePlant.EnumBlockHalf> HALF = PropertyEnum.<BlockDoublePlant.EnumBlockHalf>create("half", BlockDoublePlant.EnumBlockHalf.class);
|
||||
public static final PropertyEnum<EnumFacing> FACING = BlockHorizontal.FACING;
|
||||
|
||||
public BlockDoublePlant()
|
||||
{
|
||||
super(Material.VINE);
|
||||
this.setDefaultState(this.blockState.getBaseState().withProperty(VARIANT, BlockDoublePlant.EnumPlantType.SUNFLOWER).withProperty(HALF, BlockDoublePlant.EnumBlockHalf.LOWER).withProperty(FACING, EnumFacing.NORTH));
|
||||
this.setHardness(0.0F);
|
||||
this.setSoundType(SoundType.PLANT);
|
||||
this.setUnlocalizedName("doublePlant");
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
|
||||
{
|
||||
return FULL_BLOCK_AABB;
|
||||
}
|
||||
|
||||
private BlockDoublePlant.EnumPlantType getType(IBlockAccess blockAccess, BlockPos pos, IBlockState state)
|
||||
{
|
||||
if (state.getBlock() == this)
|
||||
{
|
||||
state = state.getActualState(blockAccess, pos);
|
||||
return (BlockDoublePlant.EnumPlantType)state.getValue(VARIANT);
|
||||
}
|
||||
else
|
||||
{
|
||||
return BlockDoublePlant.EnumPlantType.FERN;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this block can be placed exactly at the given position.
|
||||
*/
|
||||
public boolean canPlaceBlockAt(World worldIn, BlockPos pos)
|
||||
{
|
||||
return super.canPlaceBlockAt(worldIn, pos) && worldIn.isAirBlock(pos.up());
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this Block can be replaced directly by other blocks (true for e.g. tall grass)
|
||||
*/
|
||||
public boolean isReplaceable(IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
IBlockState iblockstate = worldIn.getBlockState(pos);
|
||||
|
||||
if (iblockstate.getBlock() != this)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
BlockDoublePlant.EnumPlantType blockdoubleplant$enumplanttype = (BlockDoublePlant.EnumPlantType)iblockstate.getActualState(worldIn, pos).getValue(VARIANT);
|
||||
return blockdoubleplant$enumplanttype == BlockDoublePlant.EnumPlantType.FERN || blockdoubleplant$enumplanttype == BlockDoublePlant.EnumPlantType.GRASS;
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkAndDropBlock(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
if (!this.canBlockStay(worldIn, pos, state))
|
||||
{
|
||||
boolean flag = state.getValue(HALF) == BlockDoublePlant.EnumBlockHalf.UPPER;
|
||||
BlockPos blockpos = flag ? pos : pos.up();
|
||||
BlockPos blockpos1 = flag ? pos.down() : pos;
|
||||
Block block = (Block)(flag ? this : worldIn.getBlockState(blockpos).getBlock());
|
||||
Block block1 = (Block)(flag ? worldIn.getBlockState(blockpos1).getBlock() : this);
|
||||
|
||||
if (!flag) this.dropBlockAsItem(worldIn, pos, state, 0); //Forge move above the setting to air.
|
||||
|
||||
if (block == this)
|
||||
{
|
||||
worldIn.setBlockState(blockpos, Blocks.AIR.getDefaultState(), 2);
|
||||
}
|
||||
|
||||
if (block1 == this)
|
||||
{
|
||||
worldIn.setBlockState(blockpos1, Blocks.AIR.getDefaultState(), 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canBlockStay(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
if (state.getBlock() != this) return super.canBlockStay(worldIn, pos, state); //Forge: This function is called during world gen and placement, before this block is set, so if we are not 'here' then assume it's the pre-check.
|
||||
if (state.getValue(HALF) == BlockDoublePlant.EnumBlockHalf.UPPER)
|
||||
{
|
||||
return worldIn.getBlockState(pos.down()).getBlock() == this;
|
||||
}
|
||||
else
|
||||
{
|
||||
IBlockState iblockstate = worldIn.getBlockState(pos.up());
|
||||
return iblockstate.getBlock() == this && super.canBlockStay(worldIn, pos, iblockstate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Item that this Block should drop when harvested.
|
||||
*/
|
||||
public Item getItemDropped(IBlockState state, Random rand, int fortune)
|
||||
{
|
||||
if (state.getValue(HALF) == BlockDoublePlant.EnumBlockHalf.UPPER)
|
||||
{
|
||||
return Items.AIR;
|
||||
}
|
||||
else
|
||||
{
|
||||
BlockDoublePlant.EnumPlantType blockdoubleplant$enumplanttype = (BlockDoublePlant.EnumPlantType)state.getValue(VARIANT);
|
||||
|
||||
if (blockdoubleplant$enumplanttype == BlockDoublePlant.EnumPlantType.FERN)
|
||||
{
|
||||
return Items.AIR;
|
||||
}
|
||||
else if (blockdoubleplant$enumplanttype == BlockDoublePlant.EnumPlantType.GRASS)
|
||||
{
|
||||
return rand.nextInt(8) == 0 ? Items.WHEAT_SEEDS : Items.AIR;
|
||||
}
|
||||
else
|
||||
{
|
||||
return super.getItemDropped(state, rand, fortune);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the metadata of the item this Block can drop. This method is called when the block gets destroyed. It
|
||||
* returns the metadata of the dropped item based on the old metadata of the block.
|
||||
*/
|
||||
public int damageDropped(IBlockState state)
|
||||
{
|
||||
return state.getValue(HALF) != BlockDoublePlant.EnumBlockHalf.UPPER && state.getValue(VARIANT) != BlockDoublePlant.EnumPlantType.GRASS ? ((BlockDoublePlant.EnumPlantType)state.getValue(VARIANT)).getMeta() : 0;
|
||||
}
|
||||
|
||||
public void placeAt(World worldIn, BlockPos lowerPos, BlockDoublePlant.EnumPlantType variant, int flags)
|
||||
{
|
||||
worldIn.setBlockState(lowerPos, this.getDefaultState().withProperty(HALF, BlockDoublePlant.EnumBlockHalf.LOWER).withProperty(VARIANT, variant), flags);
|
||||
worldIn.setBlockState(lowerPos.up(), this.getDefaultState().withProperty(HALF, BlockDoublePlant.EnumBlockHalf.UPPER), flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by ItemBlocks after a block is set in the world, to allow post-place logic
|
||||
*/
|
||||
public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
|
||||
{
|
||||
worldIn.setBlockState(pos.up(), this.getDefaultState().withProperty(HALF, BlockDoublePlant.EnumBlockHalf.UPPER), 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns the block's drops in the world. By the time this is called the Block has possibly been set to air via
|
||||
* Block.removedByPlayer
|
||||
*/
|
||||
public void harvestBlock(World worldIn, EntityPlayer player, BlockPos pos, IBlockState state, @Nullable TileEntity te, ItemStack stack)
|
||||
{
|
||||
{
|
||||
super.harvestBlock(worldIn, player, pos, state, te, stack);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before the Block is set to air in the world. Called regardless of if the player's tool can actually
|
||||
* collect this block
|
||||
*/
|
||||
public void onBlockHarvested(World worldIn, BlockPos pos, IBlockState state, EntityPlayer player)
|
||||
{
|
||||
if (state.getValue(HALF) == BlockDoublePlant.EnumBlockHalf.UPPER)
|
||||
{
|
||||
if (worldIn.getBlockState(pos.down()).getBlock() == this)
|
||||
{
|
||||
if (player.capabilities.isCreativeMode)
|
||||
{
|
||||
worldIn.setBlockToAir(pos.down());
|
||||
}
|
||||
else
|
||||
{
|
||||
IBlockState iblockstate = worldIn.getBlockState(pos.down());
|
||||
BlockDoublePlant.EnumPlantType blockdoubleplant$enumplanttype = (BlockDoublePlant.EnumPlantType)iblockstate.getValue(VARIANT);
|
||||
|
||||
if (blockdoubleplant$enumplanttype != BlockDoublePlant.EnumPlantType.FERN && blockdoubleplant$enumplanttype != BlockDoublePlant.EnumPlantType.GRASS)
|
||||
{
|
||||
worldIn.destroyBlock(pos.down(), true);
|
||||
}
|
||||
else if (worldIn.isRemote)
|
||||
{
|
||||
worldIn.setBlockToAir(pos.down());
|
||||
}
|
||||
else if (!player.getHeldItemMainhand().isEmpty() && player.getHeldItemMainhand().getItem() == Items.SHEARS)
|
||||
{
|
||||
this.onHarvest(worldIn, pos, iblockstate, player);
|
||||
worldIn.setBlockToAir(pos.down());
|
||||
}
|
||||
else
|
||||
{
|
||||
worldIn.destroyBlock(pos.down(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (worldIn.getBlockState(pos.up()).getBlock() == this)
|
||||
{
|
||||
worldIn.setBlockState(pos.up(), Blocks.AIR.getDefaultState(), 2);
|
||||
}
|
||||
|
||||
super.onBlockHarvested(worldIn, pos, state, player);
|
||||
}
|
||||
|
||||
private boolean onHarvest(World worldIn, BlockPos pos, IBlockState state, EntityPlayer player)
|
||||
{
|
||||
BlockDoublePlant.EnumPlantType blockdoubleplant$enumplanttype = (BlockDoublePlant.EnumPlantType)state.getValue(VARIANT);
|
||||
|
||||
if (blockdoubleplant$enumplanttype != BlockDoublePlant.EnumPlantType.FERN && blockdoubleplant$enumplanttype != BlockDoublePlant.EnumPlantType.GRASS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
player.addStat(StatList.getBlockStats(this));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a list of blocks with the same ID, but different meta (eg: wood returns 4 blocks)
|
||||
*/
|
||||
public void getSubBlocks(CreativeTabs itemIn, NonNullList<ItemStack> items)
|
||||
{
|
||||
for (BlockDoublePlant.EnumPlantType blockdoubleplant$enumplanttype : BlockDoublePlant.EnumPlantType.values())
|
||||
{
|
||||
items.add(new ItemStack(this, 1, blockdoubleplant$enumplanttype.getMeta()));
|
||||
}
|
||||
}
|
||||
|
||||
public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
return new ItemStack(this, 1, this.getType(worldIn, pos, state).getMeta());
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this IGrowable can grow
|
||||
*/
|
||||
public boolean canGrow(World worldIn, BlockPos pos, IBlockState state, boolean isClient)
|
||||
{
|
||||
BlockDoublePlant.EnumPlantType blockdoubleplant$enumplanttype = this.getType(worldIn, pos, state);
|
||||
return blockdoubleplant$enumplanttype != BlockDoublePlant.EnumPlantType.GRASS && blockdoubleplant$enumplanttype != BlockDoublePlant.EnumPlantType.FERN;
|
||||
}
|
||||
|
||||
public boolean canUseBonemeal(World worldIn, Random rand, BlockPos pos, IBlockState state)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void grow(World worldIn, Random rand, BlockPos pos, IBlockState state)
|
||||
{
|
||||
spawnAsEntity(worldIn, pos, new ItemStack(this, 1, this.getType(worldIn, pos, state).getMeta()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given metadata into a BlockState for this Block
|
||||
*/
|
||||
public IBlockState getStateFromMeta(int meta)
|
||||
{
|
||||
return (meta & 8) > 0 ? this.getDefaultState().withProperty(HALF, BlockDoublePlant.EnumBlockHalf.UPPER) : this.getDefaultState().withProperty(HALF, BlockDoublePlant.EnumBlockHalf.LOWER).withProperty(VARIANT, BlockDoublePlant.EnumPlantType.byMetadata(meta & 7));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the actual Block state of this Block at the given position. This applies properties not visible in the
|
||||
* metadata, such as fence connections.
|
||||
*/
|
||||
public IBlockState getActualState(IBlockState state, IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
if (state.getValue(HALF) == BlockDoublePlant.EnumBlockHalf.UPPER)
|
||||
{
|
||||
IBlockState iblockstate = worldIn.getBlockState(pos.down());
|
||||
|
||||
if (iblockstate.getBlock() == this)
|
||||
{
|
||||
state = state.withProperty(VARIANT, iblockstate.getValue(VARIANT));
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the BlockState into the correct metadata value
|
||||
*/
|
||||
public int getMetaFromState(IBlockState state)
|
||||
{
|
||||
return state.getValue(HALF) == BlockDoublePlant.EnumBlockHalf.UPPER ? 8 | ((EnumFacing)state.getValue(FACING)).getHorizontalIndex() : ((BlockDoublePlant.EnumPlantType)state.getValue(VARIANT)).getMeta();
|
||||
}
|
||||
|
||||
protected BlockStateContainer createBlockState()
|
||||
{
|
||||
return new BlockStateContainer(this, new IProperty[] {HALF, VARIANT, FACING});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the OffsetType for this Block. Determines if the model is rendered slightly offset.
|
||||
*/
|
||||
public Block.EnumOffsetType getOffsetType()
|
||||
{
|
||||
return Block.EnumOffsetType.XZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShearable(ItemStack item, IBlockAccess world, BlockPos pos)
|
||||
{
|
||||
IBlockState state = world.getBlockState(pos);
|
||||
EnumPlantType type = (EnumPlantType)state.getValue(VARIANT);
|
||||
return state.getValue(HALF) == EnumBlockHalf.LOWER && (type == EnumPlantType.FERN || type == EnumPlantType.GRASS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.List<ItemStack> onSheared(ItemStack item, net.minecraft.world.IBlockAccess world, BlockPos pos, int fortune)
|
||||
{
|
||||
java.util.List<ItemStack> ret = new java.util.ArrayList<ItemStack>();
|
||||
EnumPlantType type = (EnumPlantType)world.getBlockState(pos).getValue(VARIANT);
|
||||
if (type == EnumPlantType.FERN) ret.add(new ItemStack(Blocks.TALLGRASS, 2, BlockTallGrass.EnumType.FERN.getMeta()));
|
||||
if (type == EnumPlantType.GRASS) ret.add(new ItemStack(Blocks.TALLGRASS, 2, BlockTallGrass.EnumType.GRASS.getMeta()));
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static enum EnumBlockHalf implements IStringSerializable
|
||||
{
|
||||
UPPER,
|
||||
LOWER;
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return this.getName();
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return this == UPPER ? "upper" : "lower";
|
||||
}
|
||||
}
|
||||
|
||||
public static enum EnumPlantType implements IStringSerializable
|
||||
{
|
||||
SUNFLOWER(0, "sunflower"),
|
||||
SYRINGA(1, "syringa"),
|
||||
GRASS(2, "double_grass", "grass"),
|
||||
FERN(3, "double_fern", "fern"),
|
||||
ROSE(4, "double_rose", "rose"),
|
||||
PAEONIA(5, "paeonia");
|
||||
|
||||
private static final BlockDoublePlant.EnumPlantType[] META_LOOKUP = new BlockDoublePlant.EnumPlantType[values().length];
|
||||
private final int meta;
|
||||
private final String name;
|
||||
private final String unlocalizedName;
|
||||
|
||||
private EnumPlantType(int meta, String name)
|
||||
{
|
||||
this(meta, name, name);
|
||||
}
|
||||
|
||||
private EnumPlantType(int meta, String name, String unlocalizedName)
|
||||
{
|
||||
this.meta = meta;
|
||||
this.name = name;
|
||||
this.unlocalizedName = unlocalizedName;
|
||||
}
|
||||
|
||||
public int getMeta()
|
||||
{
|
||||
return this.meta;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public static BlockDoublePlant.EnumPlantType byMetadata(int meta)
|
||||
{
|
||||
if (meta < 0 || meta >= META_LOOKUP.length)
|
||||
{
|
||||
meta = 0;
|
||||
}
|
||||
|
||||
return META_LOOKUP[meta];
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public String getUnlocalizedName()
|
||||
{
|
||||
return this.unlocalizedName;
|
||||
}
|
||||
|
||||
static
|
||||
{
|
||||
for (BlockDoublePlant.EnumPlantType blockdoubleplant$enumplanttype : values())
|
||||
{
|
||||
META_LOOKUP[blockdoubleplant$enumplanttype.getMeta()] = blockdoubleplant$enumplanttype;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import net.minecraft.block.state.BlockFaceShape;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
|
||||
public class BlockDoubleStoneSlab extends BlockStoneSlab
|
||||
{
|
||||
public boolean isDouble()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the geometry of the queried face at the given position and state. This is used to decide whether things like
|
||||
* buttons are allowed to be placed on the face, or how glass panes connect to the face, among other things.
|
||||
* <p>
|
||||
* Common values are {@code SOLID}, which is the default, and {@code UNDEFINED}, which represents something that
|
||||
* does not fit the other descriptions and will generally cause other things not to connect to the face.
|
||||
*
|
||||
* @return an approximation of the form of the given face
|
||||
*/
|
||||
public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face)
|
||||
{
|
||||
return BlockFaceShape.SOLID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
public class BlockDoubleStoneSlabNew extends BlockStoneSlabNew
|
||||
{
|
||||
public boolean isDouble()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
public class BlockDoubleWoodSlab extends BlockWoodSlab
|
||||
{
|
||||
public boolean isDouble()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.Random;
|
||||
import net.minecraft.block.material.MapColor;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.BlockFaceShape;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.item.EntityFallingBlock;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.EnumParticleTypes;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class BlockDragonEgg extends Block
|
||||
{
|
||||
protected static final AxisAlignedBB DRAGON_EGG_AABB = new AxisAlignedBB(0.0625D, 0.0D, 0.0625D, 0.9375D, 1.0D, 0.9375D);
|
||||
|
||||
public BlockDragonEgg()
|
||||
{
|
||||
super(Material.DRAGON_EGG, MapColor.BLACK);
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
|
||||
{
|
||||
return DRAGON_EGG_AABB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the block is set in the Chunk data, but before the Tile Entity is set
|
||||
*/
|
||||
public void onBlockAdded(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
worldIn.scheduleUpdate(pos, this, this.tickRate(worldIn));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a neighboring block was changed and marks that this state should perform any checks during a neighbor
|
||||
* change. Cases may include when redstone power is updated, cactus blocks popping off due to a neighboring solid
|
||||
* block, etc.
|
||||
*/
|
||||
public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos)
|
||||
{
|
||||
worldIn.scheduleUpdate(pos, this, this.tickRate(worldIn));
|
||||
}
|
||||
|
||||
public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand)
|
||||
{
|
||||
this.checkFall(worldIn, pos);
|
||||
}
|
||||
|
||||
private void checkFall(World worldIn, BlockPos pos)
|
||||
{
|
||||
if (worldIn.isAirBlock(pos.down()) && BlockFalling.canFallThrough(worldIn.getBlockState(pos.down())) && pos.getY() >= 0)
|
||||
{
|
||||
int i = 32;
|
||||
|
||||
if (!BlockFalling.fallInstantly && worldIn.isAreaLoaded(pos.add(-32, -32, -32), pos.add(32, 32, 32)))
|
||||
{
|
||||
worldIn.spawnEntity(new EntityFallingBlock(worldIn, (double)((float)pos.getX() + 0.5F), (double)pos.getY(), (double)((float)pos.getZ() + 0.5F), this.getDefaultState()));
|
||||
}
|
||||
else
|
||||
{
|
||||
worldIn.setBlockToAir(pos);
|
||||
BlockPos blockpos;
|
||||
|
||||
for (blockpos = pos; worldIn.isAirBlock(blockpos) && BlockFalling.canFallThrough(worldIn.getBlockState(blockpos)) && blockpos.getY() > 0; blockpos = blockpos.down())
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
if (blockpos.getY() > 0)
|
||||
{
|
||||
worldIn.setBlockState(blockpos, this.getDefaultState(), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the block is right clicked by a player.
|
||||
*/
|
||||
public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
|
||||
{
|
||||
this.teleport(worldIn, pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onBlockClicked(World worldIn, BlockPos pos, EntityPlayer playerIn)
|
||||
{
|
||||
this.teleport(worldIn, pos);
|
||||
}
|
||||
|
||||
private void teleport(World worldIn, BlockPos pos)
|
||||
{
|
||||
IBlockState iblockstate = worldIn.getBlockState(pos);
|
||||
|
||||
if (iblockstate.getBlock() == this)
|
||||
{
|
||||
for (int i = 0; i < 1000; ++i)
|
||||
{
|
||||
BlockPos blockpos = pos.add(worldIn.rand.nextInt(16) - worldIn.rand.nextInt(16), worldIn.rand.nextInt(8) - worldIn.rand.nextInt(8), worldIn.rand.nextInt(16) - worldIn.rand.nextInt(16));
|
||||
|
||||
if (worldIn.isAirBlock(blockpos))
|
||||
{
|
||||
if (worldIn.isRemote)
|
||||
{
|
||||
for (int j = 0; j < 128; ++j)
|
||||
{
|
||||
double d0 = worldIn.rand.nextDouble();
|
||||
float f = (worldIn.rand.nextFloat() - 0.5F) * 0.2F;
|
||||
float f1 = (worldIn.rand.nextFloat() - 0.5F) * 0.2F;
|
||||
float f2 = (worldIn.rand.nextFloat() - 0.5F) * 0.2F;
|
||||
double d1 = (double)blockpos.getX() + (double)(pos.getX() - blockpos.getX()) * d0 + (worldIn.rand.nextDouble() - 0.5D) + 0.5D;
|
||||
double d2 = (double)blockpos.getY() + (double)(pos.getY() - blockpos.getY()) * d0 + worldIn.rand.nextDouble() - 0.5D;
|
||||
double d3 = (double)blockpos.getZ() + (double)(pos.getZ() - blockpos.getZ()) * d0 + (worldIn.rand.nextDouble() - 0.5D) + 0.5D;
|
||||
worldIn.spawnParticle(EnumParticleTypes.PORTAL, d1, d2, d3, (double)f, (double)f1, (double)f2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
worldIn.setBlockState(blockpos, iblockstate, 2);
|
||||
worldIn.setBlockToAir(pos);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* How many world ticks before ticking
|
||||
*/
|
||||
public int tickRate(World worldIn)
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine ambient occlusion and culling when rebuilding chunks for render
|
||||
*/
|
||||
public boolean isOpaqueCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isFullCube(IBlockState state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public boolean shouldSideBeRendered(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the geometry of the queried face at the given position and state. This is used to decide whether things like
|
||||
* buttons are allowed to be placed on the face, or how glass panes connect to the face, among other things.
|
||||
* <p>
|
||||
* Common values are {@code SOLID}, which is the default, and {@code UNDEFINED}, which represents something that
|
||||
* does not fit the other descriptions and will generally cause other things not to connect to the face.
|
||||
*
|
||||
* @return an approximation of the form of the given face
|
||||
*/
|
||||
public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face)
|
||||
{
|
||||
return BlockFaceShape.UNDEFINED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import net.minecraft.dispenser.BehaviorDefaultDispenseItem;
|
||||
import net.minecraft.dispenser.IBehaviorDispenseItem;
|
||||
import net.minecraft.inventory.IInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityDispenser;
|
||||
import net.minecraft.tileentity.TileEntityDropper;
|
||||
import net.minecraft.tileentity.TileEntityHopper;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class BlockDropper extends BlockDispenser
|
||||
{
|
||||
private final IBehaviorDispenseItem dropBehavior = new BehaviorDefaultDispenseItem();
|
||||
|
||||
protected IBehaviorDispenseItem getBehavior(ItemStack stack)
|
||||
{
|
||||
return this.dropBehavior;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new instance of a block's tile entity class. Called on placing the block.
|
||||
*/
|
||||
public TileEntity createNewTileEntity(World worldIn, int meta)
|
||||
{
|
||||
return new TileEntityDropper();
|
||||
}
|
||||
|
||||
protected void dispense(World worldIn, BlockPos pos)
|
||||
{
|
||||
BlockSourceImpl blocksourceimpl = new BlockSourceImpl(worldIn, pos);
|
||||
TileEntityDispenser tileentitydispenser = (TileEntityDispenser)blocksourceimpl.getBlockTileEntity();
|
||||
|
||||
if (tileentitydispenser != null)
|
||||
{
|
||||
int i = tileentitydispenser.getDispenseSlot();
|
||||
|
||||
if (i < 0)
|
||||
{
|
||||
worldIn.playEvent(1001, pos, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ItemStack itemstack = tileentitydispenser.getStackInSlot(i);
|
||||
|
||||
if (!itemstack.isEmpty() && net.minecraftforge.items.VanillaInventoryCodeHooks.dropperInsertHook(worldIn, pos, tileentitydispenser, i, itemstack))
|
||||
{
|
||||
EnumFacing enumfacing = (EnumFacing)worldIn.getBlockState(pos).getValue(FACING);
|
||||
BlockPos blockpos = pos.offset(enumfacing);
|
||||
IInventory iinventory = TileEntityHopper.getInventoryAtPosition(worldIn, (double)blockpos.getX(), (double)blockpos.getY(), (double)blockpos.getZ());
|
||||
ItemStack itemstack1;
|
||||
|
||||
if (iinventory == null)
|
||||
{
|
||||
itemstack1 = this.dropBehavior.dispense(blocksourceimpl, itemstack);
|
||||
}
|
||||
else
|
||||
{
|
||||
itemstack1 = TileEntityHopper.putStackInInventoryAllSlots(tileentitydispenser, iinventory, itemstack.copy().splitStack(1), enumfacing.getOpposite());
|
||||
|
||||
if (itemstack1.isEmpty())
|
||||
{
|
||||
itemstack1 = itemstack.copy();
|
||||
itemstack1.shrink(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
itemstack1 = itemstack.copy();
|
||||
}
|
||||
}
|
||||
|
||||
tileentitydispenser.setInventorySlotContents(i, itemstack1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,315 @@
|
||||
package net.minecraft.block;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class BlockDynamicLiquid extends BlockLiquid
|
||||
{
|
||||
int adjacentSourceBlocks;
|
||||
|
||||
protected BlockDynamicLiquid(Material materialIn)
|
||||
{
|
||||
super(materialIn);
|
||||
}
|
||||
|
||||
private void placeStaticBlock(World worldIn, BlockPos pos, IBlockState currentState)
|
||||
{
|
||||
worldIn.setBlockState(pos, getStaticBlock(this.blockMaterial).getDefaultState().withProperty(LEVEL, currentState.getValue(LEVEL)), 2);
|
||||
}
|
||||
|
||||
public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand)
|
||||
{
|
||||
if (!worldIn.isAreaLoaded(pos, this.getSlopeFindDistance(worldIn))) return; // Forge: avoid loading unloaded chunks
|
||||
int i = ((Integer)state.getValue(LEVEL)).intValue();
|
||||
int j = 1;
|
||||
|
||||
if (this.blockMaterial == Material.LAVA && !worldIn.provider.doesWaterVaporize())
|
||||
{
|
||||
j = 2;
|
||||
}
|
||||
|
||||
int k = this.tickRate(worldIn);
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
int l = -100;
|
||||
this.adjacentSourceBlocks = 0;
|
||||
|
||||
for (EnumFacing enumfacing : EnumFacing.Plane.HORIZONTAL)
|
||||
{
|
||||
l = this.checkAdjacentBlock(worldIn, pos.offset(enumfacing), l);
|
||||
}
|
||||
|
||||
int i1 = l + j;
|
||||
|
||||
if (i1 >= 8 || l < 0)
|
||||
{
|
||||
i1 = -1;
|
||||
}
|
||||
|
||||
int j1 = this.getDepth(worldIn.getBlockState(pos.up()));
|
||||
|
||||
if (j1 >= 0)
|
||||
{
|
||||
if (j1 >= 8)
|
||||
{
|
||||
i1 = j1;
|
||||
}
|
||||
else
|
||||
{
|
||||
i1 = j1 + 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.adjacentSourceBlocks >= 2 && net.minecraftforge.event.ForgeEventFactory.canCreateFluidSource(worldIn, pos, state, this.blockMaterial == Material.WATER))
|
||||
{
|
||||
IBlockState iblockstate = worldIn.getBlockState(pos.down());
|
||||
|
||||
if (iblockstate.getMaterial().isSolid())
|
||||
{
|
||||
i1 = 0;
|
||||
}
|
||||
else if (iblockstate.getMaterial() == this.blockMaterial && ((Integer)iblockstate.getValue(LEVEL)).intValue() == 0)
|
||||
{
|
||||
i1 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.blockMaterial == Material.LAVA && i < 8 && i1 < 8 && i1 > i && rand.nextInt(4) != 0)
|
||||
{
|
||||
k *= 4;
|
||||
}
|
||||
|
||||
if (i1 == i)
|
||||
{
|
||||
this.placeStaticBlock(worldIn, pos, state);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = i1;
|
||||
|
||||
if (i1 < 0)
|
||||
{
|
||||
worldIn.setBlockToAir(pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
state = state.withProperty(LEVEL, Integer.valueOf(i1));
|
||||
worldIn.setBlockState(pos, state, 2);
|
||||
worldIn.scheduleUpdate(pos, this, k);
|
||||
worldIn.notifyNeighborsOfStateChange(pos, this, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.placeStaticBlock(worldIn, pos, state);
|
||||
}
|
||||
|
||||
IBlockState iblockstate1 = worldIn.getBlockState(pos.down());
|
||||
|
||||
if (this.canFlowInto(worldIn, pos.down(), iblockstate1))
|
||||
{
|
||||
if (this.blockMaterial == Material.LAVA && worldIn.getBlockState(pos.down()).getMaterial() == Material.WATER)
|
||||
{
|
||||
worldIn.setBlockState(pos.down(), net.minecraftforge.event.ForgeEventFactory.fireFluidPlaceBlockEvent(worldIn, pos.down(), pos, Blocks.STONE.getDefaultState()));
|
||||
this.triggerMixEffects(worldIn, pos.down());
|
||||
return;
|
||||
}
|
||||
|
||||
if (i >= 8)
|
||||
{
|
||||
this.tryFlowInto(worldIn, pos.down(), iblockstate1, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.tryFlowInto(worldIn, pos.down(), iblockstate1, i + 8);
|
||||
}
|
||||
}
|
||||
else if (i >= 0 && (i == 0 || this.isBlocked(worldIn, pos.down(), iblockstate1)))
|
||||
{
|
||||
Set<EnumFacing> set = this.getPossibleFlowDirections(worldIn, pos);
|
||||
int k1 = i + j;
|
||||
|
||||
if (i >= 8)
|
||||
{
|
||||
k1 = 1;
|
||||
}
|
||||
|
||||
if (k1 >= 8)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (EnumFacing enumfacing1 : set)
|
||||
{
|
||||
this.tryFlowInto(worldIn, pos.offset(enumfacing1), worldIn.getBlockState(pos.offset(enumfacing1)), k1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void tryFlowInto(World worldIn, BlockPos pos, IBlockState state, int level)
|
||||
{
|
||||
if (this.canFlowInto(worldIn, pos, state))
|
||||
{
|
||||
if (state.getMaterial() != Material.AIR)
|
||||
{
|
||||
if (this.blockMaterial == Material.LAVA)
|
||||
{
|
||||
this.triggerMixEffects(worldIn, pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (state.getBlock() != Blocks.SNOW_LAYER) //Forge: Vanilla has a 'bug' where snowballs don't drop like every other block. So special case because ewww...
|
||||
state.getBlock().dropBlockAsItem(worldIn, pos, state, 0);
|
||||
}
|
||||
}
|
||||
|
||||
worldIn.setBlockState(pos, this.getDefaultState().withProperty(LEVEL, Integer.valueOf(level)), 3);
|
||||
}
|
||||
}
|
||||
|
||||
private int getSlopeDistance(World worldIn, BlockPos pos, int distance, EnumFacing calculateFlowCost)
|
||||
{
|
||||
int i = 1000;
|
||||
|
||||
for (EnumFacing enumfacing : EnumFacing.Plane.HORIZONTAL)
|
||||
{
|
||||
if (enumfacing != calculateFlowCost)
|
||||
{
|
||||
BlockPos blockpos = pos.offset(enumfacing);
|
||||
IBlockState iblockstate = worldIn.getBlockState(blockpos);
|
||||
|
||||
if (!this.isBlocked(worldIn, blockpos, iblockstate) && (iblockstate.getMaterial() != this.blockMaterial || ((Integer)iblockstate.getValue(LEVEL)).intValue() > 0))
|
||||
{
|
||||
if (!this.isBlocked(worldIn, blockpos.down(), worldIn.getBlockState(blockpos.down())))
|
||||
{
|
||||
return distance;
|
||||
}
|
||||
|
||||
if (distance < this.getSlopeFindDistance(worldIn))
|
||||
{
|
||||
int j = this.getSlopeDistance(worldIn, blockpos, distance + 1, enumfacing.getOpposite());
|
||||
|
||||
if (j < i)
|
||||
{
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
private int getSlopeFindDistance(World worldIn)
|
||||
{
|
||||
return this.blockMaterial == Material.LAVA && !worldIn.provider.doesWaterVaporize() ? 2 : 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a Set of EnumFacing
|
||||
*/
|
||||
private Set<EnumFacing> getPossibleFlowDirections(World worldIn, BlockPos pos)
|
||||
{
|
||||
int i = 1000;
|
||||
Set<EnumFacing> set = EnumSet.<EnumFacing>noneOf(EnumFacing.class);
|
||||
|
||||
for (EnumFacing enumfacing : EnumFacing.Plane.HORIZONTAL)
|
||||
{
|
||||
BlockPos blockpos = pos.offset(enumfacing);
|
||||
IBlockState iblockstate = worldIn.getBlockState(blockpos);
|
||||
|
||||
if (!this.isBlocked(worldIn, blockpos, iblockstate) && (iblockstate.getMaterial() != this.blockMaterial || ((Integer)iblockstate.getValue(LEVEL)).intValue() > 0))
|
||||
{
|
||||
int j;
|
||||
|
||||
if (this.isBlocked(worldIn, blockpos.down(), worldIn.getBlockState(blockpos.down())))
|
||||
{
|
||||
j = this.getSlopeDistance(worldIn, blockpos, 1, enumfacing.getOpposite());
|
||||
}
|
||||
else
|
||||
{
|
||||
j = 0;
|
||||
}
|
||||
|
||||
if (j < i)
|
||||
{
|
||||
set.clear();
|
||||
}
|
||||
|
||||
if (j <= i)
|
||||
{
|
||||
set.add(enumfacing);
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
private boolean isBlocked(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
Block block = state.getBlock(); //Forge: state must be valid for position
|
||||
Material mat = state.getMaterial();
|
||||
|
||||
if (!(block instanceof BlockDoor) && block != Blocks.STANDING_SIGN && block != Blocks.LADDER && block != Blocks.REEDS)
|
||||
{
|
||||
return mat != Material.PORTAL && mat != Material.STRUCTURE_VOID ? mat.blocksMovement() : true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
protected int checkAdjacentBlock(World worldIn, BlockPos pos, int currentMinLevel)
|
||||
{
|
||||
int i = this.getDepth(worldIn.getBlockState(pos));
|
||||
|
||||
if (i < 0)
|
||||
{
|
||||
return currentMinLevel;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
++this.adjacentSourceBlocks;
|
||||
}
|
||||
|
||||
if (i >= 8)
|
||||
{
|
||||
i = 0;
|
||||
}
|
||||
|
||||
return currentMinLevel >= 0 && i >= currentMinLevel ? currentMinLevel : i;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canFlowInto(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
Material material = state.getMaterial();
|
||||
return material != this.blockMaterial && material != Material.LAVA && !this.isBlocked(worldIn, pos, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the block is set in the Chunk data, but before the Tile Entity is set
|
||||
*/
|
||||
public void onBlockAdded(World worldIn, BlockPos pos, IBlockState state)
|
||||
{
|
||||
if (!this.checkForMixing(worldIn, pos, state))
|
||||
{
|
||||
worldIn.scheduleUpdate(pos, this, this.tickRate(worldIn));
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user