HyCodeYourTale
classpublicPriority 3

StairConnectedBlockRuleSet

com.hypixel.hytale.server.core.universe.world.connectedblocks.builtin.StairConnectedBlockRuleSet

extends ConnectedBlockRuleSet

implements StairLikeConnectedBlockRuleSet

14

Methods

14

Public Methods

8

Fields

1

Constructors

Constants

BuilderCodec<StairConnectedBlockRuleSet>CODEC= BuilderCodec.builder(StairConnectedBlockRuleSet.class, StairConnectedBlockRuleSet::new) .ap...
StringDEFAULT_MATERIAL_NAME= "Stair"
StairConnectedBlockRuleSet.StairType[]VALUES= values()

Constructors

public
StairConnectedBlockRuleSet()

Methods

Public Methods (14)

publicstatic
StairConnectedBlockRuleSet.StairType corner(boolean right)
public
String getMaterialName()
@Nullable@Override
public
BlockType getStairBlockType(StairConnectedBlockRuleSet.StairType stairType)
public
StairConnectedBlockRuleSet.StairType getStairType(int blockId)
@Override
public
StairConnectedBlockRuleSet.StairType getStairType(boolean inverted)
publicstatic
StairConnectedBlockRuleSet.StairType invertedCorner(boolean right)
public
boolean isCorner()
public
boolean isInvertedCorner()
public
boolean isLeft()
public
boolean isRight()
public
boolean onlyUpdateOnPlacement()
@Override
public
com.hypixel.hytale.protocol.ConnectedBlockRuleSet toPacket(BlockTypeAssetMap<String, BlockType> assetMap)
@Nullable@Override
public
com.hypixel.hytale.protocol.StairConnectedBlockRuleSet toProtocol(BlockTypeAssetMap<String, BlockType> assetMap)
public
void updateCachedBlockTypes(BlockType baseBlockType, BlockTypeAssetMap<String, BlockType> assetMap)
@Override

Fields

Protected Fields (1)

protectedObject2IntMap<StairConnectedBlockRuleSet.StairType> stairTypeToBlockId

Private/Package Fields (7)

privateInt2ObjectMap<StairConnectedBlockRuleSet.StairType> blockIdToStairType
privateConnectedBlockOutput cornerLeft
privateConnectedBlockOutput cornerRight
privateConnectedBlockOutput invertedCornerLeft
privateConnectedBlockOutput invertedCornerRight
privateString materialName
privateConnectedBlockOutput straight

Inheritance

Parent
Current
Interface
Child

Use mouse wheel to zoom, drag to pan. Click nodes to navigate.

Related Classes

Source Code

package com.hypixel.hytale.server.core.universe.world.connectedblocks.builtin;

import com.hypixel.hytale.assetstore.map.BlockTypeAssetMap;
import com.hypixel.hytale.codec.Codec;
import com.hypixel.hytale.codec.KeyedCodec;
import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.codec.validation.Validators;
import com.hypixel.hytale.math.util.ChunkUtil;
import com.hypixel.hytale.math.vector.Vector3i;
import com.hypixel.hytale.protocol.ConnectedBlockRuleSetType;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.Rotation;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.RotationTuple;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
import com.hypixel.hytale.server.core.universe.world.connectedblocks.ConnectedBlockRuleSet;
import com.hypixel.hytale.server.core.universe.world.connectedblocks.ConnectedBlocksUtil;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectIntImmutablePair;
import it.unimi.dsi.fastutil.objects.ObjectIntPair;
import java.util.Optional;
import javax.annotation.Nullable;

public class StairConnectedBlockRuleSet extends ConnectedBlockRuleSet implements StairLikeConnectedBlockRuleSet {
   public static final String DEFAULT_MATERIAL_NAME = "Stair";
   public static final BuilderCodec<StairConnectedBlockRuleSet> CODEC = BuilderCodec.builder(StairConnectedBlockRuleSet.class, StairConnectedBlockRuleSet::new)
      .append(new KeyedCodec<>("Straight", ConnectedBlockOutput.CODEC), (ruleSet, output) -> ruleSet.straight = output, ruleSet -> ruleSet.straight)
      .addValidator(Validators.nonNull())
      .add()
      .<ConnectedBlockOutput>append(
         new KeyedCodec<>("Corner_Left", ConnectedBlockOutput.CODEC), (ruleSet, output) -> ruleSet.cornerLeft = output, ruleSet -> ruleSet.cornerLeft
      )
      .addValidator(Validators.nonNull())
      .add()
      .<ConnectedBlockOutput>append(
         new KeyedCodec<>("Corner_Right", ConnectedBlockOutput.CODEC), (ruleSet, output) -> ruleSet.cornerRight = output, ruleSet -> ruleSet.cornerRight
      )
      .addValidator(Validators.nonNull())
      .add()
      .append(
         new KeyedCodec<>("Inverted_Corner_Left", ConnectedBlockOutput.CODEC),
         (ruleSet, output) -> ruleSet.invertedCornerLeft = output,
         ruleSet -> ruleSet.invertedCornerLeft
      )
      .add()
      .append(
         new KeyedCodec<>("Inverted_Corner_Right", ConnectedBlockOutput.CODEC),
         (ruleSet, output) -> ruleSet.invertedCornerRight = output,
         ruleSet -> ruleSet.invertedCornerRight
      )
      .add()
      .append(new KeyedCodec<>("MaterialName", Codec.STRING), (ruleSet, materialName) -> ruleSet.materialName = materialName, ruleSet -> ruleSet.materialName)
      .add()
      .build();
   private ConnectedBlockOutput straight;
   private ConnectedBlockOutput cornerLeft;
   private ConnectedBlockOutput cornerRight;
   private ConnectedBlockOutput invertedCornerLeft;
   private ConnectedBlockOutput invertedCornerRight;
   private String materialName = "Stair";
   private Int2ObjectMap<StairConnectedBlockRuleSet.StairType> blockIdToStairType;
   protected Object2IntMap<StairConnectedBlockRuleSet.StairType> stairTypeToBlockId;

   public StairConnectedBlockRuleSet() {
   }

   @Override
   public boolean onlyUpdateOnPlacement() {
      return false;
   }

   @Override
   public void updateCachedBlockTypes(BlockType baseBlockType, BlockTypeAssetMap<String, BlockType> assetMap) {
      int baseIndex = assetMap.getIndex(baseBlockType.getId());
      Int2ObjectMap<StairConnectedBlockRuleSet.StairType> blockIdToStairType = new Int2ObjectOpenHashMap();
      Object2IntMap<StairConnectedBlockRuleSet.StairType> stairTypeToBlockId = new Object2IntOpenHashMap();
      stairTypeToBlockId.defaultReturnValue(baseIndex);
      ConnectedBlockOutput[] outputs = new ConnectedBlockOutput[]{
         this.straight, this.cornerLeft, this.cornerRight, this.invertedCornerLeft, this.invertedCornerRight
      };
      StairConnectedBlockRuleSet.StairType[] stairTypes = StairConnectedBlockRuleSet.StairType.VALUES;

      for (int i = 0; i < outputs.length; i++) {
         ConnectedBlockOutput output = outputs[i];
         if (output != null) {
            int index = output.resolve(baseBlockType, assetMap);
            if (index != -1) {
               blockIdToStairType.put(index, stairTypes[i]);
               stairTypeToBlockId.put(stairTypes[i], index);
            }
         }
      }

      this.blockIdToStairType = blockIdToStairType;
      this.stairTypeToBlockId = stairTypeToBlockId;
   }

   @Nullable
   protected static ObjectIntPair<StairConnectedBlockRuleSet.StairType> getStairData(World world, Vector3i coordinate, @Nullable String requiredMaterialName) {
      WorldChunk chunk = world.getChunkIfLoaded(ChunkUtil.indexChunkFromBlock(coordinate.x, coordinate.z));
      if (chunk == null) {
         return null;
      } else {
         int filler = chunk.getFiller(coordinate.x, coordinate.y, coordinate.z);
         if (filler != 0) {
            return null;
         } else {
            int blockId = chunk.getBlock(coordinate);
            BlockType blockType = BlockType.getAssetMap().getAsset(blockId);
            if (blockType == null) {
               return null;
            } else if (blockType.getConnectedBlockRuleSet() instanceof StairLikeConnectedBlockRuleSet stairRuleSet) {
               String otherMaterialName = stairRuleSet.getMaterialName();
               if (requiredMaterialName != null && otherMaterialName != null && !requiredMaterialName.equals(otherMaterialName)) {
                  return null;
               } else {
                  StairConnectedBlockRuleSet.StairType stairType = stairRuleSet.getStairType(blockId);
                  if (stairType == null) {
                     return null;
                  } else {
                     int rotation = chunk.getRotationIndex(coordinate.x, coordinate.y, coordinate.z);
                     return new ObjectIntImmutablePair(stairType, rotation);
                  }
               }
            } else {
               return null;
            }
         }
      }
   }

   @Override
   public StairConnectedBlockRuleSet.StairType getStairType(int blockId) {
      return (StairConnectedBlockRuleSet.StairType)this.blockIdToStairType.get(blockId);
   }

   @Nullable
   @Override
   public String getMaterialName() {
      return this.materialName;
   }

   public BlockType getStairBlockType(StairConnectedBlockRuleSet.StairType stairType) {
      if (this.stairTypeToBlockId == null) {
         return null;
      } else {
         int resultingBlockTypeIndex = this.stairTypeToBlockId.getInt(stairType);
         return BlockType.getAssetMap().getAsset(resultingBlockTypeIndex);
      }
   }

   @Override
   public Optional<ConnectedBlocksUtil.ConnectedBlockResult> getConnectedBlockType(
      World world, Vector3i coordinate, BlockType currentBlockType, int rotation, Vector3i placementNormal, boolean isPlacement
   ) {
      RotationTuple currentRotation = RotationTuple.get(rotation);
      Rotation currentYaw = currentRotation.yaw();
      Rotation currentPitch = currentRotation.pitch();
      boolean upsideDown = currentPitch != Rotation.None;
      if (upsideDown) {
         currentYaw = currentYaw.flip();
      }

      Vector3i mutablePos = new Vector3i();
      StairConnectedBlockRuleSet.StairType resultingStair = StairConnectedBlockRuleSet.StairType.STRAIGHT;
      StairConnectedBlockRuleSet.StairConnection frontConnection = getInvertedCornerConnection(world, this, coordinate, mutablePos, currentYaw, upsideDown);
      if (frontConnection != null) {
         resultingStair = frontConnection.getStairType(true);
      }

      StairConnectedBlockRuleSet.StairConnection backConnection = getCornerConnection(world, this, coordinate, mutablePos, rotation, currentYaw, upsideDown, 1);
      if (backConnection != null) {
         resultingStair = backConnection.getStairType(false);
      }

      if (upsideDown) {
         resultingStair = switch (resultingStair) {
            case CORNER_LEFT -> StairConnectedBlockRuleSet.StairType.CORNER_RIGHT;
            case CORNER_RIGHT -> StairConnectedBlockRuleSet.StairType.CORNER_LEFT;
            case INVERTED_CORNER_LEFT -> StairConnectedBlockRuleSet.StairType.INVERTED_CORNER_RIGHT;
            case INVERTED_CORNER_RIGHT -> StairConnectedBlockRuleSet.StairType.INVERTED_CORNER_LEFT;
            default -> resultingStair;
         };
      }

      int resultingBlockTypeIndex = this.stairTypeToBlockId.getInt(resultingStair);
      BlockType resultingBlockType = BlockType.getAssetMap().getAsset(resultingBlockTypeIndex);
      if (resultingBlockType == null) {
         return Optional.empty();
      } else {
         String resultingBlockTypeKey = resultingBlockType.getId();
         return Optional.of(new ConnectedBlocksUtil.ConnectedBlockResult(resultingBlockTypeKey, rotation));
      }
   }

   protected static StairConnectedBlockRuleSet.StairConnection getCornerConnection(
      World world,
      StairLikeConnectedBlockRuleSet currentRuleSet,
      Vector3i coordinate,
      Vector3i mutablePos,
      int rotation,
      Rotation currentYaw,
      boolean upsideDown,
      int width
   ) {
      StairConnectedBlockRuleSet.StairConnection backConnection = null;
      mutablePos.assign(Vector3i.NORTH).scale(width);
      currentYaw.rotateY(mutablePos, mutablePos);
      mutablePos.add(coordinate.x, coordinate.y, coordinate.z);
      ObjectIntPair<StairConnectedBlockRuleSet.StairType> backStair = getStairData(world, mutablePos, currentRuleSet.getMaterialName());
      if (backStair == null && width > 1) {
         mutablePos.assign(Vector3i.NORTH).scale(width + 1);
         currentYaw.rotateY(mutablePos, mutablePos);
         mutablePos.add(coordinate.x, coordinate.y, coordinate.z);
         backStair = getStairData(world, mutablePos, currentRuleSet.getMaterialName());
         if (backStair != null && backStair.first() == StairConnectedBlockRuleSet.StairType.STRAIGHT) {
            backStair = null;
         }
      }

      if (backStair != null) {
         StairConnectedBlockRuleSet.StairType otherStairType = (StairConnectedBlockRuleSet.StairType)backStair.left();
         RotationTuple otherStairRotation = RotationTuple.get(backStair.rightInt());
         Rotation otherYaw = otherStairRotation.yaw();
         boolean otherUpsideDown = otherStairRotation.pitch() != Rotation.None;
         if (otherUpsideDown) {
            otherYaw = otherYaw.flip();
         }

         if (canConnectTo(currentYaw, otherYaw, upsideDown, otherUpsideDown)) {
            mutablePos.assign(Vector3i.SOUTH);
            otherYaw.rotateY(mutablePos, mutablePos);
            mutablePos.add(coordinate.x, coordinate.y, coordinate.z);
            ObjectIntPair<StairConnectedBlockRuleSet.StairType> sidewaysStair = getStairData(world, mutablePos, currentRuleSet.getMaterialName());
            if (sidewaysStair == null || sidewaysStair.rightInt() != rotation) {
               backConnection = getConnection(currentYaw, otherYaw, otherStairType, false);
            }
         }
      }

      return backConnection;
   }

   protected static StairConnectedBlockRuleSet.StairConnection getInvertedCornerConnection(
      World world, StairLikeConnectedBlockRuleSet currentRuleSet, Vector3i coordinate, Vector3i mutablePos, Rotation currentYaw, boolean upsideDown
   ) {
      StairConnectedBlockRuleSet.StairConnection frontConnection = null;
      mutablePos.assign(Vector3i.SOUTH);
      currentYaw.rotateY(mutablePos, mutablePos);
      mutablePos.add(coordinate.x, coordinate.y, coordinate.z);
      ObjectIntPair<StairConnectedBlockRuleSet.StairType> frontStair = getStairData(world, mutablePos, currentRuleSet.getMaterialName());
      if (frontStair != null) {
         StairConnectedBlockRuleSet.StairType otherStairType = (StairConnectedBlockRuleSet.StairType)frontStair.left();
         RotationTuple otherStairRotation = RotationTuple.get(frontStair.rightInt());
         Rotation otherYaw = otherStairRotation.yaw();
         boolean otherUpsideDown = otherStairRotation.pitch() != Rotation.None;
         if (otherUpsideDown) {
            otherYaw = otherYaw.flip();
         }

         if (canConnectTo(currentYaw, otherYaw, upsideDown, otherUpsideDown)) {
            frontConnection = getConnection(currentYaw, otherYaw, otherStairType, true);
         }
      }

      return frontConnection;
   }

   private static boolean canConnectTo(Rotation currentYaw, Rotation otherYaw, boolean upsideDown, boolean otherUpsideDown) {
      return otherUpsideDown == upsideDown && otherYaw != currentYaw && otherYaw.add(Rotation.OneEighty) != currentYaw;
   }

   private static StairConnectedBlockRuleSet.StairConnection getConnection(
      Rotation currentYaw, Rotation otherYaw, StairConnectedBlockRuleSet.StairType otherStairType, boolean inverted
   ) {
      if (otherYaw == currentYaw.add(Rotation.Ninety)
         && otherStairType != StairConnectedBlockRuleSet.StairType.invertedCorner(inverted)
         && otherStairType != StairConnectedBlockRuleSet.StairType.corner(!inverted)) {
         return StairConnectedBlockRuleSet.StairConnection.CORNER_LEFT;
      } else {
         return otherYaw == currentYaw.subtract(Rotation.Ninety)
               && otherStairType != StairConnectedBlockRuleSet.StairType.invertedCorner(!inverted)
               && otherStairType != StairConnectedBlockRuleSet.StairType.corner(inverted)
            ? StairConnectedBlockRuleSet.StairConnection.CORNER_RIGHT
            : null;
      }
   }

   @Nullable
   @Override
   public com.hypixel.hytale.protocol.ConnectedBlockRuleSet toPacket(BlockTypeAssetMap<String, BlockType> assetMap) {
      com.hypixel.hytale.protocol.ConnectedBlockRuleSet packet = new com.hypixel.hytale.protocol.ConnectedBlockRuleSet();
      packet.type = ConnectedBlockRuleSetType.Stair;
      packet.stair = this.toProtocol(assetMap);
      return packet;
   }

   public com.hypixel.hytale.protocol.StairConnectedBlockRuleSet toProtocol(BlockTypeAssetMap<String, BlockType> assetMap) {
      com.hypixel.hytale.protocol.StairConnectedBlockRuleSet stairPacket = new com.hypixel.hytale.protocol.StairConnectedBlockRuleSet();
      stairPacket.straightBlockId = this.getBlockIdForStairType(StairConnectedBlockRuleSet.StairType.STRAIGHT, assetMap);
      stairPacket.cornerLeftBlockId = this.getBlockIdForStairType(StairConnectedBlockRuleSet.StairType.CORNER_LEFT, assetMap);
      stairPacket.cornerRightBlockId = this.getBlockIdForStairType(StairConnectedBlockRuleSet.StairType.CORNER_RIGHT, assetMap);
      stairPacket.invertedCornerLeftBlockId = this.getBlockIdForStairType(StairConnectedBlockRuleSet.StairType.INVERTED_CORNER_LEFT, assetMap);
      stairPacket.invertedCornerRightBlockId = this.getBlockIdForStairType(StairConnectedBlockRuleSet.StairType.INVERTED_CORNER_RIGHT, assetMap);
      stairPacket.materialName = this.materialName;
      return stairPacket;
   }

   private int getBlockIdForStairType(StairConnectedBlockRuleSet.StairType stairType, BlockTypeAssetMap<String, BlockType> assetMap) {
      BlockType blockType = this.getStairBlockType(stairType);
      return blockType == null ? -1 : assetMap.getIndex(blockType.getId());
   }

   protected static enum StairConnection {
      CORNER_LEFT,
      CORNER_RIGHT;

      private StairConnection() {
      }

      public StairConnectedBlockRuleSet.StairType getStairType(boolean inverted) {
         return switch (this) {
            case CORNER_LEFT -> inverted ? StairConnectedBlockRuleSet.StairType.INVERTED_CORNER_LEFT : StairConnectedBlockRuleSet.StairType.CORNER_LEFT;
            case CORNER_RIGHT -> inverted ? StairConnectedBlockRuleSet.StairType.INVERTED_CORNER_RIGHT : StairConnectedBlockRuleSet.StairType.CORNER_RIGHT;
         };
      }
   }

   public static enum StairType {
      STRAIGHT,
      CORNER_LEFT,
      CORNER_RIGHT,
      INVERTED_CORNER_LEFT,
      INVERTED_CORNER_RIGHT;

      private static final StairConnectedBlockRuleSet.StairType[] VALUES = values();

      private StairType() {
      }

      public static StairConnectedBlockRuleSet.StairType corner(boolean right) {
         return right ? CORNER_RIGHT : CORNER_LEFT;
      }

      public static StairConnectedBlockRuleSet.StairType invertedCorner(boolean right) {
         return right ? INVERTED_CORNER_RIGHT : INVERTED_CORNER_LEFT;
      }

      public boolean isCorner() {
         return this == CORNER_LEFT || this == CORNER_RIGHT;
      }

      public boolean isInvertedCorner() {
         return this == INVERTED_CORNER_LEFT || this == INVERTED_CORNER_RIGHT;
      }

      public boolean isLeft() {
         return this == CORNER_LEFT || this == INVERTED_CORNER_LEFT;
      }

      public boolean isRight() {
         return this == CORNER_RIGHT || this == INVERTED_CORNER_RIGHT;
      }
   }
}