Skip to content

Instantly share code, notes, and snippets.

@pollend
Last active November 30, 2017 16:28
Show Gist options
  • Save pollend/148d45ae964337358887b2ab1d4cfeaf to your computer and use it in GitHub Desktop.
Save pollend/148d45ae964337358887b2ab1d4cfeaf to your computer and use it in GitHub Desktop.
package org.terasology.MyModule.blocks;
import com.google.common.collect.ImmutableSet;
import gnu.trove.map.TByteObjectMap;
import gnu.trove.map.hash.TByteObjectHashMap;
import org.terasology.entitySystem.entity.EntityRef;
import org.terasology.entitySystem.event.ReceiveEvent;
import org.terasology.entitySystem.systems.BaseComponentSystem;
import org.terasology.entitySystem.systems.RegisterMode;
import org.terasology.entitySystem.systems.RegisterSystem;
import org.terasology.math.Side;
import org.terasology.math.SideBitFlag;
import org.terasology.math.geom.Vector3i;
import org.terasology.naming.Name;
import org.terasology.registry.In;
import org.terasology.world.BlockEntityRegistry;
import org.terasology.world.WorldProvider;
import org.terasology.world.block.Block;
import org.terasology.world.block.BlockBuilderHelper;
import org.terasology.world.block.BlockComponent;
import org.terasology.world.block.BlockUri;
import org.terasology.world.block.family.BlockFamily;
import org.terasology.world.block.family.BlockFamilyFactory;
import org.terasology.world.block.family.RegisterBlockFamilyFactory;
import org.terasology.world.block.items.BlockItemComponent;
import org.terasology.world.block.items.OnBlockItemPlaced;
import org.terasology.world.block.loader.BlockFamilyDefinition;
import javax.print.attribute.standard.Sides;
import java.util.Set;
import static com.sun.xml.internal.ws.policy.sourcemodel.wspolicy.XmlToken.Name;
@RegisterBlockFamilyFactory("romancolumn")
@RegisterSystem(RegisterMode.AUTHORITY)
public class RomanColumnFamilyFactory extends BaseComponentSystem implements BlockFamilyFactory {
@In
private WorldProvider worldProvider;
@In
private BlockEntityRegistry blockEntityRegistry;
private static final ImmutableSet<String> BLOCK_NAMES = ImmutableSet.of(
"lone_block",
"on_bottom",
"on_top",
"in_a_line");
public RomanColumnFamilyFactory() {
}
@Override
public BlockFamily createBlockFamily(BlockFamilyDefinition definition, BlockBuilderHelper blockBuilder) {
TByteObjectMap<Block> blocksForConnections = new TByteObjectHashMap<>();
BlockUri blockUri = new BlockUri(definition.getUrn());
// I'm lazy so I'll just hard code all the possible combinations
blocksForConnections.put((byte) 0, makeABlock(definition, blockBuilder,"no_connections",blockUri, (byte) 0));
blocksForConnections.put(SideBitFlag.getSide(Side.TOP), makeABlock(definition, blockBuilder,"on_bottom", blockUri, SideBitFlag.getSide(Side.TOP)));
blocksForConnections.put(SideBitFlag.getSide(Side.BOTTOM), makeABlock(definition, blockBuilder,"on_top", blockUri, SideBitFlag.getSide(Side.BOTTOM)));
blocksForConnections.put(SideBitFlag.getSides(Side.BOTTOM, Side.TOP), makeABlock(definition, blockBuilder,"in_a_line", blockUri, SideBitFlag.getSides(Side.TOP, Side.BOTTOM)));
final Block archetypeBlock = blocksForConnections.get(SideBitFlag.getSides(Side.BOTTOM, Side.TOP));
return new RomanColumnFamily(blockUri, definition.getCategories(),
archetypeBlock, blocksForConnections);
}
@ReceiveEvent()
public void onPlaceBlock(OnBlockItemPlaced event, EntityRef entity) {
BlockComponent blockComponent = event.getPlacedBlock().getComponent(BlockComponent.class);
if (blockComponent == null) {
return;
}
Vector3i targetBlock = blockComponent.getPosition();
processUpdateForBlockLocation(targetBlock);
}
private void processUpdateForBlockLocation(Vector3i blockLocation) {
for (Side side : Side.values()) {
Vector3i neighborLocation = new Vector3i(blockLocation);
neighborLocation.add(side.getVector3i());
if (worldProvider.isBlockRelevant(neighborLocation)) {
Block neighborBlock = worldProvider.getBlock(neighborLocation);
final BlockFamily blockFamily = neighborBlock.getBlockFamily();
if (blockFamily instanceof RomanColumnFamily) {
RomanColumnFamily neighboursFamily = (RomanColumnFamily) blockFamily;
Block neighborBlockAfterUpdate = neighboursFamily.getBlockForNeighborUpdate(worldProvider,blockEntityRegistry,neighborLocation, neighborBlock);
if (neighborBlock != neighborBlockAfterUpdate) {
worldProvider.setBlock(neighborLocation, neighborBlockAfterUpdate);
}
}
}
}
}
private Block makeABlock(BlockFamilyDefinition definition, BlockBuilderHelper blockBuilder,String section, BlockUri blockUri, byte sides) {
Block newBlock = blockBuilder.constructSimpleBlock(definition,section);
newBlock.setUri(new BlockUri(blockUri, new Name(String.valueOf(sides))));
return newBlock;
}
@Override
public Set<String> getSectionNames() {
return BLOCK_NAMES;
}
}
package org.terasology.MyModule.blocks;
import gnu.trove.map.TByteObjectMap;
import org.terasology.math.Side;
import org.terasology.math.SideBitFlag;
import org.terasology.math.geom.Vector3i;
import org.terasology.world.BlockEntityRegistry;
import org.terasology.world.WorldProvider;
import org.terasology.world.block.Block;
import org.terasology.world.block.BlockUri;
import org.terasology.world.block.family.BlockFamily;
import org.terasology.world.block.family.UpdatesWithNeighboursFamily;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class RomanColumnFamily extends UpdatesWithNeighboursFamily {
private TByteObjectMap<Block> blocks;
// Archetype is the base block of the family
// attachmentSide is the side of the block that the block being placed is going to be attached to
public RomanColumnFamily(BlockUri blockUri, List<String> categories, Block archetypeBlock, TByteObjectMap<Block> blocks) {
super(null, blockUri, categories, archetypeBlock, blocks, (byte) 63);
this.blocks = blocks;
}
@Override
public Block getBlockForPlacement(WorldProvider worldProvider, BlockEntityRegistry blockEntityRegistry, Vector3i location, Side attachmentSide, Side direction) {
return getProperBlock(worldProvider, location);
}
@Override
public Block getBlockForNeighborUpdate(WorldProvider worldProvider, BlockEntityRegistry blockEntityRegistry, Vector3i location, Block oldBlock) {
return getProperBlock(worldProvider, location);
}
private Block getProperBlock(WorldProvider worldProvider, Vector3i location) {
byte sides = (byte)0;
for (Side side : new Side[] {Side.TOP, Side.BOTTOM}) {
Vector3i neighborLocation = new Vector3i(location);
neighborLocation.add(side.getVector3i());
if (worldProvider.isBlockRelevant(neighborLocation)) {
Block neighborBlock = worldProvider.getBlock(neighborLocation);
final BlockFamily blockFamily = neighborBlock.getBlockFamily();
if (blockFamily instanceof RomanColumnFamily) {
sides += SidbitFlag.getSide(side);
}
}
}
return blocks.get(sides); // Returns a normal column block
}
}
@pollend
Copy link
Author

pollend commented Nov 30, 2017

 @Override
    public Block getBlockFor(BlockUri blockUri) {
        if (getURI().equals(blockUri.getFamilyUri())) {
            try {
                byte connections = Byte.parseByte(blockUri.getIdentifier().toString().toLowerCase(Locale.ENGLISH));
                return blocks.get(connections);
            } catch (IllegalArgumentException e) {
                return null;
            }
        }
        return null;
    }

this function will get called to verify the URI of the associated block being looked at and since your URI never matches it creates some odd validation problems. you were using the section type for the block when this method was looking at SideBitFlag.

I added the onBlockPlaced event to resolve a neighbor update issue with the placed block. this should be resolved in the blockFamily update in step 2. https://github.com/MovingBlocks/Terasology/blob/c097e8dde466eceb6f1eb4a1774f9d70d7d71a98/engine/src/main/java/org/terasology/world/block/entity/neighbourUpdate/NeighbourBlockFamilyUpdateSystem.java#L75

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment