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 .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
root = true

[*.java]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
max_line_length = 120
trim_trailing_whitespace = true
15 changes: 15 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Contributing

Keep the code easy to read and straightforward to review.

- Use four spaces, UTF-8 and LF line endings. Aim for 120 columns; do not split a registry ID or other literal just to meet the limit.
- Put each statement on its own line and use braces for conditional and loop bodies, including early returns.
- Leave a blank line between logical steps. Keep related assignments together rather than separating every line.
- Name variables for their role. Use `inventorySlot`, `cellX` or `chunkX` when that context matters, rather than a single letter or a type abbreviation. Keep established names such as `world` and `state` when their meaning is already clear.
- Declare separate local values on separate lines. Explain packed masks and coordinate conventions where the names cannot tell the whole story.
- Write comments in plain English. Explain a decision, save-format constraint or surprising API behaviour instead of repeating what the next line says.
- Document public extension points, including when they can be called and what they preserve. Keep comments current when behaviour changes.

For Eclipse, import [the Java formatter profile](style/eclipse-java-formatter.xml) under **Java > Code Style > Formatter** and select **Sky Java**. The formatter handles layout; braces and logical grouping still need a quick human review.

Treat registry IDs, metadata palettes, configuration keys and saved NBT fields as compatibility contracts. A readability change should not alter them. Keep behavioural changes separate and run the relevant tests before submitting a pull request. See [the README](README.md) for this branch's toolchain and checks.
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,11 @@
import zone.moddev.mc.skysgrassslabs.init.ModBlocks;

/** Build-only rendered-client probe. This class is never included in release artifacts. */
@Mod(modid = ClientProbeTestMod.MOD_ID, name = "Sky's Grass Slabs Client Probe",
version = "1", acceptedMinecraftVersions = "[1.12.2]",
@Mod(
modid = ClientProbeTestMod.MOD_ID,
name = "Sky's Grass Slabs Client Probe",
version = "1",
acceptedMinecraftVersions = "[1.12.2]",
dependencies = "required-after:skysgrassslabs")
public final class ClientProbeTestMod {
public static final String MOD_ID = "skysgrassslabsclienttest";
Expand All @@ -49,30 +52,37 @@ public void initialize(FMLInitializationEvent event) {

@SubscribeEvent
public void onWorldRendered(RenderWorldLastEvent event) {
if (state == 1) ++firstWorldFrames;
if (state == 3) ++reloadWorldFrames;
if (state == 1) {
++firstWorldFrames;
}
if (state == 3) {
++reloadWorldFrames;
}
}

@SubscribeEvent
public void onClientTick(TickEvent.ClientTickEvent event) {
if (event.phase != TickEvent.Phase.END ||
!Boolean.getBoolean("skysgrassslabs.clientProbe")) return;
if (event.phase != TickEvent.Phase.END || !Boolean.getBoolean("skysgrassslabs.clientProbe")) {
return;
}

Minecraft minecraft = Minecraft.getMinecraft();
if (++stateTicks > 3600) fail(minecraft, "Timed out in client probe state " + state);

if (++stateTicks > 3600) {
fail(minecraft, "Timed out in client probe state " + state);
}
try {
switch (state) {
case 0:
if (minecraft.currentScreen instanceof GuiMainMenu) {
minecraft.launchIntegratedServer(WORLD_DIRECTORY,
"Sky's Grass Slabs Client Smoke",
new WorldSettings(81726354L, GameType.CREATIVE, false,
false, WorldType.DEFAULT));
minecraft.launchIntegratedServer(WORLD_DIRECTORY, "Sky's Grass Slabs Client Smoke",
new WorldSettings(81726354L, GameType.CREATIVE, false, false, WorldType.DEFAULT));
nextState(1);
}
break;
case 1:
if (minecraft.world != null && minecraft.player != null &&
firstWorldFrames >= 8 && stateTicks >= 100) {
if (minecraft.world != null && minecraft.player != null && firstWorldFrames >= 8
&& stateTicks >= 100) {
verifyModels(minecraft);
verifyRecipeBook();
stopIntegratedServer(minecraft);
Expand All @@ -81,16 +91,14 @@ public void onClientTick(TickEvent.ClientTickEvent event) {
break;
case 2:
if (minecraft.world == null && stateTicks >= 100) {
minecraft.launchIntegratedServer(WORLD_DIRECTORY,
"Sky's Grass Slabs Client Smoke",
new WorldSettings(81726354L, GameType.CREATIVE, false,
false, WorldType.DEFAULT));
minecraft.launchIntegratedServer(WORLD_DIRECTORY, "Sky's Grass Slabs Client Smoke",
new WorldSettings(81726354L, GameType.CREATIVE, false, false, WorldType.DEFAULT));
nextState(3);
}
break;
case 3:
if (minecraft.world != null && minecraft.player != null &&
reloadWorldFrames >= 8 && stateTicks >= 100) {
if (minecraft.world != null && minecraft.player != null && reloadWorldFrames >= 8
&& stateTicks >= 100) {
verifyModels(minecraft);
verifyRecipeBook();
stopIntegratedServer(minecraft);
Expand All @@ -117,40 +125,33 @@ private void verifyModels(Minecraft minecraft) {
Block grassSlab = ModBlocks.GRASS_SLAB;
Block pathSlab = ModBlocks.PATH_SLAB;
Block turf = ModBlocks.TURF;
IBlockState[] states = {
dirtSlab.getDefaultState().withProperty(
BlockSlab.HALF, BlockSlab.EnumBlockHalf.TOP),
dirtSlab.getDefaultState().withProperty(
BlockSlab.HALF, BlockSlab.EnumBlockHalf.BOTTOM),
grassSlab.getDefaultState().withProperty(
BlockSlab.HALF, BlockSlab.EnumBlockHalf.TOP),
grassSlab.getDefaultState().withProperty(
BlockSlab.HALF, BlockSlab.EnumBlockHalf.BOTTOM),
pathSlab.getDefaultState().withProperty(
BlockSlab.HALF, BlockSlab.EnumBlockHalf.TOP),
pathSlab.getDefaultState().withProperty(
BlockSlab.HALF, BlockSlab.EnumBlockHalf.BOTTOM),
turf.getDefaultState()
};
IBakedModel missing = minecraft.getBlockRendererDispatcher().getBlockModelShapes()
.getModelManager().getMissingModel();
IBlockState[] states = { dirtSlab.getDefaultState().withProperty(BlockSlab.HALF, BlockSlab.EnumBlockHalf.TOP),
dirtSlab.getDefaultState().withProperty(BlockSlab.HALF, BlockSlab.EnumBlockHalf.BOTTOM),
grassSlab.getDefaultState().withProperty(BlockSlab.HALF, BlockSlab.EnumBlockHalf.TOP),
grassSlab.getDefaultState().withProperty(BlockSlab.HALF, BlockSlab.EnumBlockHalf.BOTTOM),
pathSlab.getDefaultState().withProperty(BlockSlab.HALF, BlockSlab.EnumBlockHalf.TOP),
pathSlab.getDefaultState().withProperty(BlockSlab.HALF, BlockSlab.EnumBlockHalf.BOTTOM),
turf.getDefaultState() };
IBakedModel missing = minecraft.getBlockRendererDispatcher().getBlockModelShapes().getModelManager()
.getMissingModel();

for (IBlockState blockState : states) {
IBakedModel model = minecraft.getBlockRendererDispatcher().getModelForState(blockState);
ResourceLocation registryName = blockState.getBlock().getRegistryName();
if (model == null || model == missing || model.getParticleTexture() == null ||
"missingno".equals(model.getParticleTexture().getIconName())) {
throw new IllegalStateException("Missing baked model for " + registryName +
" state " + blockState);

if (model == null || model == missing || model.getParticleTexture() == null
|| "missingno".equals(model.getParticleTexture().getIconName())) {
throw new IllegalStateException("Missing baked model for " + registryName + " state " + blockState);
}
}

modelsVerified = true;
}

private void verifyRecipeBook() {
IRecipe turfRecipe = CraftingManager.REGISTRY.getObject(
new ResourceLocation("skysgrassslabs", "turf"));
if (turfRecipe == null || turfRecipe.isDynamic() ||
turfRecipe.getIngredients().size() != 2) {
IRecipe turfRecipe = CraftingManager.REGISTRY.getObject(new ResourceLocation("skysgrassslabs", "turf"));

if (turfRecipe == null || turfRecipe.isDynamic() || turfRecipe.getIngredients().size() != 2) {
throw new IllegalStateException("Turf recipe is not recipe-book compatible");
}
for (RecipeList recipeList : RecipeBookClient.ALL_RECIPES) {
Expand All @@ -159,24 +160,29 @@ private void verifyRecipeBook() {
return;
}
}

throw new IllegalStateException("Turf recipe is absent from the client recipe book");
}

private static void stopIntegratedServer(Minecraft minecraft) {
if (minecraft.world != null) minecraft.world.sendQuittingDisconnectingPacket();
if (minecraft.world != null) {
minecraft.world.sendQuittingDisconnectingPacket();
}

minecraft.loadWorld(null);
minecraft.displayGuiScreen(new GuiMainMenu());
}

private void writeMarker() throws IOException {
Properties values = new Properties();

values.setProperty("models_verified", Boolean.toString(modelsVerified));
values.setProperty("recipe_book_verified", Boolean.toString(recipeBookVerified));
values.setProperty("first_world_rendered", Boolean.toString(firstWorldFrames >= 8));
values.setProperty("reload_rendered", Boolean.toString(reloadWorldFrames >= 8));
values.setProperty("world_directory", WORLD_DIRECTORY);
try (FileOutputStream output = new FileOutputStream(
new File("client-smoke-pass.properties"))) {

try (FileOutputStream output = new FileOutputStream(new File("client-smoke-pass.properties"))) {
values.store(output, "Sky's Grass Slabs Forge 1.12.2 client gate");
}
}
Expand All @@ -189,13 +195,15 @@ private void nextState(int next) {
private static void fail(Minecraft minecraft, String message) {
try {
Properties values = new Properties();

values.setProperty("failure", message);
try (FileOutputStream output = new FileOutputStream(
new File("client-smoke-failure.properties"))) {

try (FileOutputStream output = new FileOutputStream(new File("client-smoke-failure.properties"))) {
values.store(output, "Sky's Grass Slabs client probe failure");
}
} catch (IOException ignored) {
}

minecraft.shutdown();
throw new IllegalStateException(message);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@
import zone.moddev.mc.skysgrassslabs.world.ModWorldState;

/** Creates the immutable Minecraft 1.10.2 input used by forward-upgrade tests. */
@Mod(modid = ForwardUpgradeFixtureMod.MOD_ID, name = "Sky's Grass Slabs Forward Upgrade Fixture",
version = "1", dependencies = "required-after:skysgrassslabs")
@Mod(
modid = ForwardUpgradeFixtureMod.MOD_ID,
name = "Sky's Grass Slabs Forward Upgrade Fixture",
version = "1",
dependencies = "required-after:skysgrassslabs")
public final class ForwardUpgradeFixtureMod {
public static final String MOD_ID = "skysgrassslabsforwardfixture";
private static final BlockPos ORIGIN = new BlockPos(8, 65, 8);
Expand All @@ -31,6 +34,7 @@ public final class ForwardUpgradeFixtureMod {
public void serverStarted(FMLServerStartedEvent event) throws Exception {
MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance();
WorldServer world = server.worldServerForDimension(0);

world.getGameRules().setOrCreateGameRule("randomTickSpeed", "0");
world.getWorldInfo().setRaining(false);
world.getWorldInfo().setThundering(false);
Expand All @@ -47,11 +51,14 @@ public void serverStarted(FMLServerStartedEvent event) throws Exception {
world.setBlockState(ORIGIN.east(6), defaultState(ModBlocks.TURF), 3);

BlockPos chestPos = ORIGIN.south(2);

support(world, chestPos);
world.setBlockState(chestPos, Blocks.CHEST.getDefaultState(), 3);

TileEntityChest chest = (TileEntityChest) world.getTileEntity(chestPos);
ItemStack grassStack = new ItemStack(ModBlocks.GRASS_SLAB, 3, 0);
NBTTagCompound grassData = new NBTTagCompound();

grassData.setString("fixture", "retained");
grassStack.setTagCompound(grassData);
chest.setInventorySlotContents(0, new ItemStack(ModBlocks.DIRT_SLAB, 2, 0));
Expand All @@ -60,13 +67,14 @@ public void serverStarted(FMLServerStartedEvent event) throws Exception {
chest.setInventorySlotContents(3, new ItemStack(ModBlocks.TURF, 5, 0));
chest.markDirty();

EntityItem dropped = new EntityItem(world, ORIGIN.getX() + 4.5D,
ORIGIN.getY() + 1.0D, ORIGIN.getZ() + 2.5D,
EntityItem dropped = new EntityItem(world, ORIGIN.getX() + 4.5D, ORIGIN.getY() + 1.0D, ORIGIN.getZ() + 2.5D,
new ItemStack(ModBlocks.GRASS_SLAB, 6, 0));

dropped.setNoPickupDelay();
world.spawnEntity(dropped);

ModWorldState state = ModWorldState.get(world);

state.recordChunk();
state.recordChunk();
state.recordGrassBlocks(3, 0);
Expand All @@ -78,25 +86,24 @@ public void serverStarted(FMLServerStartedEvent event) throws Exception {
state.recordUnsupported("fixture:unsupported_shape", 19);

File worldDirectory = world.getSaveHandler().getWorldDirectory();

Files.write(new File(worldDirectory, "skysgrassslabs-forward-fixture.properties").toPath(),
Arrays.asList(
"source_minecraft=1.10.2",
"source_mod_version=1.0.0.110021",
Arrays.asList("source_minecraft=1.10.2", "source_mod_version=1.0.0.110021",
"source_jar_sha256=2030960E217C3F61AE4919C91058696B02F9FAE570BE1CD7B698696EA7BEB861",
"origin=8,65,8",
"expected_blocks=7",
"expected_chest_stacks=4",
"expected_entity_stacks=1",
"schema_version=1"), StandardCharsets.UTF_8);
"origin=8,65,8", "expected_blocks=7", "expected_chest_stacks=4", "expected_entity_stacks=1",
"schema_version=1"),
StandardCharsets.UTF_8);

world.saveAllChunks(true, null);
server.initiateShutdown();
}

private static void placeSlab(WorldServer world, BlockPos pos,
net.minecraft.block.Block block, BlockSlab.EnumBlockHalf half) {
private static void placeSlab(WorldServer world, BlockPos pos, net.minecraft.block.Block block,
BlockSlab.EnumBlockHalf half) {
support(world, pos);

IBlockState state = block.getDefaultState().withProperty(BlockSlab.HALF, half);

world.setBlockState(pos, state, 3);
}

Expand All @@ -109,10 +116,10 @@ private static IBlockState defaultState(net.minecraft.block.Block block) {
}

private static void clearFixtureArea(WorldServer world) {
for (int y = ORIGIN.getY() - 1; y <= ORIGIN.getY() + 3; ++y) {
for (int z = ORIGIN.getZ() - 2; z <= ORIGIN.getZ() + 4; ++z) {
for (int x = ORIGIN.getX() - 2; x <= ORIGIN.getX() + 8; ++x) {
world.setBlockToAir(new BlockPos(x, y, z));
for (int blockY = ORIGIN.getY() - 1; blockY <= ORIGIN.getY() + 3; ++blockY) {
for (int blockZ = ORIGIN.getZ() - 2; blockZ <= ORIGIN.getZ() + 4; ++blockZ) {
for (int blockX = ORIGIN.getX() - 2; blockX <= ORIGIN.getX() + 8; ++blockX) {
world.setBlockToAir(new BlockPos(blockX, blockY, blockZ));
}
}
}
Expand Down
Loading
Loading