diff --git a/.github/workflows/gradle-publish.yml b/.github/workflows/gradle-publish.yml new file mode 100644 index 0000000..2af4616 --- /dev/null +++ b/.github/workflows/gradle-publish.yml @@ -0,0 +1,44 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# This workflow will build a package using Gradle and then publish it to GitHub packages when a release is created +# For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#Publishing-using-gradle + +name: Gradle Package + +on: + release: + types: [created] + +jobs: + build: + + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + server-id: github # Value of the distributionManagement/repository/id field of the pom.xml + settings-path: ${{ github.workspace }} # location for the settings.xml file + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + + - name: Build with Gradle + run: ./gradlew build + + # The USERNAME and TOKEN need to correspond to the credentials environment variables used in + # the publishing section of your build.gradle + - name: Publish to GitHub Packages + run: ./gradlew publish + env: + USERNAME: ${{ github.actor }} + TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..9f0ebb8 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,36 @@ +# This is a basic workflow to help you get started with Actions + +name: CI + +# Controls when the workflow will run +on: + # Triggers the workflow on push or pull request events but only for the "master" branch + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v3 + + # Runs a single command using the runners shell + - name: Run a one-line script + run: echo Hello, world! + + # Runs a set of commands using the runners shell + - name: Run a multi-line script + run: | + echo Add other actions to build, + echo test, and deploy your project. diff --git a/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index 62d94a8..ee46219 100644 --- a/src/generated/resources/.cache/cache +++ b/src/generated/resources/.cache/cache @@ -1,6 +1,6 @@ a46ab507ff2143e0354586a09eb4a47a710df479 assets/createaeronautics/blockstates/airship_assembler.json 388cbfb2ec3b4b10e3c534a347f56ff799688525 assets/createaeronautics/blockstates/levitite_casing.json -f03bd9993220fb1d344cec8604dbd88d3b7b1275 assets/createaeronautics/blockstates/propeller_bearing.json +8c8c860c6f25962e30b98f8aaf8df91ab5e4ba02 assets/createaeronautics/blockstates/propeller_bearing.json 1d6fcfae6cc5e594163e320cfc3d9c8b791a6e1c assets/createaeronautics/blockstates/stationary_potato_cannon.json ec6500ca9e9055d656869cd2ff306d420eb8bd1b assets/createaeronautics/blockstates/stirling_engine.json 56f827d9b1dcf205d37a6a9ee82019e2b9498330 assets/createaeronautics/blockstates/torsion_spring.json diff --git a/src/generated/resources/assets/createaeronautics/blockstates/propeller_bearing.json b/src/generated/resources/assets/createaeronautics/blockstates/propeller_bearing.json index e69389a..cc07574 100644 --- a/src/generated/resources/assets/createaeronautics/blockstates/propeller_bearing.json +++ b/src/generated/resources/assets/createaeronautics/blockstates/propeller_bearing.json @@ -1,54 +1,54 @@ { "variants": { "direction=push,facing=down": { - "model": "createaeronautics:block/propeller_bearing/block_reverse", + "model": "createaeronautics:block/propeller_bearing/block", "x": 180 }, "direction=pull,facing=down": { - "model": "createaeronautics:block/propeller_bearing/block_forward", + "model": "createaeronautics:block/propeller_bearing/block", "x": 180 }, "direction=push,facing=up": { - "model": "createaeronautics:block/propeller_bearing/block_reverse" + "model": "createaeronautics:block/propeller_bearing/block" }, "direction=pull,facing=up": { - "model": "createaeronautics:block/propeller_bearing/block_forward" + "model": "createaeronautics:block/propeller_bearing/block" }, "direction=push,facing=north": { - "model": "createaeronautics:block/propeller_bearing/block_reverse", + "model": "createaeronautics:block/propeller_bearing/block", "x": 90 }, "direction=pull,facing=north": { - "model": "createaeronautics:block/propeller_bearing/block_forward", + "model": "createaeronautics:block/propeller_bearing/block", "x": 90 }, "direction=push,facing=south": { - "model": "createaeronautics:block/propeller_bearing/block_reverse", + "model": "createaeronautics:block/propeller_bearing/block", "x": 90, "y": 180 }, "direction=pull,facing=south": { - "model": "createaeronautics:block/propeller_bearing/block_forward", + "model": "createaeronautics:block/propeller_bearing/block", "x": 90, "y": 180 }, "direction=push,facing=west": { - "model": "createaeronautics:block/propeller_bearing/block_reverse", + "model": "createaeronautics:block/propeller_bearing/block", "x": 90, "y": 270 }, "direction=pull,facing=west": { - "model": "createaeronautics:block/propeller_bearing/block_forward", + "model": "createaeronautics:block/propeller_bearing/block", "x": 90, "y": 270 }, "direction=push,facing=east": { - "model": "createaeronautics:block/propeller_bearing/block_reverse", + "model": "createaeronautics:block/propeller_bearing/block", "x": 90, "y": 90 }, "direction=pull,facing=east": { - "model": "createaeronautics:block/propeller_bearing/block_forward", + "model": "createaeronautics:block/propeller_bearing/block", "x": 90, "y": 90 } diff --git a/src/main/java/com/eriksonn/createaeronautics/blocks/airship_assembler/AirshipAssemblerBlock.java b/src/main/java/com/eriksonn/createaeronautics/blocks/airship_assembler/AirshipAssemblerBlock.java index 2620b3a..7398c00 100644 --- a/src/main/java/com/eriksonn/createaeronautics/blocks/airship_assembler/AirshipAssemblerBlock.java +++ b/src/main/java/com/eriksonn/createaeronautics/blocks/airship_assembler/AirshipAssemblerBlock.java @@ -1,12 +1,19 @@ package com.eriksonn.createaeronautics.blocks.airship_assembler; +import appeng.core.sync.network.ServerPacketHandler; import com.eriksonn.createaeronautics.index.CAShapes; import com.eriksonn.createaeronautics.index.CATileEntities; +import com.eriksonn.createaeronautics.inspect.InspectUI; +import com.eriksonn.createaeronautics.network.NetworkMain; +import com.eriksonn.createaeronautics.network.packet.InspectAirshipPacket; import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.foundation.gui.ScreenOpener; +import com.simibubi.create.foundation.ponder.PonderUI; import net.minecraft.block.AbstractBlock; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.item.BlockItemUseContext; import net.minecraft.state.BooleanProperty; import net.minecraft.state.StateContainer; @@ -22,6 +29,7 @@ import net.minecraft.world.World; import javax.annotation.Nullable; +import java.util.function.Function; public class AirshipAssemblerBlock extends Block implements ITE { public static final BooleanProperty ACTIVE = BooleanProperty.create("active"); @@ -59,11 +67,22 @@ public Class getTileEntityClass() { return AirshipAssemblerTileEntity.class; } - public ActionResultType use(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) { + + + @Override + public ActionResultType use(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, + BlockRayTraceResult hit) { + if (!player.mayBuild()) { return ActionResultType.FAIL; } else if (player.isShiftKeyDown()) { - return ActionResultType.FAIL; + + this.withTileEntityDo(worldIn, pos, (te) -> { + if (te.running) { + NetworkMain.sendToPlayer((ServerPlayerEntity) player, new InspectAirshipPacket(te.movedContraption.plotId)); + } + }); + return ActionResultType.SUCCESS; } else if (player.getItemInHand(handIn).isEmpty()) { if (worldIn.isClientSide) { return ActionResultType.SUCCESS; diff --git a/src/main/java/com/eriksonn/createaeronautics/blocks/airship_assembler/AirshipAssemblerTileEntity.java b/src/main/java/com/eriksonn/createaeronautics/blocks/airship_assembler/AirshipAssemblerTileEntity.java index a6c7f0a..bd66b3d 100644 --- a/src/main/java/com/eriksonn/createaeronautics/blocks/airship_assembler/AirshipAssemblerTileEntity.java +++ b/src/main/java/com/eriksonn/createaeronautics/blocks/airship_assembler/AirshipAssemblerTileEntity.java @@ -59,12 +59,11 @@ public void assemble() { contraption.removeBlocksFromWorld(this.level, BlockPos.ZERO); this.movedContraption = AirshipContraptionEntity.create(this.level, contraption); BlockPos anchor = this.worldPosition; - this.movedContraption.simulatedRigidbody.tryInit(); this.movedContraption.setPos( - (double)anchor.getX()+this.movedContraption.centerOfMassOffset.x, - (double)anchor.getY()+this.movedContraption.centerOfMassOffset.y, - (double)anchor.getZ()+this.movedContraption.centerOfMassOffset.z); + (double)anchor.getX()-this.movedContraption.centerOfMassOffset.x, + (double)anchor.getY()-this.movedContraption.centerOfMassOffset.y, + (double)anchor.getZ()-this.movedContraption.centerOfMassOffset.z); this.level.addFreshEntity(this.movedContraption); AllSoundEvents.CONTRAPTION_ASSEMBLE.playOnServer(this.level, this.worldPosition); this.running = true; @@ -90,7 +89,6 @@ public void tick() { } if(this.movedContraption!=null) { - time++; float angle=time*5.5f; MatrixStack[] stack = new MatrixStack[1]; diff --git a/src/main/java/com/eriksonn/createaeronautics/contraptions/AirshipContraptionEntity.java b/src/main/java/com/eriksonn/createaeronautics/contraptions/AirshipContraptionEntity.java index eb2ee30..d2ef87e 100644 --- a/src/main/java/com/eriksonn/createaeronautics/contraptions/AirshipContraptionEntity.java +++ b/src/main/java/com/eriksonn/createaeronautics/contraptions/AirshipContraptionEntity.java @@ -9,6 +9,7 @@ import com.eriksonn.createaeronautics.network.packet.*; import com.eriksonn.createaeronautics.physics.SimulatedContraptionRigidbody; import com.eriksonn.createaeronautics.physics.SubcontraptionRigidbody; +import com.eriksonn.createaeronautics.physics.api.ContraptionEntityPhysicsAdapter; import com.eriksonn.createaeronautics.physics.collision.shape.ICollisionShape; import com.eriksonn.createaeronautics.physics.collision.shape.MeshCollisionShape; import com.eriksonn.createaeronautics.utils.AbstractContraptionEntityExtension; @@ -19,6 +20,7 @@ import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.content.contraptions.components.structureMovement.*; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; +import com.simibubi.create.content.curiosities.tools.ExtendoGripItem; import com.simibubi.create.foundation.collision.Matrix3d; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.utility.AngleHelper; @@ -69,6 +71,7 @@ public class AirshipContraptionEntity extends AbstractContraptionEntity { float time = 0; + public boolean playPhysics = true; public Quaternion quat = Quaternion.ONE; public Vector3d velocity; public AirshipContraption airshipContraption; @@ -87,21 +90,22 @@ protected void defineSynchedData() { public AirshipContraptionEntity(EntityType type, World world) { super(type, world); - simulatedRigidbody = new SimulatedContraptionRigidbody(this); - + simulatedRigidbody = new SimulatedContraptionRigidbody((AirshipContraption) getContraption(), new ContraptionEntityPhysicsAdapter(this)); // testing // this.simulatedRigidbody.angularMomentum = new Vector3d(0, 0, 40); + airshipContraption = (AirshipContraption) contraption; System.out.println("New airship entity"); } public static AirshipContraptionEntity create(World world, AirshipContraption contraption) { AirshipContraptionEntity entity = new AirshipContraptionEntity((EntityType) CAEntityTypes.AIRSHIP_CONTRAPTION.get(), world); entity.setContraption(contraption); - entity.airshipContraption = contraption; + entity.simulatedRigidbody = new SimulatedContraptionRigidbody((AirshipContraption) entity.airshipContraption, new ContraptionEntityPhysicsAdapter(entity)); AirshipManager.INSTANCE.tryAddEntity(AirshipManager.INSTANCE.getNextId(), entity); + entity.simulatedRigidbody.tryInit(); return entity; } @@ -116,13 +120,22 @@ public static AirshipContraptionEntity create(World world, AirshipContraption co @Override public void tickContraption() { + airshipContraption = (AirshipContraption) contraption; + simulatedRigidbody.contraption = airshipContraption; AirshipAssemblerTileEntity controller = getController(); airshipContraption = (AirshipContraption) contraption; if (controller != null) controller.attach(this); - simulatedRigidbody.tick(); + if(playPhysics) { + simulatedRigidbody.tick(); + this.centerOfMassOffset = simulatedRigidbody.getCenterOfMass(); + quat=simulatedRigidbody.orientation.copy(); + double deltaTime = 0.05; + velocity=simulatedRigidbody.globalVelocity.scale(deltaTime); + move(simulatedRigidbody.globalVelocity.x* deltaTime,simulatedRigidbody.globalVelocity.y* deltaTime,simulatedRigidbody.globalVelocity.z* deltaTime); + } if (!airshipInitialized) { initFakeClientWorld(); @@ -135,7 +148,7 @@ public void tickContraption() { for (ControlledContraptionEntity contraptionEntity : subContraptions.values()) { contraptionEntity.tick(); } - fakeClientWorld.tickEntities(); +// fakeClientWorld.tickEntities(); fakeClientWorld.tickBlockEntities(); profiler.endTick(); @@ -210,9 +223,11 @@ public void onSyncedDataUpdated(DataParameter pKey) { if (pKey.equals(physicsDataAccessor)) { CompoundNBT tag = this.entityData.get((DataParameter) pKey); - simulatedRigidbody.momentum = simulatedRigidbody.arrayToVec(readDoubleArray(tag, "momentum")); - simulatedRigidbody.angularMomentum = simulatedRigidbody.arrayToVec(readDoubleArray(tag, "angularMomentum")); - simulatedRigidbody.orientation = simulatedRigidbody.arrayToQuat(readDoubleArray(tag, "orientation")); + if(tag.contains("momentum")) { + simulatedRigidbody.momentum = simulatedRigidbody.arrayToVec(readDoubleArray(tag, "momentum")); + simulatedRigidbody.angularMomentum = simulatedRigidbody.arrayToVec(readDoubleArray(tag, "angularMomentum")); + simulatedRigidbody.orientation = simulatedRigidbody.arrayToQuat(readDoubleArray(tag, "orientation")); + } } } @@ -469,6 +484,13 @@ public boolean handlePlayerInteraction2(PlayerEntity player, BlockPos localPos, public boolean handlePlayerInteraction(PlayerEntity player, BlockPos localPos, Direction side, Hand interactionHand) { + + + if(player.getItemInHand(interactionHand).getItem() instanceof ExtendoGripItem){ + simulatedRigidbody.addGlobalForce(player.getLookAngle().scale(100.0), new Vector3d(localPos.getX(), localPos.getY(), localPos.getZ())); + return true; + } + int indexOfSeat = contraption.getSeats() .indexOf(localPos); if (indexOfSeat == -1 && player instanceof ServerPlayerEntity) { @@ -479,7 +501,7 @@ public boolean handlePlayerInteraction(PlayerEntity player, BlockPos localPos, D try { state.getBlock().use(state, worldIn, dimensionPos, player, interactionHand, null); } catch (Exception e) { - + e.printStackTrace(); } return true; } diff --git a/src/main/java/com/eriksonn/createaeronautics/events/RenderEvents.java b/src/main/java/com/eriksonn/createaeronautics/events/RenderEvents.java index 43ed21f..ba6d3c0 100644 --- a/src/main/java/com/eriksonn/createaeronautics/events/RenderEvents.java +++ b/src/main/java/com/eriksonn/createaeronautics/events/RenderEvents.java @@ -45,18 +45,18 @@ public static void renderList(RenderWorldLastEvent event) { ClientPlayerEntity player = mc.player; if(player == null) return; - Vector3d origin = RaycastHelper.getTraceOrigin(mc.player); + Vector3d playerEye = RaycastHelper.getTraceOrigin(mc.player); double reach = mc.gameMode.getPickRange(); if (mc.hitResult != null && mc.hitResult.getLocation() != null) reach = Math.max(mc.hitResult.getLocation() - .distanceTo(origin), reach); + .distanceTo(playerEye), reach); - Vector3d target = RaycastHelper.getTraceTarget(mc.player, reach, origin); + Vector3d target = RaycastHelper.getTraceTarget(mc.player, reach, playerEye); for (AirshipContraptionEntity contraptionEntity : mc.level - .getEntitiesOfClass(AirshipContraptionEntity.class, new AxisAlignedBB(origin, target))) { + .getEntitiesOfClass(AirshipContraptionEntity.class, new AxisAlignedBB(playerEye, target))) { - Vector3d localOrigin = contraptionEntity.toLocalVector(origin, 1); + Vector3d localOrigin = contraptionEntity.toLocalVector(playerEye, 1); Vector3d localTarget = contraptionEntity.toLocalVector(target, 1); Contraption contraption = contraptionEntity.getContraption(); diff --git a/src/main/java/com/eriksonn/createaeronautics/inspect/InspectScenariosScreen.java b/src/main/java/com/eriksonn/createaeronautics/inspect/InspectScenariosScreen.java new file mode 100644 index 0000000..6eeef49 --- /dev/null +++ b/src/main/java/com/eriksonn/createaeronautics/inspect/InspectScenariosScreen.java @@ -0,0 +1,183 @@ +package com.eriksonn.createaeronautics.inspect; + +import com.eriksonn.createaeronautics.contraptions.AirshipContraptionEntity; +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.gui.*; +import com.simibubi.create.foundation.ponder.NavigatableSimiScreen; +import com.simibubi.create.foundation.ponder.ui.LayoutHelper; +import com.simibubi.create.foundation.ponder.ui.PonderButton; +import com.simibubi.create.foundation.utility.FontHelper; +import net.minecraft.client.MainWindow; +import net.minecraft.client.gui.widget.Widget; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.text.StringTextComponent; + +import java.util.Optional; + +public class InspectScenariosScreen extends NavigatableSimiScreen { + + + private PonderButton windTunnelButton, bouyancyTestButton, balanceTestButton; + + public static InspectScenariosScreen of(AirshipContraptionEntity movedContraption) { + return new InspectScenariosScreen(movedContraption); + } + + AirshipContraptionEntity airship; + + private InspectScenariosScreen(AirshipContraptionEntity movedContraption) { + this.airship = movedContraption; + } + @Override + protected void init() { + widgets.clear(); + super.init(); + + + int rowCount = MathHelper.clamp((int) Math.ceil(3 / 11d), 1, 3); + LayoutHelper layout = LayoutHelper.centeredHorizontal(3, rowCount, 28, 28, 8); + int itemCenterX = (int) (width * 0.5); + int itemCenterY = (int) (0.15 * height + 45); + + // wind tunnel + windTunnelButton = + new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4).showing(new ItemStack(AllBlocks.SAIL.get())) + .withCallback(() -> { + ScreenOpener.transitionTo(InspectUI.of(airship, PhysicsScenario.WIND_TUNNEL)); + });; + widgets.add(windTunnelButton); + layout.next(); + + // balance test + balanceTestButton = + new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4).showing(new ItemStack(AllBlocks.TURNTABLE.get())) + .withCallback(() -> { + ScreenOpener.transitionTo(InspectUI.of(airship, PhysicsScenario.BALANCE)); + }); + widgets.add(balanceTestButton); + layout.next(); + + // bouyancy test + bouyancyTestButton = + new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4).showing(new ItemStack(Items.WATER_BUCKET)) + .withCallback(() -> { + ScreenOpener.transitionTo(InspectUI.of(airship, PhysicsScenario.BOUYANCY)); + });; + widgets.add(bouyancyTestButton); + layout.next(); + + widgets.add(backTrack = new PonderButton(31, height - 31 - 20).enableFade(0, 5) + .showing(AllIcons.I_MTD_CLOSE) + .withCallback(() -> ScreenOpener.openPreviousScreen(this, Optional.empty()))); + backTrack.fade(1); + + } + + @Override + protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + ms.pushPose(); + ms.translate(width / 2 - 120, height * 0.15 - 40, 0); + + ms.pushPose(); + // ms.translate(0, 0, 800); + int x = 31 + 20 + 8; + int y = 31; + + String title = "Physics Scenarios"; + + int streakHeight = 35; + UIRenderHelper.streak(ms, 0, x - 4, y - 12 + streakHeight / 2, streakHeight, 240); + // PonderUI.renderBox(ms, 21, 21, 30, 30, false); + new BoxElement().withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT)) + .gradientBorder(Theme.p(Theme.Key.PONDER_IDLE)) + .at(21, 21, 100) + .withBounds(30, 30) + .render(ms); + + font.draw(ms, title, x + 8, y + 1, Theme.i(Theme.Key.TEXT)); +// y += 8; +// x += 0; +// ms.translate(x, y, 0); +// ms.translate(0, 0, 5); +// textRenderer.draw(ms, title, 0, 0, Theme.i(Theme.Key.TEXT)); + ms.popPose(); + + ms.pushPose(); + ms.translate(23, 23, 10); + ms.scale(1.66f, 1.66f, 1.66f); + ms.translate(-4, -4, 0); + ms.scale(1.5f, 1.5f, 1.5f); + RenderElement.of(AllIcons.I_PLACEMENT_SETTINGS).render(ms); + ms.popPose(); + ms.popPose(); + + ms.pushPose(); + int w = (int) (width * .45); + x = (width - w) / 2; + y = ((int)(0.15 * height + 45)) - 10 + Math.max(28, 48); + + String desc = "Physics Scenarios can be used to test various aspects of your contraptions easily"; + int h = font.wordWrapHeight(desc, w); + + // PonderUI.renderBox(ms, x - 3, y - 3, w + 6, h + 6, false); + new BoxElement().withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT)) + .gradientBorder(Theme.p(Theme.Key.PONDER_IDLE)) + .at(x - 3, y - 3, 90) + .withBounds(w + 6, h + 6) + .render(ms); + + ms.translate(0, 0, 100); + FontHelper.drawSplitString(ms, font, desc, x, y, w, Theme.i(Theme.Key.TEXT)); + ms.popPose(); + + } + + private PhysicsScenario hoveredItem = null; + + + @Override + public void tick() { + super.tick(); + + hoveredItem = null; + MainWindow w = minecraft.getWindow(); + double mouseX = minecraft.mouseHandler.xpos() * w.getGuiScaledWidth() / w.getScreenWidth(); + double mouseY = minecraft.mouseHandler.ypos() * w.getGuiScaledHeight() / w.getScreenHeight(); + for (Widget widget : widgets) { + if (widget == backTrack) + continue; + if (widget == windTunnelButton || widget == balanceTestButton || widget == bouyancyTestButton) { + if (widget.isMouseOver(mouseX, mouseY)) + if(widget == windTunnelButton) { + hoveredItem = PhysicsScenario.WIND_TUNNEL; + } else if(widget == balanceTestButton) { + hoveredItem = PhysicsScenario.BALANCE; + } else if(widget == bouyancyTestButton) { + hoveredItem = PhysicsScenario.BOUYANCY; + } else { + hoveredItem = null; + } + } + } + } + + @Override + protected void renderWindowForeground(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + + if (hoveredItem == null) + return; + + ms.pushPose(); + ms.translate(0, 0, 200); + + String text = hoveredItem.text; + renderTooltip(ms, new StringTextComponent(text), mouseX, mouseY); + + ms.popPose(); + } + + +} diff --git a/src/main/java/com/eriksonn/createaeronautics/inspect/InspectUI.java b/src/main/java/com/eriksonn/createaeronautics/inspect/InspectUI.java new file mode 100644 index 0000000..1412282 --- /dev/null +++ b/src/main/java/com/eriksonn/createaeronautics/inspect/InspectUI.java @@ -0,0 +1,751 @@ +package com.eriksonn.createaeronautics.inspect; + +import com.eriksonn.createaeronautics.contraptions.AirshipContraption; +import com.eriksonn.createaeronautics.contraptions.AirshipContraptionEntity; +import com.eriksonn.createaeronautics.index.CABlocks; +import com.eriksonn.createaeronautics.network.NetworkMain; +import com.eriksonn.createaeronautics.network.packet.PausePhysicsPacket; +import com.eriksonn.createaeronautics.particle.PropellerAirParticle; +import com.eriksonn.createaeronautics.particle.PropellerAirParticleData; +import com.eriksonn.createaeronautics.physics.SimulatedContraptionRigidbody; +import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.systems.RenderSystem; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.components.structureMovement.bearing.SailBlock; +import com.simibubi.create.foundation.gui.*; +import com.simibubi.create.foundation.ponder.*; +import com.simibubi.create.foundation.ponder.content.PonderTag; +import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; +import com.simibubi.create.foundation.ponder.ui.PonderButton; +import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.utility.*; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.tterrag.registrate.util.entry.BlockEntry; +import net.minecraft.block.Block; +import net.minecraft.block.Blocks; +import net.minecraft.client.GameSettings; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Direction; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.MutableBoundingBox; +import net.minecraft.util.math.vector.Matrix4f; +import net.minecraft.util.math.vector.Quaternion; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.util.math.vector.Vector3f; +import net.minecraft.world.gen.feature.template.Template; +import org.lwjgl.opengl.GL11; + +import java.util.ArrayList; +import java.util.Map; +import java.util.Optional; + +import static com.eriksonn.createaeronautics.inspect.PhysicsScenario.WIND_TUNNEL; + +public class InspectUI extends NavigatableSimiScreen { + + + public static NavigatableSimiScreen of(AirshipContraptionEntity movedContraption) { + return new InspectUI(movedContraption, PhysicsScenario.NONE); + } + + public static NavigatableSimiScreen of(AirshipContraptionEntity movedContraption, PhysicsScenario scenario) { + return new InspectUI(movedContraption, scenario); + } + + private InspectUI(AirshipContraptionEntity movedContraption, PhysicsScenario scenario) { + this.airship = movedContraption; + this.scenario = scenario; + } + + public static float getPartialTicks() { + float renderPartialTicks = Minecraft.getInstance() + .getFrameTime(); + + return renderPartialTicks; + } + + AirshipContraptionEntity airship; + + PhysicsScenario scenario = PhysicsScenario.NONE; + SimulatedContraptionRigidbody rigidbody; + int basePlateTop = 0; + + + // ======== WIDGETS ======== + + private PonderButton close, pause, toggleCOM; + PonderButton playPauseScenario; + PonderButton rotateScenario; + QuatWorldSection section; + WorldSectionElement propeller; + + // ========================== + + // ========= SCENARIO ======== + + int scenarioStatementWidth = 130; + int scenarioStatementStartX; + int scenarioStatementEndX; + int scenarioStatementY; + + boolean scenarioHasBegunBefore = false; + boolean playScenario = false; + + BlockPos propellerCenter; + int propellerLength = 9; + + Vector3d originalPosition; + Vector3d sectionPosition; + Quaternion sectionRotation = Quaternion.ONE; + + public boolean inScenario() { + return scenario != PhysicsScenario.NONE; + } + + // ========================== + + PonderScene scene; + + @Override + protected void init() { + widgets.clear(); + super.init(); + + // ======== Constants ======== + scenarioStatementWidth = 230; + scenarioStatementY = 40; + scenarioStatementStartX = (width - scenarioStatementWidth) / 2; + scenarioStatementEndX = scenarioStatementStartX + scenarioStatementWidth; + int spacing = 60; + int simulateWidth = 20; + + GameSettings bindings = minecraft.options; + + if(!inScenario()) { + widgets.add(new PonderButton(width / 2 - 20 + spacing, height - 40) + .withShortcut(bindings.keyInventory) + .showing(AllIcons.I_MTD_CLOSE) + .withCallback(this::onClose)); + + widgets.add(pause = new PonderButton(width / 2 - 20, height - 40) + .withShortcut(bindings.keyDrop) + .showing(airship.playPhysics ? AllIcons.I_PAUSE : AllIcons.I_PLAY) + .withCallback(() -> { + if (airship.playPhysics) { + airship.playPhysics = false; + pause.showing(AllIcons.I_PLAY); + } else { + airship.playPhysics = true; + pause.showing(AllIcons.I_PAUSE); + } + NetworkMain.sendToServer(new PausePhysicsPacket(airship.plotId, !airship.playPhysics)); + })); + + widgets.add(new PonderButton(width / 2 - 20 - spacing, height - 40) + .showing(AllIcons.I_TRASH) + .withCallback(this::onClose)); + } + + // simulate button + widgets.add(new PonderButton(width - 20 - simulateWidth, 20).showing(AllIcons.I_PLACEMENT_SETTINGS).withCallback(this::onSimulateOpen)); + + // simulation widgets + if(inScenario()) { + widgets.add(playPauseScenario = new PonderButton(scenarioStatementEndX - 20 - 8, scenarioStatementY + 6).showing(AllIcons.I_PLAY).withCallback(() -> { + playScenario = !playScenario; + + if(!scenarioHasBegunBefore) { + scenarioHasBegunBefore = true; + rotateScenario.visible = false; + } + + if(playScenario) { + playPauseScenario.showing(AllIcons.I_PAUSE); + } else { + playPauseScenario.showing(AllIcons.I_PLAY); + } + })); + widgets.add(rotateScenario = new PonderButton(scenarioStatementEndX - 20 - 20 - 8 - 8, scenarioStatementY + 6).showing(AllIcons.I_ROTATE_CCW).withCallback(() -> { + rigidbody.orientation.mul(new Quaternion(new Vector3f(0, 1, 0), (float) Math.PI / 2, false)); + })); + } + + PonderButton comButton = new PonderButton(21, 21 + 50/*, 14, 14*/); + widgets.add(comButton.showing(AllIcons.I_CONFIRM)); + + scene = new PonderScene(new PonderWorld(BlockPos.ZERO, Minecraft.getInstance().level), "", new ResourceLocation(""), new ArrayList()); + + scene.getWorld().scene = scene; + + Map blocks = airship.getContraption().getBlocks(); + + int minx = 1000, miny = 1000, minz = 1000, maxx = -1000, maxy = -100, maxz = -1000; + + for (Map.Entry entry : blocks.entrySet()) { + BlockPos pos = entry.getKey().offset(0, 128, 0); + scene.getWorld().setBlock(pos, entry.getValue().state, 0); + minx = Math.min(minx, pos.getX()); + miny = Math.min(miny, pos.getY()); + minz = Math.min(minz, pos.getZ()); + maxx = Math.max(maxx, pos.getX()); + maxy = Math.max(maxy, pos.getY()); + maxz = Math.max(maxz, pos.getZ()); + } + + basePlateTop = miny - 2; + + rigidbody = new SimulatedContraptionRigidbody((AirshipContraption) airship.getContraption(), new PonderPhysicsAdapter(this)); + + section = new QuatWorldSection(rigidbody, Selection.of(new MutableBoundingBox(minx, miny, minz, maxx, maxy, maxz))); + section.forceApplyFade(1.0f); + section.setCenterOfRotation(airship.centerOfMassOffset.add(0.5, 128.5, 0.5)); + + scene.addElement(section); + scene.getWorld().pushFakeLight(15); + + scene.setFinished(false); + + + widgets.add(backTrack = new PonderButton(31, height - 31 - 20).enableFade(0, 5) + .showing(AllIcons.I_MTD_CLOSE) + .withCallback(() -> ScreenOpener.openPreviousScreen(this, Optional.empty()))); + backTrack.fade(1); + + originalPosition = new Vector3d(0, 128, 0).add(airship.centerOfMassOffset); + sectionPosition = originalPosition; + + if(inScenario()) { + + originalPosition = originalPosition.add(airship.centerOfMassOffset); + + if(scenario == PhysicsScenario.BALANCE) { + + int fluidTop = (miny) - 3; + int fluidWidth = maxx - minx + 2; + int fluidDepth = maxz - minz + 2; + int fluidBottom = (miny) - 4; + + // fill blocks + for(int x = minx - 4; x <= maxx + 4; x++) { + for(int y = fluidBottom; y < fluidTop; y++) { + for(int z = minz - 4; z <= maxz + 4 ; z++) { + BlockPos pos = new BlockPos(x, y, z); + + // dither checkerboard on x/z axis + if((x % 2 == 0 && z % 2 != 0) || (x % 2 != 0 && z % 2 == 0)) { + scene.getWorld().setBlock(pos, Blocks.WHITE_CONCRETE.defaultBlockState(), 0); + } else { + scene.getWorld().setBlock(pos, Blocks.SNOW_BLOCK.defaultBlockState(), 0); + } + + } + } + } + + WorldSectionElement fluidSection = new WorldSectionElement(Selection.of(new MutableBoundingBox( + -fluidWidth / 2, + fluidBottom, + -fluidWidth / 2, + fluidWidth / 2, + fluidTop, + fluidWidth / 2 + ))); + fluidSection.forceApplyFade(1.0f); + + scene.addElement(fluidSection); + + } + if(scenario == WIND_TUNNEL) { + + rigidbody.doCollisions = false; + int maxX = maxx + 10; + int midY = (miny + maxy) / 2; + + // propeller center + propellerCenter = new BlockPos(maxX, midY, 0); + + // propeller + scene.getWorld().setBlock(propellerCenter, AllBlocks.ANDESITE_CASING.getDefaultState(), 0); + + + // propeller blades + for(int i = 1; i < propellerLength; i++) { + BlockPos up = propellerCenter.offset(0, i, 0); + BlockPos down = propellerCenter.offset(0, -i, 0); + BlockPos left = propellerCenter.offset(0, 0, -i); + BlockPos right = propellerCenter.offset(0, 0, i); + scene.getWorld().setBlock(up, AllBlocks.SAIL.getDefaultState().setValue(SailBlock.FACING, Direction.WEST), 0); + scene.getWorld().setBlock(down, AllBlocks.SAIL.getDefaultState().setValue(SailBlock.FACING, Direction.WEST), 0); + scene.getWorld().setBlock(left, AllBlocks.SAIL.getDefaultState().setValue(SailBlock.FACING, Direction.WEST), 0); + scene.getWorld().setBlock(right, AllBlocks.SAIL.getDefaultState().setValue(SailBlock.FACING, Direction.WEST), 0); + } + + // section + propeller = new WorldSectionElement(Selection.of(new MutableBoundingBox( + maxX - 1, + midY - propellerLength, + -propellerLength, + maxX + 1, + midY + propellerLength, + propellerLength + ))); + + propeller.forceApplyFade(1.0f); + + scene.addElement(propeller); + } + } + + } + + private void onSimulateOpen() { + ScreenOpener.transitionTo(InspectScenariosScreen.of(airship)); + } + + public Vector3d toXYZ(Quaternion quat) { + float f = quat.r() * quat.r(); + float f1 = quat.i() * quat.i(); + float f2 = quat.j() * quat.j(); + float f3 = quat.k() * quat.k(); + float f4 = f + f1 + f2 + f3; + float f5 = 2.0F * quat.r() * quat.i() - 2.0F * quat.j() * quat.k(); + float f6 = (float)Math.asin((double)(f5 / f4)); + return Math.abs(f5) > 0.999F * f4 ? new Vector3d(2.0F * (float)Math.atan2((double)quat.i(), (double)quat.r()), f6, 0.0F) : new Vector3d((float)Math.atan2((double)(2.0F * quat.j() * quat.k() + 2.0F * quat.i() * quat.r()), (double)(f - f1 - f2 + f3)), f6, (float)Math.atan2((double)(2.0F * quat.i() * quat.j() + 2.0F * quat.r() * quat.k()), (double)(f + f1 - f2 - f3))); + } + + public Vector3d toXYZDegrees(Quaternion quat) { + Vector3d vector3f = this.toXYZ(quat); + return new Vector3d((float)Math.toDegrees((double)vector3f.x()), (float)Math.toDegrees((double)vector3f.y()), (float)Math.toDegrees((double)vector3f.z())); + } + + + + @Override + public void tick() { + super.tick(); + if(scene == null) return; + scene.tick(); + + if(inScenario()) { + if(playScenario) { + rigidbody.tick(); + + // ========= Wind Tunnel Particles ========= + if(scenario == WIND_TUNNEL) { + + rigidbody.momentum = new Vector3d(10, 0, 0).scale(rigidbody.getMass()); + rigidbody.doGravity = false; + + propeller.setAnimatedRotation(propeller.getAnimatedRotation().add(16.0, 0.0, 0.0), false); + + + for(int i = 0; i < 10; i++) { + + Vector3d pos = new Vector3d(propellerCenter.getX(), propellerCenter.getY(), propellerCenter.getZ()); + + // random rotation + pos = pos.add(new Vector3d( + 0.0, + (Math.random() - 0.5) * 0.5, + (Math.random() - 0.5) * 0.5 + ).scale(propellerLength * 2.0)); + + // spawn particles + scene.getWorld().addParticle(new PropellerAirParticleData(), pos.x, pos.y, pos.z, -5, 0, 0); + } + } + + // Don't update position in wind tunnel + if(scenario != WIND_TUNNEL) { + sectionPosition = sectionPosition.add(rigidbody.globalVelocity.scale(0.05)); + } + } + + sectionRotation = rigidbody.orientation; + } + + Vector3d rotation = toXYZDegrees(sectionRotation); + section.setAnimatedRotation(rotation, false); + section.setAnimatedOffset(sectionPosition.subtract(originalPosition), false); + + // 90 degree interval snapping + if(!mouseDown) { + double currentXRot = scene.getTransform().xRotation.getValue(); + double currentYRot = scene.getTransform().yRotation.getValue(); + + double snapX = Math.round(currentXRot / 90) * 90; + double snapY = Math.round(currentYRot / 90) * 90; + + // only snap if within 10 degrees + if(Math.abs(snapX - currentXRot) < 10 && Math.abs(snapY - currentYRot) < 10) { + scene.getTransform().xRotation.chase(snapX, 15.0f, LerpedFloat.Chaser.LINEAR); + scene.getTransform().yRotation.chase(snapY, 15.0f, LerpedFloat.Chaser.LINEAR); + } + + } + } + + boolean mouseDown = false; + + @Override + public boolean mouseClicked(double x, double y, int button) { + mouseDown = true; + return super.mouseClicked(x, y, button); + } + + @Override + public boolean mouseReleased(double x, double y, int button) { + mouseDown = false; + return super.mouseReleased(x, y, button); + } + + @Override + protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + + partialTicks = getPartialTicks(); + RenderSystem.enableBlend(); + RenderSystem.disableDepthTest(); + + int tooltipColor = Theme.i(Theme.Key.TEXT_DARKER); + { + // Chapter title + ms.pushPose(); + ms.translate(0, 0, 400); + int x = 31 + 20 + 8; + int y = 31; + + font.draw(ms, "Test Physics Scenarios", width - 100 - 18 - 50, 26, tooltipColor); + + String title = "Airship #" + airship.plotId; + int wordWrappedHeight = font.wordWrapHeight(title, (width / 3)); + + int streakHeight = 35 - 9 + wordWrappedHeight; + UIRenderHelper.streak(ms, 0, x - 4, y - 12 + streakHeight / 2, streakHeight, (int) (150 * 1.0)); + UIRenderHelper.streak(ms, 180, x - 4, y - 12 + streakHeight / 2, streakHeight, (int) (30 * 1.0)); + new BoxElement() + .withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT)) + .gradientBorder(Theme.p(Theme.Key.PONDER_IDLE)) + .at(21, 21, 100) + .withBounds(30, 30) + .render(ms); + + + GuiGameElement.of(new ItemStack(CABlocks.AIRSHIP_ASSEMBLER.get().asItem())) + .scale(2) + .at(x - 39, y - 11) + .render(ms); + + font.draw(ms, "Inspecting...", x, y - 6, tooltipColor); + + y += 8; + x += 0; + + + ms.translate(x, y, 0); + FontHelper.drawSplitString(ms, font, title, 0, 0, (width / 3), + Theme.c(Theme.Key.TEXT).getRGB()); + font.draw(ms, "Disable Center Of Mass", -8, 37, Theme.c(Theme.Key.BUTTON_SUCCESS).getRGB()); + + ms.popPose(); + + if(inScenario()) { + ms.pushPose(); + ms.translate(0, 0, 400); + + // we need to let the player know they're in a scenario + UIRenderHelper.streak(ms, 0, scenarioStatementStartX, scenarioStatementY + streakHeight / 2, streakHeight, scenarioStatementWidth + 60); +// UIRenderHelper.streak(ms, 180, scenarioStatementStartX, scenarioStatementY + streakHeight / 2, streakHeight, scenarioStatementWidth / 5); + new BoxElement() + .withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT)) + .gradientBorder(Theme.p(Theme.Key.PONDER_IDLE)) + .at(scenarioStatementStartX + 1, scenarioStatementY + 1, 100) + .withBounds(30, 30) + .render(ms); + + + GuiGameElement.of(new ItemStack(((Block) scenario.item.get()).asItem())) + .scale(2) + .at(scenarioStatementStartX, scenarioStatementY) + .render(ms); + + font.draw(ms, "Pondering Scenario...", scenarioStatementStartX + 40, scenarioStatementY + 6, tooltipColor); + String scenarioTitle = scenario.toString().toLowerCase().replace("_", " "); + scenarioTitle = scenarioTitle.substring(0, 1).toUpperCase() + scenarioTitle.substring(1); + + font.draw(ms, scenarioTitle, scenarioStatementStartX + 40, scenarioStatementY + 6 + 12, Theme.c(Theme.Key.TEXT).getRGB()); + + ms.popPose(); + } + } + + if(scene != null) { + renderScene(ms, mouseX, mouseY, 0, partialTicks); + } + + RenderSystem.disableBlend(); + + } + + protected void renderScene(MatrixStack ms, int mouseX, int mouseY, int i, float partialTicks) { + SuperRenderTypeBuffer buffer = SuperRenderTypeBuffer.getInstance(); + PonderScene story = scene; + double diff = 0; + double slide = MathHelper.lerp(diff * diff, 200, 600) * diff; + slide = 1.0; + + MutableBoundingBox bounds = story.getBounds(); + float maxSpan = Math.max(Math.max(bounds.getXSpan(), bounds.getYSpan() - 128), bounds.getZSpan()); +// float scale = (float) (8.0 / maxSpan) * (inScenario() ? 1.0f : 1.0f); + float scale = 0.4f; + + RenderSystem.enableAlphaTest(); + RenderSystem.enableBlend(); + RenderSystem.enableDepthTest(); + + RenderSystem.pushMatrix(); + + // has to be outside of MS transforms, important for vertex sorting + RenderSystem.translated(0, 0, 800); + + ms.pushPose(); + ms.translate(0, 0, -400); + story.getTransform().updateScreenParams(width, height, slide); + story.getTransform().apply(ms, partialTicks, false); + story.getTransform().updateSceneRVE(partialTicks); + ms.scale(scale, scale, scale); + ms.translate(0, -128, 0); + story.renderScene(buffer, ms, partialTicks); + + + buffer.draw(); + +// ms.pushPose(); + + ms.popPose(); +// ms.popPose(); + RenderSystem.popMatrix(); + + RenderSystem.disableDepthTest(); + RenderSystem.pushMatrix(); + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder builder = tessellator.getBuilder(); + + RenderSystem.translated(0, 0, 800); + + ms.pushPose(); + ms.translate(0, 0, -800); + story.getTransform().updateScreenParams(width, height, slide); + story.getTransform().apply(ms, partialTicks, false); + + Vector3d rotation = section.getAnimatedRotation(); + + + // ms.translate(0, 128, 0); + ms.scale(scale, scale, scale); + + float size = 0.2f; + double offset = 0.5 - size / 2; + + ms.translate(offset, offset, offset); + ms.translate(airship.centerOfMassOffset.x, airship.centerOfMassOffset.y, airship.centerOfMassOffset.z); + Vector3d contraptionPositionOffset = section.getAnimatedOffset(); + ms.translate(contraptionPositionOffset.x, contraptionPositionOffset.y, contraptionPositionOffset.z); + + + Matrix4f model = ms.last().pose(); + builder.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR); + + cube(builder, size, 1.0, model, 230, 230, 0); + + if(scenario == WIND_TUNNEL) { + ms.translate(0, 0, -10); + cube(builder, size, 40.0 * 1 / offset, model, 240, 240, 240); + } + + tessellator.end(); + ms.popPose(); + RenderSystem.popMatrix(); + + } + + private void cube(BufferBuilder builder, float size, double zScale, Matrix4f model, int r, int g, int b) { + quad( + builder, + model, + new Vector3d(0, 0.0, 0.0), + new Vector3d(0, size, 0.0), + new Vector3d(size, size, 0.0), + new Vector3d(size, 0.0, 0.0), + r + 0, + g + 0, + b + 0 + ); + quad( + builder, + model, + new Vector3d(size, 0.0, size * zScale), + new Vector3d(size, size, size * zScale), + new Vector3d(0, size, size * zScale), + new Vector3d(0, 0.0, size * zScale), + r + 0, + g + 0, + b + 0 + ); + quad( + builder, + model, + new Vector3d(0, size, 0.0), + new Vector3d(0, size, size * zScale), + new Vector3d(size, size, size * zScale), + new Vector3d(size, size, 0.0), + r + 20, + g + 20, + b + 20 + ); + // bottom + quad( + builder, + model, + new Vector3d(size, 0.0, 0.0), + new Vector3d(size, 0.0, size * zScale), + new Vector3d(0, 0.0, size * zScale), + new Vector3d(0, 0.0, 0.0), + r -20, + g -20, + b -20 + ); + // top + quad( + builder, + model, + new Vector3d(0.0, 0.0, size * zScale), + new Vector3d(0.0, size, size * zScale), + new Vector3d(0, size, 0.0), + new Vector3d(0, 0.0, 0.0), + r + 0, + g + 0, + b + 0 + ); + quad( + builder, + model, + new Vector3d(size, 0.0, 0.0), + new Vector3d(size, size, 0.0), + new Vector3d(size, size, size * zScale), + new Vector3d(size, 0.0, size * zScale), + r + 0, + g + 0, + b + 0 + ); + } + + private void quad(BufferBuilder buffer, Matrix4f model, Vector3d a, Vector3d b, Vector3d c, Vector3d d, int rmod, int gmod, int bmod) { + buffer.vertex(model, (float) a.x, (float) a.y, (float) a.z).color(Math.min(rmod, 255), Math.min(gmod, 255), Math.min(Math.max(0, 0 + bmod), 255), 0).endVertex(); + buffer.vertex(model, (float) b.x, (float) b.y, (float) b.z).color(Math.min(rmod, 255), Math.min(gmod, 255), Math.min(Math.max(0, 0 + bmod), 255), 0).endVertex(); + buffer.vertex(model, (float) c.x, (float) c.y, (float) c.z).color(Math.min(rmod, 255), Math.min(gmod, 255), Math.min(Math.max(0, 0 + bmod), 255), 0).endVertex(); + buffer.vertex(model, (float) d.x, (float) d.y, (float) d.z).color(Math.min(rmod, 255), Math.min(gmod, 255), Math.min(Math.max(0, 0 + bmod), 255), 0).endVertex(); + + + +// b.vertex(model, 0, 0, 0).color(0, 255, 0, 0).endVertex(); +// b.vertex(model, 0, size, 0).color(0, 255, 0, 0).endVertex(); +// b.vertex(model, size, size, 0).color(0, 255, 0, 0).endVertex(); +// b.vertex(model, size, 0, 0).color(0, 255, 0, 0).endVertex(); + } + + @Override + public boolean mouseDragged(double p_231045_1_, double p_231045_3_, int p_231045_5_, double dragX, double dragY) { + scene.getTransform().xRotation.chase(scene.getTransform().xRotation.getChaseTarget() - dragY / 3, 100.0, LerpedFloat.Chaser.LINEAR); + scene.getTransform().yRotation.chase(scene.getTransform().yRotation.getChaseTarget() + dragX / 3, 100.0, LerpedFloat.Chaser.LINEAR); + return super.mouseDragged(p_231045_1_, p_231045_3_, p_231045_5_, dragX, dragY); + } + + @Override + protected String getBreadcrumbTitle() { + return "Airship Physics Info"; + } + + public static void renderSpeechBox(MatrixStack ms, int x, int y, int w, int h, boolean highlighted, Pointing pointing, + boolean returnWithLocalTransform) { + if (!returnWithLocalTransform) + ms.pushPose(); + + int boxX = x; + int boxY = y; + int divotX = x; + int divotY = y; + int divotRotation = 0; + int divotSize = 8; + int distance = 1; + int divotRadius = divotSize / 2; + Couple borderColors = Theme.p(highlighted ? Theme.Key.PONDER_HIGHLIGHT : Theme.Key.PONDER_IDLE); + Color c; + + switch (pointing) { + default: + case DOWN: + divotRotation = 0; + boxX -= w / 2; + boxY -= h + divotSize + 1 + distance; + divotX -= divotRadius; + divotY -= divotSize + distance; + c = borderColors.getSecond(); + break; + case LEFT: + divotRotation = 90; + boxX += divotSize + 1 + distance; + boxY -= h / 2; + divotX += distance; + divotY -= divotRadius; + c = Color.mixColors(borderColors, 0.5f); + break; + case RIGHT: + divotRotation = 270; + boxX -= w + divotSize + 1 + distance; + boxY -= h / 2; + divotX -= divotSize + distance; + divotY -= divotRadius; + c = Color.mixColors(borderColors, 0.5f); + break; + case UP: + divotRotation = 180; + boxX -= w / 2; + boxY += divotSize + 1 + distance; + divotX -= divotRadius; + divotY += distance; + c = borderColors.getFirst(); + break; + } + + new BoxElement() + .withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT)) + .gradientBorder(borderColors) + .at(boxX, boxY, 100) + .withBounds(w, h) + .render(ms); + + ms.pushPose(); + ms.translate(divotX + divotRadius, divotY + divotRadius, 10); +// ms.mulPose(Vector3f.ZP.rotationDegrees(divotRotation)); + ms.translate(-divotRadius, -divotRadius, 0); + AllGuiTextures.SPEECH_TOOLTIP_BACKGROUND.draw(ms, 0, 0); + AllGuiTextures.SPEECH_TOOLTIP_COLOR.draw(ms, 0, 0, c); + ms.popPose(); + + if (returnWithLocalTransform) { + ms.translate(boxX, boxY, 0); + return; + } + + ms.popPose(); + + } + +} diff --git a/src/main/java/com/eriksonn/createaeronautics/inspect/PhysicsScenario.java b/src/main/java/com/eriksonn/createaeronautics/inspect/PhysicsScenario.java new file mode 100644 index 0000000..dff2e26 --- /dev/null +++ b/src/main/java/com/eriksonn/createaeronautics/inspect/PhysicsScenario.java @@ -0,0 +1,31 @@ +package com.eriksonn.createaeronautics.inspect; + +import com.eriksonn.createaeronautics.index.CABlocks; +import com.eriksonn.createaeronautics.index.CAParticleTypes; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.repack.registrate.util.entry.BlockEntry; +import com.tterrag.registrate.util.entry.ItemProviderEntry; +import net.minecraft.util.IItemProvider; + +public enum PhysicsScenario { + BOUYANCY("Test the bouyancy of your contraption", AllBlocks.WATER_WHEEL), + BALANCE("Test the balance of your contraption", AllBlocks.TURNTABLE), + WIND_TUNNEL("Test the aerodynamics of your contraption", AllBlocks.SAIL), + NONE; + public String text; + public BlockEntry item = CABlocks.AIRSHIP_ASSEMBLER; + + PhysicsScenario() { + this.text = ""; + } + + PhysicsScenario(String text) { + this.text = text; + } + + PhysicsScenario(String text, BlockEntry item) { + this.text = text; + this.item = item; + + } +} diff --git a/src/main/java/com/eriksonn/createaeronautics/inspect/PonderPhysicsAdapter.java b/src/main/java/com/eriksonn/createaeronautics/inspect/PonderPhysicsAdapter.java new file mode 100644 index 0000000..e173f0d --- /dev/null +++ b/src/main/java/com/eriksonn/createaeronautics/inspect/PonderPhysicsAdapter.java @@ -0,0 +1,75 @@ +package com.eriksonn.createaeronautics.inspect; + +import com.eriksonn.createaeronautics.physics.SimulatedContraptionRigidbody; +import com.eriksonn.createaeronautics.physics.api.PhysicsAdapter; +import com.simibubi.create.foundation.utility.VecHelper; +import net.minecraft.block.BlockState; +import net.minecraft.fluid.FluidState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.shapes.VoxelShape; +import net.minecraft.util.math.shapes.VoxelShapePart; +import net.minecraft.util.math.shapes.VoxelShapes; +import net.minecraft.util.math.vector.Vector3d; + +public class PonderPhysicsAdapter implements PhysicsAdapter { + InspectUI inspectUI; + + public PonderPhysicsAdapter(InspectUI inspectUI) { + this.inspectUI = inspectUI; + } + + @Override + public Vector3d position() { + return inspectUI.sectionPosition; + } + + @Override + public FluidState getFluidState(BlockPos pos) { + return inspectUI.scene.getWorld().getBlockState(pos).getFluidState(); + } + + @Override + public Vector3d toGlobalVector(Vector3d localVec, float partialTicks) { + double x = /*MathHelper.lerp(partialTicks, oldPosition.x, */position().x; + double y = /*MathHelper.lerp(partialTicks, oldPosition.y, */position().y; + double z = /*MathHelper.lerp(partialTicks, oldPosition.z, */position().z; + Vector3d anchorVec = new Vector3d(x, y, z); + + Vector3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO); + localVec = localVec.subtract(rotationOffset).subtract(inspectUI.rigidbody.getCenterOfMass()); + localVec = applyRotation(localVec, partialTicks); + localVec = localVec.add(rotationOffset) + .add(anchorVec); + return localVec; + } + + @Override + public Vector3d applyRotation(Vector3d localPos, float partialTicks) { + return SimulatedContraptionRigidbody.rotateQuat(localPos, inspectUI.rigidbody.getPartialOrientation(partialTicks)); + } + + @Override + public Vector3d getPlotOffset() { + return new Vector3d(0, -128, 0); + } + + @Override + public BlockState getBlockState(BlockPos worldPos) { + return inspectUI.scene.getWorld().getBlockState(worldPos); + } + + @Override + public VoxelShape getCollisionShape(BlockPos position) { + if(position.getY() > inspectUI.basePlateTop) { + return VoxelShapes.empty(); + } + return inspectUI.scene.getWorld().getBlockState(position).getCollisionShape(inspectUI.scene.getWorld(), position); + } + + @Override + public VoxelShape getCollisionShapeOnContraption(BlockPos position) { + return inspectUI.airship.getContraption().getBlocks().get(position).state.getCollisionShape(inspectUI.airship.getContraption().getContraptionWorld(), position); +// return inspectUI.scene.getWorld().getBlockState(); + } +} diff --git a/src/main/java/com/eriksonn/createaeronautics/inspect/QuatWorldSection.java b/src/main/java/com/eriksonn/createaeronautics/inspect/QuatWorldSection.java new file mode 100644 index 0000000..77058c1 --- /dev/null +++ b/src/main/java/com/eriksonn/createaeronautics/inspect/QuatWorldSection.java @@ -0,0 +1,61 @@ +package com.eriksonn.createaeronautics.inspect; + +import com.eriksonn.createaeronautics.physics.SimulatedContraptionRigidbody; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.foundation.ponder.PonderScene; +import com.simibubi.create.foundation.ponder.Selection; +import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; +import com.simibubi.create.foundation.utility.VecHelper; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.vector.Quaternion; +import net.minecraft.util.math.vector.Vector3d; + +public class QuatWorldSection extends WorldSectionElement { + + SimulatedContraptionRigidbody rigidbody; + + public QuatWorldSection(SimulatedContraptionRigidbody rigidbody) { + this.rigidbody = rigidbody; + } + + public QuatWorldSection(SimulatedContraptionRigidbody rigidbody, Selection selection) { + super(selection); + this.rigidbody = rigidbody; + } + + private Vector3d reverseTransformVec(Vector3d in) { + return new Vector3d(in.x, in.y, -in.z); + } + + Vector3d prevAnimatedOffset = new Vector3d(0, 0, 0); + + @Override + public void tick(PonderScene scene) { + prevAnimatedOffset = getAnimatedOffset(); + super.tick(scene); + } + + Vector3d center; + + @Override + public void setCenterOfRotation(Vector3d center) { + this.center = center; + super.setCenterOfRotation(center); + } + + + @Override + public void transformMS(MatrixStack ms, float pt) { + MatrixTransformStack.of(ms) + .translate(VecHelper.lerp(pt, prevAnimatedOffset, getAnimatedOffset())); + ms.translate(center.x, center.y, center.z); + + Quaternion quat = rigidbody.getPartialOrientation(pt); + // invert the quaternion + quat.conj(); + + ms.mulPose(quat); + ms.translate(-center.x, -center.y, -center.z); + } +} \ No newline at end of file diff --git a/src/main/java/com/eriksonn/createaeronautics/mixins/GoggleOverlayRendererMixin.java b/src/main/java/com/eriksonn/createaeronautics/mixins/GoggleOverlayRendererMixin.java new file mode 100644 index 0000000..f492fff --- /dev/null +++ b/src/main/java/com/eriksonn/createaeronautics/mixins/GoggleOverlayRendererMixin.java @@ -0,0 +1,10 @@ +package com.eriksonn.createaeronautics.mixins; + +import com.simibubi.create.content.contraptions.goggles.GoggleOverlayRenderer; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(GoggleOverlayRenderer.class) +public class GoggleOverlayRendererMixin { + + +} diff --git a/src/main/java/com/eriksonn/createaeronautics/mixins/OutlineEntryMixin.java b/src/main/java/com/eriksonn/createaeronautics/mixins/OutlineEntryMixin.java new file mode 100644 index 0000000..a9c6b24 --- /dev/null +++ b/src/main/java/com/eriksonn/createaeronautics/mixins/OutlineEntryMixin.java @@ -0,0 +1,13 @@ +package com.eriksonn.createaeronautics.mixins; + +import com.simibubi.create.foundation.utility.outliner.Outliner; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(Outliner.OutlineEntry.class) +public interface OutlineEntryMixin { + + @Accessor + void setTicksTillRemoval(int ticks); + +} diff --git a/src/main/java/com/eriksonn/createaeronautics/mixins/OutlinerMixin.java b/src/main/java/com/eriksonn/createaeronautics/mixins/OutlinerMixin.java new file mode 100644 index 0000000..2e87f57 --- /dev/null +++ b/src/main/java/com/eriksonn/createaeronautics/mixins/OutlinerMixin.java @@ -0,0 +1,42 @@ +package com.eriksonn.createaeronautics.mixins; + +import com.eriksonn.createaeronautics.render.OutlinerMixinInterface; +import com.eriksonn.createaeronautics.render.PhysicsInfoAABBOutline; +import com.simibubi.create.foundation.utility.outliner.ChasingAABBOutline; +import com.simibubi.create.foundation.utility.outliner.Outline; +import com.simibubi.create.foundation.utility.outliner.Outliner; +import net.minecraft.util.math.AxisAlignedBB; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Map; + +@Mixin(Outliner.class) +public abstract class OutlinerMixin implements OutlinerMixinInterface { + + + @Shadow @Final private Map outlines; + + @Override public PhysicsInfoAABBOutline getAndRefreshPhysicsAABB(Object slot) { + Outliner.OutlineEntry entry = outlines.get(slot); + ((OutlineEntryMixin) entry).setTicksTillRemoval(1); + return (PhysicsInfoAABBOutline) entry.getOutline(); + } + + @Override public Outline.OutlineParams showPhysicsAABB(Object slot, AxisAlignedBB bb) { + createPhysicsAABBOutlineIfMissing(slot, bb); + PhysicsInfoAABBOutline outline = getAndRefreshPhysicsAABB(slot); + return outline.getParams(); + } + + @Override public void createPhysicsAABBOutlineIfMissing(Object slot, AxisAlignedBB bb) { + if (!outlines.containsKey(slot) || !(outlines.get(slot).getOutline() instanceof PhysicsInfoAABBOutline)) { + PhysicsInfoAABBOutline outline = new PhysicsInfoAABBOutline(bb); + outlines.put(slot, new Outliner.OutlineEntry(outline)); + } + } + + + +} diff --git a/src/main/java/com/eriksonn/createaeronautics/network/NetworkMain.java b/src/main/java/com/eriksonn/createaeronautics/network/NetworkMain.java index 0aa9995..8a13149 100644 --- a/src/main/java/com/eriksonn/createaeronautics/network/NetworkMain.java +++ b/src/main/java/com/eriksonn/createaeronautics/network/NetworkMain.java @@ -32,7 +32,9 @@ public static void init() { CHANNEL.registerMessage(packetID++, AirshipAddSubcontraptionPacket.class, AirshipAddSubcontraptionPacket::encode, AirshipAddSubcontraptionPacket::new, AirshipAddSubcontraptionPacket::handle, Optional.of(NetworkDirection.PLAY_TO_CLIENT)); CHANNEL.registerMessage(packetID++, AirshipUpdateSubcontraptionPacket.class, AirshipUpdateSubcontraptionPacket::encode, AirshipUpdateSubcontraptionPacket::new, AirshipUpdateSubcontraptionPacket::handle, Optional.of(NetworkDirection.PLAY_TO_CLIENT)); CHANNEL.registerMessage(packetID++, AirshipDestroySubcontraptionPacket.class, AirshipDestroySubcontraptionPacket::encode, AirshipDestroySubcontraptionPacket::new, AirshipDestroySubcontraptionPacket::handle, Optional.of(NetworkDirection.PLAY_TO_CLIENT)); + CHANNEL.registerMessage(packetID++, PausePhysicsPacket.class, PausePhysicsPacket::encode, PausePhysicsPacket::new, PausePhysicsPacket::handle, Optional.of(NetworkDirection.PLAY_TO_SERVER)); CHANNEL.registerMessage(packetID++, AirshipBEUpdatePacket.class, AirshipBEUpdatePacket::encode, AirshipBEUpdatePacket::new, AirshipBEUpdatePacket::handle, Optional.of(NetworkDirection.PLAY_TO_CLIENT)); + CHANNEL.registerMessage(packetID++, InspectAirshipPacket.class, InspectAirshipPacket::encode, InspectAirshipPacket::new, InspectAirshipPacket::handle, Optional.of(NetworkDirection.PLAY_TO_CLIENT)); } public static void sendToServer(T t) { diff --git a/src/main/java/com/eriksonn/createaeronautics/network/packet/InspectAirshipPacket.java b/src/main/java/com/eriksonn/createaeronautics/network/packet/InspectAirshipPacket.java new file mode 100644 index 0000000..e917cbf --- /dev/null +++ b/src/main/java/com/eriksonn/createaeronautics/network/packet/InspectAirshipPacket.java @@ -0,0 +1,40 @@ +package com.eriksonn.createaeronautics.network.packet; + +import com.eriksonn.createaeronautics.contraptions.AirshipManager; +import com.eriksonn.createaeronautics.inspect.InspectUI; +import com.eriksonn.createaeronautics.network.ClientPacketHandler; +import com.simibubi.create.foundation.gui.ScreenOpener; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.fml.network.NetworkEvent; + +import java.util.function.Supplier; + +public class InspectAirshipPacket { + public int airshipID; + + public InspectAirshipPacket(int airshipID) { + this.airshipID = airshipID; + } + + public InspectAirshipPacket(PacketBuffer buffer) { + airshipID = buffer.readInt(); + } + + public void encode(PacketBuffer buffer) { + buffer.writeInt(airshipID); + } + + + public static void handle(InspectAirshipPacket msg, Supplier ctx) { + ctx.get().enqueueWork(() -> { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> ScreenOpener.transitionTo(InspectUI.of(AirshipManager.INSTANCE.AllClientAirships.get(msg.airshipID)))); + + + }); + ctx.get().setPacketHandled(true); + } + +} diff --git a/src/main/java/com/eriksonn/createaeronautics/network/packet/PausePhysicsPacket.java b/src/main/java/com/eriksonn/createaeronautics/network/packet/PausePhysicsPacket.java new file mode 100644 index 0000000..48866a9 --- /dev/null +++ b/src/main/java/com/eriksonn/createaeronautics/network/packet/PausePhysicsPacket.java @@ -0,0 +1,40 @@ +package com.eriksonn.createaeronautics.network.packet; + +import com.eriksonn.createaeronautics.contraptions.AirshipManager; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.fml.network.NetworkEvent; + +import java.util.function.Supplier; + +public class PausePhysicsPacket { + public int airshipID; + public boolean pause; + + public PausePhysicsPacket(int airshipID, boolean pause) { + this.airshipID = airshipID; + this.pause = pause; + } + + public PausePhysicsPacket(PacketBuffer buffer) { + airshipID = buffer.readInt(); + pause = buffer.readBoolean(); + } + + public void encode(PacketBuffer buffer) { + buffer.writeInt(airshipID); + buffer.writeBoolean(pause); + } + + + public static void handle(PausePhysicsPacket msg, Supplier ctx) { + ctx.get().enqueueWork(() -> { + ServerPlayerEntity sender = ctx.get().getSender(); // the client that sent this packet + if (sender != null) { + AirshipManager.INSTANCE.AllAirships.get(msg.airshipID).playPhysics = (!msg.pause); + } + + }); + ctx.get().setPacketHandled(true); + } +} diff --git a/src/main/java/com/eriksonn/createaeronautics/physics/AbstractContraptionRigidbody.java b/src/main/java/com/eriksonn/createaeronautics/physics/AbstractContraptionRigidbody.java index 572b0d2..c1237e4 100644 --- a/src/main/java/com/eriksonn/createaeronautics/physics/AbstractContraptionRigidbody.java +++ b/src/main/java/com/eriksonn/createaeronautics/physics/AbstractContraptionRigidbody.java @@ -1,5 +1,6 @@ package com.eriksonn.createaeronautics.physics; +import com.eriksonn.createaeronautics.physics.api.PhysicsAdapter; import com.eriksonn.createaeronautics.physics.collision.shape.ICollisionShape; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; @@ -19,6 +20,7 @@ public abstract class AbstractContraptionRigidbody implements IRigidbody{ public double[][] localInertiaTensor=new double[3][3]; public double localMass; public Map sails = new HashMap<>(); + public PhysicsAdapter adapter; public void generateMassDependentParameters(Contraption contraption,Vector3d offset) { localMass=0; @@ -76,6 +78,5 @@ public void setCollisionShapes(HashMap> collisio } //#endregion - public abstract AbstractContraptionEntity getContraption(); abstract public Vector3d getPlotOffset(); } diff --git a/src/main/java/com/eriksonn/createaeronautics/physics/SimulatedContraptionRigidbody.java b/src/main/java/com/eriksonn/createaeronautics/physics/SimulatedContraptionRigidbody.java index 190aa93..d7fc258 100644 --- a/src/main/java/com/eriksonn/createaeronautics/physics/SimulatedContraptionRigidbody.java +++ b/src/main/java/com/eriksonn/createaeronautics/physics/SimulatedContraptionRigidbody.java @@ -10,6 +10,7 @@ import com.eriksonn.createaeronautics.index.CATileEntities; import com.eriksonn.createaeronautics.mixins.ControlledContraptionEntityMixin; import com.eriksonn.createaeronautics.particle.PropellerAirParticleData; +import com.eriksonn.createaeronautics.physics.api.PhysicsAdapter; import com.eriksonn.createaeronautics.physics.collision.detection.Contact; import com.eriksonn.createaeronautics.physics.collision.detection.ICollisionDetector; import com.eriksonn.createaeronautics.physics.collision.detection.impl.GJKCollisionDetector; @@ -26,16 +27,20 @@ import com.simibubi.create.content.contraptions.components.structureMovement.bearing.SailBlock; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; +import net.minecraft.fluid.FluidState; import net.minecraft.nbt.CompoundNBT; +import net.minecraft.state.Property; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; +import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Quaternion; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3f; import net.minecraft.util.math.vector.Vector3i; import net.minecraft.world.gen.feature.template.Template; +import net.minecraftforge.fluids.FluidAttributes; import java.util.*; @@ -43,8 +48,8 @@ public class SimulatedContraptionRigidbody extends AbstractContraptionRigidbody { - AirshipContraptionEntity entity; - AirshipContraption contraption; +// AirshipContraptionEntity entity; +public AirshipContraption contraption; public Quaternion orientation; public Vector3d momentum=Vector3d.ZERO; @@ -82,13 +87,15 @@ public class SimulatedContraptionRigidbody extends AbstractContraptionRigidbody // manifold solver IIterativeManifoldSolver manifoldSolver = new SequentialManifoldSolver(); - public SimulatedContraptionRigidbody(AirshipContraptionEntity entity) + public SimulatedContraptionRigidbody(AirshipContraption contraption, PhysicsAdapter adapter) { + orientation=Quaternion.ONE.copy(); //orientation=new Quaternion(0,1,0,1); //orientation.normalize(); - this.entity=entity; + this.contraption=contraption; + this.adapter=adapter; momentum=Vector3d.ZERO; principalRotation =Quaternion.ONE.copy(); @@ -101,22 +108,21 @@ public SimulatedContraptionRigidbody(AirshipContraptionEntity entity) public void tryInit() { if(!isInitialized) { - contraption=entity.airshipContraption; - generateMassDependentParameters(contraption,Vector3d.ZERO); mergeMassFromSubContraptions(); updateLevititeBuoyancy(); initCollision(); isInitialized=true; - } } + + public void tick() { + if(doGravity) addGlobalForce(new Vector3d(0, -4.0 * getMass(), 0), Vector3d.ZERO); - contraption=entity.airshipContraption; if(contraption==null) return; @@ -133,14 +139,16 @@ public void tick() - updateWings(); + + //updateInertia(); updateTileEntityInteractions(); //centerOfMass=Vector3d.ZERO; totalAccumulatedBuoyancy =0; - totalAccumulatedBuoyancy += levititeBuoyancyController.apply(orientation,entity.position()); + totalAccumulatedBuoyancy += levititeBuoyancyController.apply(orientation,adapter.position()); + updateWings(); updateRotation(); globalForce=globalForce.add(0,-totalAccumulatedBuoyancy,0); @@ -149,15 +157,16 @@ public void tick() momentum = momentum.add(rotateQuat(localForce.scale(deltaTime),orientation)).add(globalForce.scale(deltaTime)); globalForce = Vector3d.ZERO; localForce = Vector3d.ZERO; - - if(entity.position().y<75) - { - entity.move(0,75-entity.position().y,0); - if(momentum.y<0) - { - momentum=momentum.multiply(1,-0.5,1); - } - } + localTorque =Vector3d.ZERO; + globalTorque =Vector3d.ZERO; +// if(entity.position().y<75) +// { +// entity.move(0,75-entity.position().y,0); +// if(momentum.y<0) +// { +// momentum=momentum.multiply(1,-0.5,1); +// } +// } momentum=momentum.scale(0.995); globalVelocity=momentum.scale(1.0/mass); @@ -173,17 +182,75 @@ public void tick() CurrentAxisAngle+=0.01f; angularMomentum=angularMomentum.scale(0.995); - List contacts = findContacts(); + if(doCollisions) { + List contacts = findContacts(); + + manifoldSolver.preSolve(contacts); + for (int i = 0; i < CAConfig.MAX_COLLISION_ITERATIONS.get(); i++) { + manifoldSolver.solve(this, contacts, deltaTime); + } + } - manifoldSolver.preSolve(contacts); - for (int i = 0; i < CAConfig.MAX_COLLISION_ITERATIONS.get(); i++) { - manifoldSolver.solve(this, contacts, deltaTime); + if(doFluidBuoyancy) { + // fluid bouyancy + fluidBuoyancy(); } endPhysicsTick(); } + public boolean doFluidBuoyancy = true; + public boolean doCollisions = true; + public boolean doGravity = true; + + public void fluidBuoyancy() { + // for every block + for (Map.Entry entry : contraption.getBlocks().entrySet()) { + BlockPos airshipPos = entry.getKey(); + Template.BlockInfo info = entry.getValue(); + BlockState state = info.state; + + Vector3d globalPos = toGlobal(new Vector3d(airshipPos.getX(), airshipPos.getY(), airshipPos.getZ()).add(0.5, 0.5, 0.5)); + + // for all blocks within 1 block of this + for (int x = -1; x <= 1; x++) { + for (int y = -1; y <= 1; y++) { + for (int z = -1; z <= 1; z++) { + BlockPos pos = new BlockPos(globalPos.x + x, globalPos.y + y, globalPos.z + z); + FluidState fluidState = adapter.getFluidState(pos); + + if(fluidState != null && !fluidState.isEmpty()) { + // test if we are overlapping this block + AxisAlignedBB aabb1 = new AxisAlignedBB(globalPos.x - 0.5, globalPos.y - 0.5, globalPos.z - 0.5, globalPos.x + 0.5, globalPos.y + 0.5, globalPos.z + 0.5); + AxisAlignedBB aabb2 = new AxisAlignedBB(pos); + + if (aabb1.intersects(aabb2)) { + AxisAlignedBB intersect = aabb1.intersect(aabb2); + Vector3d point = toLocal(intersect.getCenter()); + double volume = intersect.getSize(); + + FluidAttributes attributes = fluidState.getType().getAttributes(); + double viscosity = attributes.getViscosity() / 1000.0; + double density = attributes.getDensity() / 1000.0; + + double buoyancy = volume * density; + + addGlobalForce(new Vector3d(0, 1.25, 0).scale(buoyancy), point); + + // water resistance & inertia + Vector3d scale = getVelocityAtPoint(point).scale(-viscosity * 0.3); + addGlobalForce(scale, point); + + } + } + + } + } + } + } + } + public void endPhysicsTick() { Vector3d v = angularVelocity.scale(deltaTime*0.5f); Quaternion q = new Quaternion((float)v.x,(float)v.y,(float)v.z, 1.0f); @@ -191,14 +258,13 @@ public void endPhysicsTick() { orientation=q; orientation.normalize(); - localTorque =Vector3d.ZERO; - globalTorque =Vector3d.ZERO; - entity.quat=orientation.copy(); - entity.velocity=globalVelocity.scale(deltaTime); - entity.setDeltaMovement(globalVelocity.scale(deltaTime)); - entity.move(globalVelocity.x* deltaTime,globalVelocity.y* deltaTime,globalVelocity.z* deltaTime); + +// entity.quat=orientation.copy(); +// entity.velocity=globalVelocity.scale(deltaTime); +// entity.setDeltaMovement(globalVelocity.scale(deltaTime)); +// entity.move(globalVelocity.x* deltaTime,globalVelocity.y* deltaTime,globalVelocity.z* deltaTime); } public void readAdditional(CompoundNBT compound, boolean spawnPacket) { @@ -286,7 +352,7 @@ public static Vector3d rotateQuatReverse(Vector3d V,Quaternion Q) void updateLevititeBuoyancy() { List levititeBlocks=new ArrayList<>(); - for (Map.Entry entry : entity.airshipContraption.getBlocks().entrySet()) + for (Map.Entry entry : contraption.getBlocks().entrySet()) { if(entry.getValue().state == CABlocks.LEVITITE_CASING.getDefaultState()) { @@ -306,7 +372,7 @@ void mergeMassFromSubContraptions() Vector3d entityOffsetPosition = rigidbody.entity.position().subtract(getPlotOffset()); Vector3d pos = rigidbody.rotateLocal(rigidbody.localCenterOfMass).add(entityOffsetPosition); mass+=rigidbody.localMass; - centerOfMass =centerOfMass.add(pos.scale(rigidbody.localMass)); + centerOfMass = centerOfMass.add(pos.scale(rigidbody.localMass)); } centerOfMass = centerOfMass.scale(1/mass); @@ -333,8 +399,6 @@ void mergeMassFromSubContraptions() inertiaTensor[i][j]+= rigidbody.localInertiaTensor[i][j] - rigidbody.localMass*posArray[i]* posArray[j]; for (int i = 0; i < 3; i++) inertiaTensor[i][i] +=rigidbody.localMass * pos.lengthSqr(); } - - entity.centerOfMassOffset=centerOfMass; } void updateRotation() { @@ -408,14 +472,6 @@ List findContacts() { findContacts(subcontraption, contacts); } - angularMomentum=angularMomentum.scale(0.995); - Vector3d v = angularVelocity.scale(PhysicsUtils.deltaTime*0.5f); - Quaternion q = new Quaternion((float)v.x,(float)v.y,(float)v.z, 1.0f); - q.mul(orientation); - orientation=q; - orientation.normalize(); - - return contacts; } @@ -451,15 +507,9 @@ void initCollision() { void generateCollisionShapes(AbstractContraptionRigidbody rb) { MeshCollisionShapeGenerator generator = new MeshCollisionShapeGenerator(rb); - AbstractContraptionEntity contraption = rb.getContraption(); - rb.setCollisionShapes(generator.generateShapes(contraption)); } - @Override - public AbstractContraptionEntity getContraption() { - return entity; - } void updateSpectralDecomposition() { @@ -673,12 +723,13 @@ void updateWings() } public Vector3d getPlotOffset() { - BlockPos plotPos = AirshipManager.getPlotPosFromId(entity.plotId); - if(entity.level.isClientSide) { - return new Vector3d(0, plotPos.getY(), 0); - } else { - return new Vector3d(plotPos.getX(), plotPos.getY(), plotPos.getZ()); - } + return adapter.getPlotOffset(); +// BlockPos plotPos = AirshipManager.getPlotPosFromId(entity.plotId); +// if(entity.level.isClientSide) { +// return new Vector3d(0, plotPos.getY(), 0); +// } else { +// return new Vector3d(plotPos.getX(), plotPos.getY(), plotPos.getZ()); +// } } void updateTileEntityInteractions() { @@ -689,7 +740,7 @@ void updateTileEntityInteractions() BlockPos pos = entry.getKey(); Vector3d posV = getLocalCoordinate(entry.getKey()); if(CATileEntities.PROPELLER_BEARING.is(te)) - addForce(getForcePropellerBearing(pos,(PropellerBearingTileEntity)te),posV); + addGlobalForce(getForcePropellerBearing(pos,(PropellerBearingTileEntity)te),posV); if(AllTileEntities.ENCASED_FAN.is(te)) addForce(getForceEncasedFan(pos,(EncasedFanTileEntity)te),posV); @@ -731,12 +782,12 @@ public Vector3d rotateLocalInverse(Vector3d point) { public Vector3d toLocal(Vector3d globalPoint) { Vector3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO); - return rotateQuatReverse(globalPoint.subtract(entity.position()).subtract(rotationOffset),orientation); + return rotateQuatReverse(globalPoint.subtract(adapter.position()).subtract(rotationOffset),orientation); } public Vector3d toGlobal(Vector3d localPoint) { Vector3d rotationalOffset = VecHelper.getCenterOf(BlockPos.ZERO); - return rotateQuat(localPoint.subtract(rotationalOffset).subtract(centerOfMass),orientation).add(rotationalOffset).add(entity.position()); + return rotateQuat(localPoint.subtract(rotationalOffset).subtract(centerOfMass),orientation).add(rotationalOffset).add(adapter.position()); } public Vector3d getVelocity() { @@ -767,6 +818,7 @@ public void addGlobalForce(Vector3d force, Vector3d pos) public void applyImpulse(Vector3d pos, Vector3d impulse) { momentum = momentum.add(impulse); globalVelocity = momentum.scale(1.0 / getMass()); + localVelocity = rotateQuatReverse(globalVelocity,orientation); Vector3d additionalAngularMomentum = rotateInverse(impulse).cross(pos); angularMomentum = angularMomentum.add(additionalAngularMomentum); @@ -782,16 +834,6 @@ Vector3d getLocalVelocityAtPosition(Vector3d pos) { return localVelocity.add(pos.cross(angularVelocity)); } - public void applyImpulse(Vector3d pos, Vector3d impulse) { - momentum = momentum.add(impulse); - globalVelocity = momentum.scale(1.0 / getMass()); - - // if(Math.abs(impulse.scale(1.0 / getMass()).lengthSqr()) < 0.05) return; - - Vector3d additionalAngularMomentum = rotateInverse(impulse).cross(pos); - angularMomentum = angularMomentum.add(additionalAngularMomentum); - updateRotation(); - } Vector3d getForcePropellerBearing(BlockPos pos,PropellerBearingTileEntity te) { if(!te.isRunning()) @@ -799,7 +841,7 @@ Vector3d getForcePropellerBearing(BlockPos pos,PropellerBearingTileEntity te) Vector3d direction=getFacingVector(te.getBlockState()); int sails = te.sailPositions.size(); - float magnitude = 0.2f*(float)Math.pow(sails,1.5f)*te.getAngularSpeed(); + float magnitude = 0.325f*(float)Math.pow(sails,1.5f)*te.getAngularSpeed(); if(te.movementDirection.getValue()==0) magnitude*=-1; return direction.scale(magnitude); @@ -813,14 +855,14 @@ Vector3d getForceEncasedFan(BlockPos pos,EncasedFanTileEntity te) direction = new Vector3d(Math.abs(direction.x),Math.abs(direction.y),Math.abs(direction.z)); float magnitude = 0.5f*te.getSpeed(); - Vector3d vector3d = entity.toGlobalVector(new Vector3d(pos.getX(), pos.getY(), pos.getZ()).add(0.5,0.5,0.5), 1.0f); + Vector3d vector3d = adapter.toGlobalVector(new Vector3d(pos.getX(), pos.getY(), pos.getZ()).add(0.5,0.5,0.5), 1.0f); Vector3d pPos = vector3d; - Vector3d veloVector = entity.applyRotation(facingVector,1.0f); + Vector3d veloVector = adapter.applyRotation(facingVector,1.0f); float particleSpeed = te.getSpeed() / 256; veloVector = veloVector.scale(Math.abs(particleSpeed)); if(Math.abs(particleSpeed) > 0) { - entity.level.addParticle(new PropellerAirParticleData(new Vector3i(vector3d.x, vector3d.y, vector3d.z)), pPos.x, pPos.y, pPos.z, veloVector.x, veloVector.y, veloVector.z); +// entity.addParticle(new PropellerAirParticleData(new Vector3i(vector3d.x, vector3d.y, vector3d.z)), pPos.x, pPos.y, pPos.z, veloVector.x, veloVector.y, veloVector.z); } return direction.scale(-magnitude); diff --git a/src/main/java/com/eriksonn/createaeronautics/physics/SubcontraptionRigidbody.java b/src/main/java/com/eriksonn/createaeronautics/physics/SubcontraptionRigidbody.java index 79e778e..93aa815 100644 --- a/src/main/java/com/eriksonn/createaeronautics/physics/SubcontraptionRigidbody.java +++ b/src/main/java/com/eriksonn/createaeronautics/physics/SubcontraptionRigidbody.java @@ -10,6 +10,7 @@ public SubcontraptionRigidbody(AbstractContraptionEntity entity,SimulatedContrap { this.entity=entity; this.parentRigidbody=parentRigidbody; + this.adapter = parentRigidbody.adapter; } @@ -34,18 +35,18 @@ public Vector3d multiplyInertiaInverse(Vector3d v) { public Vector3d rotate(Vector3d point) { - return parentRigidbody.rotate(entity.applyRotation(point,1)); + return parentRigidbody.rotate(entity.applyRotation(point,0)); } public Vector3d rotateInverse(Vector3d point) { - return entity.reverseRotation(parentRigidbody.rotateInverse(point),1); + return entity.reverseRotation(parentRigidbody.rotateInverse(point),0); } public Vector3d rotateLocal(Vector3d point) { - return entity.applyRotation(point,1); + return entity.applyRotation(point,0); } public Vector3d rotateLocalInverse(Vector3d point) { - return entity.reverseRotation(point,1); + return entity.reverseRotation(point,0); } public Vector3d toLocal(Vector3d globalPoint) { @@ -87,8 +88,8 @@ public void addGlobalForce(Vector3d pos, Vector3d force) { public void applyImpulse(Vector3d pos, Vector3d velocity) { - parentRigidbody.applyImpulse(toParent(pos),entity.reverseRotation(velocity,0)); - + parentRigidbody.applyImpulse(toParent(pos), entity.reverseRotation(velocity, 0)); + } public void applyGlobalImpulse(Vector3d pos, Vector3d velocity) { parentRigidbody.applyGlobalImpulse(toParent(pos),velocity); @@ -104,11 +105,6 @@ public Vector3d fromParent(Vector3d point) return entity.reverseRotation(point.subtract(entityOffsetPosition),1); } - @Override - public AbstractContraptionEntity getContraption() { - return entity; - } - @Override public Vector3d getPlotOffset() { return parentRigidbody.getPlotOffset(); diff --git a/src/main/java/com/eriksonn/createaeronautics/physics/api/ContraptionEntityPhysicsAdapter.java b/src/main/java/com/eriksonn/createaeronautics/physics/api/ContraptionEntityPhysicsAdapter.java new file mode 100644 index 0000000..18e6c3d --- /dev/null +++ b/src/main/java/com/eriksonn/createaeronautics/physics/api/ContraptionEntityPhysicsAdapter.java @@ -0,0 +1,65 @@ +package com.eriksonn.createaeronautics.physics.api; + +import com.eriksonn.createaeronautics.contraptions.AirshipContraptionEntity; +import com.eriksonn.createaeronautics.contraptions.AirshipManager; +import net.minecraft.block.BlockState; +import net.minecraft.fluid.FluidState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.shapes.VoxelShape; +import net.minecraft.util.math.vector.Vector3d; + +public class ContraptionEntityPhysicsAdapter implements PhysicsAdapter { + + public AirshipContraptionEntity contraption; + + public ContraptionEntityPhysicsAdapter(AirshipContraptionEntity contraption) { + this.contraption = contraption; + } + + @Override + public Vector3d position() { + return contraption.position(); + } + + @Override + public FluidState getFluidState(BlockPos pos) { + return contraption.level.getFluidState(pos); + } + + @Override + public Vector3d toGlobalVector(Vector3d add, float v) { + return contraption.toGlobalVector(add, v); + } + + @Override + public Vector3d applyRotation(Vector3d facingVector, float v) { + return contraption.applyRotation(facingVector, v); + } + + @Override + public Vector3d getPlotOffset() { + BlockPos plotPos = AirshipManager.getPlotPosFromId(contraption.plotId); + if(contraption.level.isClientSide) { + return new Vector3d(0, plotPos.getY(), 0); + } else { + return new Vector3d(plotPos.getX(), plotPos.getY(), plotPos.getZ()); + } + } + + @Override + public BlockState getBlockState(BlockPos worldPos) { + return contraption.level.getBlockState(worldPos); + } + + @Override + public VoxelShape getCollisionShape(BlockPos position) { + return contraption.level.getBlockState(position).getCollisionShape(contraption.level, position); + } + + @Override + public VoxelShape getCollisionShapeOnContraption(BlockPos position) { + return contraption.getContraption().getBlocks().get(position).state.getCollisionShape(contraption.getContraption().getContraptionWorld(), position); + } + + +} diff --git a/src/main/java/com/eriksonn/createaeronautics/physics/api/PhysicsAdapter.java b/src/main/java/com/eriksonn/createaeronautics/physics/api/PhysicsAdapter.java new file mode 100644 index 0000000..ca1e247 --- /dev/null +++ b/src/main/java/com/eriksonn/createaeronautics/physics/api/PhysicsAdapter.java @@ -0,0 +1,26 @@ +package com.eriksonn.createaeronautics.physics.api; + +import net.minecraft.block.BlockState; +import net.minecraft.fluid.FluidState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.shapes.VoxelShape; +import net.minecraft.util.math.vector.Vector3d; + +public interface PhysicsAdapter { + + Vector3d position(); + + FluidState getFluidState(BlockPos pos); + + Vector3d toGlobalVector(Vector3d add, float v); + + Vector3d applyRotation(Vector3d facingVector, float v); + + Vector3d getPlotOffset(); + + BlockState getBlockState(BlockPos worldPos); + + VoxelShape getCollisionShape(BlockPos position); + + VoxelShape getCollisionShapeOnContraption(BlockPos position); +} diff --git a/src/main/java/com/eriksonn/createaeronautics/physics/collision/detection/AbstractContraptionBasedCollisionDetector.java b/src/main/java/com/eriksonn/createaeronautics/physics/collision/detection/AbstractContraptionBasedCollisionDetector.java index f7af31b..f8c259c 100644 --- a/src/main/java/com/eriksonn/createaeronautics/physics/collision/detection/AbstractContraptionBasedCollisionDetector.java +++ b/src/main/java/com/eriksonn/createaeronautics/physics/collision/detection/AbstractContraptionBasedCollisionDetector.java @@ -23,8 +23,6 @@ public List solve(AbstractContraptionRigidbody rb, List contac // iterate over all collision shapes final HashMap> collisionShapes = rb.getCollisionShapes(); - World contraptionLevel = rb.getContraption().level; - for (Map.Entry> shapeEntry : collisionShapes.entrySet()) { // check if this block is not fully surrounded @@ -45,12 +43,12 @@ public List solve(AbstractContraptionRigidbody rb, List contac BlockPos worldPos = new BlockPos(x, y, z); // if the block is not air, we need to check for collisions - BlockState state = contraptionLevel.getBlockState(worldPos); + BlockState state = rb.adapter.getBlockState(worldPos); Block block = state.getBlock(); if(block == Blocks.AIR) continue; // get the collision shape of the block - List blockShape = new MeshCollisionShapeGenerator(rb).generateFromBlock(contraptionLevel, worldPos, state, false); + List blockShape = new MeshCollisionShapeGenerator(rb).generateFromBlock(worldPos, state, false); // if the block has no collision shape, we can skip it if(blockShape.isEmpty()) continue; diff --git a/src/main/java/com/eriksonn/createaeronautics/physics/collision/shape/ICollisionShapeGenerator.java b/src/main/java/com/eriksonn/createaeronautics/physics/collision/shape/ICollisionShapeGenerator.java index fd6fb46..8698dbc 100644 --- a/src/main/java/com/eriksonn/createaeronautics/physics/collision/shape/ICollisionShapeGenerator.java +++ b/src/main/java/com/eriksonn/createaeronautics/physics/collision/shape/ICollisionShapeGenerator.java @@ -1,6 +1,7 @@ package com.eriksonn.createaeronautics.physics.collision.shape; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import net.minecraft.block.BlockState; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockReader; @@ -20,11 +21,11 @@ public interface ICollisionShapeGenerator { * @param contraption The contraption to generate the collision shape from. * @return The generated collision shapes. */ - HashMap> generateShapes(AbstractContraptionEntity contraption); + HashMap> generateShapes(Contraption contraption); /** * Generates collision shapes given a block */ - List generateFromBlock(IBlockReader level, BlockPos position, BlockState block, boolean isOnContraption); + List generateFromBlock(BlockPos position, BlockState block, boolean isOnContraption); } diff --git a/src/main/java/com/eriksonn/createaeronautics/physics/collision/shape/MeshCollisionShapeGenerator.java b/src/main/java/com/eriksonn/createaeronautics/physics/collision/shape/MeshCollisionShapeGenerator.java index 65ae8db..53f1127 100644 --- a/src/main/java/com/eriksonn/createaeronautics/physics/collision/shape/MeshCollisionShapeGenerator.java +++ b/src/main/java/com/eriksonn/createaeronautics/physics/collision/shape/MeshCollisionShapeGenerator.java @@ -1,14 +1,13 @@ package com.eriksonn.createaeronautics.physics.collision.shape; import com.eriksonn.createaeronautics.physics.AbstractContraptionRigidbody; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.world.IBlockReader; import net.minecraft.world.gen.feature.template.Template; import java.util.ArrayList; @@ -42,9 +41,9 @@ public static Vector3d[] vertices(AxisAlignedBB box) { } @Override - public HashMap> generateShapes(AbstractContraptionEntity contraption) { + public HashMap> generateShapes(Contraption contraption) { // for every block - Map blocks = contraption.getContraption().getBlocks(); + Map blocks = contraption.getBlocks(); HashMap> shapes = new HashMap<>(); @@ -64,15 +63,15 @@ public HashMap> generateShapes(AbstractContrapti } // generate collision shapes - List collisionShapes = generateFromBlock(contraption.getContraption().getContraptionWorld(), pos, block, true); + List collisionShapes = generateFromBlock(pos, block, true); shapes.put(pos, collisionShapes); } return shapes; } - public List generateFromBlock(IBlockReader level, BlockPos position, BlockState block, boolean isOnContraption) { - VoxelShape voxelShape = block.getCollisionShape(level, position); + public List generateFromBlock(BlockPos position, BlockState block, boolean isOnContraption) { + VoxelShape voxelShape = isOnContraption ? rigidbody.adapter.getCollisionShapeOnContraption(position) : rigidbody.adapter.getCollisionShape(position); List shapes = new ArrayList<>(); diff --git a/src/main/java/com/eriksonn/createaeronautics/ponder/KineticScenes.java b/src/main/java/com/eriksonn/createaeronautics/ponder/KineticScenes.java index 965b186..ecd66e7 100644 --- a/src/main/java/com/eriksonn/createaeronautics/ponder/KineticScenes.java +++ b/src/main/java/com/eriksonn/createaeronautics/ponder/KineticScenes.java @@ -90,5 +90,6 @@ public static void stirlingEngine(SceneBuilder scene, SceneBuildingUtil util) scene.world.removeItemsFromBelt(util.grid.at(1, 1, 1)); scene.world.flapFunnel(util.grid.at(1, 2, 1), false); } + } } diff --git a/src/main/java/com/eriksonn/createaeronautics/render/OutlinerMixinInterface.java b/src/main/java/com/eriksonn/createaeronautics/render/OutlinerMixinInterface.java new file mode 100644 index 0000000..2823a8a --- /dev/null +++ b/src/main/java/com/eriksonn/createaeronautics/render/OutlinerMixinInterface.java @@ -0,0 +1,12 @@ +package com.eriksonn.createaeronautics.render; + +import com.eriksonn.createaeronautics.render.PhysicsInfoAABBOutline; +import com.simibubi.create.foundation.utility.outliner.Outline; +import net.minecraft.util.math.AxisAlignedBB; + +public interface OutlinerMixinInterface { + + PhysicsInfoAABBOutline getAndRefreshPhysicsAABB(Object slot); + Outline.OutlineParams showPhysicsAABB(Object slot, AxisAlignedBB bb); + void createPhysicsAABBOutlineIfMissing(Object slot, AxisAlignedBB bb); +} diff --git a/src/main/java/com/eriksonn/createaeronautics/render/PhysicsInfoAABBOutline.java b/src/main/java/com/eriksonn/createaeronautics/render/PhysicsInfoAABBOutline.java new file mode 100644 index 0000000..7b651cf --- /dev/null +++ b/src/main/java/com/eriksonn/createaeronautics/render/PhysicsInfoAABBOutline.java @@ -0,0 +1,22 @@ +package com.eriksonn.createaeronautics.render; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.systems.RenderSystem; +import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.utility.outliner.AABBOutline; +import net.minecraft.util.math.AxisAlignedBB; + +public class PhysicsInfoAABBOutline extends AABBOutline { + public PhysicsInfoAABBOutline(AxisAlignedBB bb) { + super(bb); + } + + @Override + public void render(MatrixStack ms, SuperRenderTypeBuffer buffer, float pt) { + RenderSystem.disableDepthTest(); + RenderSystem.depthMask(false); + super.render(ms, buffer, pt); + RenderSystem.depthMask(true); + RenderSystem.enableDepthTest(); + } +} diff --git a/src/main/java/com/eriksonn/createaeronautics/utils/BlockStateUtils.java b/src/main/java/com/eriksonn/createaeronautics/utils/BlockStateUtils.java index 48ec572..243fdc1 100644 --- a/src/main/java/com/eriksonn/createaeronautics/utils/BlockStateUtils.java +++ b/src/main/java/com/eriksonn/createaeronautics/utils/BlockStateUtils.java @@ -47,10 +47,8 @@ public static void torsionSpringBlockstate(DataGenContext void propellerBearingBlockstate(DataGenContext ctx, RegistrateBlockstateProvider prov) { prov.directionalBlock(ctx.getEntry(), - blockState -> prov.models().getExistingFile( - prov.modLoc("block/propeller_bearing/block_" + (blockState.getValue(PropellerBearingBlock.DIRECTION) == PropellerBearingBlock.Direction.PULL ? "forward" : "reverse") - ) - ) + blockState -> + prov.models().getExistingFile(prov.modLoc("block/propeller_bearing/block")) ); } diff --git a/src/main/resources/createaeronautics.mixins.json b/src/main/resources/createaeronautics.mixins.json index 7d6e09f..cd90de2 100644 --- a/src/main/resources/createaeronautics.mixins.json +++ b/src/main/resources/createaeronautics.mixins.json @@ -15,8 +15,11 @@ "ContraptionRenderMixin", "ControlledContraptionEntityMixin", "DimensionTypeMixin", + "GoggleOverlayRendererMixin", "Matrix3dAccessor", "MechanicalBearingTileEntityMixin", + "OutlineEntryMixin", + "OutlinerMixin", "PotatoProjectileEntityMixin", "RedstoneLinkNetworkMixin", "RotationPropagatorMixin",