All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.nukkit.blockstate.IMutableBlockState Maven / Gradle / Ivy

There is a newer version: 1.20.40-r1
Show newest version
package cn.nukkit.blockstate;

import cn.nukkit.api.PowerNukkitOnly;
import cn.nukkit.api.Since;
import cn.nukkit.blockproperty.BlockProperties;
import cn.nukkit.blockproperty.BlockProperty;
import cn.nukkit.blockproperty.exception.InvalidBlockPropertyException;
import cn.nukkit.blockstate.exception.InvalidBlockStateDataTypeException;
import cn.nukkit.blockstate.exception.InvalidBlockStateException;
import cn.nukkit.math.NukkitMath;
import cn.nukkit.utils.Validation;

import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.function.Consumer;

import static cn.nukkit.blockstate.Loggers.logIMutableBlockState;

@PowerNukkitOnly
@Since("1.4.0.0-PN")
@ParametersAreNonnullByDefault
public interface IMutableBlockState extends IBlockState {
    /**
     * Replace all matching states of this block state with the same states of the given block state.
     * 

States that doesn't exists in the other state are ignored. *

Only properties that matches each other will be copied, for example, if this state have an age property * going from 0 to 7 and the other have an age from 0 to 15, the age property won't change. * @throws UnsupportedOperationException If the state is from a different block id and property copying isn't supported by the implementation * @throws InvalidBlockStateException If the given storage has invalid data properties * @param state The states that will have the properties copied. */ @PowerNukkitOnly @Since("1.4.0.0-PN") default void setState(IBlockState state) throws InvalidBlockStateException { if (state.getBlockId() == getBlockId()) { setDataStorage(state.getDataStorage()); } else { //TODO Implement property value copying throw new UnsupportedOperationException(); } } /** * Replace all matching states of this block state with the same states of the given block state. * But giving opportunity to return a new instance of this mutable state if needed. * *

States that doesn't exists in the other state are ignored. *

Only properties that matches each other will be copied, for example, if this state have an age property * going from 0 to 7 and the other have an age from 0 to 15, the age property won't change. *

If the implementation recognizes that the given state does not match the current set of properties * and needs an update, it may update and return a new state with a different block id and different set * of properties that represent the expected visual state. The this change can be detected with an {@code ==} operation. * @throws UnsupportedOperationException If the state is from a different block id and property copying isn't supported by the implementation * @throws InvalidBlockStateException If the given storage has invalid data properties * @param state The states that will have the properties copied. */ @PowerNukkitOnly @Since("1.5.1.0-PN") @Nonnull default IMutableBlockState forState(@Nonnull IBlockState state) throws InvalidBlockStateException { setState(state); return this; } /** * @throws InvalidBlockStateException If the given storage has invalid data properties * @throws InvalidBlockStateDataTypeException If the storage class type is not supported */ @PowerNukkitOnly @Since("1.4.0.0-PN") void setDataStorage(@Nonnegative Number storage); /** * @throws InvalidBlockStateException If the given storage has invalid data properties */ @PowerNukkitOnly @Since("1.4.0.0-PN") void setDataStorageFromInt(@Nonnegative int storage); /** * @throws InvalidBlockStateException If the given storage has invalid data properties * @throws InvalidBlockStateDataTypeException If the storage class type is not supported */ @PowerNukkitOnly @Since("1.4.0.0-PN") default boolean setDataStorage(@Nonnegative Number storage, boolean repair) { return setDataStorage(storage, repair, null); } /** * @return if the storage was repaired */ @PowerNukkitOnly @Since("1.4.0.0-PN") default boolean setDataStorageFromInt(@Nonnegative int storage, boolean repair) { return setDataStorageFromInt(storage, repair, null); } /** * @return if the storage was repaired * @throws InvalidBlockStateException If repair is false and the storage has an invalid property state * @throws InvalidBlockStateDataTypeException If the storage has an unsupported number type */ @PowerNukkitOnly @Since("1.4.0.0-PN") default boolean setDataStorage(@Nonnegative Number storage, boolean repair, @Nullable Consumer callback) { try { setDataStorage(storage); return false; } catch (InvalidBlockStateException e) { if (repair) { BigInteger bigInteger; try { bigInteger = new BigDecimal(storage.toString()).toBigIntegerExact(); } catch (NumberFormatException | ArithmeticException e2) { InvalidBlockStateDataTypeException ex = new InvalidBlockStateDataTypeException(storage, e2); ex.addSuppressed(e); throw ex; } try { setDataStorage(repairStorage(getBlockId(), bigInteger, getProperties(), callback)); } catch (InvalidBlockPropertyException | InvalidBlockStateException e2) { InvalidBlockStateException ex = new InvalidBlockStateException(e.getState(), "The state is invalid and could not be repaired", e); ex.addSuppressed(e2); throw ex; } return true; } throw e; } } /** * @return if the storage was repaired */ @PowerNukkitOnly @Since("1.4.0.0-PN") default boolean setDataStorageFromInt(@Nonnegative final int storage, boolean repair, @Nullable Consumer callback) { try { setDataStorageFromInt(storage); return false; } catch (IllegalStateException | InvalidBlockPropertyException e) { if (repair) { setDataStorage(repairStorage(getBlockId(), BigInteger.valueOf(storage), getProperties(), callback)); return true; } throw e; } } @PowerNukkitOnly @Since("1.4.0.0-PN") default void setDataStorageFromItemBlockMeta(int itemBlockMeta) { BlockProperties allProperties = getProperties(); BlockProperties itemBlockProperties = allProperties.getItemBlockProperties(); if (allProperties.equals(itemBlockProperties)) { setDataStorageFromInt(itemBlockMeta); return; } MutableBlockState item = itemBlockProperties.createMutableState(getBlockId()); item.setDataStorageFromInt(itemBlockMeta); MutableBlockState converted = allProperties.createMutableState(getBlockId()); itemBlockProperties.getItemPropertyNames().forEach(property -> converted.setPropertyValue(property, item.getPropertyValue(property))); setDataStorage(converted.getDataStorage()); } @PowerNukkitOnly @Since("1.4.0.0-PN") void setPropertyValue(String propertyName, @Nullable Serializable value); @PowerNukkitOnly @Since("1.4.0.0-PN") void setBooleanValue(String propertyName, boolean value); @PowerNukkitOnly @Since("1.4.0.0-PN") void setIntValue(String propertyName, int value); @PowerNukkitOnly @Since("1.4.0.0-PN") default void setBooleanValue(BlockProperty property, boolean value) { setBooleanValue(property.getName(), value); } @PowerNukkitOnly @Since("1.4.0.0-PN") default void setIntValue(BlockProperty property, int value) { setIntValue(property.getName(), value); } @PowerNukkitOnly @Since("1.4.0.0-PN") default void setPropertyValue(BlockProperty property, @Nullable T value) { setPropertyValue(property.getName(), value); } @PowerNukkitOnly @Since("1.4.0.0-PN") default boolean toggleBooleanProperty(String propertyName) { boolean newValue = !getBooleanValue(propertyName); setBooleanValue(propertyName, newValue); return newValue; } @PowerNukkitOnly @Since("1.4.0.0-PN") default boolean toggleBooleanProperty(BlockProperty property) { return toggleBooleanProperty(property.getName()); } @PowerNukkitOnly @Since("1.4.0.0-PN") @SuppressWarnings("unchecked") @Nonnull static BigInteger repairStorage( @Nonnegative int blockId, @Nonnull final BigInteger storage, @Nonnull final BlockProperties properties, @Nullable final Consumer callback) { Validation.checkPositive("blockId", blockId); int checkedBits = 0; int repairs = 0; BigInteger current = storage; for (BlockProperties.RegisteredBlockProperty reg : properties.getAllProperties()) { checkedBits += reg.getProperty().getBitSize(); try { reg.validateMeta(current); } catch (InvalidBlockPropertyException e) { BlockProperty property = reg.getProperty(); int offset = reg.getOffset(); BigInteger next = property.setValue(current, offset, null); if (callback != null) { Serializable fixed = property.getValue(next, offset); BlockStateRepair stateRepair = new BlockStateRepair( blockId, properties, storage, current, next, repairs++, property, offset, property.getMetaFromBigInt(current, offset), fixed, fixed, e ); callback.accept(stateRepair); Serializable proposed = stateRepair.getProposedPropertyValue(); if (!fixed.equals(proposed)) { try { next = ((BlockProperty) property).setValue(current, offset, proposed); } catch (InvalidBlockPropertyException proposedFailed) { logIMutableBlockState.warn("Could not apply the proposed repair, using the default proposal. "+stateRepair, proposedFailed); } } } current = next; } } if (NukkitMath.bitLength(current) > checkedBits) { BigInteger validMask = BigInteger.ONE.shiftLeft(checkedBits).subtract(BigInteger.ONE); BigInteger next = current.and(validMask); if (callback != null) { BlockStateRepair stateRepair = new BlockStateRepair( blockId, properties, storage, current, next, repairs, null, checkedBits, current.shiftRight(checkedBits).intValue(), 0, 0, null); callback.accept(stateRepair); if (!Integer.valueOf(0).equals(stateRepair.getProposedPropertyValue())) { logIMutableBlockState.warn("Could not apply the proposed repair, using the default proposal. "+stateRepair, new IllegalStateException("Attempted to propose a value outside the properties boundary")); } } current = next; } return current; } @PowerNukkitOnly @Since("1.4.0.0-PN") @Nonnull static RuntimeException handleUnsupportedStorageType(@Nonnegative int blockId, @Nonnegative Number storage, RuntimeException e) { InvalidBlockStateException ex; try { ex = new InvalidBlockStateException(BlockState.of(blockId, storage), e); } catch (InvalidBlockStateDataTypeException e2) { e2.addSuppressed(e); return e2; } return ex; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy