Working in part placement

This commit is contained in:
Sebastian Hartte
2020-07-01 21:27:37 +02:00
parent 8e031ca8d6
commit f2e3d81fd7
134 changed files with 1553 additions and 1494 deletions
@@ -1,23 +0,0 @@
package appeng.items.parts;
import java.util.function.Function;
import net.minecraft.item.ItemStack;
import appeng.api.parts.IPart;
import appeng.api.util.AEColor;
public class ColoredPartItem<T extends IPart> extends PartItem<T> {
private final AEColor color;
public ColoredPartItem(Settings properties, Function<ItemStack, T> factory, AEColor color) {
super(properties, factory);
this.color = color;
}
public AEColor getColor() {
return color;
}
}
@@ -1,201 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.items.parts;
import net.minecraft.block.Block;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.renderer.RenderTypeLookup;
import net.minecraft.item.*;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.tag.BlockTags;
import net.minecraft.tag.Tag;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Identifier;
import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.registry.Registry;
import net.minecraft.text.Text;
import net.minecraft.world.EmptyBlockReader;
import net.minecraftforge.registries.ForgeRegistries;
import appeng.api.AEApi;
import appeng.api.exceptions.MissingDefinitionException;
import appeng.api.features.AEFeature;
import appeng.api.parts.IAlphaPassItem;
import appeng.api.util.AEPartLocation;
import appeng.core.AEConfig;
import appeng.core.AppEng;
import appeng.facade.FacadePart;
import appeng.facade.IFacadeItem;
import appeng.items.AEBaseItem;
public class FacadeItem extends AEBaseItem implements IFacadeItem, IAlphaPassItem {
/**
* Block tag used to explicitly whitelist blocks for use in facades.
*/
private static final Identifier TAG_WHITELISTED = new Identifier(AppEng.MOD_ID, "whitelisted/facades");
private static final String NBT_ITEM_ID = "item";
public FacadeItem(Settings properties) {
super(properties);
}
@Override
public ActionResult onItemUseFirst(ItemStack stack, ItemUsageContext context) {
return AEApi.instance().partHelper().placeBus(stack, context.getBlockPos(), context.getSide(), context.getPlayer(),
context.getHand(), context.getWorld());
}
@Override
public Text getName(ItemStack is) {
try {
final ItemStack in = this.getTextureItem(is);
if (!in.isEmpty()) {
return super.getName(is).deepCopy().append(" - ").append(in.getName());
}
} catch (final Throwable ignored) {
}
return super.getName(is);
}
@Override
public void appendStacks(ItemGroup group, DefaultedList<ItemStack> items) {
}
public ItemStack createFacadeForItem(final ItemStack itemStack, final boolean returnItem) {
if (itemStack.isEmpty() || itemStack.hasTag() || !(itemStack.getItem() instanceof BlockItem)) {
return ItemStack.EMPTY;
}
BlockItem blockItem = (BlockItem) itemStack.getItem();
Block block = blockItem.getBlock();
if (block == Blocks.AIR) {
return ItemStack.EMPTY;
}
// We only support the default state for facades. Sorry.
BlockState blockState = block.getDefaultState();
final boolean areTileEntitiesEnabled = AEConfig.instance().isFeatureEnabled(AEFeature.TILE_ENTITY_FACADES);
Tag<Block> whitelistTag = BlockTags.getCollection().getOrCreate(TAG_WHITELISTED);
final boolean isWhiteListed = block.isIn(whitelistTag);
final boolean isModel = blockState.getRenderType() == BlockRenderType.MODEL;
final BlockState defaultState = block.getDefaultState();
final boolean isTileEntity = block.hasTileEntity(defaultState);
final boolean isFullCube = defaultState.isNormalCube(EmptyBlockReader.INSTANCE, BlockPos.ZERO);
final boolean isTileEntityAllowed = !isTileEntity || (areTileEntitiesEnabled && isWhiteListed);
final boolean isBlockAllowed = isFullCube || isWhiteListed;
if (isModel && isTileEntityAllowed && isBlockAllowed) {
if (returnItem) {
return itemStack;
}
final ItemStack is = new ItemStack(this);
final CompoundTag data = new CompoundTag();
data.putString(NBT_ITEM_ID, itemStack.getItem().getRegistryName().toString());
is.setTag(data);
return is;
}
return ItemStack.EMPTY;
}
@Override
public FacadePart createPartFromItemStack(final ItemStack is, final AEPartLocation side) {
final ItemStack in = this.getTextureItem(is);
if (!in.isEmpty()) {
return new FacadePart(is, side);
}
return null;
}
@Override
public ItemStack getTextureItem(ItemStack is) {
CompoundTag nbt = is.getTag();
if (nbt == null) {
return ItemStack.EMPTY;
}
Identifier itemId = new Identifier(nbt.getString(NBT_ITEM_ID));
Item baseItem = ForgeRegistries.ITEMS.getValue(itemId);
if (baseItem == null) {
return ItemStack.EMPTY;
}
return new ItemStack(baseItem, 1);
}
@Override
public BlockState getTextureBlockState(ItemStack is) {
ItemStack baseItemStack = this.getTextureItem(is);
if (baseItemStack.isEmpty()) {
return Blocks.GLASS.getDefaultState();
}
Block block = Block.getBlockFromItem(baseItemStack.getItem());
if (block == Blocks.AIR) {
return Blocks.GLASS.getDefaultState();
}
return block.getDefaultState();
}
public ItemStack createFromID(final int id) {
ItemStack facadeStack = AEApi.instance().definitions().items().facade().maybeStack(1).orElseThrow(
() -> new MissingDefinitionException("Tried to create a facade, while facades are being deactivated."));
// Convert back to a registry name...
Item item = Registry.ITEM.getByValue(id);
if (item == Items.AIR) {
return ItemStack.EMPTY;
}
final CompoundTag facadeTag = new CompoundTag();
facadeTag.putString(NBT_ITEM_ID, item.getRegistryName().toString());
facadeStack.setTag(facadeTag);
return facadeStack;
}
@Override
public boolean useAlphaPass(final ItemStack is) {
BlockState blockState = this.getTextureBlockState(is);
if (blockState == null) {
return false;
}
return RenderTypeLookup.canRenderInLayer(blockState, RenderLayer.getTranslucent())
|| RenderTypeLookup.canRenderInLayer(blockState, RenderLayer.getTranslucentNoCrumbling());
}
}
@@ -1,59 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.items.parts;
import java.util.function.Function;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUsageContext;
import net.minecraft.util.ActionResult;
import appeng.api.AEApi;
import appeng.api.parts.IPart;
import appeng.api.parts.IPartItem;
import appeng.items.AEBaseItem;
public class PartItem<T extends IPart> extends AEBaseItem implements IPartItem<T> {
private final Function<ItemStack, T> factory;
public PartItem(Settings properties, Function<ItemStack, T> factory) {
super(properties);
this.factory = factory;
}
@Override
public ActionResult onItemUse(ItemUsageContext context) {
PlayerEntity player = context.getPlayer();
ItemStack held = player.getStackInHand(context.getHand());
if (held.getItem() != this) {
return ActionResult.PASS;
}
return AEApi.instance().partHelper().placeBus(held, context.getBlockPos(), context.getSide(), player,
context.getHand(), context.getWorld());
}
@Override
public T createPart(ItemStack is) {
return factory.apply(is);
}
}
@@ -1,46 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.items.parts;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import appeng.api.util.AEColor;
import appeng.bootstrap.IItemRendering;
import appeng.bootstrap.ItemRenderingCustomizer;
import appeng.client.render.StaticItemColor;
public class PartItemRendering extends ItemRenderingCustomizer {
private final AEColor color;
public PartItemRendering() {
this.color = AEColor.TRANSPARENT;
}
public PartItemRendering(AEColor color) {
this.color = color;
}
@Override
@Environment(EnvType.CLIENT)
public void customize(IItemRendering rendering) {
rendering.color(new StaticItemColor(color));
}
}
@@ -1,34 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.items.parts;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* This annotation is used to mark static fields or static methods that
* return/contain models used for a part. They are automatically registered as
* part of the part item registration.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.METHOD })
public @interface PartModels {
}
@@ -1,124 +0,0 @@
package appeng.items.parts;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import net.minecraft.util.Identifier;
import appeng.api.parts.IPartModel;
import appeng.core.AELog;
/**
* Helps with the reflection magic needed to gather all models for AE2 cable bus
* parts.
*/
public class PartModelsHelper {
public static List<Identifier> createModels(Class<?> clazz) {
List<Identifier> locations = new ArrayList<>();
// Check all static fields for used models
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.getAnnotation(PartModels.class) == null) {
continue;
}
if (!Modifier.isStatic(field.getModifiers())) {
AELog.error("The @PartModels annotation can only be used on static fields or methods. Was seen on: "
+ field);
continue;
}
Object value;
try {
field.setAccessible(true);
value = field.get(null);
} catch (IllegalAccessException e) {
AELog.error(e, "Cannot access field annotated with @PartModels: " + field);
continue;
}
convertAndAddLocation(field, value, locations);
}
// Check all static methods for the annotation
for (Method method : clazz.getDeclaredMethods()) {
if (method.getAnnotation(PartModels.class) == null) {
continue;
}
if (!Modifier.isStatic(method.getModifiers())) {
AELog.error("The @PartModels annotation can only be used on static fields or methods. Was seen on: "
+ method);
continue;
}
// Check for parameter count
if (method.getParameters().length != 0) {
AELog.error(
"The @PartModels annotation can only be used on static methods without parameters. Was seen on: "
+ method);
continue;
}
// Make sure we can handle the return type
Class<?> returnType = method.getReturnType();
if (!Identifier.class.isAssignableFrom(returnType)
&& !Collection.class.isAssignableFrom(returnType)) {
AELog.error(
"The @PartModels annotation can only be used on static methods that return a ResourceLocation or Collection of "
+ "ResourceLocations. Was seen on: " + method);
continue;
}
Object value;
try {
method.setAccessible(true);
value = method.invoke(null);
} catch (IllegalAccessException | InvocationTargetException e) {
AELog.error(e, "Failed to invoke the @PartModels annotated method " + method);
continue;
}
convertAndAddLocation(method, value, locations);
}
if (clazz.getSuperclass() != null) {
locations.addAll(createModels(clazz.getSuperclass()));
}
return locations;
}
private static void convertAndAddLocation(Object source, Object value, List<Identifier> locations) {
if (value == null) {
return;
}
if (value instanceof Identifier) {
locations.add((Identifier) value);
} else if (value instanceof IPartModel) {
locations.addAll(((IPartModel) value).getModels());
} else if (value instanceof Collection) {
// Check that each object is an IPartModel
Collection<?> values = (Collection<?>) value;
for (Object candidate : values) {
if (!(candidate instanceof IPartModel)) {
AELog.error("List of locations obtained from {} contains a non resource location: {}", source,
candidate);
continue;
}
locations.addAll(((IPartModel) candidate).getModels());
}
}
}
}
@@ -74,7 +74,7 @@ public class NetworkToolItem extends AEBaseItem implements IGuiItem, IAEWrench {
@Override
public TypedActionResult<ItemStack> use(final World w, final PlayerEntity p, final Hand hand) {
if (Platform.isClient()) {
final HitResult mop = AppEng.proxy.getRTR();
final HitResult mop = AppEng.instance().getRTR();
if (mop == null || mop.getType() == HitResult.Type.MISS) {
NetworkHandler.instance().sendToServer(new ClickPacket(hand));
@@ -47,7 +47,7 @@ public class ChargedStaffItem extends AEBasePoweredItem {
final float dx = (float) (Platform.getRandomFloat() * target.getWidth() + entityBoundingBox.minX);
final float dy = (float) (Platform.getRandomFloat() * target.getHeight() + entityBoundingBox.minY);
final float dz = (float) (Platform.getRandomFloat() * target.getWidth() + entityBoundingBox.minZ);
AppEng.proxy.sendToAllNearExcept(null, dx, dy, dz, 32.0, target.world,
AppEng.instance().sendToAllNearExcept(null, dx, dy, dz, 32.0, target.world,
new LightningPacket(dx, dy, dz));
}
}
@@ -205,16 +205,14 @@ public class EntropyManipulatorItem extends AEBasePoweredItem implements IBlockT
// considered for onItemUse
@Override
public TypedActionResult<ItemStack> use(final World w, final PlayerEntity p, final Hand hand) {
final HitResult target = rayTrace(w, p, RayTraceContext.FluidHandling.ANY);
final BlockHitResult target = rayTrace(w, p, RayTraceContext.FluidHandling.ANY);
if (target.getType() != HitResult.Type.BLOCK) {
return new TypedActionResult<>(ActionResult.FAIL, p.getStackInHand(hand));
} else {
BlockPos pos = ((BlockHitResult) target).getPos();
BlockPos pos = target.getBlockPos();
final BlockState state = w.getBlockState(pos);
if (state.getMaterial() == Material.LAVA || state.getMaterial() == Material.WATER) {
if (Platform.hasPermissions(new DimensionalCoord(w, pos), p)) {
ItemUsageContext context = new ItemUsageContext(p, hand, (BlockHitResult) target);
ItemUsageContext context = new ItemUsageContext(p, hand, target);
this.onItemUse(context);
}
}
@@ -327,7 +325,7 @@ public class EntropyManipulatorItem extends AEBasePoweredItem implements IBlockT
return ActionResult.FAIL;
}
if (w.isAirBlock(offsetPos)) {
if (w.isAir(offsetPos)) {
this.extractAEPower(item, 1600, Actionable.MODULATE);
w.playSound(p, offsetPos.getX() + 0.5D, offsetPos.getY() + 0.5D, offsetPos.getZ() + 0.5D,
SoundEvents.ITEM_FLINTANDSTEEL_USE, SoundCategory.PLAYERS, 1.0F,
@@ -226,7 +226,7 @@ public class MatterCannonItem extends AEBasePoweredItem implements IStorageCell<
}
try {
AppEng.proxy.sendToAllNearExcept(null, d0, d1, d2, 128, w,
AppEng.instance().sendToAllNearExcept(null, d0, d1, d2, 128, w,
new MatterCannonPacket(d0, d1, d2, (float) direction.x, (float) direction.y, (float) direction.z,
(byte) (pos.getType() == HitResult.Type.MISS ? 32
: pos.getPos().squaredDistanceTo(vec) + 1)));
@@ -265,7 +265,7 @@ public class MatterCannonItem extends AEBasePoweredItem implements IStorageCell<
}
final BlockState whatsThere = w.getBlockState(hitPos);
if (whatsThere.getMaterial().isReplaceable() && w.isAirBlock(hitPos)) {
if (whatsThere.getMaterial().isReplaceable() && w.isAir(hitPos)) {
AEApi.instance().definitions().blocks().paint().maybeBlock().ifPresent(paintBlock -> {
w.setBlockState(hitPos, paintBlock.getDefaultState(), 3);
});
@@ -335,7 +335,7 @@ public class MatterCannonItem extends AEBasePoweredItem implements IStorageCell<
}
try {
AppEng.proxy.sendToAllNearExcept(null, d0, d1, d2, 128, w,
AppEng.instance().sendToAllNearExcept(null, d0, d1, d2, 128, w,
new MatterCannonPacket(d0, d1, d2, (float) direction.x, (float) direction.y,
(float) direction.z, (byte) (pos.getType() == HitResult.Type.MISS ? 32
: pos.getPos().squaredDistanceTo(vec) + 1)));