Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ thumbs.db
*.war
*.ear
*.txt
*.ase

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/gregtech/api/GregTechAPI.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import gregtech.api.advancement.IAdvancementManager;
import gregtech.api.block.ICleanroomFilter;
import gregtech.api.block.IHeatingCoilBlockStats;
import gregtech.api.block.coil.CoilManager;
import gregtech.api.command.ICommandManager;
import gregtech.api.cover.CoverDefinition;
import gregtech.api.event.HighTierEvent;
Expand Down Expand Up @@ -55,6 +56,8 @@ public class GregTechAPI {
public static MarkerMaterialRegistry markerMaterialRegistry;
/** Will be available at the Pre-Initialization stage */
public static MTEManager mteManager;
/** Will be available at the Pre-Initialization stage */
public static CoilManager coilManager;
/** GT's data migrations API */
public static final MigrationAPI MIGRATIONS = new MigrationAPI();
public static final RecipePropertyRegistry RECIPE_PROPERTIES = new RecipePropertyRegistry();
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/gregtech/api/block/IHeatingCoilBlockStats.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

import gregtech.api.recipes.properties.impl.TemperatureProperty;
import gregtech.api.unification.material.Material;
import gregtech.client.model.ActiveVariantBlockBakedModel;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.function.BooleanSupplier;

/**
* Implement this interface on the Block Enum for your Heating Coil block
*
Expand Down Expand Up @@ -52,4 +55,12 @@ public interface IHeatingCoilBlockStats {
*/
@Nullable
Material getMaterial();

default int getColor() {
return getMaterial() == null ? 0xFFFFFFFF : getMaterial().getMaterialRGB();
}

default ActiveVariantBlockBakedModel createModel(BooleanSupplier bloomConfig) {
return null;
}
}
33 changes: 18 additions & 15 deletions src/main/java/gregtech/api/block/VariantActiveBlock.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.properties.PropertyEnum;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
Expand All @@ -25,21 +24,20 @@
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import it.unimi.dsi.fastutil.objects.ObjectSet;
import org.jetbrains.annotations.NotNull;
import team.chisel.ctm.client.state.CTMExtendedState;

import java.util.EnumMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;

public class VariantActiveBlock<T extends Enum<T> & IStringSerializable> extends VariantBlock<T> {
public abstract class VariantActiveBlock<T extends IStringSerializable & Comparable<T>> extends VariantBlock<T> {

private static final Int2ObjectMap<ObjectSet<BlockPos>> ACTIVE_BLOCKS = new Int2ObjectOpenHashMap<>();
private static final ReadWriteLock ACTIVE_BLOCKS_LOCK = new ReentrantReadWriteLock();
Expand Down Expand Up @@ -92,12 +90,17 @@ protected boolean canSilkHarvest() {
@NotNull
@Override
public BlockRenderLayer getRenderLayer() {
return getRenderLayer(VALUES[0]);
}

@NotNull
public BlockRenderLayer getRenderLayer(T value) {
return BlockRenderLayer.CUTOUT;
}

@Override
public boolean canRenderInLayer(@NotNull IBlockState state, @NotNull BlockRenderLayer layer) {
return layer == getRenderLayer() ||
return layer == getRenderLayer(getState(state)) ||
layer == BloomEffectUtil.getEffectiveBloomLayer(isBloomEnabled(getState(state)));
}

Expand All @@ -113,16 +116,15 @@ public int getMetaFromState(IBlockState state) {
if (state.getValue(ACTIVE_DEPRECATED)) {
meta += 8;
}
return meta + state.getValue(VARIANT).ordinal();
return meta + state.getValue(VARIANT);
}

@NotNull
@Override
protected BlockStateContainer createBlockState() {
Class<T> enumClass = getActualTypeParameter(getClass(), VariantActiveBlock.class);
this.VARIANT = PropertyEnum.create("variant", enumClass);
this.VALUES = enumClass.getEnumConstants();
return new ExtendedBlockState(this, new IProperty[] { VARIANT, ACTIVE_DEPRECATED },
super.createBlockState();
return new ExtendedBlockState(this,
new IProperty[] { VARIANT, ACTIVE_DEPRECATED },
new IUnlistedProperty[] { ACTIVE });
}

Expand All @@ -144,17 +146,18 @@ public IExtendedBlockState getExtendedState(@NotNull IBlockState state, @NotNull

@SideOnly(Side.CLIENT)
public void onModelRegister() {
Map<T, ModelResourceLocation> models = new EnumMap<>(VALUES[0].getDeclaringClass());
Int2ObjectMap<ModelResourceLocation> models = new Int2ObjectArrayMap<>();
for (T value : VALUES) {
int index = VARIANT.getIndexOf(value);
ModelResourceLocation inactiveModel = model(false, value);
ModelResourceLocation activeModel = model(true, value);

ActiveVariantBlockBakedModel model = new ActiveVariantBlockBakedModel(inactiveModel, activeModel,
() -> isBloomEnabled(value));
models.put(value, model.getModelLocation());
models.put(index, model.getModelLocation());

Item item = Item.getItemFromBlock(this);
ModelLoader.setCustomModelResourceLocation(item, value.ordinal(), inactiveModel);
ModelLoader.setCustomModelResourceLocation(item, index, inactiveModel);
ModelLoader.registerItemVariants(item, activeModel);
}
ModelLoader.setCustomStateMapper(this,
Expand All @@ -166,11 +169,11 @@ public void onModelRegister() {
private ModelResourceLocation model(boolean active, T variant) {
return new ModelResourceLocation(
Objects.requireNonNull(getRegistryName()),
"active=" + active + ",variant=" + VARIANT.getName(variant));
"active=" + active + ",variant=" + variant.getName());
}

@SideOnly(Side.CLIENT)
protected boolean isBloomEnabled(T value) {
public boolean isBloomEnabled(T value) {
return ConfigHolder.client.machinesEmissiveTextures;
}
}
139 changes: 120 additions & 19 deletions src/main/java/gregtech/api/block/VariantBlock.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.PropertyEnum;
import net.minecraft.block.properties.PropertyHelper;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.resources.I18n;
Expand All @@ -18,31 +18,42 @@
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

import com.google.common.base.Optional;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.lang.reflect.Array;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class VariantBlock<T extends Enum<T> & IStringSerializable> extends Block {
public abstract class VariantBlock<T extends IStringSerializable & Comparable<T>> extends Block {

protected PropertyEnum<T> VARIANT;
protected PropertyIntMap<T> VARIANT;
protected T[] VALUES;

public VariantBlock(@NotNull Material materialIn) {
super(materialIn);
if (VALUES.length > 0 && VALUES[0] instanceof IStateHarvestLevel) {
updateHarvestLevels();
setCreativeTab(GTCreativeTabs.TAB_GREGTECH);
setDefaultState(this.blockState.getBaseState().withProperty(VARIANT, 0));
}

protected void updateHarvestLevels() {
if (VALUES.length > 0 && VALUES[0] instanceof IStateHarvestLevel stateHarvestLevel) {
for (T t : VALUES) {
IStateHarvestLevel stateHarvestLevel = (IStateHarvestLevel) t;
IBlockState state = getState(t);
setHarvestLevel(stateHarvestLevel.getHarvestTool(state), stateHarvestLevel.getHarvestLevel(state),
state);
setHarvestLevel(stateHarvestLevel.getHarvestTool(state),
stateHarvestLevel.getHarvestLevel(state), state);
}
}
setCreativeTab(GTCreativeTabs.TAB_GREGTECH);
setDefaultState(this.blockState.getBaseState().withProperty(VARIANT, VALUES[0]));
}

@Override
Expand All @@ -53,11 +64,11 @@ public void getSubBlocks(@NotNull CreativeTabs tab, @NotNull NonNullList<ItemSta
}

public IBlockState getState(T variant) {
return getDefaultState().withProperty(VARIANT, variant);
return getDefaultState().withProperty(VARIANT, VARIANT.getIndexOf(variant));
}

public T getState(IBlockState blockState) {
return blockState.getValue(VARIANT);
return VARIANT.getValue(blockState.getValue(VARIANT));
}

public T getState(ItemStack stack) {
Expand All @@ -69,18 +80,34 @@ public ItemStack getItemVariant(T variant) {
}

public ItemStack getItemVariant(T variant, int amount) {
return new ItemStack(this, amount, variant.ordinal());
return new ItemStack(this, amount, VARIANT.getIndexOf(variant));
}

@NotNull
@Override
protected BlockStateContainer createBlockState() {
Class<T> enumClass = getActualTypeParameter(getClass(), VariantBlock.class);
this.VARIANT = PropertyEnum.create("variant", enumClass);
this.VALUES = enumClass.getEnumConstants();
this.VARIANT = new PropertyIntMap<>("variant", computeVariants());
this.VALUES = VARIANT.getValues();
return new BlockStateContainer(this, VARIANT);
}

@NotNull
protected Collection<T> computeVariants() {
Class<T> enumClass = null;
for (Class<?> innerClazz : getClass().getClasses()) {
var enums = innerClazz.getEnumConstants();
if (enums != null && enums[0] instanceof IStringSerializable) {
// noinspection unchecked
enumClass = (Class<T>) innerClazz;
break;
}
}
if (enumClass == null) {
enumClass = getActualTypeParameter(getClass(), VariantBlock.class);;
}
return Arrays.asList(enumClass.getEnumConstants());
}

@Override
@SideOnly(Side.CLIENT)
public void addInformation(@NotNull ItemStack stack, @Nullable World player, @NotNull List<String> tooltip,
Expand All @@ -104,26 +131,100 @@ public int damageDropped(@NotNull IBlockState state) {
@Override
@SuppressWarnings("deprecation")
public IBlockState getStateFromMeta(int meta) {
return getDefaultState().withProperty(VARIANT, VALUES[meta % VALUES.length]);
return getDefaultState().withProperty(VARIANT, meta % VALUES.length);
}

@Override
public int getMetaFromState(IBlockState state) {
return state.getValue(VARIANT).ordinal();
return state.getValue(VARIANT);
}

// magic is here
@SuppressWarnings("unchecked")
protected static <T, R> Class<T> getActualTypeParameter(Class<? extends R> thisClass, Class<R> declaringClass) {
Type type = thisClass.getGenericSuperclass();

while (!(type instanceof ParameterizedType) || ((ParameterizedType) type).getRawType() != declaringClass) {
while (!(type instanceof ParameterizedType pType) || pType.getRawType() != declaringClass) {
if (type instanceof ParameterizedType) {
type = ((Class<?>) ((ParameterizedType) type).getRawType()).getGenericSuperclass();
} else {
type = ((Class<?>) type).getGenericSuperclass();
}
}
return (Class<T>) ((ParameterizedType) type).getActualTypeArguments()[0];
var arg = pType.getActualTypeArguments()[0];
if (!(arg instanceof Class<?>)) {
throw new ClassCastException(String.format("cannot cast %s to a class!", arg));
}
return (Class<T>) pType.getActualTypeArguments()[0];
}

protected static class PropertyIntMap<O extends Comparable<O> & IStringSerializable>
extends PropertyHelper<Integer> {

private final Int2ObjectMap<O> intMap;
private final Object2IntMap<O> reverse;
private final O[] allowedObjects;

@SuppressWarnings("unchecked")
protected PropertyIntMap(String name, Collection<O> values) {
super(name, Integer.class);
if (values.isEmpty()) throw new IllegalArgumentException("values are empty!");
if (values.size() > 16) throw new IllegalArgumentException("values cannot be greater than 16!");

this.intMap = new Int2ObjectArrayMap<>(values.size());
this.reverse = new Object2IntArrayMap<>(values.size());

O first = values.iterator().next();
this.allowedObjects = (O[]) Array.newInstance(first.getClass(), values.size());

for (O value : values) {
int size = this.intMap.size();
this.allowedObjects[size] = value;
this.intMap.put(size, value);
this.reverse.put(value, size);
}
}

@Override
public @NotNull Collection<Integer> getAllowedValues() {
return this.intMap.keySet();
}

public @NotNull O[] getValues() {
return this.allowedObjects;
}

@Override
@Deprecated
public @NotNull String getName(@NotNull Integer value) {
return getNameByInt(value);
}

public @NotNull String getNameByInt(int value) {
return getValue(value).getName();
}

@Override
public @NotNull Optional<Integer> parseValue(@NotNull String value) {
for (O object : reverse.keySet()) {
if (object.getName().equals(value)) {
return Optional.of(getIndexOf(object));
}
}
return Optional.absent();
}

@Override
public int hashCode() {
return 31 * super.hashCode() + this.allowedObjects.hashCode();
}

public int getIndexOf(O value) {
return this.reverse.getInt(value);
}

public O getValue(int index) {
return this.intMap.get(index);
}
}
}
3 changes: 2 additions & 1 deletion src/main/java/gregtech/api/block/VariantItemBlock.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

import org.jetbrains.annotations.NotNull;

public class VariantItemBlock<R extends Enum<R> & IStringSerializable, T extends VariantBlock<R>> extends ItemBlock {
public class VariantItemBlock<R extends IStringSerializable & Comparable<R>, T extends VariantBlock<R>>
extends ItemBlock {

private final T genericBlock;

Expand Down
6 changes: 6 additions & 0 deletions src/main/java/gregtech/api/block/coil/BuilderFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package gregtech.api.block.coil;

public interface BuilderFactory {

CoilBlockBuilder makeBuilder(int id, String name);
}
Loading
Loading