Skip to content

Commit

Permalink
Add block/meta and item/meta pair classes (#98)
Browse files Browse the repository at this point in the history
  • Loading branch information
RecursivePineapple authored Jan 9, 2025
1 parent bdf4234 commit 3580876
Show file tree
Hide file tree
Showing 11 changed files with 629 additions and 0 deletions.
83 changes: 83 additions & 0 deletions src/main/java/com/gtnewhorizon/gtnhlib/util/data/BlockMeta.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package com.gtnewhorizon.gtnhlib.util.data;

import java.util.Objects;

import javax.annotation.Nonnull;

import net.minecraft.block.Block;

/**
* A mutable implementation of {@link ImmutableBlockMeta}. If your API should return a mutable pair, return this
* instead. Must follow the same contracts as the immutable version if this is ever upcast to a
* {@link ImmutableBlockMeta} in your API. If this type is exposed instead of the immutable interface, assume that the
* contained values can change.
*/
public class BlockMeta implements ImmutableBlockMeta {

@Nonnull
private Block block;
private int meta;

public BlockMeta(@Nonnull Block block, int meta) {
this.block = block;
this.meta = meta;
}

public BlockMeta(@Nonnull Block block) {
this(block, 0);
}

@Override
@Nonnull
public Block getBlock() {
return block;
}

@Override
public int getBlockMeta() {
return meta;
}

/**
* Note: see the header comment in {@link ImmutableBlockMeta} for this method's contract.
*/
public BlockMeta setBlock(@Nonnull Block block) {
this.block = Objects.requireNonNull(block);

return this;
}

/**
* Note: see the header comment in {@link ImmutableBlockMeta} for this method's contract.
*/
public BlockMeta setBlockMeta(int meta) {
this.meta = meta;

return this;
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + block.hashCode();
result = prime * result + meta;
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
BlockMeta other = (BlockMeta) obj;
if (!block.equals(other.block)) return false;
if (meta != other.meta) return false;
return true;
}

@Override
public String toString() {
return "BlockMeta [block=" + block + ", meta=" + meta + "]";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.gtnewhorizon.gtnhlib.util.data;

import java.util.function.Supplier;

import net.minecraft.block.Block;

/**
* A supplier that provides an Block. This is its own type because superclasses save their generics, allowing the JVM to
* differentiate between functional interfaces at runtime. Without this interface, two methods overloads that accept a
* Supplier with different generics but an otherwise identical method signature would cause a compilation error.
*/
@FunctionalInterface
public interface BlockSupplier extends Supplier<Block> {

}
15 changes: 15 additions & 0 deletions src/main/java/com/gtnewhorizon/gtnhlib/util/data/IMod.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.gtnewhorizon.gtnhlib.util.data;

/**
* An interface for any mod enums. Represents a mod.
*/
public interface IMod {

boolean isModLoaded();

/** Gets the mod id. */
String getID();

/** Gets the mod's resource location prefix. */
String getResourceLocation();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.gtnewhorizon.gtnhlib.util.data;

import javax.annotation.Nonnull;

import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraftforge.oredict.OreDictionary;

/**
* An immutable block-meta pair. This must not be cast down to its mutable version unless you have a very good reason.
* It can be assumed that the values of {@link #getBlock()} and {@link #getBlockMeta()} will never change for this
* object if the object is exposed through an API.
*/
public interface ImmutableBlockMeta {

/**
* The value of this must not change while this object is exposed via an API.
*
* @return The block stored in this pair.
*/
@Nonnull
public Block getBlock();

/**
* The value of this must not change while this object is exposed via an API.
*
* @return The block's metadata stored in this pair. May be {@link OreDictionary#WILDCARD_VALUE}.
*/
public int getBlockMeta();

/**
* Gets the corresponding item for this block. Subclasses may provide a faster implementation.
*/
public default Item getItem() {
return Item.getItemFromBlock(getBlock());
}

/**
* Checks if this pair matches the given block & meta.
*
* @param block The block.
* @param meta The meta. If this parameter or {@link #getBlockMeta()} equals {@link OreDictionary#WILDCARD_VALUE}
* then meta checks are ignored.
* @return Whether this pair matches or not.
*/
public default boolean matches(Block block, int meta) {
return getBlock() == block
&& (meta == OreDictionary.WILDCARD_VALUE || getBlockMeta() == OreDictionary.WILDCARD_VALUE
|| getBlockMeta() == meta);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.gtnewhorizon.gtnhlib.util.data;

import javax.annotation.Nonnull;

import net.minecraft.block.Block;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraftforge.oredict.OreDictionary;

/**
* An immutable item-meta pair. This must not be cast down to its mutable version unless you have a very good reason. It
* can be assumed that the values of {@link #getItem()} and {@link #getItemMeta()} will never change for this object if
* the object is exposed through an API.
*/
public interface ImmutableItemMeta {

/**
* The value of this must not change while this object is exposed via an API.
*
* @return The item stored in this pair.
*/
@Nonnull
public Item getItem();

/**
* The value of this must not change while this object is exposed via an API.
*
* @return The item's metadata stored in this pair. May be {@link OreDictionary#WILDCARD_VALUE}.
*/
public int getItemMeta();

/**
* Gets the corresponding block for this item. Subclasses may provide a faster implementation.
*/
public default Block getBlock() {
return Block.getBlockFromItem(getItem());
}

/**
* Checks if this pair matches the given ItemStack's item and metadata.
*/
public default boolean matches(ItemStack stack) {
if (stack == null) return false;

return matches(stack.getItem(), Items.feather.getDamage(stack));
}

/**
* Checks if this pair matches the given item & meta.
*
* @param Item The item.
* @param meta The meta. If this parameter or {@link #getItemMeta()} equals {@link OreDictionary#WILDCARD_VALUE}
* then meta checks are ignored.
* @return Whether this pair matches or not.
*/
public default boolean matches(Item item, int meta) {
return getItem() == item
&& (meta == OreDictionary.WILDCARD_VALUE || getItemMeta() == OreDictionary.WILDCARD_VALUE
|| getItemMeta() == meta);
}

/** Converts this pair to an ItemStack. */
public default ItemStack toStack(int amount) {
int meta = getItemMeta();

return new ItemStack(getItem(), amount, meta == OreDictionary.WILDCARD_VALUE ? 0 : meta);
}
}
82 changes: 82 additions & 0 deletions src/main/java/com/gtnewhorizon/gtnhlib/util/data/ItemMeta.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.gtnewhorizon.gtnhlib.util.data;

import java.util.Objects;

import javax.annotation.Nonnull;

import net.minecraft.item.Item;

/**
* A mutable implementation of {@link ImmutableItemMeta}. If your API should return a mutable pair, return this instead.
* Must follow the same contracts as the immutable version if this is ever upcast to a {@link ImmutableItemMeta} in your
* API. If this type is exposed instead of the immutable interface, assume that the contained values can change.
*/
public class ItemMeta implements ImmutableItemMeta {

@Nonnull
private Item item;
private int meta;

public ItemMeta(@Nonnull Item item, int meta) {
this.item = item;
this.meta = meta;
}

public ItemMeta(@Nonnull Item item) {
this(item, 0);
}

@Override
@Nonnull
public Item getItem() {
return item;
}

@Override
public int getItemMeta() {
return meta;
}

/**
* Note: see the header comment in {@link ImmutableItemMeta} for this method's contract.
*/
public ItemMeta setItem(@Nonnull Item item) {
this.item = Objects.requireNonNull(item);

return this;
}

/**
* Note: see the header comment in {@link ImmutableItemMeta} for this method's contract.
*/
public ItemMeta setItemMeta(int meta) {
this.meta = meta;

return this;
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + item.hashCode();
result = prime * result + meta;
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
ItemMeta other = (ItemMeta) obj;
if (!item.equals(other.item)) return false;
if (meta != other.meta) return false;
return true;
}

@Override
public String toString() {
return "ItemMeta [item=" + item + ", meta=" + meta + "]";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.gtnewhorizon.gtnhlib.util.data;

import java.util.function.Supplier;

import net.minecraft.item.ItemStack;

/**
* A supplier that provides an ItemStack. This is its own type because superclasses save their generics, allowing the
* JVM to differentiate between functional interfaces at runtime. Without this interface, two methods overloads that
* accept a Supplier with different generics but an otherwise identical method signature would cause a compilation
* error.
*/
@FunctionalInterface
public interface ItemStackSupplier extends Supplier<ItemStack> {

}
15 changes: 15 additions & 0 deletions src/main/java/com/gtnewhorizon/gtnhlib/util/data/ItemSupplier.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.gtnewhorizon.gtnhlib.util.data;

import java.util.function.Supplier;

import net.minecraft.item.Item;

/**
* A supplier that provides an Item. This is its own type because superclasses save their generics, allowing the JVM to
* differentiate between functional interfaces at runtime. Without this interface, two methods overloads that accept a
* Supplier with different generics but an otherwise identical method signature would cause a compilation error.
*/
@FunctionalInterface
public interface ItemSupplier extends Supplier<Item> {

}
Loading

0 comments on commit 3580876

Please sign in to comment.