Compare commits

...

2 Commits

Author SHA1 Message Date
passplease da2fd0e78a Add contributor and fix bugs on server 2025-06-07 14:28:36 +08:00
passplease e674baed2d Fix bug and create workflow file 2025-05-17 17:21:31 +08:00
14 changed files with 145 additions and 45 deletions

64
.github/workflows/publish.yml vendored Normal file
View File

@ -0,0 +1,64 @@
name: Build
on:
workflow_dispatch:
push:
branches:
- master
paths:
- src/*
- gradle/*
- .github/workflows/*
- build.gradle
- gradle.properties
- settings.gradle
jobs:
build:
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup JDK
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
with:
gradle-version: '8.4'
- name: Test Server
run: gradle runGameTestServer
continue-on-error: true
- name: Build with Gradle
run: gradle build
- name: Create timestamp
id: create_timestamp
run: echo "timestamp=$(date '+%Y-%m-%d-%H-%M-%S')" >> $GITHUB_OUTPUT
shell: bash
- uses: Kir-Antipov/mc-publish@v3.3
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
github-tag: 1.19.2-Forge-${{ steps.create_timestamp.outputs.timestamp }}
github-draft: false
github-prerelease: false
- uses: actions/upload-artifact@v4
with:
overwrite: true
include-hidden-files: true
path: |
**/logs/
**/crash-reports/
build/libs
retention-days: 7
if: always()

4
.gitignore vendored
View File

@ -1,5 +1,7 @@
/run/
/1.19.2-run/
/.vscode/
/.idea/
/bin/
/build/
/build/
gradle/

View File

@ -1,15 +1,21 @@
# Welcome to SCS !
## Download Code
If you want to download code on your computer, please change gradle version in `gradle\wrapper` or build like workflow: `publish.yml`
## Download Links
* For CurseForge: ["CurseForge"](https://www.curseforge.com/minecraft/mc-mods/smartercontraptionstorage)
* Modrinth: ["Modrinth"](https://modrinth.com/mod/smarter-contraption-storage)
* If you come from China, you can also use [MCMODS](https://www.mcmod.cn/class/15306.html)
## What Can It Do?
* It is a mod aiming at making containers on contraptions smarter. After applying this mod, you can control your each container on contraption separately when them are blocks (planning to make them act like actors)
* Secondly, it adds support to other containers those Create haven't allowed, such as [Drawers](https://www.curseforge.com/minecraft/mc-mods/storage-drawers) ,(planning) [TrashBins](https://www.curseforge.com/minecraft/mc-mods/trash-cans) and any others you request me to support
* Secondly, it adds support to other containers those Create haven't allowed, such as [Drawers](https://www.curseforge.com/minecraft/mc-mods/storage-drawers) , [TrashBins](https://www.curseforge.com/minecraft/mc-mods/trash-cans) and any others you request me to support
* Thirdly, it plans to add some interesting and useful features to create
## How to Give Me Some Advice
* First of all, GitHub is always the best place
* For Chinese, you can also find more links in [MCMODS](https://www.mcmod.cn/class/15306.html)
## About Plans
1) Support 1.21.1
- [x] Support 1.21.1
- [ ] Transplant all stuff to 1.20.1 and 1.21.1
## License
[MIT_License](https://mit-license.org/)
[MIT_License](https://mit-license.org/)
## Thanks
Thanks to [KAllFix](https://center.mcmod.cn/170204/) improves the code and offer me help.

View File

@ -1,18 +1,24 @@
buildscript {
repositories {
// These repositories are only for Gradle plugins, put any other repositories in the repository overlays further below
maven { url = 'https://maven.parchmentmc.org' }
maven { url = 'https://repo.spongepowered.org/repository/maven-public/' }
maven { url = 'https://maven.minecraftforge.net' }
mavenLocal()
mavenCentral()
}
dependencies {
classpath "net.minecraftforge.gradle:ForgeGradle:5.1.74"
classpath 'org.spongepowered:mixingradle:0.7-SNAPSHOT'
classpath "org.parchmentmc:librarian:1.+"
}
}
plugins {
id 'eclipse'
id 'idea'
id 'net.minecraftforge.gradle' version '[6.0.16,6.2)'
id 'maven-publish'
id 'net.minecraftforge.gradle' version '[6.0,6.2)'
id 'org.parchmentmc.librarian.forgegradle' version '1.+'
}
@ -73,7 +79,7 @@ minecraft {
runs {
// applies to all the run configs below
configureEach {
workingDirectory project.file('run')
workingDirectory project.file('1.19.2-run')
// Recommended logging data for a userdev environment
// The markers can be added/remove as needed separated by commas.
@ -103,6 +109,7 @@ minecraft {
server {
property 'forge.enabledGameTestNamespaces', mod_id
args '--nogui'
workingDirectory project.file('1.19.2-run/server')
}
// This run config launches GameTestServer and runs all registered gametests, then exits.
@ -166,7 +173,6 @@ dependencies {
runtimeOnly fg.deobf("curse.maven:mekanism-268560:4644795")
runtimeOnly fg.deobf("curse.maven:cyclops-core-232758:4681659")
runtimeOnly fg.deobf("curse.maven:capabilityproxy-266479:3929855")
runtimeOnly fg.deobf("curse.maven:toms-storage-378609:4649846")
compileOnly fg.deobf("com.tterrag.registrate:Registrate:${registrate_version}")
implementation fg.deobf("curse.maven:create-328085:4835190")
implementation fg.deobf("curse.maven:storage-drawers-223852:5648923")

View File

@ -42,7 +42,7 @@ mod_name=SmarterContraptionStorage
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
mod_license=MIT_License
# The mod version. See https://semver.org/
mod_version=1.19.2-1.3
mod_version=1.19.2-1.3.2
# The group ID for the mod. It is only important when publishing as an artifact to Excludes.BuildNBTFile Maven repository.
# This should match the base package used for the mod sources.
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html

View File

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
distributionUrl=https:\//mirrors.cloud.tencent.com/gradle/gradle-8.4-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

View File

@ -71,6 +71,7 @@ public interface HelperMenuProvider<T extends StorageHandlerHelper> extends Cont
ContraptionMenuProvider.super.error();
}
@OnlyIn(Dist.CLIENT)
<U extends Screen & MenuAccess<?>> U createScreen(MovingBlockEntityMenu menu, Inventory inventory, Component component);
default void writeToBuffer(@NotNull FriendlyByteBuf buffer) {

View File

@ -3,8 +3,11 @@ package net.smartercontraptionstorage.AddStorage.GUI.BlockEntityMenu;
import com.simibubi.create.foundation.utility.Pair;
import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld;
import net.minecraft.client.Minecraft;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.smartercontraptionstorage.Message.MenuLevelPacket;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
@ -25,10 +28,10 @@ public class MenuLevel extends WrappedWorld {
private static Level tickingLevel;
public static MenuLevel level = new MenuLevel();
private static ClientMenuLevel clientLevel = null;
private MenuLevel() {
super(Minecraft.getInstance().level);
private MenuLevel(Level level) {
super(level);
}
public static Map<Pair<Integer, Long>, BlockEntity> getBlocks(){
@ -59,26 +62,35 @@ public class MenuLevel extends WrappedWorld {
return blocks.get(pair);
}
public static MenuLevel tickingBlockEntity(Pair<Integer, Long> pair,boolean isClient) {
private static MenuLevel clientLevel(){
if(clientLevel == null){
clientLevel = new ClientMenuLevel();
}
return clientLevel.clientLevel;
}
public static MenuLevel level(Level level) {
if(level.isClientSide()) {
return clientLevel();
}
else if(level instanceof ServerLevel){
return new MenuLevel(level);
}else throw new RuntimeException("Open menu get null server level !");
}
public static MenuLevel tickingBlockEntity(Pair<Integer, Long> pair,Level level){
if(tickingBlockEntity != null){
tickingBlockEntity.setLevel(tickingLevel);
}
if(blocks.containsKey(pair)) {
tickingBlockEntity = blocks.get(pair);
tickingLevel = tickingBlockEntity.getLevel();
tickingBlockEntity.setLevel(level);
MenuLevel menuLevel = level(level);
tickingBlockEntity.setLevel(menuLevel);
return menuLevel;
} else {
tickingBlockEntity = null;
tickingLevel = null;
throw new IllegalArgumentException("Pair is not found ! Pair: " + pair);
}
level.isClientSide = isClient;
return level;
}
public static MenuLevel tickingBlockEntity(Pair<Integer, Long> pair,Level level){
MenuLevel value = tickingBlockEntity(pair, level.isClientSide());
tickingLevel = level;
return value;
}
private static void setTickingBlockEntity(BlockEntity blockEntity){
@ -107,4 +119,9 @@ public class MenuLevel extends WrappedWorld {
entityIn.level = tickingLevel;
return tickingLevel.addFreshEntity(entityIn);
}
private static class ClientMenuLevel{
@OnlyIn(Dist.CLIENT)
protected MenuLevel clientLevel = new MenuLevel(Minecraft.getInstance().level);
}
}

View File

@ -15,6 +15,8 @@ import net.minecraft.world.item.Item;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.items.ItemStackHandler;
import net.p3pp3rf1y.sophisticatedbackpacks.backpack.BackpackBlock;
import net.p3pp3rf1y.sophisticatedbackpacks.backpack.BackpackBlockEntity;
@ -106,7 +108,7 @@ public class SBackPacksHandlerHelper extends StorageHandlerHelper implements Hel
return MenuLevel.levelRun((setter) -> {
setter.accept(getBlockEntity());
Level level = player.level;
player.level = MenuLevel.level;
player.level = MenuLevel.level(level);
BackpackContainer container = new BackpackContainer(i, player, new BackpackContext.Block(getBlockEntity().getBlockPos()));
player.level = level;
return container;
@ -118,6 +120,7 @@ public class SBackPacksHandlerHelper extends StorageHandlerHelper implements Hel
return menu.getMenu() instanceof BackpackContainer;
}
@OnlyIn(Dist.CLIENT)
@Override
public BackpackScreen createScreen(MovingBlockEntityMenu menu, Inventory inventory, Component component) {
return new BackpackScreen((BackpackContainer) menu.getMenu(), inventory, component);

View File

@ -13,6 +13,8 @@ import net.minecraft.world.item.Item;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.items.ItemStackHandler;
import net.p3pp3rf1y.sophisticatedcore.inventory.InventoryHandler;
import net.p3pp3rf1y.sophisticatedcore.util.BlockItemBase;
@ -111,7 +113,7 @@ public class SStorageBlockHelper extends StorageHandlerHelper implements HelperM
if(getPair() != null) {
MenuLevel.tickingBlockEntity(getPair(),player.level);
Level level = player.level;
player.level = MenuLevel.level;
player.level = MenuLevel.level(level);
menu = isLimitedBarrelBlock() ? new LimitedBarrelContainerMenu(i, player, getBlockEntity().getBlockPos()) : new StorageContainerMenu(i,player,getBlockEntity().getBlockPos());
player.level = level;
}
@ -123,6 +125,7 @@ public class SStorageBlockHelper extends StorageHandlerHelper implements HelperM
return isLimitedBarrelBlock() ? menu.getMenu() instanceof LimitedBarrelContainerMenu : menu.getMenu() instanceof StorageContainerMenu;
}
@OnlyIn(Dist.CLIENT)
@Override
public StorageScreen createScreen(MovingBlockEntityMenu menu, Inventory inventory, Component component) {
if(isLimitedBarrelBlock()) {

View File

@ -16,6 +16,8 @@ import net.minecraft.world.item.Item;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.capabilities.ForgeCapabilities;
import net.minecraftforge.items.ItemStackHandler;
import net.smartercontraptionstorage.AddStorage.GUI.BlockEntityMenu.HelperMenuProvider;
@ -124,6 +126,7 @@ public class ToolboxHandlerHelper extends StorageHandlerHelper implements NeedDe
return pair;
}
@OnlyIn(Dist.CLIENT)
@Override
public ToolboxScreen createScreen(MovingBlockEntityMenu menu, Inventory inventory, Component component) {
return new ToolboxScreen((ToolboxMenu) menu.getMenu(),inventory,component);

View File

@ -138,9 +138,10 @@ public abstract class ContraptionMixin implements Gettable {
public void help_deserialize(Level world, CompoundTag nbt, boolean spawnData, CallbackInfo ci){
FunctionChanger.getBlockEntity = (pos) -> {
try {
BlockEntity entity;
if(spawnData) {
BlockPos localPos = toLocalPos(pos);
return presentBlockEntities.get(localPos);
entity = presentBlockEntities.get(localPos);
} else {
StructureTemplate.StructureBlockInfo info = blocks.get(pos);
CompoundTag tag = info.nbt;
@ -148,9 +149,13 @@ public abstract class ContraptionMixin implements Gettable {
tag.putInt("x", info.pos.getX());
tag.putInt("y", info.pos.getY());
tag.putInt("z", info.pos.getZ());
return BlockEntity.loadStatic(info.pos,info.state,tag);
entity = BlockEntity.loadStatic(info.pos,info.state,tag);
} else return null;
}
if(entity != null){
entity.setLevel(world);
}
return entity;
} catch (Exception e) {
return presentBlockEntities.values().stream().filter(blockEntity -> blockEntity.getBlockPos().equals(pos)).findFirst().orElse(null);
}

View File

@ -140,14 +140,18 @@ public class SmarterContraptionStorage {
// Some client setup code
ModList list = ModList.get();
if(list.isLoaded("create")){
MenuScreens.register(MovingBlockEntityMenu.BlockEntityMenu.get(), MovingBlockEntityScreen::new);
register(ToolboxHandlerHelper.INSTANCE);
SCS_Ponder.register();
if(list.isLoaded("trashcans")) {
MenuScreens.register(TrashHandlerHelper.TrashHandler.TrashCanMenu.get(), MovingTrashCanScreen::new);
register(new TrashHandlerHelper());
register(new TrashcanFluidHelper());
SCS_Ponder.registerTrashCan();
}
if(list.isLoaded("storagedrawers")) {
MenuScreens.register(DrawersHandlerHelper.NormalDrawerHandler.DrawerMenu.get(), MovingDrawerScreen::new);
MenuScreens.register(CompactingHandlerHelper.CompactingHandler.CompactingDrawerMenu.get(), MovingCompactingDrawerScreen::new);
register(new DrawersHandlerHelper());
register(new CompactingHandlerHelper());
PonderRegistry.TAGS.forTag(CONTROLLABLE_CONTAINERS).add(ModBlocks.CONTROLLER.get());
@ -169,27 +173,13 @@ public class SmarterContraptionStorage {
// if(list.isLoaded("sophisticatedstorage"))
// register(SStorageBlockHelper.INSTANCE);
if(list.isLoaded("functionalstorage")){
MenuScreens.register(FunctionalDrawersHandlerHelper.FDrawersHandler.MENU_TYPE.get(),MovingFunctionalDrawerScreen::new);
MenuScreens.register(FunctionalCompactingHandlerHelper.FCDrawersHandler.MENU_TYPE.get(),MovingFunctionalCompactingScreen::new);
register(new FunctionalDrawersHandlerHelper());
register(new FunctionalCompactingHandlerHelper());
register(new FunctionalFluidHandlerHelper());
}
}
event.enqueueWork(() -> {
if(list.isLoaded("create")){
MenuScreens.register(MovingBlockEntityMenu.BlockEntityMenu.get(), MovingBlockEntityScreen::new);
if(list.isLoaded("trashcans")) {
MenuScreens.register(TrashHandlerHelper.TrashHandler.TrashCanMenu.get(), MovingTrashCanScreen::new);
}
if(list.isLoaded("storagedrawers")){
MenuScreens.register(DrawersHandlerHelper.NormalDrawerHandler.DrawerMenu.get(), MovingDrawerScreen::new);
MenuScreens.register(CompactingHandlerHelper.CompactingHandler.CompactingDrawerMenu.get(), MovingCompactingDrawerScreen::new);
}
if(list.isLoaded("functionalstorage")){
MenuScreens.register(FunctionalDrawersHandlerHelper.FDrawersHandler.MENU_TYPE.get(),MovingFunctionalDrawerScreen::new);
MenuScreens.register(FunctionalCompactingHandlerHelper.FCDrawersHandler.MENU_TYPE.get(),MovingFunctionalCompactingScreen::new);
}
}
});
}
}
}

View File

@ -8,11 +8,11 @@
"Contraption.ContraptionControlsBlockEntityMixin",
"Contraption.ContraptionMixin",
"Contraption.MountedStorageManagerMixin",
"Render.RenderMixin",
"Storage.MountedFluidStorageMixin",
"Storage.MountedStorageMixin"
],
"client": [
"Render.RenderMixin"
],
"injectors": {
"defaultRequire": 1