Skip to content

Instantly share code, notes, and snippets.

@reoseah
Created February 5, 2020 20:58
Show Gist options
  • Save reoseah/e82700d9d9e7cd6aa62872f44ec9085c to your computer and use it in GitHub Desktop.
Save reoseah/e82700d9d9e7cd6aa62872f44ec9085c to your computer and use it in GitHub Desktop.
simple components
package velvet.components;
import org.eclipse.jdt.annotation.Nullable;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockView;
public interface BlockComponentFallback<T> {
@Nullable
T getComponent(BlockState state, BlockView view, BlockPos pos, Direction direction);
}
package velvet.components;
import org.eclipse.jdt.annotation.Nullable;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockView;
public interface BlockWithComponents {
@Nullable
<T> T getComponent(Component<T> component, BlockState state, BlockView view, BlockPos pos, Direction side);
}
package velvet.components;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.Validate;
import net.minecraft.block.BlockState;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockView;
import velvet.components.ItemWithComponents.ItemStackUpdater;
/**
* Component provides a unified interface to work with features of game objects,
* primarily storage and transport of items and fluids, by using different
* overloads of {@linkplain Component#getComponent}, which return an object
* representing and handling a requested feature.
*/
public class Component<T> {
protected final T defaultValue;
protected final List<BlockComponentFallback<T>> blockFallbacks = new ArrayList<>();
public Component(T defaultValue) {
this.defaultValue = defaultValue;
}
public T getDefault() {
return this.defaultValue;
}
public T getComponent(ItemStack stack, ItemStackUpdater updater) {
Item item = stack.getItem();
if (item instanceof ItemWithComponents) {
T component = ((ItemWithComponents) item).getComponent(this, stack, updater);
if (component != null) {
return component;
}
}
return this.defaultValue;
}
public T getComponent(BlockView view, BlockPos pos, Direction direction) {
BlockState state = view.getBlockState(pos);
if (state.getBlock() instanceof BlockWithComponents) {
T component = ((BlockWithComponents) state.getBlock()).getComponent(this, state, view, pos, direction);
if (component != null) {
return component;
}
}
for (BlockComponentFallback<T> provider : this.blockFallbacks) {
T component = provider.getComponent(state, view, pos, direction);
if (component != null) {
return component;
}
}
return this.defaultValue;
}
public void addComponentFallback(BlockComponentFallback<T> provider) {
this.blockFallbacks.add(Validate.notNull(provider));
}
@Override
public final boolean equals(Object obj) {
return this == obj;
}
@Override
public final int hashCode() {
return System.identityHashCode(this);
}
}
package velvet.components;
import org.eclipse.jdt.annotation.Nullable;
import net.minecraft.item.ItemStack;
public interface ItemWithComponents {
@Nullable
<T> T getComponent(Component<T> component, ItemStack stack, ItemStackUpdater updater);
/**
* Functional interface for changing item stack/notifying of its mutation.
* <p>
* Components should **ALWAYS** call it when they mutate their item, otherwise
* changes might be not saved, leading to duplication bugs and other issues.
*/
@FunctionalInterface
public interface ItemStackUpdater {
void updateStack(ItemStack stack);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment