Initial commit

This commit is contained in:
Sr_endi 2021-05-21 16:29:43 +02:00
commit a8392f44a0
16 changed files with 806 additions and 0 deletions

118
.gitignore vendored Normal file
View file

@ -0,0 +1,118 @@
# User-specific stuff
.idea/
*.iml
*.ipr
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
.gradle
build/
# Ignore Gradle GUI config
gradle-app.setting
# Cache of project
.gradletasknamecache
**/build/
# Common working directory
run/
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar

20
README.md Normal file
View file

@ -0,0 +1,20 @@
# CC Tutorial
This is a little tutorial on how peripherals in cc works.
We use the simple system with the IPeripheral interface.
If you want to see, how I use this system with more functions and blocks, take a look at [Advanced Peripherals](https://github.com/Seniorendi/AdvancedPeripherals)
We create a peripheral with two functions:
* isRaining - a main thread function which will return true when it rains
* sendMessage - a function which will send a message to every player
## Content
* CCBlock - Our normal block, nothing special
* CCPeripheral - Our peripheral, here we register functions and manage connected computers
* Registration - Normal registration to register our blocks, items and so on
* CCTutorial - Our main class
* CCTileEntity - Our tile entity

112
build.gradle Normal file
View file

@ -0,0 +1,112 @@
buildscript {
repositories {
maven { url = 'https://maven.minecraftforge.net' }
mavenCentral()
}
dependencies {
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '4.1.+', changing: true
}
}
apply plugin: 'net.minecraftforge.gradle'
group = 'de.srendi.cctutorial'
version = '1.0'
archivesBaseName = 'cctutorial'
java.toolchain.languageVersion = JavaLanguageVersion.of(8)
minecraft {
mappings channel: 'snapshot', version: '20210309-1.16.5'
runs {
client {
workingDirectory project.file('run')
property 'forge.logging.markers', 'REGISTRIES'
// Recommended logging level for the console
// You can set various levels here.
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
property 'forge.logging.console.level', 'debug'
mods {
cctutorial {
source sourceSets.main
}
}
}
server {
workingDirectory project.file('run')
property 'forge.logging.markers', 'REGISTRIES'
// Recommended logging level for the console
// You can set various levels here.
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
property 'forge.logging.console.level', 'debug'
mods {
cctutorial {
source sourceSets.main
}
}
}
data {
workingDirectory project.file('run')
property 'forge.logging.markers', 'REGISTRIES'
// Recommended logging level for the console
// You can set various levels here.
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
property 'forge.logging.console.level', 'debug'
// Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
args '--mod', 'cctutorial', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/')
mods {
cctutorial {
source sourceSets.main
}
}
}
}
}
// Include resources generated by data generators.
sourceSets.main.resources { srcDir 'src/generated/resources' }
repositories {
maven { url 'https://squiddev.cc/maven/' }
}
dependencies {
// Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed
// that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied.
// The userdev artifact is a special name and will get all sorts of transformations applied to it.
minecraft 'net.minecraftforge:forge:1.16.5-36.1.23'
implementation fg.deobf("org.squiddev:cc-tweaked-1.16.4:${cc_version}")
}
// Example for how to get properties into the manifest for reading by the runtime..
jar {
manifest {
attributes([
"Specification-Title" : "cctutorial",
//"Specification-Vendor": "cctutorial authors",
"Specification-Version" : "1", // We are version 1 of ourselves
"Implementation-Title" : project.name,
"Implementation-Version" : project.version,
//"Implementation-Vendor": "cctutorial authors",
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
])
}
}
jar.finalizedBy('reobfJar')

3
gradle.properties Normal file
View file

@ -0,0 +1,3 @@
org.gradle.jvmargs=-Xmx3G
org.gradle.daemon=false
cc_version=1.95.3

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View file

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

185
gradlew vendored Normal file
View file

@ -0,0 +1,185 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

89
gradlew.bat vendored Normal file
View file

@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

1
settings.gradle Normal file
View file

@ -0,0 +1 @@
rootProject.name = 'cctutorial'

View file

@ -0,0 +1,29 @@
package de.srendi.cctutorial.cctutorial;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.material.Material;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.IBlockReader;
import javax.annotation.Nullable;
public class CCBlock extends Block {
public CCBlock() {
super(Properties.create(Material.IRON).hardnessAndResistance(5, 10));
}
//Create a new tile entity with our registry object
@Nullable
@Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return Registration.CC_TILEENTITY.get().create();
}
//Say minecraft, our CCBlock has a tile entity.
@Override
public boolean hasTileEntity(BlockState state) {
return true;
}
}

View file

@ -0,0 +1,97 @@
package de.srendi.cctutorial.cctutorial;
import dan200.computercraft.api.lua.LuaFunction;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral;
import net.minecraft.util.text.StringTextComponent;
import net.minecraftforge.fml.server.ServerLifecycleHooks;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* Our peripheral class, this is the class where we will register functions for our block.
*/
public class CCPeripheral implements IPeripheral {
/**
* A list of all our connected computers. We need this for event usages.
*/
List<IComputerAccess> connectedComputers = new ArrayList<>();
/**
* This is our tile entity, we set the tile entity when we create a new peripheral. We use this tile entity to access the block or the world
*/
private final CCTileEntity tileEntity;
/**
*
* @param tileEntity the tile entity of this peripheral
*/
public CCPeripheral(CCTileEntity tileEntity) {
this.tileEntity = tileEntity;
}
/**
* We use getType to set the name for our peripheral. A modem would wrap our block as "test_n"
*
* @return the name of our peripheral
*/
@Nonnull
@Override
public String getType() {
return "test";
}
/**
* CC use this method to check, if the peripheral in front of the modem is our peripheral
*/
@Override
public boolean equals(@Nullable IPeripheral iPeripheral) {
return this == iPeripheral;
}
/**
* Will be called when a computer disconnects from our block
*/
@Override
public void detach(@Nonnull IComputerAccess computer) {
connectedComputers.remove(computer);
}
/**
* Will be called when a computer connects to our block
*/
@Override
public void attach(@Nonnull IComputerAccess computer) {
connectedComputers.add(computer);
}
public CCTileEntity getTileEntity() {
return tileEntity;
}
/**
* To register functions for our block, wee need to create final methods with the {@link LuaFunction} annotation
* This function will send a message to every player on the Server
*/
@LuaFunction
public final void sendMessage(String message) {
//Used to get the current server and all online players.
ServerLifecycleHooks.getCurrentServer().getPlayerList().getPlayers().forEach(player -> {
//Now, send the message
player.sendStatusMessage(new StringTextComponent(message), false);
});
}
/**
* Because we want to access the world, we need to run this function on the main thread.
*/
@LuaFunction(mainThread = true)
public final boolean isRaining() {
return getTileEntity().getWorld().getRainStrength(0) > 0;
}
}

View file

@ -0,0 +1,36 @@
package de.srendi.cctutorial.cctutorial;
import dan200.computercraft.api.peripheral.IPeripheral;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL;
public class CCTileEntity extends TileEntity {
public CCTileEntity() {
super(Registration.CC_TILEENTITY.get());
}
/**
* Our peripheral, we create a new peripheral for each new tile entity
*/
protected CCPeripheral peripheral = new CCPeripheral(this);
private LazyOptional<IPeripheral> peripheralCap;
/**
* When a computer modem tries to wrap our block, the modem will call getCapability to receive our peripheral.
*/
@Override
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction direction) {
if (cap == CAPABILITY_PERIPHERAL) {
if (peripheralCap == null) {
peripheralCap = LazyOptional.of(() -> peripheral);
}
return peripheralCap.cast();
}
return super.getCapability(cap, direction);
}
}

View file

@ -0,0 +1,22 @@
package de.srendi.cctutorial.cctutorial;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.Mod;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
// The value here should match an entry in the META-INF/mods.toml file
@Mod("cctutorial")
public class CCtutorial {
//Our mod id
public static final String MODID = "cctutorial";
// Directly reference a log4j logger.
private static final Logger LOGGER = LogManager.getLogger();
public CCtutorial() {
Registration.register();
// Register ourselves for server and other game events we are interested in. Currently, we do not use any events
MinecraftForge.EVENT_BUS.register(this);
}
}

View file

@ -0,0 +1,42 @@
package de.srendi.cctutorial.cctutorial;
import com.google.common.collect.Sets;
import net.minecraft.block.Block;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.tileentity.TileEntityType;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.RegistryObject;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import java.util.function.Supplier;
public class Registration {
public static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, CCtutorial.MODID);
public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, CCtutorial.MODID);
public static final DeferredRegister<TileEntityType<?>> TILE_ENTITIES = DeferredRegister.create(ForgeRegistries.TILE_ENTITIES, CCtutorial.MODID);
//Blocks
public static final RegistryObject<Block> CC_BLOCK = register("tutorial_block", CCBlock::new);
private static <T extends Block> RegistryObject<T> register(String name, Supplier<T> block) {
RegistryObject<T> registryObject = BLOCKS.register(name, block);
ITEMS.register(name, ()->new BlockItem(registryObject.get(), new Item.Properties().group(ItemGroup.REDSTONE)));
return registryObject;
}
//Tile Entities
public static final RegistryObject<TileEntityType<CCTileEntity>> CC_TILEENTITY = Registration.TILE_ENTITIES.register("tutorial_block", () -> new TileEntityType<>(CCTileEntity::new, Sets.newHashSet(CC_BLOCK.get()), null));
//Register our stuff
public static void register() {
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
BLOCKS.register(modEventBus);
ITEMS.register(modEventBus);
TILE_ENTITIES.register(modEventBus);
}
}

View file

@ -0,0 +1,40 @@
modLoader = "javafml" #mandatory
loaderVersion = "[36,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions.
license = "All rights reserved"
[[mods]] #mandatory
# The modid of the mod
modId = "cctutorial" #mandatory
version = "1.0" #mandatory
# A display name for the mod
displayName = "CCtutorial" #mandatory
# The description text for the mod (multi line!) (#mandatory)
description = '''
A mod to show you, how the magic of cc works.
'''
# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional.
[[dependencies.cctutorial]] #optional
# the modid of the dependency
modId = "forge" #mandatory
# Does this dependency have to exist - if not, ordering below must be specified
mandatory = true #mandatory
# The version range of the dependency
versionRange = "[36,)" #mandatory
# An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory
ordering = "NONE"
# Side this dependency is applied on - BOTH, CLIENT or SERVER
side = "BOTH"
# Here's another dependency
[[dependencies.advancedperipherals]]
modId = "computercraft"
mandatory = true
versionRange = "1.95.3"
ordering = "NONE"
side = "BOTH"
[[dependencies.cctutorial]]
modId = "minecraft"
mandatory = true
# This version range declares a minimum of the current minecraft version up to but not including the next major version
versionRange = "1.16.5"
ordering = "NONE"
side = "BOTH"

View file

@ -0,0 +1,7 @@
{
"pack": {
"description": "cctutorial resources",
"pack_format": 6,
"_comment": "A pack_format of 6 requires json lang files and some texture changes from 1.16.2. Note: we require v6 pack meta for all mods."
}
}