mirror of
https://github.com/Creators-of-Create/Create.git
synced 2025-03-03 22:34:42 +01:00
Merge branch 'mc1.20.1/feature-dev' of https://github.com/Creators-of-Create/Create-Concealed into mc1.20.1/feature-dev
This commit is contained in:
commit
d821f11b32
49 changed files with 1203 additions and 860 deletions
20
changelog.md
20
changelog.md
|
@ -130,6 +130,7 @@ _Now using Flywheel 1.0_
|
|||
- Fixed vaults and tanks rotated in place not updating their multiblock correctly
|
||||
- Hose pulley now deletes lilypads and other surface foliage
|
||||
- Fixed crushing wheels not applying looting to killed entities
|
||||
- Updated contraption chunkban protections, corrected limits and made them much harder to hit
|
||||
|
||||
#### API Changes
|
||||
|
||||
|
@ -138,6 +139,7 @@ _Now using Flywheel 1.0_
|
|||
- Added `#create:chain_rideable` to mark items as valid for riding a chain with
|
||||
- Added `#create:invalid_for_track_paving` for items
|
||||
- Added `#create:sugar_cane_variants` to allow the mechanical saw to work with custom sugarcane variants (#7263)
|
||||
- Added `#create:not_harvestable` to disallow blocks that the mechanical harvester would otherwise try to harvest
|
||||
- New API for custom storage block behaviour on contraptions.
|
||||
For simple cases, create provides the `#create:simple_mounted_storage` and `#create:chest_mounted_storage` block tags.
|
||||
- Added `#create:non_breakable` to mark blocks that cannot be broken by block-breaking kinetics
|
||||
|
@ -149,6 +151,22 @@ _Now using Flywheel 1.0_
|
|||
- Synced AllPortalTracks with Create Fabric
|
||||
- Implemented DyeHelper api (#7265)
|
||||
- Implemented api to add custom block train conductors (#7030)
|
||||
- Convert Potato Cannon project types into a dynamic registry
|
||||
- Convert Potato Cannon projectile types into a dynamic registry
|
||||
- Everything can be done with datapacks now, and there is no need to write a mod unless you need to add new
|
||||
Render Modes, Entity Hit Actions or Block Hit Actions
|
||||
- Reworked the AttachedRegistry class into SimpleRegistry and added Provider functionality
|
||||
- Exposed all custom registries as API
|
||||
- Exposed a handful of previously internal classes to the API, and gave them some cleanup
|
||||
- BlockSpoutingBehaviour
|
||||
- MovementBehaviour
|
||||
- MovingInteractionBehaviour
|
||||
- DisplaySource
|
||||
- DisplayTarget
|
||||
- ContraptionMovementSetting
|
||||
- BoilerHeater
|
||||
- PortalTrackProvider
|
||||
- BlockMovementChecks
|
||||
- ContraptionType
|
||||
- MountedDispenseBehavior
|
||||
- BlockStressValues
|
||||
- OpenPipeEffectHandler
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"values": [
|
||||
"minecraft:fire"
|
||||
]
|
||||
}
|
|
@ -268,7 +268,6 @@ import com.simibubi.create.foundation.data.ModelGen;
|
|||
import com.simibubi.create.foundation.data.SharedProperties;
|
||||
import com.simibubi.create.foundation.item.ItemDescription;
|
||||
import com.simibubi.create.foundation.item.UncontainableBlockItem;
|
||||
import com.simibubi.create.foundation.utility.ColorHandlers;
|
||||
import com.simibubi.create.foundation.utility.DyeHelper;
|
||||
import com.simibubi.create.infrastructure.config.CStress;
|
||||
import com.tterrag.registrate.providers.RegistrateRecipeProvider;
|
||||
|
@ -296,6 +295,7 @@ import net.minecraft.world.item.enchantment.Enchantments;
|
|||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.IronBarsBlock;
|
||||
import net.minecraft.world.level.block.RedStoneWireBlock;
|
||||
import net.minecraft.world.level.block.RotatedPillarBlock;
|
||||
import net.minecraft.world.level.block.SoundType;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
|
@ -1259,7 +1259,8 @@ public class AllBlocks {
|
|||
.transform(pickaxeOnly())
|
||||
.blockstate(new ControllerRailGenerator()::generate)
|
||||
.addLayer(() -> RenderType::cutoutMipped)
|
||||
.color(() -> ColorHandlers::getRedstonePower)
|
||||
.color(() -> () -> (state, world, pos, layer) -> RedStoneWireBlock
|
||||
.getColorForPower(pos != null && world != null ? state.getValue(BlockStateProperties.POWER) : 0))
|
||||
.tag(BlockTags.RAILS)
|
||||
.item()
|
||||
.model((c, p) -> p.generated(c, Create.asResource("block/" + c.getName())))
|
||||
|
|
|
@ -5,7 +5,7 @@ import java.util.Map;
|
|||
import java.util.function.Supplier;
|
||||
|
||||
import com.simibubi.create.api.contraption.ContraptionType;
|
||||
import com.simibubi.create.api.registry.CreateRegistries;
|
||||
import com.simibubi.create.api.registry.CreateBuiltInRegistries;
|
||||
import com.simibubi.create.content.contraptions.Contraption;
|
||||
import com.simibubi.create.content.contraptions.bearing.BearingContraption;
|
||||
import com.simibubi.create.content.contraptions.bearing.ClockworkContraption;
|
||||
|
@ -17,34 +17,29 @@ import com.simibubi.create.content.contraptions.piston.PistonContraption;
|
|||
import com.simibubi.create.content.contraptions.pulley.PulleyContraption;
|
||||
import com.simibubi.create.content.trains.entity.CarriageContraption;
|
||||
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
import net.minecraft.core.Holder.Reference;
|
||||
import net.minecraft.core.Registry;
|
||||
|
||||
public class AllContraptionTypes {
|
||||
private static final DeferredRegister<ContraptionType> REGISTER = DeferredRegister.create(CreateRegistries.CONTRAPTION_TYPE, Create.ID);
|
||||
|
||||
public static final Map<String, ContraptionType> BY_LEGACY_NAME = new HashMap<>();
|
||||
|
||||
public static final RegistryObject<ContraptionType> PISTON = register("piston", PistonContraption::new);
|
||||
public static final RegistryObject<ContraptionType> BEARING = register("bearing", BearingContraption::new);
|
||||
public static final RegistryObject<ContraptionType> PULLEY = register("pulley", PulleyContraption::new);
|
||||
public static final RegistryObject<ContraptionType> CLOCKWORK = register("clockwork", ClockworkContraption::new);
|
||||
public static final RegistryObject<ContraptionType> MOUNTED = register("mounted", MountedContraption::new);
|
||||
public static final RegistryObject<ContraptionType> STABILIZED = register("stabilized", StabilizedContraption::new);
|
||||
public static final RegistryObject<ContraptionType> GANTRY = register("gantry", GantryContraption::new);
|
||||
public static final RegistryObject<ContraptionType> CARRIAGE = register("carriage", CarriageContraption::new);
|
||||
public static final RegistryObject<ContraptionType> ELEVATOR = register("elevator", ElevatorContraption::new);
|
||||
public static final Reference<ContraptionType> PISTON = register("piston", PistonContraption::new);
|
||||
public static final Reference<ContraptionType> BEARING = register("bearing", BearingContraption::new);
|
||||
public static final Reference<ContraptionType> PULLEY = register("pulley", PulleyContraption::new);
|
||||
public static final Reference<ContraptionType> CLOCKWORK = register("clockwork", ClockworkContraption::new);
|
||||
public static final Reference<ContraptionType> MOUNTED = register("mounted", MountedContraption::new);
|
||||
public static final Reference<ContraptionType> STABILIZED = register("stabilized", StabilizedContraption::new);
|
||||
public static final Reference<ContraptionType> GANTRY = register("gantry", GantryContraption::new);
|
||||
public static final Reference<ContraptionType> CARRIAGE = register("carriage", CarriageContraption::new);
|
||||
public static final Reference<ContraptionType> ELEVATOR = register("elevator", ElevatorContraption::new);
|
||||
|
||||
private static RegistryObject<ContraptionType> register(String name, Supplier<? extends Contraption> factory) {
|
||||
return REGISTER.register(name, () -> {
|
||||
ContraptionType type = new ContraptionType(factory);
|
||||
BY_LEGACY_NAME.put(name, type);
|
||||
return type;
|
||||
});
|
||||
private static Reference<ContraptionType> register(String name, Supplier<? extends Contraption> factory) {
|
||||
ContraptionType type = new ContraptionType(factory);
|
||||
BY_LEGACY_NAME.put(name, type);
|
||||
|
||||
return Registry.registerForHolder(CreateBuiltInRegistries.CONTRAPTION_TYPE, Create.asResource(name), type);
|
||||
}
|
||||
|
||||
public static void register(IEventBus modEventBus) {
|
||||
REGISTER.register(modEventBus);
|
||||
public static void init() {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,6 +130,7 @@ public class AllPartialModels {
|
|||
CHAIN_CONVEYOR_SHAFT = block("chain_conveyor/shaft"),
|
||||
|
||||
FROGPORT_BODY = block("package_frogport/body"), FROGPORT_HEAD = block("package_frogport/head"),
|
||||
FROGPORT_HEAD_GOGGLES = block("package_frogport/head_goggles"),
|
||||
FROGPORT_TONGUE = block("package_frogport/tongue"),
|
||||
POSTBOX_FLAG = block("package_postbox/flag"),
|
||||
|
||||
|
|
|
@ -113,6 +113,7 @@ public class AllTags {
|
|||
FALLBACK_MOUNTED_STORAGE_BLACKLIST,
|
||||
ROOTS,
|
||||
SUGAR_CANE_VARIANTS,
|
||||
NON_HARVESTABLE,
|
||||
|
||||
CORALS,
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ import com.simibubi.create.content.schematics.ServerSchematicLoader;
|
|||
import com.simibubi.create.content.trains.GlobalRailwayManager;
|
||||
import com.simibubi.create.content.trains.bogey.BogeySizes;
|
||||
import com.simibubi.create.content.trains.track.AllPortalTracks;
|
||||
import com.simibubi.create.foundation.CreateNBTProcessors;
|
||||
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
||||
import com.simibubi.create.foundation.advancement.AllTriggers;
|
||||
import com.simibubi.create.foundation.block.CopperRegistries;
|
||||
|
@ -33,7 +34,6 @@ import com.simibubi.create.foundation.data.CreateRegistrate;
|
|||
import com.simibubi.create.foundation.item.ItemDescription;
|
||||
import com.simibubi.create.foundation.item.KineticStats;
|
||||
import com.simibubi.create.foundation.item.TooltipModifier;
|
||||
import com.simibubi.create.foundation.utility.CreateNBTProcessors;
|
||||
import com.simibubi.create.infrastructure.command.ServerLagger;
|
||||
import com.simibubi.create.infrastructure.config.AllConfigs;
|
||||
import com.simibubi.create.infrastructure.data.CreateDatagen;
|
||||
|
@ -137,12 +137,6 @@ public class Create {
|
|||
|
||||
AllConfigs.register(modLoadingContext);
|
||||
|
||||
// TODO - Make these use Registry.register and move them into the RegisterEvent
|
||||
AllArmInteractionPointTypes.register(modEventBus);
|
||||
AllFanProcessingTypes.register(modEventBus);
|
||||
AllItemAttributeTypes.register(modEventBus);
|
||||
AllContraptionTypes.register(modEventBus);
|
||||
|
||||
// FIXME: some of these registrations are not thread-safe
|
||||
BogeySizes.init();
|
||||
AllBogeyStyles.init();
|
||||
|
@ -189,6 +183,10 @@ public class Create {
|
|||
}
|
||||
|
||||
public static void onRegister(final RegisterEvent event) {
|
||||
AllArmInteractionPointTypes.init();
|
||||
AllFanProcessingTypes.init();
|
||||
AllItemAttributeTypes.init();
|
||||
AllContraptionTypes.init();
|
||||
AllPotatoProjectileRenderModes.init();
|
||||
AllPotatoProjectileEntityHitActions.init();
|
||||
AllPotatoProjectileBlockHitActions.init();
|
||||
|
|
|
@ -20,9 +20,9 @@ import com.simibubi.create.content.schematics.client.SchematicHandler;
|
|||
import com.simibubi.create.content.trains.GlobalRailwayManager;
|
||||
import com.simibubi.create.foundation.ClientResourceReloadListener;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsClient;
|
||||
import com.simibubi.create.foundation.model.ModelSwapper;
|
||||
import com.simibubi.create.foundation.ponder.CreatePonderPlugin;
|
||||
import com.simibubi.create.foundation.render.AllInstanceTypes;
|
||||
import com.simibubi.create.foundation.utility.ModelSwapper;
|
||||
import com.simibubi.create.infrastructure.config.AllConfigs;
|
||||
import com.simibubi.create.infrastructure.gui.CreateMainMenuScreen;
|
||||
|
||||
|
@ -40,6 +40,7 @@ import net.minecraft.network.chat.Component;
|
|||
import net.minecraft.network.chat.ComponentUtils;
|
||||
import net.minecraft.network.chat.HoverEvent;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||
|
||||
|
|
|
@ -4,8 +4,6 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import com.simibubi.create.api.equipment.potatoCannon.PotatoProjectileEntityHitAction.Type;
|
||||
|
@ -17,15 +15,12 @@ import com.simibubi.create.content.equipment.potatoCannon.AllPotatoProjectileRen
|
|||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Holder.Reference;
|
||||
import net.minecraft.core.HolderSet;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.core.RegistryCodecs;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.data.worldgen.BootstapContext;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.EntityHitResult;
|
||||
|
@ -55,26 +50,12 @@ public record PotatoCannonProjectileType(HolderSet<Item> items, int reloadTicks,
|
|||
PotatoProjectileBlockHitAction.CODEC.optionalFieldOf("on_entity_hit").forGetter(p -> p.onBlockHit)
|
||||
).apply(i, PotatoCannonProjectileType::new));
|
||||
|
||||
@Nullable
|
||||
public static PotatoCannonProjectileType getTypeForItem(Level level, Item item) {
|
||||
public static Optional<Reference<PotatoCannonProjectileType>> getTypeForItem(RegistryAccess registryAccess, Item item) {
|
||||
// Cache this if it causes performance issues, but it probably won't
|
||||
List<PotatoCannonProjectileType> types = level.registryAccess()
|
||||
.lookupOrThrow(CreateRegistries.POTATO_PROJECTILE_TYPE)
|
||||
return registryAccess.lookupOrThrow(CreateRegistries.POTATO_PROJECTILE_TYPE)
|
||||
.listElements()
|
||||
.map(Reference::value)
|
||||
.toList();
|
||||
|
||||
for (PotatoCannonProjectileType type : types)
|
||||
if (type.items.contains(item.builtInRegistryHolder()))
|
||||
return type;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Optional<PotatoCannonProjectileType> getTypeForStack(Level level, ItemStack item) {
|
||||
if (item.isEmpty())
|
||||
return Optional.empty();
|
||||
return Optional.ofNullable(getTypeForItem(level, item.getItem()));
|
||||
.filter(ref -> ref.value().items.contains(item.builtInRegistryHolder()))
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
public boolean preEntityHit(ItemStack stack, EntityHitResult ray) {
|
||||
|
@ -96,8 +77,6 @@ public record PotatoCannonProjectileType(HolderSet<Item> items, int reloadTicks,
|
|||
}
|
||||
|
||||
public static class Builder {
|
||||
private ResourceLocation id;
|
||||
|
||||
private final List<Holder<Item>> items = new ArrayList<>();
|
||||
private int reloadTicks = 10;
|
||||
private int damage = 1;
|
||||
|
@ -114,10 +93,6 @@ public record PotatoCannonProjectileType(HolderSet<Item> items, int reloadTicks,
|
|||
private PotatoProjectileEntityHitAction onEntityHit = null;
|
||||
private PotatoProjectileBlockHitAction onBlockHit = null;
|
||||
|
||||
public Builder(ResourceLocation id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Builder reloadTicks(int reload) {
|
||||
this.reloadTicks = reload;
|
||||
return this;
|
||||
|
@ -209,8 +184,8 @@ public record PotatoCannonProjectileType(HolderSet<Item> items, int reloadTicks,
|
|||
return this;
|
||||
}
|
||||
|
||||
public void register(BootstapContext<PotatoCannonProjectileType> ctx) {
|
||||
PotatoCannonProjectileType type = new PotatoCannonProjectileType(
|
||||
public PotatoCannonProjectileType build() {
|
||||
return new PotatoCannonProjectileType(
|
||||
HolderSet.direct(items),
|
||||
reloadTicks,
|
||||
damage,
|
||||
|
@ -227,12 +202,6 @@ public record PotatoCannonProjectileType(HolderSet<Item> items, int reloadTicks,
|
|||
Optional.ofNullable(onEntityHit),
|
||||
Optional.ofNullable(onBlockHit)
|
||||
);
|
||||
ctx.register(ResourceKey.create(CreateRegistries.POTATO_PROJECTILE_TYPE, id), type);
|
||||
}
|
||||
|
||||
public void registerAndAssign(BootstapContext<PotatoCannonProjectileType> ctx, ItemLike... items) {
|
||||
addItems(items);
|
||||
register(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,6 @@ import com.simibubi.create.content.trains.bogey.AbstractBogeyBlock;
|
|||
import com.simibubi.create.foundation.blockEntity.IMultiBlockEntityContainer;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour;
|
||||
import com.simibubi.create.foundation.utility.BlockHelper;
|
||||
import com.simibubi.create.foundation.utility.ICoordinate;
|
||||
import com.simibubi.create.infrastructure.config.AllConfigs;
|
||||
|
||||
import net.createmod.catnip.data.Iterate;
|
||||
|
@ -86,6 +85,7 @@ import net.minecraft.core.BlockPos;
|
|||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.core.HolderGetter;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
|
@ -1389,7 +1389,7 @@ public abstract class Contraption {
|
|||
public void expandBoundsAroundAxis(Axis axis) {
|
||||
Set<BlockPos> blocks = getBlocks().keySet();
|
||||
|
||||
int radius = (int) (Math.ceil(Math.sqrt(getRadius(blocks, axis))));
|
||||
int radius = (int) (Math.ceil(getRadius(blocks, axis)));
|
||||
|
||||
int maxX = radius + 2;
|
||||
int maxY = radius + 2;
|
||||
|
@ -1398,13 +1398,13 @@ public abstract class Contraption {
|
|||
int minY = -radius - 1;
|
||||
int minZ = -radius - 1;
|
||||
|
||||
if (axis == Direction.Axis.X) {
|
||||
if (axis == Axis.X) {
|
||||
maxX = (int) bounds.maxX;
|
||||
minX = (int) bounds.minX;
|
||||
} else if (axis == Direction.Axis.Y) {
|
||||
} else if (axis == Axis.Y) {
|
||||
maxY = (int) bounds.maxY;
|
||||
minY = (int) bounds.minY;
|
||||
} else if (axis == Direction.Axis.Z) {
|
||||
} else if (axis == Axis.Z) {
|
||||
maxZ = (int) bounds.maxZ;
|
||||
minZ = (int) bounds.minZ;
|
||||
}
|
||||
|
@ -1489,32 +1489,38 @@ public abstract class Contraption {
|
|||
});
|
||||
}
|
||||
|
||||
public static float getRadius(Set<BlockPos> blocks, Direction.Axis axis) {
|
||||
public static double getRadius(Iterable<? extends Vec3i> blocks, Axis axis) {
|
||||
Axis axisA;
|
||||
Axis axisB;
|
||||
|
||||
switch (axis) {
|
||||
case X:
|
||||
return getMaxDistSqr(blocks, BlockPos::getY, BlockPos::getZ);
|
||||
case Y:
|
||||
return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getZ);
|
||||
case Z:
|
||||
return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getY);
|
||||
case X -> {
|
||||
axisA = Axis.Y;
|
||||
axisB = Axis.Z;
|
||||
}
|
||||
case Y -> {
|
||||
axisA = Axis.X;
|
||||
axisB = Axis.Z;
|
||||
}
|
||||
case Z -> {
|
||||
axisA = Axis.X;
|
||||
axisB = Axis.Y;
|
||||
}
|
||||
default -> throw new IllegalStateException("Unexpected value: " + axis);
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Impossible axis");
|
||||
}
|
||||
int maxDistSq = 0;
|
||||
for (Vec3i vec : blocks) {
|
||||
int a = vec.get(axisA);
|
||||
int b = vec.get(axisB);
|
||||
|
||||
public static float getMaxDistSqr(Set<BlockPos> blocks, ICoordinate one, ICoordinate other) {
|
||||
float maxDistSq = -1;
|
||||
for (BlockPos pos : blocks) {
|
||||
float a = one.get(pos);
|
||||
float b = other.get(pos);
|
||||
|
||||
float distSq = a * a + b * b;
|
||||
int distSq = a * a + b * b;
|
||||
|
||||
if (distSq > maxDistSq)
|
||||
maxDistSq = distSq;
|
||||
}
|
||||
|
||||
return maxDistSq;
|
||||
return Math.sqrt(maxDistSq);
|
||||
}
|
||||
|
||||
public MountedStorageManager getStorage() {
|
||||
|
|
|
@ -57,12 +57,15 @@ public class HarvesterMovementBehaviour implements MovementBehaviour {
|
|||
@Override
|
||||
public void visitNewPosition(MovementContext context, BlockPos pos) {
|
||||
Level world = context.world;
|
||||
BlockState stateVisited = world.getBlockState(pos);
|
||||
boolean notCropButCuttable = false;
|
||||
|
||||
if (world.isClientSide)
|
||||
return;
|
||||
|
||||
BlockState stateVisited = world.getBlockState(pos);
|
||||
if (stateVisited.isAir() || AllBlockTags.NON_HARVESTABLE.matches(stateVisited))
|
||||
return;
|
||||
|
||||
boolean notCropButCuttable = false;
|
||||
|
||||
if (!isValidCrop(world, pos, stateVisited)) {
|
||||
if (isValidOther(world, pos, stateVisited))
|
||||
notCropButCuttable = true;
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package com.simibubi.create.content.equipment.clipboard;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.simibubi.create.foundation.utility.CreateNBTProcessors;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.foundation.CreateNBTProcessors;
|
||||
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
|
@ -11,9 +12,8 @@ import net.minecraft.network.FriendlyByteBuf;
|
|||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraftforge.network.NetworkEvent.Context;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraftforge.network.NetworkEvent.Context;
|
||||
|
||||
public class ClipboardEditPacket extends SimplePacketBase {
|
||||
|
||||
|
|
|
@ -21,32 +21,34 @@ import net.minecraft.world.item.Items;
|
|||
import net.minecraft.world.level.block.Blocks;
|
||||
|
||||
public class AllPotatoProjectileTypes {
|
||||
public static ResourceKey<PotatoCannonProjectileType> FALLBACK = ResourceKey.create(CreateRegistries.POTATO_PROJECTILE_TYPE, Create.asResource("fallback"));
|
||||
public static final ResourceKey<PotatoCannonProjectileType> FALLBACK = ResourceKey.create(CreateRegistries.POTATO_PROJECTILE_TYPE, Create.asResource("fallback"));
|
||||
|
||||
public static void bootstrap(BootstapContext<PotatoCannonProjectileType> ctx) {
|
||||
create("fallback")
|
||||
register(ctx, "fallback", new PotatoCannonProjectileType.Builder()
|
||||
.damage(0)
|
||||
.register(ctx);
|
||||
.build());
|
||||
|
||||
create("potato")
|
||||
register(ctx, "potato", new PotatoCannonProjectileType.Builder()
|
||||
.damage(5)
|
||||
.reloadTicks(15)
|
||||
.velocity(1.25f)
|
||||
.knockback(1.5f)
|
||||
.renderTumbling()
|
||||
.onBlockHit(new PlantCrop(Blocks.POTATOES))
|
||||
.registerAndAssign(ctx, Items.POTATO);
|
||||
.addItems(Items.POTATO)
|
||||
.build());
|
||||
|
||||
create("baked_potato")
|
||||
register(ctx, "baked_potato", new PotatoCannonProjectileType.Builder()
|
||||
.damage(5)
|
||||
.reloadTicks(15)
|
||||
.velocity(1.25f)
|
||||
.knockback(0.5f)
|
||||
.renderTumbling()
|
||||
.preEntityHit(SetOnFire.seconds(3))
|
||||
.registerAndAssign(ctx, Items.BAKED_POTATO);
|
||||
.addItems(Items.BAKED_POTATO)
|
||||
.build());
|
||||
|
||||
create("carrot")
|
||||
register(ctx, "carrot", new PotatoCannonProjectileType.Builder()
|
||||
.damage(4)
|
||||
.reloadTicks(12)
|
||||
.velocity(1.45f)
|
||||
|
@ -54,18 +56,20 @@ public class AllPotatoProjectileTypes {
|
|||
.renderTowardMotion(140, 1)
|
||||
.soundPitch(1.5f)
|
||||
.onBlockHit(new PlantCrop(Blocks.CARROTS))
|
||||
.registerAndAssign(ctx, Items.CARROT);
|
||||
.addItems(Items.CARROT)
|
||||
.build());
|
||||
|
||||
create("golden_carrot")
|
||||
register(ctx, "golden_carrot", new PotatoCannonProjectileType.Builder()
|
||||
.damage(12)
|
||||
.reloadTicks(15)
|
||||
.velocity(1.45f)
|
||||
.knockback(0.5f)
|
||||
.renderTowardMotion(140, 2)
|
||||
.soundPitch(1.5f)
|
||||
.registerAndAssign(ctx, Items.GOLDEN_CARROT);
|
||||
.addItems(Items.GOLDEN_CARROT)
|
||||
.build());
|
||||
|
||||
create("sweet_berry")
|
||||
register(ctx, "sweet_berry", new PotatoCannonProjectileType.Builder()
|
||||
.damage(3)
|
||||
.reloadTicks(10)
|
||||
.knockback(0.1f)
|
||||
|
@ -73,9 +77,10 @@ public class AllPotatoProjectileTypes {
|
|||
.renderTumbling()
|
||||
.splitInto(3)
|
||||
.soundPitch(1.25f)
|
||||
.registerAndAssign(ctx, Items.SWEET_BERRIES);
|
||||
.addItems(Items.SWEET_BERRIES)
|
||||
.build());
|
||||
|
||||
create("glow_berry")
|
||||
register(ctx, "glow_berry", new PotatoCannonProjectileType.Builder()
|
||||
.damage(2)
|
||||
.reloadTicks(10)
|
||||
.knockback(0.05f)
|
||||
|
@ -84,9 +89,10 @@ public class AllPotatoProjectileTypes {
|
|||
.splitInto(2)
|
||||
.soundPitch(1.2f)
|
||||
.onEntityHit(new PotionEffect(MobEffects.GLOWING, 1, 200, false))
|
||||
.registerAndAssign(ctx, Items.GLOW_BERRIES);
|
||||
.addItems(Items.GLOW_BERRIES)
|
||||
.build());
|
||||
|
||||
create("chocolate_berry")
|
||||
register(ctx, "chocolate_berry", new PotatoCannonProjectileType.Builder()
|
||||
.damage(4)
|
||||
.reloadTicks(10)
|
||||
.knockback(0.2f)
|
||||
|
@ -94,36 +100,40 @@ public class AllPotatoProjectileTypes {
|
|||
.renderTumbling()
|
||||
.splitInto(3)
|
||||
.soundPitch(1.25f)
|
||||
.registerAndAssign(ctx, AllItems.CHOCOLATE_BERRIES.get());
|
||||
.addItems(AllItems.CHOCOLATE_BERRIES.get())
|
||||
.build());
|
||||
|
||||
create("poison_potato")
|
||||
register(ctx, "poison_potato", new PotatoCannonProjectileType.Builder()
|
||||
.damage(5)
|
||||
.reloadTicks(15)
|
||||
.knockback(0.05f)
|
||||
.velocity(1.25f)
|
||||
.renderTumbling()
|
||||
.onEntityHit(new PotionEffect(MobEffects.POISON, 1, 160, true))
|
||||
.registerAndAssign(ctx, Items.POISONOUS_POTATO);
|
||||
.addItems(Items.POISONOUS_POTATO)
|
||||
.build());
|
||||
|
||||
create("chorus_fruit")
|
||||
register(ctx, "chorus_fruit", new PotatoCannonProjectileType.Builder()
|
||||
.damage(3)
|
||||
.reloadTicks(15)
|
||||
.velocity(1.20f)
|
||||
.knockback(0.05f)
|
||||
.renderTumbling()
|
||||
.onEntityHit(new ChorusTeleport(20))
|
||||
.registerAndAssign(ctx, Items.CHORUS_FRUIT);
|
||||
.addItems(Items.CHORUS_FRUIT)
|
||||
.build());
|
||||
|
||||
create("apple")
|
||||
register(ctx, "apple", new PotatoCannonProjectileType.Builder()
|
||||
.damage(5)
|
||||
.reloadTicks(10)
|
||||
.velocity(1.45f)
|
||||
.knockback(0.5f)
|
||||
.renderTumbling()
|
||||
.soundPitch(1.1f)
|
||||
.registerAndAssign(ctx, Items.APPLE);
|
||||
.addItems(Items.APPLE)
|
||||
.build());
|
||||
|
||||
create("honeyed_apple")
|
||||
register(ctx, "honeyed_apple", new PotatoCannonProjectileType.Builder()
|
||||
.damage(6)
|
||||
.reloadTicks(15)
|
||||
.velocity(1.35f)
|
||||
|
@ -131,9 +141,10 @@ public class AllPotatoProjectileTypes {
|
|||
.renderTumbling()
|
||||
.soundPitch(1.1f)
|
||||
.onEntityHit(new PotionEffect(MobEffects.MOVEMENT_SLOWDOWN, 2, 160, true))
|
||||
.registerAndAssign(ctx, AllItems.HONEYED_APPLE.get());
|
||||
.addItems(AllItems.HONEYED_APPLE.get())
|
||||
.build());
|
||||
|
||||
create("golden_apple")
|
||||
register(ctx, "golden_apple", new PotatoCannonProjectileType.Builder()
|
||||
.damage(1)
|
||||
.reloadTicks(100)
|
||||
.velocity(1.45f)
|
||||
|
@ -141,9 +152,10 @@ public class AllPotatoProjectileTypes {
|
|||
.renderTumbling()
|
||||
.soundPitch(1.1f)
|
||||
.onEntityHit(CureZombieVillager.INSTANCE)
|
||||
.registerAndAssign(ctx, Items.GOLDEN_APPLE);
|
||||
.addItems(Items.GOLDEN_APPLE)
|
||||
.build());
|
||||
|
||||
create("enchanted_golden_apple")
|
||||
register(ctx, "enchanted_golden_apple", new PotatoCannonProjectileType.Builder()
|
||||
.damage(1)
|
||||
.reloadTicks(100)
|
||||
.velocity(1.45f)
|
||||
|
@ -151,27 +163,30 @@ public class AllPotatoProjectileTypes {
|
|||
.renderTumbling()
|
||||
.soundPitch(1.1f)
|
||||
.onEntityHit(new FoodEffects(Foods.ENCHANTED_GOLDEN_APPLE, false))
|
||||
.registerAndAssign(ctx, Items.ENCHANTED_GOLDEN_APPLE);
|
||||
.addItems(Items.ENCHANTED_GOLDEN_APPLE)
|
||||
.build());
|
||||
|
||||
create("beetroot")
|
||||
register(ctx, "beetroot", new PotatoCannonProjectileType.Builder()
|
||||
.damage(2)
|
||||
.reloadTicks(5)
|
||||
.velocity(1.6f)
|
||||
.knockback(0.1f)
|
||||
.renderTowardMotion(140, 2)
|
||||
.soundPitch(1.6f)
|
||||
.registerAndAssign(ctx, Items.BEETROOT);
|
||||
.addItems(Items.BEETROOT)
|
||||
.build());
|
||||
|
||||
create("melon_slice")
|
||||
register(ctx, "melon_slice", new PotatoCannonProjectileType.Builder()
|
||||
.damage(3)
|
||||
.reloadTicks(8)
|
||||
.knockback(0.1f)
|
||||
.velocity(1.45f)
|
||||
.renderTumbling()
|
||||
.soundPitch(1.5f)
|
||||
.registerAndAssign(ctx, Items.MELON_SLICE);
|
||||
.addItems(Items.MELON_SLICE)
|
||||
.build());
|
||||
|
||||
create("glistering_melon")
|
||||
register(ctx, "glistering_melon", new PotatoCannonProjectileType.Builder()
|
||||
.damage(5)
|
||||
.reloadTicks(8)
|
||||
.knockback(0.1f)
|
||||
|
@ -179,9 +194,10 @@ public class AllPotatoProjectileTypes {
|
|||
.renderTumbling()
|
||||
.soundPitch(1.5f)
|
||||
.onEntityHit(new PotionEffect(MobEffects.GLOWING, 1, 100, true))
|
||||
.registerAndAssign(ctx, Items.GLISTERING_MELON_SLICE);
|
||||
.addItems(Items.GLISTERING_MELON_SLICE)
|
||||
.build());
|
||||
|
||||
create("melon_block")
|
||||
register(ctx, "melon_block", new PotatoCannonProjectileType.Builder()
|
||||
.damage(8)
|
||||
.reloadTicks(20)
|
||||
.knockback(2.0f)
|
||||
|
@ -189,9 +205,10 @@ public class AllPotatoProjectileTypes {
|
|||
.renderTumbling()
|
||||
.soundPitch(0.9f)
|
||||
.onBlockHit(new PlaceBlockOnGround(Blocks.MELON))
|
||||
.registerAndAssign(ctx, Blocks.MELON);
|
||||
.addItems(Blocks.MELON)
|
||||
.build());
|
||||
|
||||
create("pumpkin_block")
|
||||
register(ctx, "pumpkin_block", new PotatoCannonProjectileType.Builder()
|
||||
.damage(6)
|
||||
.reloadTicks(15)
|
||||
.knockback(2.0f)
|
||||
|
@ -199,9 +216,10 @@ public class AllPotatoProjectileTypes {
|
|||
.renderTumbling()
|
||||
.soundPitch(0.9f)
|
||||
.onBlockHit(new PlaceBlockOnGround(Blocks.PUMPKIN))
|
||||
.registerAndAssign(ctx, Blocks.PUMPKIN);
|
||||
.addItems(Blocks.PUMPKIN)
|
||||
.build());
|
||||
|
||||
create("pumpkin_pie")
|
||||
register(ctx, "pumpkin_pie", new PotatoCannonProjectileType.Builder()
|
||||
.damage(7)
|
||||
.reloadTicks(15)
|
||||
.knockback(0.05f)
|
||||
|
@ -209,18 +227,20 @@ public class AllPotatoProjectileTypes {
|
|||
.renderTumbling()
|
||||
.sticky()
|
||||
.soundPitch(1.1f)
|
||||
.registerAndAssign(ctx, Items.PUMPKIN_PIE);
|
||||
.addItems(Items.PUMPKIN_PIE)
|
||||
.build());
|
||||
|
||||
create("cake")
|
||||
register(ctx, "cake", new PotatoCannonProjectileType.Builder()
|
||||
.damage(8)
|
||||
.reloadTicks(15)
|
||||
.knockback(0.1f)
|
||||
.velocity(1.1f)
|
||||
.renderTumbling()
|
||||
.sticky()
|
||||
.registerAndAssign(ctx, Items.CAKE);
|
||||
.addItems(Items.CAKE)
|
||||
.build());
|
||||
|
||||
create("blaze_cake")
|
||||
register(ctx, "blaze_cake", new PotatoCannonProjectileType.Builder()
|
||||
.damage(15)
|
||||
.reloadTicks(20)
|
||||
.knockback(0.3f)
|
||||
|
@ -228,18 +248,20 @@ public class AllPotatoProjectileTypes {
|
|||
.renderTumbling()
|
||||
.sticky()
|
||||
.preEntityHit(SetOnFire.seconds(12))
|
||||
.registerAndAssign(ctx, AllItems.BLAZE_CAKE.get());
|
||||
.addItems(AllItems.BLAZE_CAKE.get())
|
||||
.build());
|
||||
|
||||
create("fish")
|
||||
register(ctx, "fish", new PotatoCannonProjectileType.Builder()
|
||||
.damage(4)
|
||||
.knockback(0.6f)
|
||||
.velocity(1.3f)
|
||||
.renderTowardMotion(140, 1)
|
||||
.sticky()
|
||||
.soundPitch(1.3f)
|
||||
.registerAndAssign(ctx, Items.COD, Items.COOKED_COD, Items.SALMON, Items.COOKED_SALMON, Items.TROPICAL_FISH);
|
||||
.addItems(Items.COD, Items.COOKED_COD, Items.SALMON, Items.COOKED_SALMON, Items.TROPICAL_FISH)
|
||||
.build());
|
||||
|
||||
create("pufferfish")
|
||||
register(ctx, "pufferfish", new PotatoCannonProjectileType.Builder()
|
||||
.damage(4)
|
||||
.knockback(0.4f)
|
||||
.velocity(1.1f)
|
||||
|
@ -247,9 +269,10 @@ public class AllPotatoProjectileTypes {
|
|||
.sticky()
|
||||
.onEntityHit(new FoodEffects(Foods.PUFFERFISH, false))
|
||||
.soundPitch(1.1f)
|
||||
.registerAndAssign(ctx, Items.PUFFERFISH);
|
||||
.addItems(Items.PUFFERFISH)
|
||||
.build());
|
||||
|
||||
create("suspicious_stew")
|
||||
register(ctx, "suspicious_stew", new PotatoCannonProjectileType.Builder()
|
||||
.damage(3)
|
||||
.reloadTicks(40)
|
||||
.knockback(0.2f)
|
||||
|
@ -257,10 +280,11 @@ public class AllPotatoProjectileTypes {
|
|||
.renderTowardMotion(140, 1)
|
||||
.dropStack(Items.BOWL.getDefaultInstance())
|
||||
.onEntityHit(SuspiciousStew.INSTANCE)
|
||||
.registerAndAssign(ctx, Items.SUSPICIOUS_STEW);
|
||||
.addItems(Items.SUSPICIOUS_STEW)
|
||||
.build());
|
||||
}
|
||||
|
||||
private static PotatoCannonProjectileType.Builder create(String name) {
|
||||
return new PotatoCannonProjectileType.Builder(Create.asResource(name));
|
||||
private static void register(BootstapContext<PotatoCannonProjectileType> ctx, String name, PotatoCannonProjectileType type) {
|
||||
ctx.register(ResourceKey.create(CreateRegistries.POTATO_PROJECTILE_TYPE, Create.asResource(name)), type);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,15 +11,14 @@ import com.simibubi.create.AllEnchantments;
|
|||
import com.simibubi.create.AllEntityTypes;
|
||||
import com.simibubi.create.CreateClient;
|
||||
import com.simibubi.create.api.equipment.potatoCannon.PotatoCannonProjectileType;
|
||||
import com.simibubi.create.api.registry.CreateRegistries;
|
||||
import com.simibubi.create.content.equipment.armor.BacktankUtil;
|
||||
import com.simibubi.create.content.equipment.zapper.ShootableGadgetItemMethods;
|
||||
import com.simibubi.create.foundation.item.CustomArmPoseItem;
|
||||
import com.simibubi.create.foundation.item.render.SimpleCustomRenderer;
|
||||
import com.simibubi.create.foundation.utility.CreateLang;
|
||||
import com.simibubi.create.foundation.utility.GlobalRegistryAccess;
|
||||
import com.simibubi.create.infrastructure.config.AllConfigs;
|
||||
|
||||
import net.createmod.catnip.animation.AnimationTickHolder;
|
||||
import net.createmod.catnip.math.VecHelper;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
@ -28,6 +27,7 @@ import net.minecraft.client.player.AbstractClientPlayer;
|
|||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.network.chat.CommonComponents;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
|
@ -51,22 +51,188 @@ import net.minecraft.world.phys.Vec3;
|
|||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.client.extensions.common.IClientItemExtensions;
|
||||
import net.minecraftforge.server.ServerLifecycleHooks;
|
||||
|
||||
public class PotatoCannonItem extends ProjectileWeaponItem implements CustomArmPoseItem {
|
||||
|
||||
public static ItemStack CLIENT_CURRENT_AMMO = ItemStack.EMPTY;
|
||||
public static final int MAX_DAMAGE = 100;
|
||||
|
||||
public PotatoCannonItem(Properties properties) {
|
||||
super(properties.defaultDurability(MAX_DAMAGE));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Ammo getAmmo(Player player, ItemStack heldStack) {
|
||||
ItemStack ammoStack = player.getProjectile(heldStack);
|
||||
if (ammoStack.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Optional<Holder.Reference<PotatoCannonProjectileType>> optionalType = PotatoCannonProjectileType.getTypeForItem(player.level().registryAccess(), ammoStack.getItem());
|
||||
if (optionalType.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Ammo(ammoStack, optionalType.get().get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult useOn(UseOnContext context) {
|
||||
return use(context.getLevel(), context.getPlayer(), context.getHand()).getResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {
|
||||
ItemStack heldStack = player.getItemInHand(hand);
|
||||
if (ShootableGadgetItemMethods.shouldSwap(player, heldStack, hand, s -> s.getItem() instanceof PotatoCannonItem)) {
|
||||
return InteractionResultHolder.fail(heldStack);
|
||||
}
|
||||
|
||||
Ammo ammo = getAmmo(player, heldStack);
|
||||
if (ammo == null) {
|
||||
return InteractionResultHolder.pass(heldStack);
|
||||
}
|
||||
ItemStack ammoStack = ammo.stack();
|
||||
PotatoCannonProjectileType projectileType = ammo.type();
|
||||
|
||||
if (level.isClientSide) {
|
||||
CreateClient.POTATO_CANNON_RENDER_HANDLER.dontAnimateItem(hand);
|
||||
return InteractionResultHolder.success(heldStack);
|
||||
}
|
||||
|
||||
Vec3 barrelPos = ShootableGadgetItemMethods.getGunBarrelVec(player, hand == InteractionHand.MAIN_HAND,
|
||||
new Vec3(.75f, -0.15f, 1.5f));
|
||||
Vec3 correction =
|
||||
ShootableGadgetItemMethods.getGunBarrelVec(player, hand == InteractionHand.MAIN_HAND, new Vec3(-.05f, 0, 0))
|
||||
.subtract(player.position()
|
||||
.add(0, player.getEyeHeight(), 0));
|
||||
|
||||
Vec3 lookVec = player.getLookAngle();
|
||||
Vec3 motion = lookVec.add(correction)
|
||||
.normalize()
|
||||
.scale(2)
|
||||
.scale(projectileType.velocityMultiplier());
|
||||
|
||||
float soundPitch = projectileType.soundPitch() + (level.getRandom().nextFloat() - .5f) / 4f;
|
||||
|
||||
boolean spray = projectileType.split() > 1;
|
||||
Vec3 sprayBase = VecHelper.rotate(new Vec3(0, 0.1, 0), 360 * level.getRandom().nextFloat(), Axis.Z);
|
||||
float sprayChange = 360f / projectileType.split();
|
||||
|
||||
ItemStack ammoStackCopy = ammoStack.copy();
|
||||
|
||||
for (int i = 0; i < projectileType.split(); i++) {
|
||||
PotatoProjectileEntity projectile = AllEntityTypes.POTATO_PROJECTILE.create(level);
|
||||
projectile.setItem(ammoStackCopy);
|
||||
projectile.setEnchantmentEffectsFromCannon(heldStack);
|
||||
|
||||
Vec3 splitMotion = motion;
|
||||
if (spray) {
|
||||
float imperfection = 40 * (level.getRandom().nextFloat() - 0.5f);
|
||||
Vec3 sprayOffset = VecHelper.rotate(sprayBase, i * sprayChange + imperfection, Axis.Z);
|
||||
splitMotion = splitMotion.add(VecHelper.lookAt(sprayOffset, motion));
|
||||
}
|
||||
|
||||
if (i != 0)
|
||||
projectile.recoveryChance = 0;
|
||||
|
||||
projectile.setPos(barrelPos.x, barrelPos.y, barrelPos.z);
|
||||
projectile.setDeltaMovement(splitMotion);
|
||||
projectile.setOwner(player);
|
||||
level.addFreshEntity(projectile);
|
||||
}
|
||||
|
||||
if (!player.isCreative()) {
|
||||
ammoStack.shrink(1);
|
||||
if (ammoStack.isEmpty())
|
||||
player.getInventory().removeItem(ammoStack);
|
||||
}
|
||||
|
||||
if (!BacktankUtil.canAbsorbDamage(player, maxUses()))
|
||||
heldStack.hurtAndBreak(1, player, p -> p.broadcastBreakEvent(hand));
|
||||
|
||||
ShootableGadgetItemMethods.applyCooldown(player, heldStack, hand, s -> s.getItem() instanceof PotatoCannonItem, projectileType.reloadTicks());
|
||||
ShootableGadgetItemMethods.sendPackets(player,
|
||||
b -> new PotatoCannonPacket(barrelPos, lookVec.normalize(), ammoStack, hand, soundPitch, b));
|
||||
return InteractionResultHolder.success(heldStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void appendHoverText(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (player == null) {
|
||||
super.appendHoverText(stack, level, tooltip, flag);
|
||||
return;
|
||||
}
|
||||
|
||||
Ammo ammo = getAmmo(player, stack);
|
||||
if (ammo == null) {
|
||||
super.appendHoverText(stack, level, tooltip, flag);
|
||||
return;
|
||||
}
|
||||
ItemStack ammoStack = ammo.stack();
|
||||
PotatoCannonProjectileType type = ammo.type();
|
||||
|
||||
int power = stack.getEnchantmentLevel(Enchantments.POWER_ARROWS);
|
||||
int punch = stack.getEnchantmentLevel(Enchantments.PUNCH_ARROWS);
|
||||
final float additionalDamageMult = 1 + power * .2f;
|
||||
final float additionalKnockback = punch * .5f;
|
||||
|
||||
String _attack = "potato_cannon.ammo.attack_damage";
|
||||
String _reload = "potato_cannon.ammo.reload_ticks";
|
||||
String _knockback = "potato_cannon.ammo.knockback";
|
||||
|
||||
tooltip.add(CommonComponents.EMPTY);
|
||||
tooltip.add(Component.translatable(ammoStack.getDescriptionId()).append(Component.literal(":"))
|
||||
.withStyle(ChatFormatting.GRAY));
|
||||
MutableComponent spacing = CommonComponents.space();
|
||||
ChatFormatting green = ChatFormatting.GREEN;
|
||||
ChatFormatting darkGreen = ChatFormatting.DARK_GREEN;
|
||||
|
||||
float damageF = type.damage() * additionalDamageMult;
|
||||
MutableComponent damage = Component.literal(damageF == Mth.floor(damageF) ? "" + Mth.floor(damageF) : "" + damageF);
|
||||
MutableComponent reloadTicks = Component.literal("" + type.reloadTicks());
|
||||
MutableComponent knockback =
|
||||
Component.literal("" + (type.knockback() + additionalKnockback));
|
||||
|
||||
damage = damage.withStyle(additionalDamageMult > 1 ? green : darkGreen);
|
||||
knockback = knockback.withStyle(additionalKnockback > 0 ? green : darkGreen);
|
||||
reloadTicks = reloadTicks.withStyle(darkGreen);
|
||||
|
||||
tooltip.add(spacing.plainCopy()
|
||||
.append(CreateLang.translateDirect(_attack, damage)
|
||||
.withStyle(darkGreen)));
|
||||
tooltip.add(spacing.plainCopy()
|
||||
.append(CreateLang.translateDirect(_reload, reloadTicks)
|
||||
.withStyle(darkGreen)));
|
||||
tooltip.add(spacing.plainCopy()
|
||||
.append(CreateLang.translateDirect(_knockback, knockback)
|
||||
.withStyle(darkGreen)));
|
||||
|
||||
super.appendHoverText(stack, level, tooltip, flag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAttackBlock(BlockState state, Level world, BlockPos pos, Player player) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {
|
||||
return slotChanged || newStack.getItem() != oldStack.getItem();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Predicate<ItemStack> getAllSupportedProjectiles() {
|
||||
return stack -> PotatoCannonProjectileType.getTypeForItem(GlobalRegistryAccess.getOrThrow(), stack.getItem())
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultProjectileRange() {
|
||||
return 15;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApplyAtEnchantingTable(ItemStack stack, Enchantment enchantment) {
|
||||
if (enchantment == Enchantments.POWER_ARROWS)
|
||||
|
@ -82,11 +248,6 @@ public class PotatoCannonItem extends ProjectileWeaponItem implements CustomArmP
|
|||
return super.canApplyAtEnchantingTable(stack, enchantment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult useOn(UseOnContext context) {
|
||||
return use(context.getLevel(), context.getPlayer(), context.getHand()).getResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBarVisible(ItemStack stack) {
|
||||
return BacktankUtil.isBarVisible(stack, maxUses());
|
||||
|
@ -102,175 +263,10 @@ public class PotatoCannonItem extends ProjectileWeaponItem implements CustomArmP
|
|||
return BacktankUtil.getBarColor(stack, maxUses());
|
||||
}
|
||||
|
||||
private int maxUses() {
|
||||
private static int maxUses() {
|
||||
return AllConfigs.server().equipment.maxPotatoCannonShots.get();
|
||||
}
|
||||
|
||||
public boolean isCannon(ItemStack stack) {
|
||||
return stack.getItem() instanceof PotatoCannonItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {
|
||||
ItemStack stack = player.getItemInHand(hand);
|
||||
return findAmmoInInventory(level, player, stack).map(itemStack -> {
|
||||
if (ShootableGadgetItemMethods.shouldSwap(player, stack, hand, this::isCannon))
|
||||
return InteractionResultHolder.fail(stack);
|
||||
|
||||
if (level.isClientSide) {
|
||||
CreateClient.POTATO_CANNON_RENDER_HANDLER.dontAnimateItem(hand);
|
||||
return InteractionResultHolder.success(stack);
|
||||
}
|
||||
|
||||
Vec3 barrelPos = ShootableGadgetItemMethods.getGunBarrelVec(player, hand == InteractionHand.MAIN_HAND,
|
||||
new Vec3(.75f, -0.15f, 1.5f));
|
||||
Vec3 correction =
|
||||
ShootableGadgetItemMethods.getGunBarrelVec(player, hand == InteractionHand.MAIN_HAND, new Vec3(-.05f, 0, 0))
|
||||
.subtract(player.position()
|
||||
.add(0, player.getEyeHeight(), 0));
|
||||
|
||||
PotatoCannonProjectileType projectileType = PotatoCannonProjectileType.getTypeForStack(level, itemStack)
|
||||
.orElseGet(() ->
|
||||
level.registryAccess()
|
||||
.lookupOrThrow(CreateRegistries.POTATO_PROJECTILE_TYPE)
|
||||
.getOrThrow(AllPotatoProjectileTypes.FALLBACK)
|
||||
.value()
|
||||
);
|
||||
Vec3 lookVec = player.getLookAngle();
|
||||
Vec3 motion = lookVec.add(correction)
|
||||
.normalize()
|
||||
.scale(2)
|
||||
.scale(projectileType.velocityMultiplier());
|
||||
|
||||
float soundPitch = projectileType.soundPitch() + (level.getRandom().nextFloat() - .5f) / 4f;
|
||||
|
||||
boolean spray = projectileType.split() > 1;
|
||||
Vec3 sprayBase = VecHelper.rotate(new Vec3(0, 0.1, 0), 360 * level.getRandom().nextFloat(), Axis.Z);
|
||||
float sprayChange = 360f / projectileType.split();
|
||||
|
||||
for (int i = 0; i < projectileType.split(); i++) {
|
||||
PotatoProjectileEntity projectile = AllEntityTypes.POTATO_PROJECTILE.create(level);
|
||||
projectile.setItem(itemStack);
|
||||
projectile.setEnchantmentEffectsFromCannon(stack);
|
||||
|
||||
Vec3 splitMotion = motion;
|
||||
if (spray) {
|
||||
float imperfection = 40 * (level.getRandom().nextFloat() - 0.5f);
|
||||
Vec3 sprayOffset = VecHelper.rotate(sprayBase, i * sprayChange + imperfection, Axis.Z);
|
||||
splitMotion = splitMotion.add(VecHelper.lookAt(sprayOffset, motion));
|
||||
}
|
||||
|
||||
if (i != 0)
|
||||
projectile.recoveryChance = 0;
|
||||
|
||||
projectile.setPos(barrelPos.x, barrelPos.y, barrelPos.z);
|
||||
projectile.setDeltaMovement(splitMotion);
|
||||
projectile.setOwner(player);
|
||||
level.addFreshEntity(projectile);
|
||||
}
|
||||
|
||||
if (!player.isCreative()) {
|
||||
itemStack.shrink(1);
|
||||
if (itemStack.isEmpty())
|
||||
player.getInventory().removeItem(itemStack);
|
||||
}
|
||||
|
||||
if (!BacktankUtil.canAbsorbDamage(player, maxUses()))
|
||||
stack.hurtAndBreak(1, player, p -> p.broadcastBreakEvent(hand));
|
||||
|
||||
Integer cooldown =
|
||||
findAmmoInInventory(level, player, stack).flatMap(i -> PotatoCannonProjectileType.getTypeForStack(level, i))
|
||||
.map(potatoCannonProjectileType -> potatoCannonProjectileType.reloadTicks())
|
||||
.orElse(10);
|
||||
|
||||
ShootableGadgetItemMethods.applyCooldown(player, stack, hand, this::isCannon, cooldown);
|
||||
ShootableGadgetItemMethods.sendPackets(player,
|
||||
b -> new PotatoCannonPacket(barrelPos, lookVec.normalize(), itemStack, hand, soundPitch, b));
|
||||
return InteractionResultHolder.success(stack);
|
||||
})
|
||||
.orElse(InteractionResultHolder.pass(stack));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {
|
||||
return slotChanged || newStack.getItem() != oldStack.getItem();
|
||||
}
|
||||
|
||||
private Optional<ItemStack> findAmmoInInventory(Level level, Player player, ItemStack held) {
|
||||
ItemStack findAmmo = player.getProjectile(held);
|
||||
return PotatoCannonProjectileType.getTypeForStack(level, findAmmo)
|
||||
.map($ -> findAmmo);
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public static Optional<ItemStack> getAmmoforPreview(ItemStack cannon) {
|
||||
if (AnimationTickHolder.getTicks() % 3 != 0)
|
||||
return Optional.of(CLIENT_CURRENT_AMMO)
|
||||
.filter(stack -> !stack.isEmpty());
|
||||
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
CLIENT_CURRENT_AMMO = ItemStack.EMPTY;
|
||||
if (player == null)
|
||||
return Optional.empty();
|
||||
ItemStack findAmmo = player.getProjectile(cannon);
|
||||
Optional<ItemStack> found = PotatoCannonProjectileType.getTypeForStack(Minecraft.getInstance().level, findAmmo)
|
||||
.map($ -> findAmmo);
|
||||
found.ifPresent(stack -> CLIENT_CURRENT_AMMO = stack);
|
||||
return found;
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void appendHoverText(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {
|
||||
int power = stack.getEnchantmentLevel(Enchantments.POWER_ARROWS);
|
||||
int punch = stack.getEnchantmentLevel(Enchantments.PUNCH_ARROWS);
|
||||
final float additionalDamageMult = 1 + power * .2f;
|
||||
final float additionalKnockback = punch * .5f;
|
||||
|
||||
getAmmoforPreview(stack).ifPresent(ammo -> {
|
||||
String _attack = "potato_cannon.ammo.attack_damage";
|
||||
String _reload = "potato_cannon.ammo.reload_ticks";
|
||||
String _knockback = "potato_cannon.ammo.knockback";
|
||||
|
||||
tooltip.add(CommonComponents.EMPTY);
|
||||
tooltip.add(Component.translatable(ammo.getDescriptionId()).append(Component.literal(":"))
|
||||
.withStyle(ChatFormatting.GRAY));
|
||||
PotatoCannonProjectileType type = PotatoCannonProjectileType.getTypeForStack(Minecraft.getInstance().level, ammo)
|
||||
.get();
|
||||
MutableComponent spacing = CommonComponents.space();
|
||||
ChatFormatting green = ChatFormatting.GREEN;
|
||||
ChatFormatting darkGreen = ChatFormatting.DARK_GREEN;
|
||||
|
||||
float damageF = type.damage() * additionalDamageMult;
|
||||
MutableComponent damage = Component.literal(damageF == Mth.floor(damageF) ? "" + Mth.floor(damageF) : "" + damageF);
|
||||
MutableComponent reloadTicks = Component.literal("" + type.reloadTicks());
|
||||
MutableComponent knockback =
|
||||
Component.literal("" + (type.knockback() + additionalKnockback));
|
||||
|
||||
damage = damage.withStyle(additionalDamageMult > 1 ? green : darkGreen);
|
||||
knockback = knockback.withStyle(additionalKnockback > 0 ? green : darkGreen);
|
||||
reloadTicks = reloadTicks.withStyle(darkGreen);
|
||||
|
||||
tooltip.add(spacing.plainCopy()
|
||||
.append(CreateLang.translateDirect(_attack, damage)
|
||||
.withStyle(darkGreen)));
|
||||
tooltip.add(spacing.plainCopy()
|
||||
.append(CreateLang.translateDirect(_reload, reloadTicks)
|
||||
.withStyle(darkGreen)));
|
||||
tooltip.add(spacing.plainCopy()
|
||||
.append(CreateLang.translateDirect(_knockback, knockback)
|
||||
.withStyle(darkGreen)));
|
||||
});
|
||||
super.appendHoverText(stack, level, tooltip, flag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Predicate<ItemStack> getAllSupportedProjectiles() {
|
||||
Level level = ServerLifecycleHooks.getCurrentServer().getLevel(Level.OVERWORLD);
|
||||
return stack -> PotatoCannonProjectileType.getTypeForStack(level, stack)
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onEntitySwing(ItemStack stack, LivingEntity entity) {
|
||||
return true;
|
||||
|
@ -290,15 +286,12 @@ public class PotatoCannonItem extends ProjectileWeaponItem implements CustomArmP
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultProjectileRange() {
|
||||
return 15;
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void initializeClient(Consumer<IClientItemExtensions> consumer) {
|
||||
consumer.accept(SimpleCustomRenderer.create(this, new PotatoCannonItemRenderer()));
|
||||
}
|
||||
|
||||
public record Ammo(ItemStack stack, PotatoCannonProjectileType type) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,47 +5,69 @@ import com.mojang.math.Axis;
|
|||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.CreateClient;
|
||||
import com.simibubi.create.content.equipment.potatoCannon.PotatoCannonItem.Ammo;
|
||||
import com.simibubi.create.foundation.item.render.CustomRenderedItemModel;
|
||||
import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer;
|
||||
import com.simibubi.create.foundation.item.render.PartialItemModelRenderer;
|
||||
|
||||
import dev.engine_room.flywheel.lib.model.baked.PartialModel;
|
||||
import dev.engine_room.flywheel.lib.transform.TransformStack;
|
||||
import net.createmod.catnip.animation.AnimationTickHolder;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.entity.ItemRenderer;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.HumanoidArm;
|
||||
import net.minecraft.world.item.ItemDisplayContext;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import net.minecraftforge.client.IItemDecorator;
|
||||
|
||||
public class PotatoCannonItemRenderer extends CustomRenderedItemModelRenderer {
|
||||
public static final IItemDecorator DECORATOR = (guiGraphics, font, stack, xOffset, yOffset) -> {
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Ammo ammo = PotatoCannonItem.getAmmo(player, stack);
|
||||
if (ammo == null || AllItems.POTATO_CANNON.is(ammo.stack())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PoseStack poseStack = guiGraphics.pose();
|
||||
poseStack.pushPose();
|
||||
poseStack.translate(xOffset, yOffset + 8, 100);
|
||||
poseStack.scale(.5f, .5f, .5f);
|
||||
guiGraphics.renderItem(ammo.stack(), 0, 0);
|
||||
poseStack.popPose();
|
||||
return false;
|
||||
};
|
||||
|
||||
protected static final PartialModel COG = PartialModel.of(Create.asResource("item/potato_cannon/cog"));
|
||||
|
||||
@Override
|
||||
protected void render(ItemStack stack, CustomRenderedItemModel model, PartialItemModelRenderer renderer,
|
||||
ItemDisplayContext transformType, PoseStack ms, MultiBufferSource buffer, int light, int overlay) {
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
ItemRenderer itemRenderer = mc.getItemRenderer();
|
||||
renderer.render(model.getOriginalModel(), light);
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
LocalPlayer player = mc.player;
|
||||
boolean mainHand = player.getMainHandItem() == stack;
|
||||
boolean offHand = player.getOffhandItem() == stack;
|
||||
boolean leftHanded = player.getMainArm() == HumanoidArm.LEFT;
|
||||
|
||||
float offset = .5f / 16;
|
||||
float worldTime = AnimationTickHolder.getRenderTime() / 10;
|
||||
float angle = worldTime * -25;
|
||||
float speed = CreateClient.POTATO_CANNON_RENDER_HANDLER.getAnimation(mainHand ^ leftHanded,
|
||||
AnimationTickHolder.getPartialTicks());
|
||||
float angle = AnimationTickHolder.getRenderTime() * -2.5f;
|
||||
|
||||
if (player != null) {
|
||||
boolean inMainHand = player.getMainHandItem() == stack;
|
||||
boolean inOffHand = player.getOffhandItem() == stack;
|
||||
|
||||
if (inMainHand || inOffHand) {
|
||||
boolean leftHanded = player.getMainArm() == HumanoidArm.LEFT;
|
||||
float speed = CreateClient.POTATO_CANNON_RENDER_HANDLER.getAnimation(inMainHand ^ leftHanded,
|
||||
AnimationTickHolder.getPartialTicks());
|
||||
angle += 360 * Mth.clamp(speed * 5, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (mainHand || offHand)
|
||||
angle += 360 * Mth.clamp(speed * 5, 0, 1);
|
||||
angle %= 360;
|
||||
float offset = .5f / 16;
|
||||
|
||||
ms.pushPose();
|
||||
ms.translate(0, offset, 0);
|
||||
|
@ -53,20 +75,5 @@ public class PotatoCannonItemRenderer extends CustomRenderedItemModelRenderer {
|
|||
ms.translate(0, -offset, 0);
|
||||
renderer.render(COG.get(), light);
|
||||
ms.popPose();
|
||||
|
||||
if (transformType == ItemDisplayContext.GUI) {
|
||||
PotatoCannonItem.getAmmoforPreview(stack).ifPresent(ammo -> {
|
||||
if (AllItems.POTATO_CANNON.is(ammo)) return;
|
||||
|
||||
PoseStack localMs = new PoseStack();
|
||||
localMs.translate(-1 / 4f, -1 / 4f, 1);
|
||||
localMs.scale(.5f, .5f, .5f);
|
||||
TransformStack.of(localMs)
|
||||
.rotateYDegrees(-34);
|
||||
itemRenderer.renderStatic(ammo, ItemDisplayContext.GUI, light, OverlayTexture.NO_OVERLAY, localMs,
|
||||
buffer, mc.level, 0);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.simibubi.create.content.equipment.potatoCannon;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.content.equipment.zapper.ShootableGadgetRenderHandler;
|
||||
import com.simibubi.create.foundation.particle.AirParticleData;
|
||||
|
||||
|
@ -26,8 +25,7 @@ public class PotatoCannonRenderHandler extends ShootableGadgetRenderHandler {
|
|||
|
||||
@Override
|
||||
protected boolean appliesTo(ItemStack stack) {
|
||||
return AllItems.POTATO_CANNON.get()
|
||||
.isCannon(stack);
|
||||
return stack.getItem() instanceof PotatoCannonItem;
|
||||
}
|
||||
|
||||
public void beforeShoot(float nextPitch, Vec3 location, Vec3 motion, ItemStack stack) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.simibubi.create.content.equipment.potatoCannon;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.simibubi.create.AllEnchantments;
|
||||
import com.simibubi.create.AllSoundEvents;
|
||||
|
@ -58,28 +59,17 @@ public class PotatoProjectileEntity extends AbstractHurtingProjectile implements
|
|||
protected float additionalKnockback = 0;
|
||||
protected float recoveryChance = 0;
|
||||
|
||||
public PotatoProjectileEntity(EntityType<? extends AbstractHurtingProjectile> type, Level world) {
|
||||
super(type, world);
|
||||
}
|
||||
|
||||
public ItemStack getItem() {
|
||||
return stack;
|
||||
public PotatoProjectileEntity(EntityType<? extends AbstractHurtingProjectile> type, Level level) {
|
||||
super(type, level);
|
||||
}
|
||||
|
||||
public void setItem(ItemStack stack) {
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
public PotatoCannonProjectileType getProjectileType() {
|
||||
if (type == null)
|
||||
type = PotatoCannonProjectileType.getTypeForStack(level(), stack)
|
||||
.orElseGet(() ->
|
||||
level().registryAccess()
|
||||
.lookupOrThrow(CreateRegistries.POTATO_PROJECTILE_TYPE)
|
||||
.getOrThrow(AllPotatoProjectileTypes.FALLBACK)
|
||||
.value()
|
||||
);
|
||||
return type;
|
||||
type = PotatoCannonProjectileType.getTypeForItem(level().registryAccess(), stack.getItem())
|
||||
.orElseGet(() -> level().registryAccess()
|
||||
.registryOrThrow(CreateRegistries.POTATO_PROJECTILE_TYPE)
|
||||
.getHolderOrThrow(AllPotatoProjectileTypes.FALLBACK))
|
||||
.value();
|
||||
}
|
||||
|
||||
public void setEnchantmentEffectsFromCannon(ItemStack cannon) {
|
||||
|
@ -98,9 +88,18 @@ public class PotatoProjectileEntity extends AbstractHurtingProjectile implements
|
|||
recoveryChance = .125f + recovery * .125f;
|
||||
}
|
||||
|
||||
public ItemStack getItem() {
|
||||
return stack;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PotatoCannonProjectileType getProjectileType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readAdditionalSaveData(CompoundTag nbt) {
|
||||
stack = ItemStack.of(nbt.getCompound("Item"));
|
||||
setItem(ItemStack.of(nbt.getCompound("Item")));
|
||||
additionalDamageMult = nbt.getFloat("AdditionalDamage");
|
||||
additionalKnockback = nbt.getFloat("AdditionalKnockback");
|
||||
recoveryChance = nbt.getFloat("Recovery");
|
||||
|
@ -116,6 +115,7 @@ public class PotatoProjectileEntity extends AbstractHurtingProjectile implements
|
|||
super.addAdditionalSaveData(nbt);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Entity getStuckEntity() {
|
||||
if (stuckEntity == null)
|
||||
return null;
|
||||
|
@ -136,27 +136,26 @@ public class PotatoProjectileEntity extends AbstractHurtingProjectile implements
|
|||
if (getStuckEntity() != null)
|
||||
return stuckRenderer;
|
||||
|
||||
return getProjectileType().renderMode();
|
||||
return type.renderMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
PotatoCannonProjectileType projectileType = getProjectileType();
|
||||
|
||||
Entity stuckEntity = getStuckEntity();
|
||||
if (stuckEntity != null) {
|
||||
if (getY() < stuckEntity.getY() - 0.1) {
|
||||
pop(position());
|
||||
kill();
|
||||
} else {
|
||||
stuckFallSpeed += 0.007 * projectileType.gravityMultiplier();
|
||||
stuckFallSpeed += 0.007 * type.gravityMultiplier();
|
||||
stuckOffset = stuckOffset.add(0, -stuckFallSpeed, 0);
|
||||
Vec3 pos = stuckEntity.position()
|
||||
.add(stuckOffset);
|
||||
setPos(pos.x, pos.y, pos.z);
|
||||
}
|
||||
} else {
|
||||
setDeltaMovement(getDeltaMovement().add(0, -0.05 * projectileType.gravityMultiplier(), 0)
|
||||
.scale(projectileType.drag()));
|
||||
setDeltaMovement(getDeltaMovement().add(0, -0.05 * type.gravityMultiplier(), 0)
|
||||
.scale(type.drag()));
|
||||
}
|
||||
|
||||
super.tick();
|
||||
|
@ -186,9 +185,8 @@ public class PotatoProjectileEntity extends AbstractHurtingProjectile implements
|
|||
|
||||
Vec3 hit = ray.getLocation();
|
||||
Entity target = ray.getEntity();
|
||||
PotatoCannonProjectileType projectileType = getProjectileType();
|
||||
float damage = projectileType.damage() * additionalDamageMult;
|
||||
float knockback = projectileType.knockback() + additionalKnockback;
|
||||
float damage = type.damage() * additionalDamageMult;
|
||||
float knockback = type.knockback() + additionalKnockback;
|
||||
Entity owner = this.getOwner();
|
||||
|
||||
if (!target.isAlive())
|
||||
|
@ -211,7 +209,7 @@ public class PotatoProjectileEntity extends AbstractHurtingProjectile implements
|
|||
|
||||
if (target instanceof WitherBoss && ((WitherBoss) target).isPowered())
|
||||
return;
|
||||
if (projectileType.preEntityHit(stack, ray))
|
||||
if (type.preEntityHit(stack, ray))
|
||||
return;
|
||||
|
||||
boolean targetIsEnderman = target.getType() == EntityType.ENDERMAN;
|
||||
|
@ -229,11 +227,11 @@ public class PotatoProjectileEntity extends AbstractHurtingProjectile implements
|
|||
if (targetIsEnderman)
|
||||
return;
|
||||
|
||||
if (!projectileType.onEntityHit(stack, ray) && onServer) {
|
||||
if (!type.onEntityHit(stack, ray) && onServer) {
|
||||
if (random.nextDouble() <= recoveryChance) {
|
||||
recoverItem();
|
||||
} else {
|
||||
spawnAtLocation(projectileType.dropStack());
|
||||
spawnAtLocation(type.dropStack());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -297,7 +295,7 @@ public class PotatoProjectileEntity extends AbstractHurtingProjectile implements
|
|||
protected void onHitBlock(BlockHitResult ray) {
|
||||
Vec3 hit = ray.getLocation();
|
||||
pop(hit);
|
||||
if (!getProjectileType().onBlockHit(level(), stack, ray) && !level().isClientSide) {
|
||||
if (!type.onBlockHit(level(), stack, ray) && !level().isClientSide) {
|
||||
if (random.nextDouble() <= recoveryChance) {
|
||||
recoverItem();
|
||||
} else {
|
||||
|
|
|
@ -6,19 +6,17 @@ import net.minecraft.world.item.enchantment.Enchantment;
|
|||
import net.minecraft.world.item.enchantment.EnchantmentCategory;
|
||||
|
||||
public class PotatoRecoveryEnchantment extends Enchantment {
|
||||
|
||||
public PotatoRecoveryEnchantment(Rarity p_i46731_1_, EnchantmentCategory p_i46731_2_, EquipmentSlot[] p_i46731_3_) {
|
||||
super(p_i46731_1_, p_i46731_2_, p_i46731_3_);
|
||||
public PotatoRecoveryEnchantment(Rarity rarity, EnchantmentCategory category, EquipmentSlot[] slots) {
|
||||
super(rarity, category, slots);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxLevel() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canApplyAtEnchantingTable(ItemStack stack) {
|
||||
return stack.getItem() instanceof PotatoCannonItem;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import com.simibubi.create.AllRecipeTypes;
|
|||
import com.simibubi.create.AllTags.AllBlockTags;
|
||||
import com.simibubi.create.AllTags.AllFluidTags;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.api.registry.CreateRegistries;
|
||||
import com.simibubi.create.api.registry.CreateBuiltInRegistries;
|
||||
import com.simibubi.create.content.kinetics.fan.processing.HauntingRecipe.HauntingWrapper;
|
||||
import com.simibubi.create.content.kinetics.fan.processing.SplashingRecipe.SplashingWrapper;
|
||||
import com.simibubi.create.content.processing.burner.BlazeBurnerBlock;
|
||||
|
@ -24,6 +24,7 @@ import it.unimi.dsi.fastutil.objects.Object2ReferenceOpenHashMap;
|
|||
import net.createmod.catnip.math.VecHelper;
|
||||
import net.createmod.catnip.theme.Color;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.core.particles.BlockParticleOption;
|
||||
import net.minecraft.core.particles.DustParticleOptions;
|
||||
|
@ -54,14 +55,10 @@ import net.minecraft.world.level.block.state.BlockState;
|
|||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
import net.minecraftforge.items.wrapper.RecipeWrapper;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
|
||||
public class AllFanProcessingTypes {
|
||||
private static final DeferredRegister<FanProcessingType> REGISTER = DeferredRegister.create(CreateRegistries.FAN_PROCESSING_TYPE, Create.ID);
|
||||
|
||||
public static final BlastingType BLASTING = register("blasting", new BlastingType());
|
||||
public static final HauntingType HAUNTING = register("haunting", new HauntingType());
|
||||
public static final SmokingType SMOKING = register("smoking", new SmokingType());
|
||||
|
@ -80,12 +77,10 @@ public class AllFanProcessingTypes {
|
|||
}
|
||||
|
||||
private static <T extends FanProcessingType> T register(String name, T type) {
|
||||
REGISTER.register(name, () -> type);
|
||||
return type;
|
||||
return Registry.register(CreateBuiltInRegistries.FAN_PROCESSING_TYPE, Create.asResource(name), type);
|
||||
}
|
||||
|
||||
public static void register(IEventBus eventBus) {
|
||||
REGISTER.register(eventBus);
|
||||
public static void init() {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
|
|
@ -8,7 +8,7 @@ import org.apache.commons.lang3.mutable.MutableBoolean;
|
|||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.api.registry.CreateRegistries;
|
||||
import com.simibubi.create.api.registry.CreateBuiltInRegistries;
|
||||
import com.simibubi.create.content.kinetics.base.KineticBlockEntity;
|
||||
import com.simibubi.create.content.kinetics.belt.BeltBlock;
|
||||
import com.simibubi.create.content.kinetics.belt.BeltBlockEntity;
|
||||
|
@ -36,6 +36,7 @@ import com.simibubi.create.foundation.item.SmartInventory;
|
|||
import net.createmod.catnip.math.VecHelper;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.world.Containers;
|
||||
import net.minecraft.world.InteractionResultHolder;
|
||||
|
@ -57,15 +58,11 @@ import net.minecraft.world.level.block.state.BlockState;
|
|||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
import net.minecraftforge.items.wrapper.SidedInvWrapper;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
|
||||
public class AllArmInteractionPointTypes {
|
||||
private static final DeferredRegister<ArmInteractionPointType> REGISTER = DeferredRegister.create(CreateRegistries.ARM_INTERACTION_POINT_TYPE, Create.ID);
|
||||
|
||||
static {
|
||||
register("basin", new BasinType());
|
||||
register("belt", new BeltType());
|
||||
|
@ -87,11 +84,10 @@ public class AllArmInteractionPointTypes {
|
|||
}
|
||||
|
||||
private static <T extends ArmInteractionPointType> void register(String name, T type) {
|
||||
REGISTER.register(name, () -> type);
|
||||
Registry.register(CreateBuiltInRegistries.ARM_INTERACTION_POINT_TYPE, Create.asResource(name), type);
|
||||
}
|
||||
|
||||
public static void register(IEventBus eventBus) {
|
||||
REGISTER.register(eventBus);
|
||||
public static void init() {
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -26,7 +26,6 @@ import com.simibubi.create.foundation.item.ItemHelper;
|
|||
import com.simibubi.create.foundation.recipe.RecipeConditions;
|
||||
import com.simibubi.create.foundation.recipe.RecipeFinder;
|
||||
import com.simibubi.create.foundation.utility.AbstractBlockBreakQueue;
|
||||
import com.simibubi.create.foundation.utility.TreeCutter;
|
||||
import com.simibubi.create.infrastructure.config.AllConfigs;
|
||||
|
||||
import net.createmod.catnip.math.VecHelper;
|
||||
|
|
|
@ -10,7 +10,6 @@ import com.simibubi.create.content.contraptions.render.ContraptionMatrices;
|
|||
import com.simibubi.create.content.kinetics.base.BlockBreakingMovementBehaviour;
|
||||
import com.simibubi.create.foundation.damageTypes.CreateDamageSources;
|
||||
import com.simibubi.create.foundation.utility.AbstractBlockBreakQueue;
|
||||
import com.simibubi.create.foundation.utility.TreeCutter;
|
||||
import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld;
|
||||
|
||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||
|
@ -25,6 +24,7 @@ import net.minecraft.world.item.ItemStack;
|
|||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package com.simibubi.create.foundation.utility;
|
||||
package com.simibubi.create.content.kinetics.saw;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
@ -18,6 +18,7 @@ import com.simibubi.create.AllTags;
|
|||
import com.simibubi.create.AllTags.AllBlockTags;
|
||||
import com.simibubi.create.compat.Mods;
|
||||
import com.simibubi.create.compat.dynamictrees.DynamicTree;
|
||||
import com.simibubi.create.foundation.utility.AbstractBlockBreakQueue;
|
||||
|
||||
import net.createmod.catnip.data.Iterate;
|
||||
import net.minecraft.core.BlockPos;
|
|
@ -3,11 +3,9 @@ package com.simibubi.create.content.logistics.item.filter.attribute;
|
|||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import com.simibubi.create.AllRecipeTypes;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.api.registry.CreateRegistries;
|
||||
import com.simibubi.create.api.registry.CreateBuiltInRegistries;
|
||||
import com.simibubi.create.content.kinetics.fan.processing.AllFanProcessingTypes;
|
||||
import com.simibubi.create.content.logistics.item.filter.attribute.attributes.AddedByAttribute;
|
||||
import com.simibubi.create.content.logistics.item.filter.attribute.attributes.BookAuthorAttribute;
|
||||
|
@ -25,6 +23,7 @@ import com.simibubi.create.content.logistics.item.filter.attribute.attributes.as
|
|||
import com.simibubi.create.content.logistics.item.filter.attribute.attributes.astralsorcery.AstralSorceryPerkGemAttribute;
|
||||
import com.simibubi.create.content.logistics.item.filter.attribute.legacydeserializers.AllItemAttributeLegacyDeserializers;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
|
@ -38,14 +37,11 @@ import net.minecraft.world.level.block.ComposterBlock;
|
|||
import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity;
|
||||
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
import net.minecraftforge.items.wrapper.RecipeWrapper;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
|
||||
// TODO - Documentation
|
||||
public class AllItemAttributeTypes {
|
||||
private static final DeferredRegister<ItemAttributeType> REGISTER = DeferredRegister.create(CreateRegistries.ITEM_ATTRIBUTE_TYPE, Create.ID);
|
||||
private static final RecipeWrapper RECIPE_WRAPPER = new RecipeWrapper(new ItemStackHandler(1));
|
||||
|
||||
public static final ItemAttributeType
|
||||
|
@ -94,7 +90,6 @@ public class AllItemAttributeTypes {
|
|||
.isPresent();
|
||||
}
|
||||
|
||||
// TODO - Move away from stream()
|
||||
private static boolean maxEnchanted(ItemStack s) {
|
||||
return EnchantmentHelper.getEnchantments(s)
|
||||
.entrySet()
|
||||
|
@ -112,14 +107,10 @@ public class AllItemAttributeTypes {
|
|||
}
|
||||
|
||||
private static ItemAttributeType register(String id, ItemAttributeType type) {
|
||||
REGISTER.register(id, () -> type);
|
||||
return type;
|
||||
return Registry.register(CreateBuiltInRegistries.ITEM_ATTRIBUTE_TYPE, Create.asResource(id), type);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static void register(IEventBus modEventBus) {
|
||||
REGISTER.register(modEventBus);
|
||||
|
||||
public static void init() {
|
||||
// Register legacy deserializers to maintain backwards compatability
|
||||
AllItemAttributeLegacyDeserializers.register();
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.simibubi.create.content.logistics.packagePort.frogport;
|
|||
import java.util.List;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.api.equipment.goggles.IHaveHoveringInformation;
|
||||
import com.simibubi.create.content.logistics.box.PackageItem;
|
||||
import com.simibubi.create.content.logistics.box.PackageStyles;
|
||||
|
@ -27,6 +28,8 @@ import net.minecraft.network.chat.Component;
|
|||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
|
@ -45,6 +48,7 @@ public class FrogportBlockEntity extends PackagePortBlockEntity implements IHave
|
|||
public LerpedFloat animationProgress;
|
||||
public LerpedFloat anticipationProgress;
|
||||
public boolean currentlyDepositing;
|
||||
public boolean goggles;
|
||||
|
||||
public boolean sendAnticipate;
|
||||
|
||||
|
@ -66,6 +70,7 @@ public class FrogportBlockEntity extends PackagePortBlockEntity implements IHave
|
|||
manualOpenAnimationProgress = LerpedFloat.linear()
|
||||
.startWithValue(0)
|
||||
.chase(0, 0.35, Chaser.LINEAR);
|
||||
goggles = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -127,7 +132,7 @@ public class FrogportBlockEntity extends PackagePortBlockEntity implements IHave
|
|||
}
|
||||
|
||||
if (anticipationProgress.getValue() == 1)
|
||||
anticipationProgress.updateChaseTarget(0);
|
||||
anticipationProgress.startWithValue(0);
|
||||
|
||||
manualOpenAnimationProgress.updateChaseTarget(openTracker.openCount > 0 ? 1 : 0);
|
||||
boolean wasOpen = manualOpenAnimationProgress.getValue() > 0;
|
||||
|
@ -311,6 +316,8 @@ public class FrogportBlockEntity extends PackagePortBlockEntity implements IHave
|
|||
}
|
||||
if (failedLastExport)
|
||||
NBTHelper.putMarker(tag, "FailedLastExport");
|
||||
if (goggles)
|
||||
NBTHelper.putMarker(tag, "Goggles");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -318,6 +325,7 @@ public class FrogportBlockEntity extends PackagePortBlockEntity implements IHave
|
|||
super.read(tag, clientPacket);
|
||||
passiveYaw = tag.getFloat("PlacedYaw");
|
||||
failedLastExport = tag.getBoolean("FailedLastExport");
|
||||
goggles = tag.getBoolean("Goggles");
|
||||
if (!clientPacket)
|
||||
animatedPackage = null;
|
||||
if (tag.contains("AnimatedPackage")) {
|
||||
|
@ -350,5 +358,23 @@ public class FrogportBlockEntity extends PackagePortBlockEntity implements IHave
|
|||
if (level.isClientSide())
|
||||
sounds.open(level, worldPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult use(Player player) {
|
||||
if (player == null)
|
||||
return InteractionResult.PASS;
|
||||
|
||||
ItemStack mainHandItem = player.getMainHandItem();
|
||||
if (!goggles && AllItems.GOGGLES.isIn(mainHandItem)) {
|
||||
goggles = true;
|
||||
if (!level.isClientSide()) {
|
||||
notifyUpdate();
|
||||
level.playSound(null, worldPosition, SoundEvents.ARMOR_EQUIP_GOLD, SoundSource.BLOCKS, 0.5f, 1.0f);
|
||||
}
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
return super.use(player);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ public class FrogportRenderer extends SmartBlockEntityRenderer<FrogportBlockEnti
|
|||
.overlay(overlay)
|
||||
.renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped()));
|
||||
|
||||
SuperByteBuffer head = CachedBuffers.partial(AllPartialModels.FROGPORT_HEAD, blockEntity.getBlockState());
|
||||
SuperByteBuffer head = CachedBuffers.partial(blockEntity.goggles ? AllPartialModels.FROGPORT_HEAD_GOGGLES : AllPartialModels.FROGPORT_HEAD, blockEntity.getBlockState());
|
||||
|
||||
head.center()
|
||||
.rotateYDegrees(yaw)
|
||||
|
|
|
@ -23,7 +23,7 @@ import net.minecraftforge.registries.ForgeRegistries;
|
|||
|
||||
public class FrogportVisual extends AbstractBlockEntityVisual<FrogportBlockEntity> implements SimpleDynamicVisual {
|
||||
private final TransformedInstance body;
|
||||
private final TransformedInstance head;
|
||||
private TransformedInstance head;
|
||||
private final TransformedInstance tongue;
|
||||
private final TransformedInstance rig;
|
||||
private final TransformedInstance box;
|
||||
|
@ -33,6 +33,7 @@ public class FrogportVisual extends AbstractBlockEntityVisual<FrogportBlockEntit
|
|||
private float lastHeadPitch = Float.NaN;
|
||||
private float lastTonguePitch = Float.NaN;
|
||||
private float lastTongueLength = Float.NaN;
|
||||
private boolean lastGoggles = false;
|
||||
|
||||
public FrogportVisual(VisualizationContext ctx, FrogportBlockEntity blockEntity, float partialTick) {
|
||||
super(ctx, blockEntity, partialTick);
|
||||
|
@ -69,6 +70,8 @@ public class FrogportVisual extends AbstractBlockEntityVisual<FrogportBlockEntit
|
|||
}
|
||||
|
||||
private void animate(float partialTicks) {
|
||||
updateGoggles();
|
||||
|
||||
float yaw = blockEntity.getYaw();
|
||||
|
||||
float headPitch = 80;
|
||||
|
@ -172,6 +175,28 @@ public class FrogportVisual extends AbstractBlockEntityVisual<FrogportBlockEntit
|
|||
}
|
||||
}
|
||||
|
||||
public void updateGoggles() {
|
||||
if (blockEntity.goggles && !lastGoggles) {
|
||||
head.delete();
|
||||
head = instancerProvider()
|
||||
.instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.FROGPORT_HEAD_GOGGLES))
|
||||
.createInstance();
|
||||
lastHeadPitch = -1;
|
||||
updateLight(0);
|
||||
lastGoggles = true;
|
||||
}
|
||||
|
||||
if (!blockEntity.goggles && lastGoggles) {
|
||||
head.delete();
|
||||
head = instancerProvider()
|
||||
.instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.FROGPORT_HEAD))
|
||||
.createInstance();
|
||||
lastHeadPitch = -1;
|
||||
updateLight(0);
|
||||
lastGoggles = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void renderPackage(Vec3 diff, float scale, float itemDistance) {
|
||||
if (blockEntity.animatedPackage == null || scale < 0.45) {
|
||||
rig.handle()
|
||||
|
|
|
@ -18,9 +18,11 @@ public abstract class PercentOrProgressBarDisplaySource extends NumericSingleLin
|
|||
|
||||
@Override
|
||||
protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) {
|
||||
Float currentLevel = getProgress(context);
|
||||
if (currentLevel == null)
|
||||
Float rawProgress = this.getProgress(context);
|
||||
if (rawProgress == null)
|
||||
return EMPTY_LINE;
|
||||
// clamp just in case - #7371
|
||||
float currentLevel = Mth.clamp(rawProgress, 0, 1);
|
||||
if (!progressBarActive(context))
|
||||
return formatNumeric(context, currentLevel);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package com.simibubi.create.foundation.utility;
|
||||
package com.simibubi.create.foundation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -12,6 +12,7 @@ import net.minecraft.nbt.Tag;
|
|||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
|
||||
public class CreateNBTProcessors {
|
||||
|
@ -29,7 +30,7 @@ public class CreateNBTProcessors {
|
|||
if (!data.contains("Book", Tag.TAG_COMPOUND))
|
||||
return data;
|
||||
CompoundTag book = data.getCompound("Book");
|
||||
|
||||
|
||||
// Writable books can't have click events, so they're safe to keep
|
||||
ResourceLocation writableBookResource = ForgeRegistries.ITEMS.getKey(Items.WRITABLE_BOOK);
|
||||
if (writableBookResource != null && book.getString("id").equals(writableBookResource.toString()))
|
|
@ -2,6 +2,7 @@ package com.simibubi.create.foundation.events;
|
|||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.AllPackets;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.CreateClient;
|
||||
|
@ -27,6 +28,7 @@ import com.simibubi.create.content.equipment.clipboard.ClipboardValueSettingsHan
|
|||
import com.simibubi.create.content.equipment.extendoGrip.ExtendoGripRenderHandler;
|
||||
import com.simibubi.create.content.equipment.goggles.GoggleOverlayRenderer;
|
||||
import com.simibubi.create.content.equipment.hats.CreateHatArmorLayer;
|
||||
import com.simibubi.create.content.equipment.potatoCannon.PotatoCannonItemRenderer;
|
||||
import com.simibubi.create.content.equipment.toolbox.ToolboxHandlerClient;
|
||||
import com.simibubi.create.content.equipment.zapper.ZapperItem;
|
||||
import com.simibubi.create.content.equipment.zapper.terrainzapper.WorldshaperRenderHandler;
|
||||
|
@ -71,11 +73,11 @@ import com.simibubi.create.foundation.utility.ServerSpeedProvider;
|
|||
import com.simibubi.create.foundation.utility.TickBasedCache;
|
||||
import com.simibubi.create.infrastructure.config.AllConfigs;
|
||||
|
||||
import net.createmod.catnip.animation.AnimationTickHolder;
|
||||
import net.createmod.catnip.config.ui.BaseConfigScreen;
|
||||
import net.createmod.catnip.levelWrappers.WrappedClientLevel;
|
||||
import net.createmod.catnip.render.DefaultSuperRenderTypeBuffer;
|
||||
import net.createmod.catnip.render.SuperRenderTypeBuffer;
|
||||
import net.createmod.catnip.animation.AnimationTickHolder;
|
||||
import net.createmod.catnip.levelWrappers.WrappedClientLevel;
|
||||
import net.createmod.ponder.foundation.PonderTooltipHandler;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
@ -90,12 +92,14 @@ import net.minecraft.world.level.LevelAccessor;
|
|||
import net.minecraft.world.level.material.Fluid;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.ConfigScreenHandler;
|
||||
import net.minecraftforge.client.event.ClientPlayerNetworkEvent;
|
||||
import net.minecraftforge.client.event.EntityRenderersEvent;
|
||||
import net.minecraftforge.client.event.RegisterClientReloadListenersEvent;
|
||||
import net.minecraftforge.client.event.RegisterGuiOverlaysEvent;
|
||||
import net.minecraftforge.client.event.RegisterItemDecorationsEvent;
|
||||
import net.minecraftforge.client.event.RenderLevelStageEvent;
|
||||
import net.minecraftforge.client.event.RenderLevelStageEvent.Stage;
|
||||
import net.minecraftforge.client.event.ViewportEvent;
|
||||
|
@ -370,6 +374,11 @@ public class ClientEvents {
|
|||
event.registerAbove(VanillaGuiOverlay.HOTBAR.id(), "toolbox", ToolboxHandlerClient.OVERLAY);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void registerItemDecorations(RegisterItemDecorationsEvent event) {
|
||||
event.register(AllItems.POTATO_CANNON, PotatoCannonItemRenderer.DECORATOR);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onLoadComplete(FMLLoadCompleteEvent event) {
|
||||
ModContainer createContainer = ModList.get()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package com.simibubi.create.foundation.utility;
|
||||
package com.simibubi.create.foundation.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -17,6 +17,7 @@ import net.minecraft.client.resources.model.ModelResourceLocation;
|
|||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
||||
import net.minecraftforge.client.event.ModelEvent;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
package com.simibubi.create.foundation.utility;
|
||||
|
||||
import net.minecraft.client.color.block.BlockColor;
|
||||
import net.minecraft.client.color.item.ItemColor;
|
||||
import net.minecraft.client.renderer.BiomeColors;
|
||||
import net.minecraft.world.level.GrassColor;
|
||||
import net.minecraft.world.level.block.RedStoneWireBlock;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
|
||||
public class ColorHandlers {
|
||||
|
||||
public static BlockColor getGrassyBlock() {
|
||||
return (state, world, pos, layer) -> pos != null && world != null ? BiomeColors.getAverageGrassColor(world, pos)
|
||||
: GrassColor.get(0.5D, 1.0D);
|
||||
}
|
||||
|
||||
public static ItemColor getGrassyItem() {
|
||||
return (stack, layer) -> GrassColor.get(0.5D, 1.0D);
|
||||
}
|
||||
|
||||
public static BlockColor getRedstonePower() {
|
||||
return (state, world, pos, layer) -> RedStoneWireBlock
|
||||
.getColorForPower(pos != null && world != null ? state.getValue(BlockStateProperties.POWER) : 0);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package com.simibubi.create.foundation.utility;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.server.ServerLifecycleHooks;
|
||||
|
||||
public final class GlobalRegistryAccess {
|
||||
private static Supplier<@Nullable RegistryAccess> supplier;
|
||||
|
||||
static {
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> supplier = () -> {
|
||||
ClientPacketListener packetListener = Minecraft.getInstance().getConnection();
|
||||
if (packetListener == null) {
|
||||
return null;
|
||||
}
|
||||
return packetListener.registryAccess();
|
||||
});
|
||||
|
||||
if (supplier == null) {
|
||||
supplier = () -> {
|
||||
MinecraftServer server = ServerLifecycleHooks.getCurrentServer();
|
||||
if (server == null) {
|
||||
return null;
|
||||
}
|
||||
return server.registryAccess();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static RegistryAccess get() {
|
||||
return supplier.get();
|
||||
}
|
||||
|
||||
public static RegistryAccess getOrThrow() {
|
||||
RegistryAccess registryAccess = get();
|
||||
if (registryAccess == null) {
|
||||
throw new IllegalStateException("Could not get RegistryAccess");
|
||||
}
|
||||
return registryAccess;
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
package com.simibubi.create.foundation.utility;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ICoordinate {
|
||||
float get(BlockPos from);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.simibubi.create.foundation.utility;
|
||||
package com.simibubi.create.infrastructure;
|
||||
|
||||
import static com.simibubi.create.AllBlocks.ADJUSTABLE_CHAIN_GEARSHIFT;
|
||||
import static com.simibubi.create.AllBlocks.ANDESITE_ENCASED_SHAFT;
|
||||
|
@ -65,6 +65,7 @@ import net.minecraft.world.level.block.Block;
|
|||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
|
||||
import net.minecraftforge.common.ForgeMod;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
|
@ -25,10 +25,10 @@ public class CreateContraptionTypeTagsProvider extends TagsProvider<ContraptionT
|
|||
@Override
|
||||
protected void addTags(Provider pProvider) {
|
||||
tag(AllContraptionTypeTags.OPENS_CONTROLS.tag).add(
|
||||
TagEntry.element(AllContraptionTypes.CARRIAGE.getId())
|
||||
TagEntry.element(AllContraptionTypes.CARRIAGE.key().location())
|
||||
);
|
||||
tag(AllContraptionTypeTags.REQUIRES_VEHICLE_FOR_RENDER.tag).add(
|
||||
TagEntry.element(AllContraptionTypes.MOUNTED.getId())
|
||||
TagEntry.element(AllContraptionTypes.MOUNTED.key().location())
|
||||
);
|
||||
|
||||
// VALIDATE
|
||||
|
|
|
@ -127,6 +127,9 @@ public class CreateRegistrateTags {
|
|||
prov.tag(AllBlockTags.SUGAR_CANE_VARIANTS.tag)
|
||||
.add(Blocks.SUGAR_CANE);
|
||||
|
||||
prov.tag(AllBlockTags.NON_HARVESTABLE.tag)
|
||||
.add(Blocks.FIRE);
|
||||
|
||||
prov.tag(AllBlockTags.CORALS.tag)
|
||||
.add(Blocks.DEAD_TUBE_CORAL, Blocks.DEAD_BRAIN_CORAL, Blocks.DEAD_BUBBLE_CORAL, Blocks.DEAD_FIRE_CORAL,
|
||||
Blocks.DEAD_HORN_CORAL, Blocks.TUBE_CORAL, Blocks.BRAIN_CORAL, Blocks.BUBBLE_CORAL,
|
||||
|
|
|
@ -19,11 +19,13 @@ import net.minecraft.gametest.framework.GameTest;
|
|||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.projectile.Arrow;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.CropBlock;
|
||||
import net.minecraft.world.level.block.LeverBlock;
|
||||
import net.minecraft.world.level.block.RedstoneLampBlock;
|
||||
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
@GameTestGroup(path = "contraptions")
|
||||
|
@ -228,4 +230,48 @@ public class TestContraptions {
|
|||
// public static void trainObserver(CreateGameTestHelper helper) {
|
||||
// helper.fail("NYI");
|
||||
// }
|
||||
|
||||
@GameTest(template = "dispensers_dont_fight")
|
||||
public static void dispensersDontFight(CreateGameTestHelper helper) {
|
||||
helper.pullLever(2, 3, 1);
|
||||
BlockPos bottom = new BlockPos(6, 4, 1);
|
||||
BlockPos top = new BlockPos(6, 6, 1);
|
||||
BlockPos dispenser = new BlockPos(3, 4, 1);
|
||||
|
||||
helper.succeedWhen(() -> {
|
||||
helper.assertEntitiesPresent(EntityType.ARROW, bottom, 3, 0);
|
||||
helper.assertEntityNotPresent(EntityType.ARROW, top);
|
||||
helper.assertBlockPresent(Blocks.DISPENSER, dispenser);
|
||||
helper.assertContainerContains(dispenser, new ItemStack(Items.ARROW, 2));
|
||||
});
|
||||
}
|
||||
|
||||
@GameTest(template = "dispensers_refill")
|
||||
public static void dispensersRefill(CreateGameTestHelper helper) {
|
||||
BlockPos lever = new BlockPos(2, 3, 1);
|
||||
helper.pullLever(lever);
|
||||
BlockPos barrel = lever.above();
|
||||
BlockPos dispenser = barrel.east();
|
||||
|
||||
helper.succeedWhen(() -> {
|
||||
helper.assertBlockPresent(Blocks.DISPENSER, dispenser);
|
||||
helper.assertContainerContains(dispenser, new ItemStack(Items.SPECTRAL_ARROW, 2));
|
||||
helper.assertContainerEmpty(barrel);
|
||||
});
|
||||
}
|
||||
|
||||
@GameTest(template = "vaults_protect_fuel")
|
||||
public static void vaultsProtectFuel(CreateGameTestHelper helper) {
|
||||
BlockPos lever = new BlockPos(2, 2, 1);
|
||||
helper.pullLever(lever);
|
||||
BlockPos barrelLamp = new BlockPos(1, 3, 3);
|
||||
BlockPos vaultLamp = barrelLamp.east(2);
|
||||
|
||||
helper.runAtTickTime(10, () -> helper.pullLever(lever));
|
||||
|
||||
helper.succeedWhen(() -> {
|
||||
helper.assertBlockProperty(barrelLamp, RedstoneLampBlock.LIT, false);
|
||||
helper.assertBlockProperty(vaultLamp, RedstoneLampBlock.LIT, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.mutable.MutableBoolean;
|
||||
|
||||
import com.simibubi.create.AllBlockEntityTypes;
|
||||
import com.simibubi.create.content.fluids.hosePulley.HosePulleyFluidHandler;
|
||||
import com.simibubi.create.content.fluids.pipes.valve.FluidValveBlock;
|
||||
|
@ -18,15 +20,22 @@ import net.minecraft.gametest.framework.GameTest;
|
|||
import net.minecraft.gametest.framework.GameTestAssertException;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.monster.Zombie;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.alchemy.PotionUtils;
|
||||
import net.minecraft.world.item.alchemy.Potions;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.FarmBlock;
|
||||
import net.minecraft.world.level.block.LeverBlock;
|
||||
import net.minecraft.world.level.block.RedstoneLampBlock;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.FluidType;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
|
@ -299,4 +308,59 @@ public class TestFluids {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
@GameTest(template = "open_pipes")
|
||||
public static void openPipes(CreateGameTestHelper helper) {
|
||||
BlockPos effects = new BlockPos(2, 4, 2);
|
||||
BlockPos removers = new BlockPos(3, 5, 2);
|
||||
|
||||
BlockPos firstSeat = new BlockPos(4, 2, 1);
|
||||
BlockPos secondSeat = firstSeat.south(2);
|
||||
|
||||
Zombie firstZombie = helper.spawn(EntityType.ZOMBIE, firstSeat);
|
||||
Zombie secondZombie = helper.spawn(EntityType.ZOMBIE, secondSeat);
|
||||
|
||||
helper.pullLever(effects);
|
||||
|
||||
MutableBoolean stage1 = new MutableBoolean(true);
|
||||
|
||||
helper.succeedWhen(() -> {
|
||||
if (stage1.booleanValue()) {
|
||||
helper.assertTrue(firstZombie.isOnFire(), "not ignited");
|
||||
helper.assertFalse(secondZombie.getActiveEffects().isEmpty(), "no effects");
|
||||
// success, stage 2 time
|
||||
stage1.setFalse();
|
||||
helper.pullLever(effects);
|
||||
helper.pullLever(removers);
|
||||
helper.fail("switching stages");
|
||||
} else {
|
||||
helper.assertFalse(firstZombie.isOnFire(), "not extinguished");
|
||||
helper.assertTrue(secondZombie.getActiveEffects().isEmpty(), "has effects");
|
||||
// all done
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@GameTest(template = "spouting", timeoutTicks = CreateGameTestHelper.TEN_SECONDS)
|
||||
public static void spouting(CreateGameTestHelper helper) {
|
||||
BlockPos farmland = new BlockPos(3, 2, 3);
|
||||
BlockPos depot = new BlockPos(5, 2, 1);
|
||||
helper.pullLever(2, 3, 2);
|
||||
ItemStack waterBottle = PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER);
|
||||
|
||||
helper.succeedWhen(() -> {
|
||||
// lava
|
||||
helper.assertBlockPresent(Blocks.LAVA_CAULDRON, 3, 2, 1);
|
||||
// water
|
||||
helper.assertBlockProperty(farmland, FarmBlock.MOISTURE, 7);
|
||||
helper.assertBlockPresent(Blocks.MUD, farmland.east(1));
|
||||
helper.assertBlockPresent(Blocks.MUD, farmland.east(2));
|
||||
helper.assertBlockPresent(Blocks.MUD, farmland.east(3));
|
||||
helper.assertBlockPresent(Blocks.WATER_CAULDRON, farmland.east(4));
|
||||
|
||||
helper.assertContainerContains(depot, Items.WATER_BUCKET);
|
||||
helper.assertContainerContains(depot.east(1), waterBottle);
|
||||
helper.assertContainerContains(depot.east(2), Items.GRASS_BLOCK);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import net.minecraft.world.item.enchantment.EnchantmentInstance;
|
|||
import net.minecraft.world.item.enchantment.Enchantments;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.RedstoneLampBlock;
|
||||
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
|
@ -390,4 +391,22 @@ public class TestItems {
|
|||
helper.assertNixiePower(halfPearlNixie, 8);
|
||||
});
|
||||
}
|
||||
|
||||
@GameTest(template = "fan_processing", timeoutTicks = CreateGameTestHelper.TEN_SECONDS)
|
||||
public static void fanProcessing(CreateGameTestHelper helper) {
|
||||
// why does the redstone explode
|
||||
BlockPos.betweenClosed(new BlockPos(2, 7, 3), new BlockPos(11, 7, 3)).forEach(
|
||||
pos -> helper.setBlock(pos, Blocks.REDSTONE_WIRE)
|
||||
);
|
||||
helper.pullLever(1, 7, 3);
|
||||
List<BlockPos> lamps = List.of(
|
||||
new BlockPos(1, 2, 1), new BlockPos(5, 2, 1), new BlockPos(7, 2, 1),
|
||||
new BlockPos(9, 2, 1), new BlockPos(11, 2, 1)
|
||||
);
|
||||
helper.succeedWhen(() -> {
|
||||
for (BlockPos lamp : lamps) {
|
||||
helper.assertBlockProperty(lamp, RedstoneLampBlock.LIT, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"textures": {
|
||||
"0": "create:block/port2",
|
||||
"1": "create:block/port",
|
||||
"2": "create:block/froggles",
|
||||
"particle": "create:block/port2"
|
||||
},
|
||||
"render_type": "minecraft:cutout",
|
||||
"elements": [
|
||||
{
|
||||
"from": [2, 9, 2],
|
||||
"to": [14, 14, 14],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 9, 11]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 6, 2.5], "texture": "#1"},
|
||||
"east": {"uv": [12, 0, 6, 2.5], "texture": "#1"},
|
||||
"south": {"uv": [6, 10, 12, 12.5], "texture": "#1"},
|
||||
"west": {"uv": [6, 0, 12, 2.5], "texture": "#1"},
|
||||
"up": {"uv": [0, 10, 6, 16], "rotation": 180, "texture": "#1"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [14, 9, 2],
|
||||
"to": [2, 14, 14],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [20, 10, 11]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 6, 2.5], "texture": "#1"},
|
||||
"east": {"uv": [12, 0, 6, 2.5], "texture": "#1"},
|
||||
"south": {"uv": [6, 10, 12, 12.5], "texture": "#1"},
|
||||
"west": {"uv": [6, 0, 12, 2.5], "texture": "#1"},
|
||||
"up": {"uv": [0, 10, 6, 16], "rotation": 180, "texture": "#1"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [2, 10, 2],
|
||||
"to": [14, 10, 11],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 11]},
|
||||
"faces": {
|
||||
"down": {"uv": [0, 0, 6, 4.5], "rotation": 180, "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [1.8, 11, 1.8],
|
||||
"to": [5, 14.2, 5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [2, 11, 2]},
|
||||
"faces": {
|
||||
"north": {"uv": [4.5, 0, 6, 1.5], "texture": "#1"},
|
||||
"east": {"uv": [8, 5.5, 9.5, 7], "texture": "#1"},
|
||||
"south": {"uv": [8, 5.5, 9.5, 7], "texture": "#1"},
|
||||
"west": {"uv": [6, 0, 7.5, 1.5], "texture": "#1"},
|
||||
"up": {"uv": [4.5, 14.5, 6, 16], "rotation": 180, "texture": "#1"},
|
||||
"down": {"uv": [8, 5.5, 9.5, 7], "texture": "#1"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [11, 11, 1.8],
|
||||
"to": [14.2, 14.2, 5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [11, 11, 2]},
|
||||
"faces": {
|
||||
"north": {"uv": [6, 0, 4.5, 1.5], "texture": "#1"},
|
||||
"east": {"uv": [7.5, 0, 6, 1.5], "texture": "#1"},
|
||||
"south": {"uv": [8, 5.5, 9.5, 7], "texture": "#1"},
|
||||
"west": {"uv": [8, 5.5, 9.5, 7], "texture": "#1"},
|
||||
"up": {"uv": [4.5, 14.5, 6, 16], "rotation": 270, "texture": "#1"},
|
||||
"down": {"uv": [8, 5.5, 9.5, 7], "texture": "#1"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "lense ext",
|
||||
"from": [1.6, 10, 1.6],
|
||||
"to": [14.4, 14.4, 6],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [2, 10, 2]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 12, 12, 16], "texture": "#2"},
|
||||
"east": {"uv": [16, 12, 12, 16], "texture": "#2"},
|
||||
"west": {"uv": [12, 12, 16, 16], "texture": "#2"},
|
||||
"up": {"uv": [12, 12, 0, 8], "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "lense int",
|
||||
"from": [14.4, 10, 1.6],
|
||||
"to": [1.6, 14.4, 6],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [15, 10, 2]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 12, 12, 16], "texture": "#2"},
|
||||
"east": {"uv": [16, 12, 12, 16], "texture": "#2"},
|
||||
"west": {"uv": [12, 12, 16, 16], "texture": "#2"},
|
||||
"up": {"uv": [12, 12, 0, 8], "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "strap ext",
|
||||
"from": [1.6, 10, 6],
|
||||
"to": [14.4, 14.4, 14.4],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [2, 10, 6]},
|
||||
"faces": {
|
||||
"east": {"uv": [8, 0, 0, 4], "texture": "#2"},
|
||||
"south": {"uv": [0, 4, 12, 8], "texture": "#2"},
|
||||
"west": {"uv": [0, 0, 8, 4], "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "strap int",
|
||||
"from": [14.4, 10, 6],
|
||||
"to": [1.6, 14.4, 14.4],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [15, 10, 6]},
|
||||
"faces": {
|
||||
"east": {"uv": [8, 0, 0, 4], "texture": "#2"},
|
||||
"south": {"uv": [12, 4, 0, 8], "texture": "#2"},
|
||||
"west": {"uv": [0, 0, 8, 4], "texture": "#2"}
|
||||
}
|
||||
}
|
||||
],
|
||||
"groups": [
|
||||
{
|
||||
"name": "port_head",
|
||||
"origin": [8, 8, 8],
|
||||
"color": 0,
|
||||
"children": [0, 1, 2, 3, 4]
|
||||
},
|
||||
{
|
||||
"name": "froggles",
|
||||
"origin": [8, 8, 8],
|
||||
"color": 0,
|
||||
"children": [5, 6, 7, 8]
|
||||
}
|
||||
]
|
||||
}
|
BIN
src/main/resources/assets/create/textures/block/froggles.png
Normal file
BIN
src/main/resources/assets/create/textures/block/froggles.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 582 B |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Add table
Reference in a new issue