crwdns154697:0crwdne154697:0
crwdns154699:0crwdne154699:0
crwdns154701:0crwdne154701:0
- crwdns154703:0crwdne154703:0 
- crwdns154705:0crwdne154705:0 
crwdns154707:0crwdne154707:0
- crwdns154709:0crwdne154709:0 
- crwdns154711:0crwdne154711:0 
- crwdns154713:0crwdne154713:0 
- crwdns154715:0crwdne154715:0 
crwdns154717:0crwdne154717:0
Note
crwdns154719:0:doc:crwdne154719:0
crwdns154721:0crwdne154721:0
crwdns154723:0crwdne154723:0
public class SpongeHealthData extends AbstractData<HealthData, ImmutableHealthData> implements HealthData {
    [...]
}
crwdns154725:0crwdne154725:0
crwdns154727:0crwdne154727:0
crwdns154729:0crwdne154729:0
- crwdns154731:0crwdne154731:0 
- crwdns154733:0crwdne154733:0 
crwdns154735:0crwdne154735:0
- crwdns154737:0crwdne154737:0 
- crwdns154739:0crwdne154739:0 
- crwdns154741:0crwdne154741:0 
import static com.google.common.base.Preconditions.checkArgument;
public class SpongeHealthData {
    public SpongeHealthData() {
        this(DataConstants.DEFAULT_HEALTH, DataConstants.DEFAULT_HEALTH);
    }
    public SpongeHealthData(double currentHealth, double maxHealth) {
        super(HealthData.class);
        checkArgument(currentHealth >= DataConstants.MINIMUM_HEALTH && currentHealth <= (double) Float.MAX_VALUE);
        checkArgument(maxHealth >= DataConstants.MINIMUM_HEALTH && maxHealth <= (double) Float.MAX_VALUE);
        this.currentHealth = currentHealth;
        this.maximumHealth = maxHealth;
        this.registerGettersAndSetters();
    }
    ...
}
crwdns154743:0crwdne154743:0
Note
crwdns154745:0crwdne154745:0
crwdns154747:0crwdne154747:0
crwdns154749:0crwdne154749:0
public MutableBoundedValue<Double> health() {
    return SpongeValueFactory.boundedBuilder(Keys.HEALTH)
        .minimum(DataConstants.MINIMUM_HEALTH)
        .maximum(this.maximumHealth)
        .defaultValue(this.maximumHealth)
        .actualValue(this.currentHealth)
        .build();
}
Tip
crwdns154751:0crwdne154751:0
crwdns154753:0crwdne154753:0
crwdns154755:0crwdne154755:0
crwdns154757:0crwdne154757:0
crwdns154759:0crwdne154759:0
public DataContainer toContainer() {
    return new MemoryDataContainer()
        .set(Keys.HEALTH, this.currentHealth)
        .set(Keys.MAX_HEALTH, this.maximumHealth);
}
crwdns154761:0crwdne154761:0
crwdns154763:0crwdne154763:0
- crwdns154765:0crwdne154765:0 
- crwdns154767:0crwdne154767:0 
- crwdns154769:0crwdne154769:0 
crwdns154771:0crwdne154771:0
private void setCurrentHealthIfValid(double value) {
    if (value >= DataConstants.MINIMUM_HEALTH && value <= (double) Float.MAX_VALUE) {
        this.currentHealth = value;
    } else {
        throw new IllegalArgumentException("Invalid value for current health");
    }
}
private void setMaximumHealthIfValid(double value) {
    if (value >= DataConstants.MINIMUM_HEALTH && value <= (double) Float.MAX_VALUE) {
        this.maximumHealth = value;
    } else {
        throw new IllegalArgumentException("Invalid value for maximum health");
    }
}
private void registerGettersAndSetters() {
    registerFieldGetter(Keys.HEALTH, () -> SpongeHealthData.this.currentHealth);
    registerFieldSetter(Keys.HEALTH, SpongeHealthData.this::setCurrentHealthIfValid);
    registerKeyValue(Keys.HEALTH, SpongeHealthData.this::health);
    registerFieldGetter(Keys.MAX_HEALTH, () -> SpongeHealthData.this.maximumHealth);
    registerFieldSetter(Keys.MAX_HEALTH, SpongeHealthData.this::setMaximumHealthIfValid);
    registerKeyValue(Keys.MAX_HEALTH, SpongeHealthData.this::maxHealth);
}
crwdns154773:0crwdne154773:0
Tip
crwdns154775:0crwdne154775:0
crwdns154777:0crwdne154777:0
crwdns154779:0crwdne154779:0
crwdns154781:0crwdne154781:0
crwdns154783:0crwdne154783:0
- crwdns154785:0crwdne154785:0 
- crwdns154787:0crwdne154787:0 
- crwdns154789:0crwdne154789:0 
crwdns154791:0crwdne154791:0
Tip
crwdns154793:0crwdne154793:0
crwdns154795:0crwdne154795:0
crwdns154797:0crwdne154797:0
keyMap.put("health"), makeSingleKey(Double.class, MutableBoundedValue.class, of("Health")));
keyMap.put("max_health", makeSingleKey(Double.class, MutableBoundedValue.class, of("MaxHealth")));
crwdns154799:0crwdne154799:0
crwdns154801:0crwdne154801:0
crwdns154803:0crwdne154803:0
crwdns154805:0crwdne154805:0
crwdns154807:0crwdne154807:0
public class HealthDataProcessor extends AbstractEntityDataProcessor<EntityLivingBase, HealthData, ImmutableHealthData> {
    public HealthDataProcessor() {
        super(EntityLivingBase.class);
    }
    [...]
}
crwdns154809:0crwdne154809:0
Tip
crwdns154811:0crwdne154811:0
crwdns154813:0crwdne154813:0
crwdns154815:0crwdne154815:0
crwdns154817:0crwdne154817:0
crwdns154819:0crwdne154819:0
protected boolean doesDataExist(EntityLivingBase entity) {
    return true;
}
crwdns154821:0crwdne154821:0
crwdns154823:0crwdne154823:0
crwdns154825:0crwdne154825:0
crwdns154827:0crwdne154827:0
protected boolean set(EntityLivingBase entity, Map<Key<?>, Object> keyValues) {
    entity.getEntityAttribute(SharedMonsterAttributes.maxHealth)
        .setBaseValue(((Double) keyValues.get(Keys.MAX_HEALTH)).floatValue());
    entity.setHealth(((Double) keyValues.get(Keys.HEALTH)).floatValue());
    return true;
}
Tip
crwdns154829:0:doc:crwdnd154829:0:javadoc:crwdne154829:0
Warning
crwdns154831:0crwdne154831:0
crwdns154833:0crwdne154833:0
crwdns154835:0crwdne154835:0
crwdns154837:0crwdne154837:0
crwdns154839:0crwdne154839:0
public DataTransactionResult remove(DataHolder dataHolder) {
    return DataTransactionBuilder.failNoData();
}
crwdns154841:0crwdne154841:0
crwdns154843:0crwdne154843:0
crwdns154845:0crwdne154845:0
Warning
crwdns154847:0crwdne154847:0
protected Map<Key<?>, ?> getValues(EntityLivingBase entity) {
    final double health = entity.getHealth();
    final double maxHealth = entity.getMaxHealth();
    return ImmutableMap.<Key<?>, Object>of(Keys.HEALTH, health, Keys.MAX_HEALTH, maxHealth);
}
crwdns154849:0crwdne154849:0
crwdns154851:0crwdne154851:0
crwdns154853:0crwdne154853:0
public Optional<HealthData> fill(DataContainer container, HealthData healthData) {
    final Optional<Double> health = container.getDouble(Keys.HEALTH.getQuery());
    final Optional<Double> maxHealth = container.getDouble(Keys.MAX_HEALTH.getQuery());
    if (health.isPresent() && maxHealth.isPresent()) {
        healthData.set(Keys.HEALTH, health.get());
        healthData.set(Keys.MAX_HEALTH, maxHealth.get());
        return Optional.of(healthData);
    }
    return Optional.empty();
}
crwdns154855:0crwdne154855:0
crwdns154857:0crwdne154857:0
crwdns154859:0crwdne154859:0
crwdns154861:0crwdne154861:0
protected HealthData createManipulator() {
    return new SpongeHealthData();
}
crwdns154863:0crwdne154863:0
crwdns154865:0crwdne154865:0
crwdns154867:0crwdne154867:0
public class HealthValueProcessor extends AbstractSpongeValueProcessor<EntityLivingBase, Double,
    MutableBoundedValue<Double> {
    public HealthValueProcessor() {
        super(EntityLivingBase.class, Keys.HEALTH);
    }
    [...]
}
crwdns154869:0crwdne154869:0
Tip
crwdns154871:0crwdne154871:0
crwdns154873:0crwdne154873:0
protected MutableBoundedValue<Double> constructValue(Double value) {
    return SpongeValueFactory.boundedBuilder(Keys.HEALTH)
        .minimum(DataConstants.MINIMUM_HEALTH)
        .maximum((double) Float.MAX_VALUE)
        .defaultValue(DataConstants.DEFAULT_HEALTH)
        .actualValue(value)
        .build();
}
protected ImmutableValue<Double> constructImmutableValue(Double value) {
    return constructValue(value).asImmutable();
}
protected Optional<Double> getVal(EntityLivingBase container) {
    return Optional.of((double) container.getHealth());
}
crwdns154875:0crwdne154875:0
protected boolean set(EntityLivingBase container, Double value) {
    if (value >= DataConstants.MINIMUM_HEALTH && value <= (double) Float.MAX_VALUE) {
        container.setHealth(value.floatValue());
        return true;
    }
    return false;
}
crwdns154877:0crwdne154877:0
public DataTransactionResult removeFrom(ValueContainer<?> container) {
    return DataTransactionBuilder.failNoData();
}
crwdns154879:0crwdne154879:0
crwdns154881:0crwdne154881:0
crwdns154883:0crwdne154883:0
crwdns154885:0crwdne154885:0
crwdns154887:0crwdne154887:0
dataRegistry.registerDataProcessorAndImpl(HealthData.class, SpongeHealthData.class,
    ImmutableHealthData.class, ImmutableSpongeHealthData.class,
    new HealthDataProcessor());
crwdns154889:0crwdne154889:0
crwdns154891:0crwdne154891:0
dataRegistry.registerValueProcessor(Keys.HEALTH, new HealthValueProcessor());
dataRegistry.registerValueProcessor(Keys.MAX_HEALTH, new MaxHealthValueProcessor());
crwdns154893:0crwdne154893:0
crwdns154895:0crwdne154895:0
@Mixin(BlockHorizontal.class)
public abstract class MixinBlockHorizontal extends MixinBlock {
    [...]
}
crwdns154897:0crwdne154897:0
@Override
public boolean supports(Class<? extends ImmutableDataManipulator<?, ?>> immutable) {
    return super.supports(immutable) || ImmutableDirectionalData.class.isAssignableFrom(immutable);
}
crwdns154899:0crwdne154899:0
@Override
public Optional<BlockState> getStateWithData(IBlockState blockState, ImmutableDataManipulator<?, ?> manipulator) {
    if (manipulator instanceof ImmutableDirectionalData) {
        final Direction direction = ((ImmutableDirectionalData) manipulator).direction().get();
        final EnumFacing facing = DirectionResolver.getFor(direction);
        return Optional.of((BlockState) blockState.withProperty(BlockHorizontal.FACING, facing));
    }
    return super.getStateWithData(blockState, manipulator);
}
crwdns154901:0crwdne154901:0
@Override
public <E> Optional<BlockState> getStateWithValue(IBlockState blockState, Key<? extends BaseValue<E>> key, E value) {
    if (key.equals(Keys.DIRECTION)) {
        final Direction direction = (Direction) value;
        final EnumFacing facing = DirectionResolver.getFor(direction);
        return Optional.of((BlockState) blockState.withProperty(BlockHorizontal.FACING, facing));
    }
    return super.getStateWithValue(blockState, key, value);
}
crwdns154903:0crwdne154903:0
@Override
public List<ImmutableDataManipulator<?, ?>> getManipulators(IBlockState blockState) {
    return ImmutableList.<ImmutableDataManipulator<?, ?>>builder()
            .addAll(super.getManipulators(blockState))
            .add(new ImmutableSpongeDirectionalData(DirectionResolver.getFor(blockState.getValue(BlockHorizontal.FACING))))
            .build();
}
crwdns154905:0crwdne154905:0
crwdns154907:0crwdne154907:0
crwdns154909:0crwdne154909:0