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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
0.1.12.110021 - Alpha

I've tidied up the eaves on the Rye cottages. The grain now runs along the fascia
board, and you can see its timber edge from below.

- Fit a dark oak soffit underneath a clay fascia to line the eaves. Stack two dark
oak slabs vertically to make four soffits.
- You can add or remove the soffit with the gutter in place. Lined and exposed
sections can share the same run of guttering.

0.1.11.110021 - Alpha

I've added iron guttering and downpipes to the Rye kit.
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ All six vanilla wood types are available. Cob comes in blocks, slabs and stairs,
thatch, slate and clay tile roofs have automatic corners and separate ridge caps.
Clay tiles also come as full and half-depth hanging panels for gables and upper walls.
Finish clay roofs with timber fascia boards at the eaves and matching trim along the gable and ridge.
Fit a dark oak soffit underneath to line the eaves.
Fit iron guttering to the fascia and run a downpipe under the overhang. Connected outlets and pipes drip in the rain.

Leaded windows bring some light into the houses. Choose diamond or rectangular leading,
Expand Down
11 changes: 8 additions & 3 deletions docs/BUILDING-GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
Permanent building components for the Iron Age series, starting on Minecraft 1.10.2 Forge.
Architecture runs independently of Iron Age Furniture.

Version 0.1.11.110021 contains raw and limewashed cob blocks,
Version 0.1.12.110021 contains raw and limewashed cob blocks,
stairs and slabs; modular wattle-and-daub walls in all six vanilla woods; and smooth
thatch, slate and clay tile roofs with automatic corners and separate ridge caps, plus jettied-storey walls,
timber floors, support brackets, hanging clay tiles and openable leaded windows. There are 525 visible
timber floors, support brackets, hanging clay tiles and openable leaded windows. There are 526 visible
variants including the wood and finish choices. Architecture remains standalone.

## Wattle and daub
Expand Down Expand Up @@ -75,6 +75,11 @@ Use full hanging tiles to fill the stepped gable beneath a clay roof. Thin hangi
tiles share the half-block plane with straight thin timber panels and thin leaded windows.
Place against one of these pieces to inherit its occupied half. Sneak to choose the half manually.

Two dark oak slabs stacked vertically make four soffits. Right-click the underside of
a clay fascia with a soffit to line that section of the eaves. Sneak and right-click
underneath with empty hands to take the lining back off. You can fit a soffit before
or after the gutter. The fascia still takes the same gutter or outlet either way.

## Guttering

Use a gutter or outlet on the outside face of a bare clay fascia. Level sections join
Expand Down Expand Up @@ -240,4 +245,4 @@ Thatch and timber-bearing walls burn; plain daub, cob and slate do not. There is

See [development instructions](DEVELOPMENT.md) for builds, Eclipse and disposable runtime checks.
This is an early alpha. Automated checks and manual visual/gameplay review are recorded separately.
The Rye Downpipe Shoe Preview shows both pipe offsets and the shoe on a cobbled street.
The Rye Eaves Preview shows lined and exposed eaves on neighbouring cottages.
2 changes: 1 addition & 1 deletion docs/DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ ends, both offsets and the rain path. The legacy-fascia mode opens a copy of the
preview and verifies the original bare fascias. Use a fresh runtime root for each candidate.

The optional client probe requires iaa.probe=true, iaa.clientProbe=true and iaa.keepRunning=true.
It creates its own Rye Downpipe Shoe Preview, checks mesh and material variants and both
It creates its own Rye Eaves Preview, checks mesh and material variants and both
creative tabs, captures dry and rain views of the cottage row, then shuts down.
Every visible item must also provide a translated crafting hint without tooltip errors.
The client script's PreviewName argument selects a separate save without replacing an earlier preview.
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ org.gradle.parallel=false
net.minecraftforge.gradle.merge-source-sets=false
minecraft_version=1.10.2
forge_version=12.18.3.2511
mod_version=0.1.11.110021
mod_version=0.1.12.110021
mod_group=zone.moddev.mc
mod_id=ironagearchitecture
mod_name=Iron Age Architecture
Expand Down
8 changes: 8 additions & 0 deletions scripts/generate-resources.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,14 @@ for (const [part,label] of [['fascia','Fascia'],['verge','Verge'],['ridge_end','
variants[`facing=${facing},right=${right}`] = {model:`${ns}:${mesh}`};
}
state(name,variants); item(name,mesh);
if (part === 'fascia') state(name + '_lined',variants);
lang[`tile.${ns}.${name}.name`] = `Clay Tile ${label}`;
}
model('dark_oak_soffit',{parent:'minecraft:block/block',textures:{wood:'minecraft:blocks/planks_big_oak',particle:'minecraft:blocks/planks_big_oak'},
elements:[{from:[0,7,1],to:[16,8.25,15],faces:Object.fromEntries(
['down','up','north','south','west','east'].map(face=>[face,{texture:'#wood'}]))}]});
item('dark_oak_soffit','dark_oak_soffit');
lang[`item.${ns}.dark_oak_soffit.name`] = 'Dark Oak Soffit';
model('drain_mesh',{parent:'minecraft:block/block',textures:{particle:'minecraft:blocks/iron_block'}});
for (const [name,label] of [['iron_gutter','Iron Gutter'],['iron_gutter_outlet','Iron Gutter Outlet']]) {
item(name,'drain_mesh');
Expand Down Expand Up @@ -191,6 +197,8 @@ for(const [w,wood] of woods.entries()) for(const finish of [0,1]) for(const thin
state('open_window_leaf',Object.fromEntries(Object.keys(facings).map(facing=>[`facing=${facing}`,{model:`${ns}:window_mesh`}])));
for(let meta=0;meta<2;meta++) {item(`leaded_pane_${meta}`,'window_mesh');lang[`item.${ns}.leaded_pane.${meta}.name`]=`${meta?'Rectangular':'Diamond'} Leaded Pane`;}
for (const [key,label] of Object.entries({
'soffit.fit':'Fit under a clay fascia. Sneak and use an empty hand underneath to recover it.',
'soffit.craft':'Stack two dark oak slabs in the crafting grid to make four soffits.',
'gutter.fit':'Fit to the outside face of a bare clay fascia. Sneak and use an empty hand to recover it.',
'gutter.outlet':'Place a downpipe beneath the outlet to carry rain down.',
'gutter.craft':'Three iron ingots in a row make six gutters. Add an ingot to make an outlet.',
Expand Down
4 changes: 2 additions & 2 deletions scripts/invoke-client-preview.ps1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
param(
[string]$Runtime='D:\IronAgeArchitecture\manual-testing\rye-downpipe-shoe-0.1.11\native-client-final',
[string]$PreviewName='Rye Downpipe Shoe Preview',
[string]$Runtime='D:\IronAgeArchitecture\manual-testing\rye-eaves-0.1.12\native-client-verified',
[string]$PreviewName='Rye Eaves Preview',
[string]$ServerTemplate='D:\IronAgeArchitecture\manual-testing\jetties-0.1.2-final\core',
[string]$GradleHome='D:\GradleCaches\minecraft-mods-shared',
[string]$AssetsDirectory='',
Expand Down
4 changes: 2 additions & 2 deletions scripts/invoke-runtime-probe.ps1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
param(
[ValidateSet('core','reload','furniture','disabled','legacy','legacy-daub','legacy-jetties','legacy-fascia','iron-age','late-medieval','mixed-eras','no-eras','invalid-era','windows-disabled','clay-disabled','clay-only')][string]$Mode='core',
[string]$RuntimeRoot='D:\IronAgeArchitecture\manual-testing\rye-downpipe-shoe-0.1.11',
[string]$RuntimeRoot='D:\IronAgeArchitecture\manual-testing\rye-eaves-0.1.12',
[string]$ServerTemplate='D:\IronAgeArchitecture\manual-testing\jetties-0.1.2-final\core',
[string]$FurnitureJar='D:\IronAgeArchitecture\manual-testing\jetties-0.1.2-final\furniture\mods\iron-age-furniture-0.3.0.110021.jar',
[string]$Java8='C:\Users\johnb\.gradle\jdks\temurin-8-amd64-windows.2\bin\java.exe'
Expand Down Expand Up @@ -101,7 +101,7 @@ if($Mode -eq 'legacy-jetties') {$args+='-Diaa.legacyJetties=true'}
if($Mode -eq 'legacy-fascia') {$args+='-Diaa.legacyFascia=true'}
if($Mode -eq 'core') {$args+=@('-Diaa.eraMatrix=true','-Diaa.recipeMatrix=true')}
if($Mode -eq 'disabled') {$args+='-Diaa.expectedVariants=0'}
if($Mode -eq 'clay-only') {$args+=@('-Diaa.expectedVariants=15','-Diaa.clayOnly=true','-Diaa.recipeMatrix=true')}
if($Mode -eq 'clay-only') {$args+=@('-Diaa.expectedVariants=16','-Diaa.clayOnly=true','-Diaa.recipeMatrix=true')}
$args+=@('-jar',$forge,'nogui')
Push-Location $folder
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public final class ArchitectureBlocks {
public static WindowLeafBlock WINDOW_LEAF;
public static LeadedPaneItem LEADED_PANE;
public static GutterItem GUTTER, GUTTER_OUTLET;
public static SoffitItem SOFFIT;
public static DownpipeBlock DOWNPIPE, DOWNPIPE_OFFSET, DOWNPIPE_SHOE;

public static int variants(Block block) {
Expand All @@ -53,6 +54,7 @@ public static List<ItemStack> visibleStacks() {
if (GUTTER != null) {
result.add(new ItemStack(GUTTER));
result.add(new ItemStack(GUTTER_OUTLET));
result.add(new ItemStack(SOFFIT));
}
return result;
}
Expand All @@ -62,7 +64,7 @@ public static List<FrameBlock> meshes() {
public static FrameBlock DAUB;
public static final List<RoofBlock> ROOFS = new ArrayList<>();
public static TileHangingBlock CLAY_HANGING, CLAY_HANGING_THIN;
public static FasciaBlock CLAY_FASCIA;
public static FasciaBlock CLAY_FASCIA, CLAY_FASCIA_LINED;
public static TrimmedRoofBlock CLAY_VERGE, CLAY_RIDGE_END;
private ArchitectureBlocks() { }
public static <T extends Block> T block(T block, String name) {
Expand Down Expand Up @@ -109,7 +111,7 @@ public static void register() {
CLAY_HANGING_THIN = block(new TileHangingBlock(true), "clay_tile_hanging_thin");
item(CLAY_HANGING, new TileHangingItem(CLAY_HANGING));
item(CLAY_HANGING_THIN, new TileHangingItem(CLAY_HANGING_THIN));
CLAY_FASCIA = block(new FasciaBlock(), "clay_tile_fascia");
CLAY_FASCIA = block(new FasciaBlock(false), "clay_tile_fascia");
item(CLAY_FASCIA, new EraItemBlock(CLAY_FASCIA));
ROOFS.add(CLAY_FASCIA);
CLAY_VERGE = roofTrim("clay_tile_verge", TrimmedRoofBlock.Kind.VERGE);
Expand All @@ -122,6 +124,13 @@ public static void register() {
item(DOWNPIPE_OFFSET, new DownpipeItem(DOWNPIPE_OFFSET));
DOWNPIPE_SHOE = block(new DownpipeBlock(DownpipeBlock.Kind.SHOE), "iron_downpipe_shoe");
item(DOWNPIPE_SHOE, new DownpipeItem(DOWNPIPE_SHOE));
// The lined fascia keeps the same orientation and gutter metadata as the bare one.
CLAY_FASCIA_LINED = block(new FasciaBlock(true), "clay_tile_fascia_lined");
ROOFS.add(CLAY_FASCIA_LINED);
SOFFIT = new SoffitItem();
SOFFIT.setRegistryName(new ResourceLocation(IronAgeArchitecture.MODID, "dark_oak_soffit"));
SOFFIT.setUnlocalizedName(IronAgeArchitecture.MODID + ".dark_oak_soffit");
GameRegistry.register(SOFFIT);
}
EraCatalog.assignPrimaryTabs();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ public static void register() {
}
}
if(ArchitectureConfig.windows) registerWindows();
if (ArchitectureConfig.clayTiles) registerGuttering();
if (ArchitectureConfig.clayTiles) {
registerGuttering();
shaped(new ItemStack(ArchitectureBlocks.SOFFIT, 4), "D", "D", 'D', new ItemStack(Blocks.WOODEN_SLAB, 1, 5));
}
for(RoofBlock roof:ArchitectureBlocks.ROOFS) if(!roof.isRidge() && !(roof instanceof TrimmedRoofBlock)) {
Object material;
switch (roof.materialKey) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public final class EraCatalog {
private EraCatalog() { }
public static EnumSet<Era> eras(Item item) {
if(item==null||item.getRegistryName()==null||!IronAgeArchitecture.MODID.equals(item.getRegistryName().getResourceDomain())) return EnumSet.noneOf(Era.class);
if(item instanceof JettyBracketItem||item instanceof LeadedPaneItem||item instanceof GutterItem) return EnumSet.of(Era.LATE_MEDIEVAL_TUDOR);
if(item instanceof JettyBracketItem||item instanceof LeadedPaneItem||item instanceof GutterItem||item instanceof SoffitItem) return EnumSet.of(Era.LATE_MEDIEVAL_TUDOR);
if(!(item instanceof ItemBlock)) return EnumSet.noneOf(Era.class);
Block block=((ItemBlock)item).getBlock();
boolean shared=ArchitectureBlocks.COB.contains(block)||ArchitectureBlocks.SLABS.contains(block)||ArchitectureBlocks.STAIRS.contains(block)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;

/** Permanent building components in the Iron Age series. */
@Mod(modid = IronAgeArchitecture.MODID, name = "Iron Age Architecture", version = "0.1.11.110021",
@Mod(modid = IronAgeArchitecture.MODID, name = "Iron Age Architecture", version = "0.1.12.110021",
acceptedMinecraftVersions = "[1.10.2]", dependencies = "required-after:Forge@[12.18.3.2511,)")
public final class IronAgeArchitecture {
public static final String MODID = "ironagearchitecture";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
Expand All @@ -25,8 +27,11 @@ public final class FasciaBlock extends TrimmedRoofBlock {
public static final PropertyInteger FITTING = PropertyInteger.create("fitting", 0, 2);
public static final PropertyInteger ENDS = PropertyInteger.create("ends", 0, 3);

public FasciaBlock() {
public final boolean lined;

public FasciaBlock(boolean lined) {
super(Kind.FASCIA);
this.lined = lined;
setDefaultState(getDefaultState().withProperty(FITTING, 0).withProperty(ENDS, 3));
}

Expand Down Expand Up @@ -56,7 +61,7 @@ public FasciaBlock() {
private boolean connects(IBlockAccess world, BlockPos pos, EnumFacing facing) {
if (world instanceof World && !((World)world).isBlockLoaded(pos)) return false;
IBlockState other = world.getBlockState(pos);
return other.getBlock() == this && other.getValue(FACING) == facing && other.getValue(FITTING) != 0;
return other.getBlock() instanceof FasciaBlock && other.getValue(FACING) == facing && other.getValue(FITTING) != 0;
}

@Override public List<AxisAlignedBB> collision(IBlockState state) {
Expand All @@ -68,24 +73,46 @@ private boolean connects(IBlockAccess world, BlockPos pos, EnumFacing facing) {

@Override public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player,
EnumHand hand, @Nullable ItemStack held, EnumFacing side, float x, float y, float z) {
int fitting = state.getValue(FITTING);
EnumFacing facing = state.getValue(FACING);
if (!player.isSneaking() || hand != EnumHand.MAIN_HAND || held != null || player.getHeldItemOffhand() != null || fitting == 0)
if (!player.isSneaking() || hand != EnumHand.MAIN_HAND || held != null || player.getHeldItemOffhand() != null)
return false;
EnumFacing inverse = facing.getAxis() == EnumFacing.Axis.X ? facing.getOpposite() : facing;
if (RoofGeometry.rotate(x, y, z, inverse)[2] < RoofTrimGeometry.EAVE + 1e-4 || y > 3.0 / 16)
return false;
if (!world.isBlockModifiable(player, pos) || !player.canPlayerEdit(pos, side, fittingStack(fitting))) return false;
if (!world.isRemote && world.setBlockState(pos, state.withProperty(FITTING, 0), 3)) {
if (!player.capabilities.isCreativeMode) {
ItemStack recovered = fittingStack(fitting);
if (!player.inventory.addItemStackToInventory(recovered)) spawnAsEntity(world, pos, recovered);
}
playFit(world, player, pos);

int fitting = state.getValue(FITTING);
boolean removeSoffit = lined && side == EnumFacing.DOWN && onUnderside(state, x, y, z);
boolean removeGutter = fitting != 0 && localDepth(state, x, y, z) >= RoofTrimGeometry.EAVE + 1e-4 && y <= 3.0 / 16;
if (!removeSoffit && !removeGutter) return false;

ItemStack recovered = removeSoffit ? new ItemStack(ArchitectureBlocks.SOFFIT) : fittingStack(fitting);
if (!world.isBlockModifiable(player, pos) || !player.canPlayerEdit(pos, side, recovered)) return false;
if (!world.isRemote) {
IBlockState replacement = removeSoffit ? withLining(state, false) : state.withProperty(FITTING, 0);
if (!world.setBlockState(pos, replacement, 3)) return false;
if (!player.capabilities.isCreativeMode && !player.inventory.addItemStackToInventory(recovered))
spawnAsEntity(world, pos, recovered);
if (removeSoffit) playLining(world, player, pos);
else playFit(world, player, pos);
}
return true;
}

public static IBlockState withLining(IBlockState state, boolean lined) {
FasciaBlock target = lined ? ArchitectureBlocks.CLAY_FASCIA_LINED : ArchitectureBlocks.CLAY_FASCIA;
return target.getDefaultState().withProperty(FACING, state.getValue(FACING)).withProperty(FITTING, state.getValue(FITTING));
}

static boolean onUnderside(IBlockState state, float x, float y, float z) {
return y <= 1e-4 && localDepth(state, x, y, z) <= RoofTrimGeometry.EAVE + 1e-4;
}

private static double localDepth(IBlockState state, float x, float y, float z) {
EnumFacing facing = state.getValue(FACING);
EnumFacing inverse = facing.getAxis() == EnumFacing.Axis.X ? facing.getOpposite() : facing;
return RoofGeometry.rotate(x, y, z, inverse)[2];
}

static void playLining(World world, EntityPlayer player, BlockPos pos) {
world.playSound(player, pos, SoundType.WOOD.getPlaceSound(), SoundCategory.BLOCKS, .6F, .9F);
}

public static void playFit(World world, EntityPlayer player, BlockPos pos) {
world.playSound(player, pos, SoundType.METAL.getPlaceSound(), SoundCategory.BLOCKS, .6F, .9F);
}
Expand All @@ -94,10 +121,19 @@ private static ItemStack fittingStack(int fitting) {
return new ItemStack(fitting == 2 ? ArchitectureBlocks.GUTTER_OUTLET : ArchitectureBlocks.GUTTER);
}

@Override public Item getItemDropped(IBlockState state, Random random, int fortune) {
return Item.getItemFromBlock(ArchitectureBlocks.CLAY_FASCIA);
}

@Override public ItemStack getPickBlock(IBlockState state, RayTraceResult hit, World world, BlockPos pos, EntityPlayer player) {
return new ItemStack(ArchitectureBlocks.CLAY_FASCIA);
}

@Override public List<ItemStack> getDrops(IBlockAccess world, BlockPos pos, IBlockState state, int fortune) {
List<ItemStack> drops = super.getDrops(world, pos, state, fortune);
int fitting = state.getValue(FITTING);
if (fitting != 0) drops.add(fittingStack(fitting));
if (lined) drops.add(new ItemStack(ArchitectureBlocks.SOFFIT));
return drops;
}

Expand Down
Loading
Loading