Skip to content

Instantly share code, notes, and snippets.

@jamierocks
Last active February 12, 2017 13:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jamierocks/c7c20ba0feda1c6f2f798bfd4738ff45 to your computer and use it in GitHub Desktop.
Save jamierocks/c7c20ba0feda1c6f2f798bfd4738ff45 to your computer and use it in GitHub Desktop.
A block builder system for Minecraft Forge. Licensed MIT.
@SubscribeEvent
public static void registerBlocks(RegistryEvent.Register<Block> event) {
// tungsten
registerBlock(event.getRegistry(), UnnamedBlock.oreBuilder()
.identifier("tungsten_ore")
.drop(() -> tungsten, ItemDropBehaviour.Ore.of(1, 3))
.drop(ExpDropBehaviour.of(2, 5))
.build());
registerBlock(event.getRegistry(), UnnamedBlock.builder()
.identifier("tungsten_block")
.build());
// hardened stuff
registerBlock(event.getRegistry(), UnnamedBlock.glassBuilder()
.identifier("hardened_glass")
.hardness(0.75f) // glass hardness is 0.3, this is 1.5x
.resistance(10f) // same as stone
.build());
}
/*
* This file is part of unnamed, licensed under the MIT License (MIT).
*
* Copyright (c) 2017, Jamie Mansfield <https://www.jamierocks.uk/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package uk.jamierocks.mc.unnamed.block;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.Item;
import net.minecraft.util.BlockRenderLayer;
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;
import java.util.function.Supplier;
/**
* An interface used to describe the behaviour for constructing a {@link UnnamedBlock}.
*/
public interface ConstructionBehaviour {
/**
* The default construction behaviour.
*/
ConstructionBehaviour DEFAULT = UnnamedBlock::new;
/**
* The construction behaviour for ores.
*/
ConstructionBehaviour GLASS = new ConstructionBehaviour() {
@Override
public UnnamedBlock construct(String identifier, Material materialIn, Supplier<Item> dropped, ItemDropBehaviour itemDropBehaviour,
ExpDropBehaviour expDropBehaviour) {
return new UnnamedBlock(identifier, materialIn, dropped, itemDropBehaviour, expDropBehaviour) {
@SideOnly(Side.CLIENT)
public BlockRenderLayer getBlockLayer() {
return BlockRenderLayer.TRANSLUCENT;
}
@Override
public boolean isFullCube(IBlockState state) {
return false;
}
@Override
protected boolean canSilkHarvest() {
return true;
}
@Override
public boolean isOpaqueCube(IBlockState state) {
return false;
}
// adapted from BlockGlass#shouldSideBeRendered(IBlockState, IBlockAccess, BlockPos, EnumFacing)
@SideOnly(Side.CLIENT)
public boolean shouldSideBeRendered(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side) {
final IBlockState iblockstate = blockAccess.getBlockState(pos.offset(side));
final Block block = iblockstate.getBlock();
return blockState != iblockstate || block != this && super.shouldSideBeRendered(blockState, blockAccess, pos, side);
}
};
}
};
/**
* Gets a constructed {@link UnnamedBlock} with the given parameters.
*
* @param identifier The block identifier
* @param materialIn The block material
* @param dropped The item dropped by the block
* @param itemDropBehaviour The item drop behaviour
* @param expDropBehaviour The exp drop behaviour
* @return The constructed block
*/
UnnamedBlock construct(String identifier, Material materialIn, Supplier<Item> dropped,
ItemDropBehaviour itemDropBehaviour, ExpDropBehaviour expDropBehaviour);
}
/*
* This file is part of unnamed, licensed under the MIT License (MIT).
*
* Copyright (c) 2017, Jamie Mansfield <https://www.jamierocks.uk/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package uk.jamierocks.mc.unnamed.block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import java.util.Random;
/**
* An interface used to describe the behaviour for exp drops for an {@link UnnamedBlock}.
*/
public interface ExpDropBehaviour {
/**
* The default drop behaviour.
*/
ExpDropBehaviour DEFAULT = of(0);
/**
* Creates a drop behaviour that drops the given exp quantity.
*
* @param quantity The quantity of exp to drop
* @return The drop behaviour
*/
static ExpDropBehaviour of(int quantity) {
return (state, world, pos, fortune) -> quantity;
}
/**
* Creates a drop behaviour that drops based on given exp quantity range.
*
* @param minimum The minimum quantity of exp to drop
* @param maximum The maximum quantity of exp to drop
* @return The drop behaviour
*/
static ExpDropBehaviour of(int minimum, int maximum) {
return (state, world, pos, fortune) -> {
final Random random = world instanceof World ? ((World) world).rand : new Random();
return MathHelper.getInt(random, minimum, maximum);
};
}
/**
* Gets the quantity of exp to be dropped.
*
* @param state The block state
* @param world The world
* @param pos The position
* @param fortune The fortune
* @return The quantity dropped
*/
int getQuantityDropped(IBlockState state, IBlockAccess world, BlockPos pos, int fortune);
}
/*
* This file is part of unnamed, licensed under the MIT License (MIT).
*
* Copyright (c) 2017, Jamie Mansfield <https://www.jamierocks.uk/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package uk.jamierocks.mc.unnamed.block;
import net.minecraft.util.math.MathHelper;
import java.util.Random;
/**
* An interface used to describe the behaviour for item drops for an {@link UnnamedBlock}.
*/
public interface ItemDropBehaviour {
/**
* A drop behaviour for dropping no items.
*/
ItemDropBehaviour DROP_NONE = of(0);
/**
* The default drop behaviour.
*/
ItemDropBehaviour DEFAULT = of(1);
/**
* Creates a drop behaviour that drops the given item quantity.
*
* @param quantity The quantity of items to drop
* @return The drop behaviour
*/
static ItemDropBehaviour of(int quantity) {
return (random) -> quantity;
}
/**
* Creates a drop behaviour that drops based on given item quantity range.
*
* @param minimum The minimum quantity of items to drop
* @param maximum The maximum quantity of items to drop
* @return The drop behaviour
*/
static ItemDropBehaviour of(int minimum, int maximum) {
return (random) -> MathHelper.getInt(random, minimum, maximum);
}
/**
* Gets the quantity of items to be dropped.
*
* @param random The random
* @return The quantity dropped
*/
int getQuantityDropped(Random random);
/**
* Gets the quantity of items to be dropped, with bonus applied.
*
* @param fortune The fortune
* @param random The random
* @return The quantity dropped
*/
default int getQuantityDroppedWithBonus(int fortune, Random random) {
return this.getQuantityDropped(random);
}
interface Ore extends ItemDropBehaviour {
/**
* A drop behaviour for dropping no items.
*/
Ore DROP_NONE = of(0);
/**
* The default drop behaviour.
*/
Ore DEFAULT = of(1);
/**
* Creates a drop behaviour that drops the given item quantity for an ore.
*
* @param quantity The quantity of items to drop
* @return The drop behaviour
*/
static Ore of(int quantity) {
return (random) -> quantity;
}
/**
* Creates a drop behaviour that drops based on given item quantity range for an ore.
*
* @param minimum The minimum quantity of items to drop
* @param maximum The maximum quantity of items to drop
* @return The drop behaviour
*/
static Ore of(int minimum, int maximum) {
return (random) -> MathHelper.getInt(random, minimum, maximum);
}
// based on code from BlockOre#quantityDroppedWithBonus(int, Random)
@Override
default int getQuantityDroppedWithBonus(int fortune, Random random) {
if (fortune > 0) {
int i = random.nextInt(fortune + 2) - 1;
if (i < 0) {
i = 0;
}
return this.getQuantityDropped(random) * (i + 1);
} else {
return this.getQuantityDropped(random);
}
}
}
}
/*
* This file is part of unnamed, licensed under the MIT License (MIT).
*
* Copyright (c) 2017, Jamie Mansfield <https://www.jamierocks.uk/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package uk.jamierocks.mc.unnamed.block;
import static com.google.common.base.Preconditions.checkNotNull;
import net.minecraft.block.Block;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.Item;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import uk.jamierocks.mc.unnamed.UnnamedMod;
import uk.jamierocks.mc.unnamed.util.BlockHelper;
import java.util.Optional;
import java.util.Random;
import java.util.function.Supplier;
/**
* An extension of {@link Block} used by all blocks in Unnamed.
*/
public class UnnamedBlock extends Block {
protected final Supplier<Item> dropped;
protected final ItemDropBehaviour itemDropBehaviour;
protected final ExpDropBehaviour expDropBehaviour;
public UnnamedBlock(String identifier, Material materialIn, Supplier<Item> dropped,
ItemDropBehaviour itemDropBehaviour, ExpDropBehaviour expDropBehaviour) {
super(materialIn);
this.dropped = dropped;
this.itemDropBehaviour = itemDropBehaviour;
this.expDropBehaviour = expDropBehaviour;
BlockHelper.setBlockNames(this, identifier);
this.setCreativeTab(UnnamedMod.creativeTab);
}
@Override
public Item getItemDropped(IBlockState state, Random rand, int fortune) {
if (this.dropped != null) {
return this.dropped.get();
}
return super.getItemDropped(state, rand, fortune);
}
@Override
public int quantityDropped(Random random) {
return this.itemDropBehaviour.getQuantityDropped(random);
}
@Override
public int quantityDroppedWithBonus(int fortune, Random random) {
return this.itemDropBehaviour.getQuantityDroppedWithBonus(fortune, random);
}
@Override
public int getExpDrop(IBlockState state, IBlockAccess world, BlockPos pos, int fortune) {
return this.expDropBehaviour.getQuantityDropped(state, world, pos, fortune);
}
@Override // this is needed for its public access modifier
public Block setSoundType(SoundType sound) {
return super.setSoundType(sound);
}
public static Builder builder() {
return new Builder();
}
public static Builder oreBuilder() {
return new Builder()
.drop(ItemDropBehaviour.Ore.DEFAULT);
}
public static Builder glassBuilder() {
return new Builder(ConstructionBehaviour.GLASS)
.material(Material.GLASS)
.soundType(SoundType.GLASS)
.drop(ItemDropBehaviour.DROP_NONE)
.hardness(0.3f)
.resistance(1.0f);
}
public static class Builder {
private final ConstructionBehaviour defaultConstructionBehaviour;
private String identifier;
private Material material = Material.ROCK;
private Optional<SoundType> soundType = Optional.empty();
private Supplier<Item> drop;
private ItemDropBehaviour itemDropBehaviour = ItemDropBehaviour.DEFAULT;
private ExpDropBehaviour expDropBehaviour = ExpDropBehaviour.DEFAULT;
private Optional<Float> hardness = Optional.empty();
private Optional<Float> resistance = Optional.empty();
private Builder() {
this(ConstructionBehaviour.DEFAULT);
}
private Builder(ConstructionBehaviour defaultConstructionBehaviour) {
this.defaultConstructionBehaviour = defaultConstructionBehaviour;
}
public Builder identifier(String identifier) {
this.identifier = identifier;
return this;
}
public Builder material(Material material) {
this.material = material;
return this;
}
public Builder soundType(SoundType soundType) {
this.soundType = Optional.of(soundType);
return this;
}
public Builder drop(Supplier<Item> drop) {
this.drop = drop;
return this;
}
public Builder drop(ItemDropBehaviour dropBehaviour) {
this.itemDropBehaviour = dropBehaviour;
return this;
}
public Builder drop(ExpDropBehaviour dropBehaviour) {
this.expDropBehaviour = dropBehaviour;
return this;
}
public Builder drop(Supplier<Item> drop, ItemDropBehaviour dropBehaviour) {
this.drop = drop;
this.itemDropBehaviour = dropBehaviour;
return this;
}
public Builder hardness(float hardness) {
this.hardness = Optional.of(hardness);
return this;
}
public Builder resistance(float resistance) {
this.resistance = Optional.of(resistance);
return this;
}
public UnnamedBlock build(ConstructionBehaviour constructionBehaviour) {
checkNotNull(this.identifier, "An identifier is required to build a block!");
final UnnamedBlock block =
constructionBehaviour.construct(this.identifier, this.material, this.drop, this.itemDropBehaviour, this.expDropBehaviour);
this.hardness.ifPresent(block::setHardness);
this.resistance.ifPresent(block::setResistance);
this.soundType.ifPresent(block::setSoundType);
return block;
}
public UnnamedBlock build() {
return this.build(this.defaultConstructionBehaviour);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment