├── .github └── workflows │ └── maven.yml ├── README.md ├── pom.xml ├── screenshot.png └── src └── main └── java └── com └── cubk └── nsc2 ├── Agent.java ├── JavaPlugin.java ├── NSC.java ├── gui ├── AddressSwapperFrame.java └── DebugFrame.java ├── handler ├── PacketManager.java ├── PacketProcessor.java └── ThreadScanner.java ├── module ├── Module.java └── modules │ ├── AbuseDetector.java │ └── MotionCalculator.java ├── packet ├── ClientPacketWrapper.java ├── Packet.java ├── PacketData.java ├── ServerPacketWrapper.java ├── ToString.java └── wrappers │ ├── client │ ├── C00PacketKeepAlive.java │ ├── C01PacketChatMessage.java │ ├── C02PacketUseEntity.java │ ├── C03PacketPlayer.java │ ├── C04PacketPlayerPosition.java │ ├── C05PacketPlayerLook.java │ ├── C06PacketPlayerPosLook.java │ ├── C07PacketPlayerDigging.java │ ├── C08PacketPlayerBlockPlacement.java │ ├── C09PacketHeldItemChange.java │ ├── C0APacketAnimation.java │ ├── C0BPacketEntityAction.java │ ├── C0CPacketInput.java │ ├── C0DPacketCloseWindow.java │ ├── C0EPacketClickWindow.java │ ├── C0FPacketConfirmTransaction.java │ ├── C10PacketCreativeInventoryAction.java │ ├── C11PacketEnchantItem.java │ ├── C13PacketPlayerAbilities.java │ ├── C14PacketTabComplete.java │ └── C17PacketCustomPayload.java │ └── server │ └── S12PacketEntityVelocity.java ├── plugin ├── Parser.java ├── PluginAPI.java ├── PluginData.java └── PluginLoader.java ├── struct ├── Constant.java ├── EnumFacing.java ├── ItemStack.java ├── Position.java ├── Vector3.java └── nbt │ ├── NBTBase.java │ ├── NBTException.java │ ├── NBTSizeTracker.java │ ├── NBTTagByte.java │ ├── NBTTagByteArray.java │ ├── NBTTagCompound.java │ ├── NBTTagDouble.java │ ├── NBTTagEnd.java │ ├── NBTTagFloat.java │ ├── NBTTagInt.java │ ├── NBTTagIntArray.java │ ├── NBTTagList.java │ ├── NBTTagLong.java │ ├── NBTTagShort.java │ └── NBTTagString.java ├── transformer ├── Transformer.java ├── TransformerManager.java └── transformers │ └── BootstrapTransformer.java └── util ├── MathHelper.java ├── MathUtil.java └── TimerUtil.java /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | name: Build and Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - Dev 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Checkout repository 14 | uses: actions/checkout@v2 15 | 16 | - name: Set up Java 17 | uses: actions/setup-java@v2 18 | with: 19 | java-version: '17' 20 | distribution: 'adopt' 21 | 22 | - name: Build JAR 23 | run: mvn package 24 | 25 | - name: Upload JAR 26 | uses: actions/upload-artifact@v2 27 | with: 28 | name: Release 29 | path: target/NSC2-2.0.jar 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NSC2 2 | 3 | A Packet logger for minecraft 1.8.9 (WIP) 4 | 5 | Just for fun, do not use this project to steal any client's bypasses (except sleep). 6 | 7 | ## Features 8 | 9 | - Log obfuscated client (tested: faiths, novoline, moon, phantom) 10 | - Decode packet detailed information 11 | - Work in online server 12 | - Calculate timer speed 13 | - Display real motionXYZ bps and position 14 | 15 | ## Function not implemented 16 | 17 | - Support 1.8.9 only, Incompatible with viaversion 18 | - Packet decoding only available for client packet 19 | 20 | ## Usage 21 | 22 | - Call `NSC.getInstance().start();` using any method. 23 | - Use Agent `-javaagent:NSC2.jar` 24 | 25 | ![](screenshot.png) 26 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | com.cubk 7 | NSC2 8 | 2.0 9 | 10 | 11 | 1.8 12 | 1.8 13 | UTF-8 14 | UTF-8 15 | UTF-8 16 | 9.6 17 | 18 | 19 | 20 | 21 | org.ow2.asm 22 | asm 23 | ${asm.version} 24 | 25 | 26 | org.ow2.asm 27 | asm-tree 28 | ${asm.version} 29 | 30 | 31 | org.ow2.asm 32 | asm-util 33 | ${asm.version} 34 | 35 | 36 | org.ow2.asm 37 | asm-analysis 38 | ${asm.version} 39 | 40 | 41 | org.ow2.asm 42 | asm-commons 43 | ${asm.version} 44 | 45 | 46 | io.netty 47 | netty-all 48 | 4.0.23.Final 49 | provided 50 | 51 | 52 | com.google.code.gson 53 | gson 54 | 2.2.4 55 | provided 56 | 57 | 58 | org.projectlombok 59 | lombok 60 | 1.18.22 61 | provided 62 | 63 | 64 | 65 | 66 | 67 | 68 | org.apache.maven.plugins 69 | maven-assembly-plugin 70 | 3.6.0 71 | 72 | 73 | jar-with-dependencies 74 | 75 | 76 | 77 | com.cubk.nsc2.Agent 78 | true 79 | 80 | 81 | 82 | 83 | 84 | 85 | make-assembly 86 | package 87 | 88 | single 89 | 90 | 91 | 92 | 93 | 94 | org.apache.maven.plugins 95 | maven-compiler-plugin 96 | 3.10.1 97 | 98 | 1.8 99 | 1.8 100 | 101 | 102 | org.projectlombok 103 | lombok 104 | 1.18.22 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/union4dev/MinecraftPacketLogger/f63de7ae4130a08f71ff13b51fced04ccc08915a/screenshot.png -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/Agent.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2; 2 | 3 | import com.cubk.nsc2.transformer.TransformerManager; 4 | 5 | import java.lang.instrument.Instrumentation; 6 | 7 | public class Agent { 8 | public static Instrumentation instrumentation; 9 | 10 | public static void premain(String args, Instrumentation instrumentation) { 11 | System.out.println("[NSC] Loaded."); 12 | Agent.instrumentation = instrumentation; 13 | instrumentation.addTransformer(new TransformerManager()); 14 | NSC.getInstance().start(); 15 | } 16 | } -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/JavaPlugin.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2; 2 | 3 | import com.cubk.nsc2.plugin.PluginData; 4 | 5 | public interface JavaPlugin { 6 | 7 | ThreadLocal descriptionFile = new ThreadLocal<>(); 8 | 9 | void onLoad(); 10 | 11 | void onUnload(); 12 | 13 | default PluginData getDescriptionFile() { 14 | return descriptionFile.get(); 15 | } 16 | 17 | default void setDescriptionFile(PluginData descriptionFile) { 18 | if (this.descriptionFile.get() != null) { 19 | throw new RuntimeException("Can't set the description file. Its already set!"); 20 | } 21 | this.descriptionFile.set(descriptionFile); 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/NSC.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2; 2 | 3 | import com.cubk.nsc2.gui.DebugFrame; 4 | import com.cubk.nsc2.handler.PacketManager; 5 | import com.cubk.nsc2.handler.PacketProcessor; 6 | import com.cubk.nsc2.handler.ThreadScanner; 7 | import com.cubk.nsc2.plugin.PluginAPI; 8 | import com.cubk.nsc2.plugin.PluginLoader; 9 | import lombok.Getter; 10 | 11 | import java.io.File; 12 | import java.io.PrintWriter; 13 | import java.io.StringWriter; 14 | 15 | public class NSC { 16 | 17 | @Getter 18 | private PacketProcessor packetProcessor; 19 | 20 | private DebugFrame debugFrame; 21 | @Getter 22 | private PluginAPI pluginAPI; 23 | 24 | @Getter 25 | private static NSC instance = new NSC(); 26 | 27 | public static void printStacktrace(Throwable throwable) { 28 | throwable.printStackTrace(); 29 | } 30 | 31 | public DebugFrame getClickGui() { 32 | return debugFrame; 33 | } 34 | 35 | public String getStacktrace(final Throwable throwable) { 36 | final StringWriter sw = new StringWriter(); 37 | final PrintWriter pw = new PrintWriter(sw, true); 38 | throwable.printStackTrace(pw); 39 | return sw.getBuffer().toString(); 40 | } 41 | 42 | public void start() { 43 | System.out.println("[NSC] Initializing..."); 44 | instance = this; 45 | 46 | File plugins = new File("nsc_plugins"); 47 | 48 | if (!plugins.exists()) 49 | plugins.mkdir(); 50 | 51 | PacketManager packetManager = new PacketManager(); 52 | packetProcessor = new PacketProcessor(); 53 | 54 | new ThreadScanner().start(); 55 | new Thread(packetManager::onLoop).start(); 56 | 57 | pluginAPI = PluginAPI.getApi(pluginLoader -> new PluginLoader(), "loader"); 58 | System.out.println("[NSC] Loading plugins form " + plugins.getAbsolutePath()); 59 | pluginAPI.loadAll(plugins); 60 | 61 | debugFrame = new DebugFrame(); 62 | debugFrame.setVisible(true); 63 | 64 | 65 | } 66 | 67 | public static native void log(String string); 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/gui/AddressSwapperFrame.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.gui; 2 | 3 | import lombok.Getter; 4 | 5 | import javax.swing.*; 6 | import java.awt.*; 7 | 8 | public class AddressSwapperFrame extends JFrame { 9 | @Getter 10 | private static JCheckBox use = new JCheckBox("Use Address Swapper"); 11 | @Getter 12 | private static JTextField originalHostField; 13 | @Getter 14 | private static JTextField targetServerField; 15 | @Getter 16 | private static JTextField targetPortField; 17 | 18 | public AddressSwapperFrame() { 19 | setTitle("Address Swapper"); 20 | setLayout(new GridBagLayout()); 21 | setAlwaysOnTop(true); 22 | GridBagConstraints gbc = new GridBagConstraints(); 23 | gbc.insets = new Insets(5, 5, 5, 5); 24 | originalHostField = new JTextField("mc.hypixel.net"); 25 | targetServerField = new JTextField(); 26 | targetPortField = new JTextField("25565"); 27 | 28 | Dimension textFieldDimension = new Dimension(200, 25); 29 | originalHostField.setPreferredSize(textFieldDimension); 30 | targetServerField.setPreferredSize(textFieldDimension); 31 | targetPortField.setPreferredSize(textFieldDimension); 32 | 33 | JButton confirmButton = new JButton("Dispose"); 34 | confirmButton.addActionListener(e -> dispose()); 35 | 36 | gbc.gridx = 0; 37 | gbc.gridy = 0; 38 | add(new JLabel("Enable"), gbc); 39 | gbc.gridx = 1; 40 | add(use, gbc); 41 | 42 | gbc.gridx = 0; 43 | gbc.gridy = 1; 44 | add(new JLabel("Original Host:"), gbc); 45 | gbc.gridx = 1; 46 | add(originalHostField, gbc); 47 | 48 | gbc.gridx = 0; 49 | gbc.gridy = 2; 50 | add(new JLabel("Target Server:"), gbc); 51 | gbc.gridx = 1; 52 | add(targetServerField, gbc); 53 | 54 | gbc.gridx = 0; 55 | gbc.gridy = 3; 56 | add(new JLabel("Target Port:"), gbc); 57 | gbc.gridx = 1; 58 | add(targetPortField, gbc); 59 | 60 | gbc.gridx = 1; 61 | gbc.gridy = 4; 62 | add(confirmButton, gbc); 63 | 64 | pack(); 65 | setLocationRelativeTo(null); 66 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/gui/DebugFrame.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.gui; 2 | 3 | import com.cubk.nsc2.packet.PacketData; 4 | 5 | import javax.swing.*; 6 | import javax.swing.table.DefaultTableModel; 7 | import java.awt.*; 8 | import java.awt.event.MouseAdapter; 9 | import java.awt.event.MouseEvent; 10 | import java.util.HashMap; 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | public class DebugFrame extends JFrame { 15 | private final JTable packetTable; 16 | private final JTable packetInfoTable; 17 | private final JTextArea logTextArea; 18 | private final JTextArea otherInfoTextArea; 19 | private final JTextField searchField; 20 | private final JCheckBox clientCheckBox; 21 | private final JCheckBox serverCheckBox; 22 | private final JButton startPauseButton; 23 | private JLabel data; 24 | private final Map> dataMap = new HashMap<>(); 25 | private boolean isRunning = false; 26 | 27 | public DebugFrame() { 28 | super("N.S.C. 2.0"); 29 | String[] columnNames = {"#", "Event Type", "Event Data", "Side", "Timestamp"}; 30 | DefaultTableModel tableModel = new DefaultTableModel(columnNames, 0) { 31 | @Override 32 | public boolean isCellEditable(int row, int column) { 33 | return false; 34 | } 35 | }; 36 | packetTable = new JTable(tableModel); 37 | 38 | packetTable.addMouseListener(new MouseAdapter() { 39 | public void mouseClicked(MouseEvent e) { 40 | if (e.getClickCount() == 2) { 41 | int selectedRow = packetTable.getSelectedRow(); 42 | DefaultTableModel infoTableModel = (DefaultTableModel) packetInfoTable.getModel(); 43 | infoTableModel.setRowCount(0); 44 | for (PacketData.Data data : dataMap.get(Integer.parseInt(tableModel.getValueAt(selectedRow, 0).toString()))) { 45 | infoTableModel.addRow(new Object[]{data.type.getSimpleName(), data.name, data.value}); 46 | } 47 | } 48 | } 49 | }); 50 | 51 | searchField = new JTextField(20); 52 | clientCheckBox = new JCheckBox("Client"); 53 | clientCheckBox.setSelected(true); 54 | serverCheckBox = new JCheckBox("Server"); 55 | serverCheckBox.setSelected(false); 56 | 57 | JButton searchButton = new JButton("Search"); 58 | searchButton.addActionListener(e -> searchPackets()); 59 | 60 | String[] infoColumnNames = {"Data Type", "Data Name", "Data"}; 61 | DefaultTableModel infoTableModel = new DefaultTableModel(infoColumnNames, 0) { 62 | @Override 63 | public boolean isCellEditable(int row, int column) { 64 | return false; 65 | } 66 | }; 67 | packetInfoTable = new JTable(infoTableModel); 68 | 69 | JTabbedPane tabbedPane = new JTabbedPane(); 70 | logTextArea = new JTextArea(); 71 | logTextArea.setFont(new Font("Consolas", Font.PLAIN, 12)); 72 | otherInfoTextArea = new JTextArea(); 73 | 74 | tabbedPane.addTab("Log", new JScrollPane(logTextArea)); 75 | tabbedPane.addTab("Packet Information", new JScrollPane(packetInfoTable)); 76 | tabbedPane.addTab("Other Information", new JScrollPane(otherInfoTextArea)); 77 | 78 | JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); 79 | splitPane.setTopComponent(createUpperPanel()); 80 | splitPane.setBottomComponent(tabbedPane); 81 | splitPane.setResizeWeight(0.7); 82 | 83 | startPauseButton = new JButton("Start"); 84 | startPauseButton.addActionListener(e -> { 85 | if (isRunning) { 86 | stop(); 87 | } else { 88 | run(); 89 | } 90 | }); 91 | 92 | setLayout(new BorderLayout()); 93 | add(splitPane, BorderLayout.CENTER); 94 | add(startPauseButton, BorderLayout.SOUTH); 95 | 96 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 97 | setSize(800, 600); 98 | setLocationRelativeTo(null); 99 | 100 | JMenuBar menuBar = createMenu(); 101 | setJMenuBar(menuBar); 102 | } 103 | 104 | private static JMenuBar createMenu() { 105 | JMenuBar menuBar = new JMenuBar(); 106 | JMenu toolMenu = new JMenu("Tools"); 107 | 108 | JMenuItem swapperItem = new JMenuItem("Address Swapper"); 109 | swapperItem.addActionListener(e -> new AddressSwapperFrame().setVisible(true)); 110 | 111 | toolMenu.add(swapperItem); 112 | 113 | menuBar.add(toolMenu); 114 | return menuBar; 115 | } 116 | 117 | private JPanel createUpperPanel() { 118 | JPanel upperPanel = new JPanel(new BorderLayout()); 119 | JPanel topPanel = new JPanel(new FlowLayout()); 120 | topPanel.add(searchField); 121 | topPanel.add(clientCheckBox); 122 | topPanel.add(serverCheckBox); 123 | topPanel.add(new JButton("Search")); 124 | topPanel.add(data = new JLabel("Data")); 125 | upperPanel.add(topPanel, BorderLayout.NORTH); 126 | 127 | JScrollPane scrollPane = new JScrollPane(packetTable); 128 | scrollPane.setAutoscrolls(true); 129 | upperPanel.add(scrollPane, BorderLayout.CENTER); 130 | 131 | return upperPanel; 132 | } 133 | 134 | 135 | private void searchPackets() { 136 | String searchText = searchField.getText().toLowerCase(); 137 | 138 | // TODO 139 | } 140 | 141 | private void run() { 142 | isRunning = true; 143 | startPauseButton.setText("Pause"); 144 | } 145 | 146 | private void stop() { 147 | isRunning = false; 148 | startPauseButton.setText("Start"); 149 | } 150 | 151 | public void addPacket(PacketData packetData) { 152 | if (!isRunning) return; 153 | 154 | if (!serverCheckBox.isSelected() && !packetData.outgoing) return; 155 | if (!clientCheckBox.isSelected() && packetData.outgoing) return; 156 | 157 | DefaultTableModel tableModel = (DefaultTableModel) packetTable.getModel(); 158 | String[] rowData = {String.valueOf(tableModel.getRowCount() + 1), packetData.packetClass.getSimpleName(), packetData.packetName, packetData.outgoing ? "Outgoing" : "Incoming", String.valueOf(packetData.time)}; 159 | tableModel.addRow(rowData); 160 | 161 | dataMap.put(tableModel.getRowCount(), packetData.getDataList()); 162 | 163 | int rowCount = packetTable.getRowCount(); 164 | if (rowCount > 0) { 165 | Rectangle rect = packetTable.getCellRect(rowCount - 1, 0, true); 166 | packetTable.scrollRectToVisible(rect); 167 | } 168 | } 169 | 170 | public void log(String message, String suffix) { 171 | logTextArea.append(String.format("[%s][%s] %s", System.currentTimeMillis(), suffix, message) + "\n"); 172 | } 173 | 174 | public void setOtherInfo(String info) { 175 | otherInfoTextArea.setText(info); 176 | } 177 | 178 | public void setData(String info) { 179 | data.setText(info); 180 | } 181 | 182 | } 183 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/handler/PacketManager.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.handler; 2 | 3 | import com.cubk.nsc2.NSC; 4 | import com.cubk.nsc2.packet.PacketData; 5 | import com.cubk.nsc2.struct.Constant; 6 | import io.netty.buffer.ByteBuf; 7 | import io.netty.buffer.Unpooled; 8 | import io.netty.channel.*; 9 | 10 | import javax.swing.*; 11 | import java.lang.reflect.Field; 12 | import java.lang.reflect.Method; 13 | 14 | public class PacketManager { 15 | 16 | public void onLoop() { 17 | while (true) { 18 | try { 19 | Object nh = Constant.method_getNetHandler.invoke(Constant.object_theMinecraft); 20 | if (nh != null) { 21 | Object nm = Constant.method_getNetworkManager.invoke(nh); 22 | if (nm != null) 23 | inject(Constant.method_getNetworkManager.getReturnType(), nm); 24 | } 25 | 26 | } catch (Exception ignored) { 27 | } 28 | } 29 | } 30 | 31 | public void inject(Class netClass, Object networkManager) { 32 | Channel channel = null; 33 | 34 | for (Field field : netClass.getDeclaredFields()) { 35 | try { 36 | if (field.getType().getName().equals("io.netty.channel.Channel")) { 37 | try { 38 | field.setAccessible(true); 39 | channel = (Channel) field.get(networkManager); 40 | } catch (Exception e) { 41 | NSC.printStacktrace(e); 42 | } 43 | } 44 | } catch (Exception e) { 45 | e.printStackTrace(); 46 | } 47 | } 48 | if (channel != null) { 49 | ChannelPipeline pipeline = channel.pipeline(); 50 | if (pipeline.context(PacketListener.class) == null && pipeline.context("packet_handler") != null) { 51 | channel.pipeline().addBefore("packet_handler", "lunarclient", new PacketListener()); 52 | 53 | } 54 | 55 | } else { 56 | JOptionPane.showMessageDialog(null, "Error [2]", "Internal error, failed to initialize\nNo channel found", JOptionPane.ERROR_MESSAGE); 57 | } 58 | } 59 | } 60 | 61 | class PacketListener extends ChannelDuplexHandler { 62 | @Override 63 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 64 | PacketData wrapper = new PacketData(msg.getClass(), msg.getClass().getSimpleName(), false); 65 | if (!handle(false, msg, wrapper)) 66 | super.channelRead(ctx, msg); 67 | } 68 | 69 | @Override 70 | public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { 71 | PacketData wrapper = new PacketData(msg.getClass(), msg.getClass().getSimpleName(), true); 72 | if (!handle(true, msg, wrapper)) 73 | super.write(ctx, msg, promise); 74 | } 75 | 76 | private boolean handle(boolean outgoing, Object packet, PacketData wrapper) { 77 | if (outgoing) { 78 | try { 79 | Object sb = Constant.class_EnumConnectionState.getDeclaredField("PLAY").get(null); 80 | Object sb2 = Constant.class_EnumPacketDirection.getDeclaredField("SERVERBOUND").get(null); 81 | Integer id = (Integer) Constant.method_getPacketId.invoke(sb, sb2, packet); 82 | if (id == 3 && Constant.name_writeData == null) { 83 | for (Method method : packet.getClass().getMethods()) { 84 | try { 85 | if (method.getParameters()[0].getType() != boolean.class) { 86 | ByteBuf buf = Unpooled.buffer(); 87 | Constant.class_PacketBuffer = method.getParameters()[0].getType().getConstructor(ByteBuf.class); 88 | Object packetBuffer = method.getParameters()[0].getType().getConstructor(ByteBuf.class).newInstance(buf); 89 | try { 90 | method.invoke(packet, packetBuffer); 91 | Constant.name_writeData = method.getName(); 92 | } catch (Throwable ignored) { 93 | } 94 | } 95 | } catch (Exception ignored) { 96 | 97 | } 98 | } 99 | } 100 | if (Constant.name_writeData != null) { 101 | return NSC.getInstance().getPacketProcessor().processClientPacket(id, packet, wrapper); 102 | } 103 | } catch (Exception e) { 104 | NSC.printStacktrace(e); 105 | } 106 | } else { 107 | try { 108 | Object sb = Constant.class_EnumConnectionState.getDeclaredField("PLAY").get(null); 109 | Object sb2 = Constant.class_EnumPacketDirection.getDeclaredField("CLIENTBOUND").get(null); 110 | Integer id = (Integer) Constant.method_getPacketId.invoke(sb, sb2, packet); 111 | return NSC.getInstance().getPacketProcessor().processServerPacket(id, packet, wrapper); 112 | } catch (Exception e) { 113 | NSC.printStacktrace(e); 114 | } 115 | } 116 | return false; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/handler/PacketProcessor.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.handler; 2 | 3 | import com.cubk.nsc2.NSC; 4 | import com.cubk.nsc2.module.Module; 5 | import com.cubk.nsc2.module.modules.AbuseDetector; 6 | import com.cubk.nsc2.module.modules.MotionCalculator; 7 | import com.cubk.nsc2.packet.ClientPacketWrapper; 8 | import com.cubk.nsc2.packet.PacketData; 9 | import com.cubk.nsc2.packet.ServerPacketWrapper; 10 | import com.cubk.nsc2.packet.wrappers.client.*; 11 | import com.cubk.nsc2.packet.wrappers.server.S12PacketEntityVelocity; 12 | import com.cubk.nsc2.struct.Constant; 13 | import com.cubk.nsc2.util.TimerUtil; 14 | import io.netty.buffer.ByteBuf; 15 | import io.netty.buffer.Unpooled; 16 | 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | import java.util.Map; 20 | import java.util.concurrent.ConcurrentHashMap; 21 | import java.util.concurrent.atomic.AtomicBoolean; 22 | 23 | public class PacketProcessor { 24 | private static final Map wrappersClient = new ConcurrentHashMap<>(); 25 | private static final Map wrappersServer = new ConcurrentHashMap<>(); 26 | 27 | private final TimerUtil timer = new TimerUtil(); 28 | private final List modules = new ArrayList<>(); 29 | private final List tick = new ArrayList<>(); 30 | 31 | private final MotionCalculator motionCalculator; 32 | 33 | static { 34 | wrappersClient.put(0x00, new C00PacketKeepAlive()); 35 | wrappersClient.put(0x01, new C01PacketChatMessage()); 36 | wrappersClient.put(0x02, new C02PacketUseEntity()); 37 | wrappersClient.put(0x03, new C03PacketPlayer()); 38 | wrappersClient.put(0x04, new C04PacketPlayerPosition()); 39 | wrappersClient.put(0x05, new C05PacketPlayerLook()); 40 | wrappersClient.put(0x06, new C06PacketPlayerPosLook()); 41 | wrappersClient.put(0x07, new C07PacketPlayerDigging()); 42 | wrappersClient.put(0x08, new C08PacketPlayerBlockPlacement()); 43 | wrappersClient.put(0x09, new C09PacketHeldItemChange()); 44 | wrappersClient.put(0x0A, new C0APacketAnimation()); 45 | wrappersClient.put(0x0B, new C0BPacketEntityAction()); 46 | wrappersClient.put(0x0C, new C0CPacketInput()); 47 | wrappersClient.put(0x0D, new C0DPacketCloseWindow()); 48 | wrappersClient.put(0x0E, new C0EPacketClickWindow()); 49 | wrappersClient.put(0x0F, new C0FPacketConfirmTransaction()); 50 | wrappersClient.put(0x10, new C10PacketCreativeInventoryAction()); 51 | wrappersClient.put(0x11, new C11PacketEnchantItem()); 52 | wrappersClient.put(0x13, new C13PacketPlayerAbilities()); 53 | wrappersClient.put(0x14, new C14PacketTabComplete()); 54 | wrappersClient.put(0x17, new C17PacketCustomPayload()); 55 | 56 | wrappersServer.put(0x12, new S12PacketEntityVelocity()); 57 | } 58 | 59 | public PacketProcessor() { 60 | modules.add(new AbuseDetector()); 61 | modules.add(motionCalculator = new MotionCalculator()); 62 | } 63 | 64 | public void loop() { 65 | 66 | NSC.getInstance().getClickGui().setData(""); 67 | 68 | StringBuilder sb = new StringBuilder(); 69 | 70 | sb.append("Timer: ").append(getPPS() / 20f).append("\n"); 71 | sb.append("MotionX: ").append(motionCalculator.motionX).append("\n"); 72 | sb.append("MotionY: ").append(motionCalculator.motionY).append("\n"); 73 | sb.append("MotionZ: ").append(motionCalculator.motionZ).append("\n"); 74 | 75 | sb.append("Rotation: (").append(motionCalculator.yaw).append("/").append(motionCalculator.pitch).append(")\n"); 76 | 77 | if (motionCalculator.motionX != 0 || motionCalculator.motionZ != 0) { 78 | sb.append("Speed: ").append(motionCalculator.speed).append("\n"); 79 | sb.append("Movement Yaw: ").append(motionCalculator.movementYaw); 80 | 81 | sb.append(" (").append(motionCalculator.getStrafeDifferences()).append(")"); 82 | 83 | sb.append("\n"); 84 | } 85 | 86 | if (motionCalculator.lastPosition != null) { 87 | sb.append("Position: ").append(motionCalculator.lastPosition).append("\n"); 88 | } 89 | 90 | NSC.getInstance().getClickGui().setOtherInfo(sb.toString()); 91 | 92 | timer.reset(); 93 | } 94 | 95 | private int getPPS() { 96 | long time = System.currentTimeMillis(); 97 | this.tick.removeIf(aLong -> aLong + 1000L < time); 98 | return this.tick.size(); 99 | } 100 | 101 | 102 | public boolean processServerPacket(int id, Object packet, PacketData pw) { 103 | 104 | try { 105 | if (Constant.class_PacketBuffer == null) return false; 106 | 107 | ServerPacketWrapper wrapper = wrappersServer.getOrDefault(id, null); 108 | 109 | if (wrapper == null) { 110 | return false; 111 | } 112 | 113 | wrapper = wrapper.getClass().newInstance(); 114 | 115 | ByteBuf buf = Unpooled.buffer(); 116 | Object buffer = Constant.class_PacketBuffer.newInstance(buf); 117 | packet.getClass().getDeclaredMethod(Constant.name_writeData, buffer.getClass()).invoke(packet, buffer); 118 | wrapper.parser(buf, pw); 119 | 120 | NSC.getInstance().getClickGui().addPacket(pw); 121 | 122 | AtomicBoolean AtomicFuck = new AtomicBoolean(false); 123 | ServerPacketWrapper finalWrapper = wrapper; 124 | modules.forEach(module -> AtomicFuck.set(module.handleServerPacket(finalWrapper))); 125 | loop(); 126 | return AtomicFuck.get(); 127 | } catch (Exception e) { 128 | NSC.printStacktrace(e); 129 | } 130 | return false; 131 | } 132 | 133 | public boolean processClientPacket(int id, Object packet, PacketData pw) { 134 | try { 135 | if (Constant.class_PacketBuffer == null) return false; 136 | 137 | ClientPacketWrapper wrapper = wrappersClient.getOrDefault(id, null); 138 | 139 | if (wrapper == null) { 140 | NSC.getInstance().getClickGui().log("Failed to parse packet: " + id + " " + packet.getClass().getSimpleName(), "warn"); 141 | return false; 142 | } 143 | 144 | wrapper = wrapper.getClass().newInstance(); 145 | 146 | ByteBuf buf = Unpooled.buffer(); 147 | Object buffer = Constant.class_PacketBuffer.newInstance(buf); 148 | packet.getClass().getDeclaredMethod(Constant.name_writeData, buffer.getClass()).invoke(packet, buffer); 149 | pw.setPacketName(wrapper.getClass().getSimpleName()); 150 | wrapper.parser(buf, pw); 151 | 152 | NSC.getInstance().getClickGui().addPacket(pw); 153 | 154 | if (wrapper instanceof C03PacketPlayer) { 155 | tick.add(System.currentTimeMillis() + 10L); 156 | } 157 | 158 | AtomicBoolean AtomicFuck = new AtomicBoolean(false); 159 | ClientPacketWrapper finalWrapper = wrapper; 160 | modules.forEach(module -> AtomicFuck.set(module.handleClientPacket(finalWrapper))); 161 | loop(); 162 | return AtomicFuck.get(); 163 | } catch (Exception e) { 164 | NSC.printStacktrace(e); 165 | } 166 | return false; 167 | } 168 | 169 | 170 | } 171 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/handler/ThreadScanner.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.handler; 2 | 3 | import com.cubk.nsc2.struct.Constant; 4 | import io.netty.util.AttributeKey; 5 | 6 | import javax.swing.*; 7 | import java.lang.reflect.Field; 8 | import java.lang.reflect.Method; 9 | import java.lang.reflect.Modifier; 10 | 11 | public class ThreadScanner extends Thread { 12 | 13 | @Override 14 | public void run() { 15 | Thread[] threads = new Thread[1024]; 16 | long start = System.currentTimeMillis(); 17 | Object minecraftObj = null; 18 | Class minecraftClass = null; 19 | do { 20 | int count = Thread.enumerate(threads); 21 | for (int i = 0; i < count; i++) { 22 | if (threads[i].getName().equals("Client thread")) { 23 | StackTraceElement[] stack = threads[i].getStackTrace(); 24 | for (StackTraceElement element : stack) { 25 | try { 26 | Class clazz = Class.forName(element.getClassName(), true, threads[i].getContextClassLoader()); 27 | for (Field f : clazz.getDeclaredFields()) { 28 | if (Modifier.isStatic(f.getModifiers()) && f.getType() == clazz) { 29 | f.setAccessible(true); 30 | minecraftClass = clazz; 31 | minecraftObj = f.get(null); 32 | break; 33 | } 34 | } 35 | } catch (ClassNotFoundException e) { 36 | ; 37 | } catch (Exception e) { 38 | System.exit(0); 39 | } 40 | } 41 | } 42 | } 43 | try { 44 | Thread.sleep(5L); 45 | } catch (InterruptedException e) { 46 | return; 47 | } 48 | } while (minecraftObj == null && System.currentTimeMillis() - start < 60000); 49 | 50 | if (minecraftObj == null) { 51 | try { 52 | Class clazz = Class.forName("net.minecraft.client.Minecraft"); 53 | for (Field f : clazz.getDeclaredFields()) { 54 | if (Modifier.isStatic(f.getModifiers()) && f.getType() == clazz) { 55 | Field.setAccessible(new Field[]{f}, true); 56 | minecraftObj = f.get(null); 57 | } 58 | } 59 | } catch (Throwable t) { 60 | } 61 | } 62 | if (minecraftObj != null && minecraftClass != null) { 63 | Constant.object_theMinecraft = minecraftObj; 64 | Field netMgr = null; 65 | 66 | for (Field field : minecraftClass.getDeclaredFields()) { 67 | try { 68 | if (field.getType().getSuperclass().getName().equals("io.netty.channel.SimpleChannelInboundHandler")) { 69 | netMgr = field; 70 | } 71 | } catch (Exception ignored) { 72 | 73 | } 74 | } 75 | 76 | if (netMgr != null) { 77 | netMgr.setAccessible(true); 78 | 79 | for (Method method : minecraftClass.getMethods()) { 80 | if (method.getReturnType().getInterfaces().length == 1) { 81 | try { 82 | if (method.getReturnType().getInterfaces()[0].getInterfaces()[0].getMethods().length == 1) { 83 | Constant.method_getNetHandler = method; 84 | for (Method method1 : method.getReturnType().getDeclaredMethods()) { 85 | if (Modifier.isPublic(method1.getModifiers())) { 86 | if (method1.getReturnType().getName().equals(netMgr.getType().getName())) { 87 | Constant.method_getNetworkManager = method1; 88 | } 89 | } 90 | } 91 | } 92 | } catch (Exception e) { 93 | 94 | } 95 | } 96 | } 97 | for (Method method : netMgr.getType().getDeclaredMethods()) { 98 | try { 99 | if (method.getParameters()[0].getType().getSuperclass() == Enum.class) { 100 | Constant.class_EnumConnectionState = method.getParameters()[0].getType(); 101 | for (Method method1 : Constant.class_EnumConnectionState.getMethods()) { 102 | try { 103 | if (method1.getParameters()[0].getType().getSuperclass() == Enum.class && method1.getReturnType() == Integer.class) { 104 | Constant.class_EnumPacketDirection = method1.getParameters()[0].getType(); 105 | Constant.method_getPacketId = method1; 106 | } 107 | } catch (Exception e) { 108 | } 109 | } 110 | } 111 | } catch (Exception e) { 112 | } 113 | } 114 | 115 | for (Field field : netMgr.getType().getDeclaredFields()) { 116 | if (field.getType() == AttributeKey.class) { 117 | try { 118 | field.setAccessible(true); 119 | Constant.object_attribute_key = (AttributeKey) field.get(null); 120 | } catch (IllegalAccessException e) { 121 | throw new RuntimeException(e); 122 | 123 | } 124 | } 125 | } 126 | } else { 127 | JOptionPane.showMessageDialog(null, "Error [0]", "Internal error, failed to initialize\nNo network manager found", JOptionPane.ERROR_MESSAGE); 128 | } 129 | 130 | } else { 131 | JOptionPane.showMessageDialog(null, "Error [1]", "Internal error, failed to initialize\nNo minecraft found", JOptionPane.ERROR_MESSAGE); 132 | } 133 | } 134 | } -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/module/Module.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.module; 2 | 3 | import com.cubk.nsc2.NSC; 4 | import com.cubk.nsc2.packet.ClientPacketWrapper; 5 | import com.cubk.nsc2.packet.ServerPacketWrapper; 6 | 7 | public interface Module { 8 | 9 | // Return true for cancel 10 | 11 | default boolean handleClientPacket(ClientPacketWrapper wrapper) { 12 | return false; 13 | } 14 | 15 | default boolean handleServerPacket(ServerPacketWrapper wrapper) { 16 | return false; 17 | } 18 | 19 | String getName(); 20 | 21 | default void log(String message) { 22 | NSC.getInstance().getClickGui().log(message, getName()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/module/modules/AbuseDetector.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.module.modules; 2 | 3 | import com.cubk.nsc2.module.Module; 4 | import com.cubk.nsc2.packet.ClientPacketWrapper; 5 | import com.cubk.nsc2.packet.wrappers.client.C03PacketPlayer; 6 | import com.cubk.nsc2.packet.wrappers.client.C05PacketPlayerLook; 7 | import com.cubk.nsc2.packet.wrappers.client.C06PacketPlayerPosLook; 8 | 9 | public class AbuseDetector implements Module { 10 | 11 | @Override 12 | public boolean handleClientPacket(ClientPacketWrapper wrapper) { 13 | if (wrapper instanceof C03PacketPlayer) { 14 | if (wrapper instanceof C05PacketPlayerLook || wrapper instanceof C06PacketPlayerPosLook) { 15 | if (((C03PacketPlayer) wrapper).pitch > 90 || ((C03PacketPlayer) wrapper).pitch < -90) { 16 | log("Invalid pitch detected, possibly exploit abuse! (" + ((C03PacketPlayer) wrapper).pitch + ")"); 17 | } 18 | } 19 | } 20 | return false; 21 | } 22 | 23 | @Override 24 | public String getName() { 25 | return "Exploit Abuse Detector"; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/module/modules/MotionCalculator.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.module.modules; 2 | 3 | import com.cubk.nsc2.module.Module; 4 | import com.cubk.nsc2.packet.ClientPacketWrapper; 5 | import com.cubk.nsc2.packet.wrappers.client.C04PacketPlayerPosition; 6 | import com.cubk.nsc2.packet.wrappers.client.C05PacketPlayerLook; 7 | import com.cubk.nsc2.packet.wrappers.client.C06PacketPlayerPosLook; 8 | import com.cubk.nsc2.struct.Position; 9 | import com.cubk.nsc2.util.MathHelper; 10 | 11 | public class MotionCalculator implements Module { 12 | public Position lastPosition = null; 13 | public float yaw; 14 | public float pitch; 15 | 16 | public double speed; 17 | public double motionX; 18 | public double motionY; 19 | public double motionZ; 20 | public float movementYaw; 21 | 22 | @Override 23 | public String getName() { 24 | return "Motion"; 25 | } 26 | 27 | @Override 28 | public boolean handleClientPacket(ClientPacketWrapper packet) { 29 | if (packet instanceof C04PacketPlayerPosition || packet instanceof C06PacketPlayerPosLook || packet instanceof C05PacketPlayerLook) { 30 | double speed = 0; 31 | if (packet instanceof C04PacketPlayerPosition) { 32 | final C04PacketPlayerPosition playerPosition = (C04PacketPlayerPosition) packet; 33 | if (lastPosition != null) { 34 | motionX = playerPosition.x - lastPosition.getX(); 35 | motionY = playerPosition.y - lastPosition.getY(); 36 | motionZ = playerPosition.z - lastPosition.getZ(); 37 | speed = Math.sqrt(motionX * motionX + motionZ * motionZ); 38 | double movementYawRad = Math.atan2(-motionX, motionZ); 39 | movementYaw = (float) Math.toDegrees(movementYawRad); 40 | movementYaw = MathHelper.wrapAngleTo180_float(movementYaw); 41 | } 42 | lastPosition = new Position(playerPosition.x, playerPosition.y, playerPosition.z); 43 | } else if (packet instanceof C06PacketPlayerPosLook) { 44 | final C06PacketPlayerPosLook playerPosLook = (C06PacketPlayerPosLook) packet; 45 | if (lastPosition != null) { 46 | this.yaw = playerPosLook.yaw; 47 | this.pitch = playerPosLook.pitch; 48 | motionX = playerPosLook.x - lastPosition.getX(); 49 | motionY = playerPosLook.y - lastPosition.getY(); 50 | motionZ = playerPosLook.z - lastPosition.getZ(); 51 | speed = Math.sqrt(motionX * motionX + motionZ * motionZ); 52 | double movementYawRad = Math.atan2(-motionX, motionZ); 53 | movementYaw = (float) Math.toDegrees(movementYawRad); 54 | movementYaw = MathHelper.wrapAngleTo180_float(movementYaw); 55 | } 56 | lastPosition = new Position(playerPosLook.x, playerPosLook.y, playerPosLook.z); 57 | } else { 58 | C05PacketPlayerLook packetPlayerLook = (C05PacketPlayerLook) packet; 59 | this.yaw = packetPlayerLook.yaw; 60 | this.pitch = packetPlayerLook.pitch; 61 | } 62 | this.speed = speed * 20; 63 | } 64 | return false; 65 | } 66 | 67 | public float getStrafeDifferences() { 68 | return Math.abs(MathHelper.wrapAngleTo180_float(movementYaw - yaw)); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/ClientPacketWrapper.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet; 2 | 3 | 4 | public interface ClientPacketWrapper extends Packet, ToString { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/Packet.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet; 2 | 3 | import com.cubk.nsc2.struct.ItemStack; 4 | import com.cubk.nsc2.struct.Position; 5 | import com.cubk.nsc2.struct.nbt.NBTBase; 6 | import com.cubk.nsc2.struct.nbt.NBTSizeTracker; 7 | import com.cubk.nsc2.struct.nbt.NBTTagCompound; 8 | import com.cubk.nsc2.struct.nbt.NBTTagEnd; 9 | import io.netty.buffer.ByteBuf; 10 | import io.netty.buffer.ByteBufInputStream; 11 | import io.netty.handler.codec.DecoderException; 12 | 13 | import java.io.*; 14 | import java.nio.charset.StandardCharsets; 15 | 16 | public interface Packet { 17 | void parser(ByteBuf buf, PacketData packetData); 18 | 19 | default Position readPosition(ByteBuf buf) { 20 | return Position.fromLong(buf.readLong()); 21 | } 22 | 23 | default > T readEnumValue(Class enumClass, ByteBuf buf) { 24 | return (T) ((Enum[]) enumClass.getEnumConstants())[readVarIntFromBuffer(buf)]; 25 | } 26 | 27 | default String readStringFromBuffer(ByteBuf buf, int maxLength) { 28 | int i = this.readVarIntFromBuffer(buf); 29 | 30 | if (i > maxLength * 4) { 31 | throw new DecoderException("The received encoded string buffer length is longer than maximum allowed (" + i + " > " + maxLength * 4 + ")"); 32 | } else if (i < 0) { 33 | throw new DecoderException("The received encoded string buffer length is less than zero! Weird string!"); 34 | } else { 35 | String s = new String(buf.readBytes(i).array(), StandardCharsets.UTF_8); 36 | 37 | if (s.length() > maxLength) { 38 | throw new DecoderException("The received string length is longer than maximum allowed (" + i + " > " + maxLength + ")"); 39 | } else { 40 | return s; 41 | } 42 | } 43 | } 44 | 45 | default ItemStack readItemStackFromBuffer(ByteBuf buf) { 46 | ItemStack itemstack = null; 47 | int i = buf.readShort(); 48 | 49 | if (i >= 0) { 50 | try { 51 | int j = buf.readByte(); 52 | int k = buf.readShort(); 53 | itemstack = new ItemStack(i, j, k); 54 | this.readNBTTagCompoundFromBuffer(buf); 55 | } catch (Exception e) { 56 | e.printStackTrace(); 57 | } 58 | } 59 | 60 | return itemstack; 61 | } 62 | 63 | default NBTTagCompound readNBTTagCompoundFromBuffer(ByteBuf buf) throws IOException { 64 | int i = buf.readerIndex(); 65 | byte b0 = buf.readByte(); 66 | 67 | if (b0 == 0) { 68 | return null; 69 | } else { 70 | buf.readerIndex(i); 71 | return read(new ByteBufInputStream(buf), new NBTSizeTracker(2097152L)); 72 | } 73 | } 74 | 75 | default NBTTagCompound read(File p_74797_0_) throws IOException { 76 | if (!p_74797_0_.exists()) { 77 | return null; 78 | } else { 79 | DataInputStream datainputstream = new DataInputStream(new FileInputStream(p_74797_0_)); 80 | NBTTagCompound nbttagcompound; 81 | 82 | try { 83 | nbttagcompound = read(datainputstream, NBTSizeTracker.INFINITE); 84 | } finally { 85 | datainputstream.close(); 86 | } 87 | 88 | return nbttagcompound; 89 | } 90 | } 91 | 92 | default NBTTagCompound read(DataInput p_152456_0_, NBTSizeTracker p_152456_1_) throws IOException { 93 | NBTBase nbtbase = func_152455_a(p_152456_0_, 0, p_152456_1_); 94 | 95 | if (nbtbase instanceof NBTTagCompound) { 96 | return (NBTTagCompound) nbtbase; 97 | } else { 98 | throw new IOException("Root tag must be a named compound tag"); 99 | } 100 | } 101 | 102 | default NBTBase func_152455_a(DataInput p_152455_0_, int p_152455_1_, NBTSizeTracker p_152455_2_) throws IOException { 103 | byte b0 = p_152455_0_.readByte(); 104 | 105 | if (b0 == 0) { 106 | return new NBTTagEnd(); 107 | } else { 108 | 109 | 110 | try { 111 | p_152455_0_.readUTF(); 112 | NBTBase nbtbase = NBTBase.createNewByType(b0); 113 | nbtbase.read(p_152455_0_, p_152455_1_, p_152455_2_); 114 | return nbtbase; 115 | } catch (IOException ioexception) { 116 | ioexception.printStackTrace(); 117 | return null; 118 | } 119 | } 120 | } 121 | 122 | 123 | default int readVarIntFromBuffer(ByteBuf buf) { 124 | int i = 0; 125 | int j = 0; 126 | 127 | while (true) { 128 | byte b0 = buf.readByte(); 129 | i |= (b0 & 127) << j++ * 7; 130 | 131 | if (j > 5) { 132 | throw new RuntimeException("VarInt too big"); 133 | } 134 | 135 | if ((b0 & 128) != 128) { 136 | break; 137 | } 138 | } 139 | 140 | return i; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/PacketData.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public class PacketData { 10 | public final Class packetClass; 11 | @Getter 12 | private final List dataList; 13 | public final boolean outgoing; 14 | public final long time; 15 | @Setter 16 | public String packetName; 17 | 18 | public PacketData(Class packetClass, String packetName, boolean outgoing) { 19 | this.packetClass = packetClass; 20 | this.packetName = packetName; 21 | this.outgoing = outgoing; 22 | this.time = System.currentTimeMillis(); 23 | this.dataList = new ArrayList<>(); 24 | } 25 | 26 | public static class Data { 27 | public final Class type; 28 | public final String name; 29 | public final String value; 30 | 31 | public Data(Class type, String name, Object value) { 32 | this.type = type; 33 | this.name = name; 34 | this.value = String.valueOf(value); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/ServerPacketWrapper.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet; 2 | 3 | public interface ServerPacketWrapper extends Packet { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/ToString.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet; 2 | 3 | public interface ToString { 4 | String wrapToString(); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/wrappers/client/C00PacketKeepAlive.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet.wrappers.client; 2 | 3 | import com.cubk.nsc2.packet.ClientPacketWrapper; 4 | import com.cubk.nsc2.packet.PacketData; 5 | import io.netty.buffer.ByteBuf; 6 | 7 | public class C00PacketKeepAlive implements ClientPacketWrapper { 8 | public int key; 9 | 10 | @Override 11 | public void parser(ByteBuf buf, PacketData packetData) { 12 | this.key = readVarIntFromBuffer(buf); 13 | packetData.getDataList().add(new PacketData.Data(Integer.class, "key", key)); 14 | } 15 | 16 | @Override 17 | public String wrapToString() { 18 | return String.format("new C00PacketKeepAlive(%s)", key); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/wrappers/client/C01PacketChatMessage.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet.wrappers.client; 2 | 3 | import com.cubk.nsc2.packet.ClientPacketWrapper; 4 | import com.cubk.nsc2.packet.PacketData; 5 | import io.netty.buffer.ByteBuf; 6 | 7 | public class C01PacketChatMessage implements ClientPacketWrapper { 8 | private String message; 9 | 10 | @Override 11 | public void parser(ByteBuf buf, PacketData packetData) { 12 | this.message = readStringFromBuffer(buf, 100); 13 | packetData.getDataList().add(new PacketData.Data(String.class, "message", message)); 14 | } 15 | 16 | @Override 17 | public String wrapToString() { 18 | return String.format("new C01PacketChatMessage(%s)", message); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/wrappers/client/C02PacketUseEntity.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet.wrappers.client; 2 | 3 | import com.cubk.nsc2.packet.ClientPacketWrapper; 4 | import com.cubk.nsc2.packet.PacketData; 5 | import com.cubk.nsc2.struct.Vector3; 6 | import io.netty.buffer.ByteBuf; 7 | 8 | public class C02PacketUseEntity implements ClientPacketWrapper { 9 | public int entityId; 10 | public Action action; 11 | public Vector3 hitVec; 12 | 13 | 14 | @Override 15 | public void parser(ByteBuf buf, PacketData packetData) { 16 | this.entityId = readVarIntFromBuffer(buf); 17 | this.action = readEnumValue(Action.class, buf); 18 | packetData.getDataList().add(new PacketData.Data(Integer.class, "entityId", entityId)); 19 | packetData.getDataList().add(new PacketData.Data(Action.class, "action", action)); 20 | if (this.action == Action.INTERACT_AT) { 21 | this.hitVec = new Vector3(buf.readFloat(), buf.readFloat(), buf.readFloat()); 22 | packetData.getDataList().add(new PacketData.Data(Vector3.class, "hitVec", hitVec)); 23 | } 24 | } 25 | 26 | @Override 27 | public String wrapToString() { 28 | if (action == Action.INTERACT_AT) { 29 | return String.format("new C02PacketUseEntity(%s,new Vec3(%s,%s,%s))", entityId, hitVec.getX(), hitVec.getY(), hitVec.getZ()); 30 | } else { 31 | return String.format("new C02PacketUseEntity(%s,C02PacketUseEntity.Action.%s)", entityId, action.name()); 32 | } 33 | } 34 | 35 | @SuppressWarnings("unused") 36 | public enum Action { 37 | INTERACT, 38 | ATTACK, 39 | INTERACT_AT; 40 | } 41 | } -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/wrappers/client/C03PacketPlayer.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet.wrappers.client; 2 | 3 | import com.cubk.nsc2.packet.ClientPacketWrapper; 4 | import com.cubk.nsc2.packet.PacketData; 5 | import io.netty.buffer.ByteBuf; 6 | 7 | public class C03PacketPlayer implements ClientPacketWrapper { 8 | 9 | public double x; 10 | public double y; 11 | public double z; 12 | public float yaw; 13 | public float pitch; 14 | public boolean onGround; 15 | public boolean rotating; 16 | 17 | @Override 18 | public void parser(ByteBuf buf, PacketData data) { 19 | onGround = buf.readUnsignedByte() != 0; 20 | data.getDataList().add(new PacketData.Data(Boolean.class, "onGround", onGround)); 21 | data.getDataList().add(new PacketData.Data(Boolean.class, "rotating", rotating)); 22 | 23 | data.getDataList().add(new PacketData.Data(Double.class, "x", this.x)); 24 | data.getDataList().add(new PacketData.Data(Double.class, "y", this.y)); 25 | data.getDataList().add(new PacketData.Data(Double.class, "z", this.z)); 26 | 27 | data.getDataList().add(new PacketData.Data(Float.class, "yaw", this.yaw)); 28 | data.getDataList().add(new PacketData.Data(Float.class, "pitch", this.pitch)); 29 | } 30 | 31 | @Override 32 | public String wrapToString() { 33 | return String.format("new C03PacketPlayer(%s)", onGround); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/wrappers/client/C04PacketPlayerPosition.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet.wrappers.client; 2 | 3 | import com.cubk.nsc2.packet.PacketData; 4 | import io.netty.buffer.ByteBuf; 5 | 6 | public class C04PacketPlayerPosition extends C03PacketPlayer { 7 | 8 | @Override 9 | public void parser(ByteBuf buf, PacketData packetData) { 10 | this.x = buf.readDouble(); 11 | this.y = buf.readDouble(); 12 | this.z = buf.readDouble(); 13 | super.parser(buf, packetData); 14 | } 15 | 16 | @Override 17 | public String wrapToString() { 18 | return String.format("new C03PacketPlayer.C04PacketPlayerPosition(%s,%s,%s,%s)", x, y, z, onGround); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/wrappers/client/C05PacketPlayerLook.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet.wrappers.client; 2 | 3 | import com.cubk.nsc2.packet.PacketData; 4 | import io.netty.buffer.ByteBuf; 5 | 6 | public class C05PacketPlayerLook extends C03PacketPlayer { 7 | @Override 8 | public void parser(ByteBuf buf, PacketData packetData) { 9 | this.rotating = true; 10 | this.yaw = buf.readFloat(); 11 | this.pitch = buf.readFloat(); 12 | 13 | 14 | super.parser(buf, packetData); 15 | } 16 | 17 | @Override 18 | public String wrapToString() { 19 | return String.format("new C03PacketPlayer.C05PacketPlayerLook(%s,%s,%s)", yaw, pitch, onGround); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/wrappers/client/C06PacketPlayerPosLook.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet.wrappers.client; 2 | 3 | import com.cubk.nsc2.packet.PacketData; 4 | import io.netty.buffer.ByteBuf; 5 | 6 | 7 | public class C06PacketPlayerPosLook extends C03PacketPlayer { 8 | 9 | @Override 10 | public void parser(ByteBuf buf, PacketData packetData) { 11 | this.x = buf.readDouble(); 12 | this.y = buf.readDouble(); 13 | this.z = buf.readDouble(); 14 | this.yaw = buf.readFloat(); 15 | this.pitch = buf.readFloat(); 16 | super.parser(buf, packetData); 17 | } 18 | 19 | @Override 20 | public String wrapToString() { 21 | return String.format("new C03PacketPlayer.C06PacketPlayerPosLook(%s,%s,%s,%s,%s,%s)", x, y, z, yaw, pitch, onGround); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/wrappers/client/C07PacketPlayerDigging.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet.wrappers.client; 2 | 3 | import com.cubk.nsc2.packet.ClientPacketWrapper; 4 | import com.cubk.nsc2.packet.PacketData; 5 | import com.cubk.nsc2.struct.EnumFacing; 6 | import com.cubk.nsc2.struct.Position; 7 | import io.netty.buffer.ByteBuf; 8 | 9 | public class C07PacketPlayerDigging implements ClientPacketWrapper { 10 | public Position position; 11 | public EnumFacing facing; 12 | public Action status; 13 | 14 | @Override 15 | public void parser(ByteBuf buf, PacketData packetData) { 16 | this.status = readEnumValue(Action.class, buf); 17 | this.position = readPosition(buf); 18 | this.facing = EnumFacing.getFront(buf.readUnsignedByte()); 19 | packetData.getDataList().add(new PacketData.Data(Position.class, "position", position)); 20 | packetData.getDataList().add(new PacketData.Data(EnumFacing.class, "facing", facing)); 21 | packetData.getDataList().add(new PacketData.Data(Action.class, "action", status)); 22 | } 23 | 24 | @Override 25 | public String wrapToString() { 26 | return String.format("new C07PacketPlayerDigging(C07PacketPlayerDigging.Action.%s,new BlockPos(%s,%s,%s),EnumFacing.%s)", status.name(), position.getX(), position.getY(), position.getZ(), facing.name()); 27 | } 28 | 29 | @SuppressWarnings("unused") 30 | public enum Action { 31 | START_DESTROY_BLOCK, 32 | ABORT_DESTROY_BLOCK, 33 | STOP_DESTROY_BLOCK, 34 | DROP_ALL_ITEMS, 35 | DROP_ITEM, 36 | RELEASE_USE_ITEM, 37 | SWAP_HELD_ITEMS, 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/wrappers/client/C08PacketPlayerBlockPlacement.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet.wrappers.client; 2 | 3 | import com.cubk.nsc2.packet.ClientPacketWrapper; 4 | import com.cubk.nsc2.packet.PacketData; 5 | import com.cubk.nsc2.struct.ItemStack; 6 | import com.cubk.nsc2.struct.Position; 7 | import io.netty.buffer.ByteBuf; 8 | 9 | public class C08PacketPlayerBlockPlacement implements ClientPacketWrapper { 10 | 11 | public Position position; 12 | public int placedBlockDirection; 13 | public ItemStack stack; 14 | public float facingX; 15 | public float facingY; 16 | public float facingZ; 17 | 18 | @Override 19 | public void parser(ByteBuf buf, PacketData packetData) { 20 | this.position = readPosition(buf); 21 | this.placedBlockDirection = buf.readUnsignedByte(); 22 | this.stack = readItemStackFromBuffer(buf); 23 | this.facingX = (float) buf.readUnsignedByte() / getOffset(); 24 | this.facingY = (float) buf.readUnsignedByte() / getOffset(); 25 | this.facingZ = (float) buf.readUnsignedByte() / getOffset(); 26 | 27 | packetData.getDataList().add(new PacketData.Data(Position.class, "position", position)); 28 | packetData.getDataList().add(new PacketData.Data(Integer.class, "placedBlockDirection", placedBlockDirection)); 29 | packetData.getDataList().add(new PacketData.Data(ItemStack.class, "stack", stack)); 30 | packetData.getDataList().add(new PacketData.Data(Float.class, "facingX", facingX)); 31 | packetData.getDataList().add(new PacketData.Data(Float.class, "facingY", facingY)); 32 | packetData.getDataList().add(new PacketData.Data(Float.class, "facingZ", facingZ)); 33 | } 34 | 35 | private float getOffset() { 36 | return 16.0F; 37 | } 38 | 39 | @Override 40 | public String wrapToString() { 41 | return String.format("new C08PacketPlayerBlockPlacement(new BlockPos(%s,%s,%s),%s,%s,%s,%s,%s)", position.getX(), position.getY(), position.getZ(), placedBlockDirection, "item", facingX, facingY, facingZ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/wrappers/client/C09PacketHeldItemChange.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet.wrappers.client; 2 | 3 | import com.cubk.nsc2.packet.ClientPacketWrapper; 4 | import com.cubk.nsc2.packet.PacketData; 5 | import io.netty.buffer.ByteBuf; 6 | 7 | public class C09PacketHeldItemChange implements ClientPacketWrapper { 8 | public int slotId; 9 | 10 | @Override 11 | public void parser(ByteBuf buf, PacketData packetData) { 12 | this.slotId = buf.readShort(); 13 | packetData.getDataList().add(new PacketData.Data(Integer.class, "slot", slotId)); 14 | } 15 | 16 | @Override 17 | public String wrapToString() { 18 | return String.format("new C09PacketHeldItemChange(%s)", slotId); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/wrappers/client/C0APacketAnimation.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet.wrappers.client; 2 | 3 | import com.cubk.nsc2.packet.PacketData; 4 | import com.cubk.nsc2.packet.ClientPacketWrapper; 5 | import io.netty.buffer.ByteBuf; 6 | 7 | public class C0APacketAnimation implements ClientPacketWrapper { 8 | 9 | @Override 10 | public void parser(ByteBuf buf, PacketData packetData) { 11 | } 12 | 13 | @Override 14 | public String wrapToString() { 15 | return "new C0APacketAnimation()"; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/wrappers/client/C0BPacketEntityAction.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet.wrappers.client; 2 | 3 | import com.cubk.nsc2.packet.ClientPacketWrapper; 4 | import com.cubk.nsc2.packet.PacketData; 5 | import io.netty.buffer.ByteBuf; 6 | 7 | public class C0BPacketEntityAction implements ClientPacketWrapper { 8 | public int entityID; 9 | public Action action; 10 | public int auxData; 11 | 12 | @Override 13 | public void parser(ByteBuf buf, PacketData packetData) { 14 | this.entityID = readVarIntFromBuffer(buf); 15 | this.action = readEnumValue(Action.class, buf); 16 | this.auxData = readVarIntFromBuffer(buf); 17 | packetData.getDataList().add(new PacketData.Data(Integer.class, "entityID", entityID)); 18 | packetData.getDataList().add(new PacketData.Data(Action.class, "action", action)); 19 | packetData.getDataList().add(new PacketData.Data(Integer.class, "auxData", auxData)); 20 | } 21 | 22 | @Override 23 | public String wrapToString() { 24 | if (auxData == 0) { 25 | return String.format("new C0BPacketEntityAction(%s,C0BPacketEntityAction.Action.%s)", entityID, action.name()); 26 | } else { 27 | return String.format("new C0BPacketEntityAction(%s,C0BPacketEntityAction.Action.%s,%s)", entityID, action.name(), auxData); 28 | } 29 | } 30 | 31 | @SuppressWarnings("unused") 32 | public enum Action { 33 | START_SNEAKING, 34 | STOP_SNEAKING, 35 | STOP_SLEEPING, 36 | START_SPRINTING, 37 | STOP_SPRINTING, 38 | RIDING_JUMP, 39 | OPEN_INVENTORY; 40 | } 41 | } -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/wrappers/client/C0CPacketInput.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet.wrappers.client; 2 | 3 | import com.cubk.nsc2.packet.ClientPacketWrapper; 4 | import com.cubk.nsc2.packet.PacketData; 5 | import io.netty.buffer.ByteBuf; 6 | 7 | public class C0CPacketInput implements ClientPacketWrapper { 8 | public float strafeSpeed; 9 | 10 | /** 11 | * Positive for forward, negative for backward 12 | */ 13 | public float forwardSpeed; 14 | public boolean jumping; 15 | public boolean sneaking; 16 | 17 | @Override 18 | public void parser(ByteBuf buf, PacketData packetData) { 19 | this.strafeSpeed = buf.readFloat(); 20 | this.forwardSpeed = buf.readFloat(); 21 | byte b0 = buf.readByte(); 22 | this.jumping = (b0 & 1) > 0; 23 | this.sneaking = (b0 & 2) > 0; 24 | packetData.getDataList().add(new PacketData.Data(Float.class, "strafe", strafeSpeed)); 25 | packetData.getDataList().add(new PacketData.Data(Float.class, "forward", forwardSpeed)); 26 | packetData.getDataList().add(new PacketData.Data(Boolean.class, "jumping", jumping)); 27 | packetData.getDataList().add(new PacketData.Data(Boolean.class, "sneaking", sneaking)); 28 | } 29 | 30 | @Override 31 | public String wrapToString() { 32 | return String.format("new C0CPacketInput(%s,%s,%s,%s)", strafeSpeed, forwardSpeed, jumping, sneaking); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/wrappers/client/C0DPacketCloseWindow.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet.wrappers.client; 2 | 3 | import com.cubk.nsc2.packet.ClientPacketWrapper; 4 | import com.cubk.nsc2.packet.PacketData; 5 | import io.netty.buffer.ByteBuf; 6 | 7 | public class C0DPacketCloseWindow implements ClientPacketWrapper { 8 | 9 | public int windowId; 10 | 11 | @Override 12 | public void parser(ByteBuf buf, PacketData packetData) { 13 | this.windowId = buf.readByte(); 14 | packetData.getDataList().add(new PacketData.Data(Integer.class, "windowId", windowId)); 15 | } 16 | 17 | @Override 18 | public String wrapToString() { 19 | return String.format("new C0DPacketCloseWindow(%s)", windowId); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/wrappers/client/C0EPacketClickWindow.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet.wrappers.client; 2 | 3 | import com.cubk.nsc2.packet.ClientPacketWrapper; 4 | import com.cubk.nsc2.packet.PacketData; 5 | import com.cubk.nsc2.struct.ItemStack; 6 | import io.netty.buffer.ByteBuf; 7 | 8 | public class C0EPacketClickWindow implements ClientPacketWrapper { 9 | public int windowId; 10 | public int slotId; 11 | public int usedButton; 12 | public short actionNumber; 13 | public ItemStack clickedItem; 14 | public int mode; 15 | 16 | @Override 17 | public void parser(ByteBuf buf, PacketData packetData) { 18 | this.windowId = buf.readByte(); 19 | this.slotId = buf.readShort(); 20 | this.usedButton = buf.readByte(); 21 | this.actionNumber = buf.readShort(); 22 | this.mode = buf.readByte(); 23 | this.clickedItem = readItemStackFromBuffer(buf); 24 | 25 | packetData.getDataList().add(new PacketData.Data(Integer.class, "windowId", windowId)); 26 | packetData.getDataList().add(new PacketData.Data(Integer.class, "slotId", slotId)); 27 | packetData.getDataList().add(new PacketData.Data(Integer.class, "usedButton", usedButton)); 28 | packetData.getDataList().add(new PacketData.Data(Short.class, "actionNumber", actionNumber)); 29 | packetData.getDataList().add(new PacketData.Data(ItemStack.class, "clickedItem", clickedItem)); 30 | packetData.getDataList().add(new PacketData.Data(Integer.class, "mode", mode)); 31 | } 32 | 33 | @Override 34 | public String wrapToString() { 35 | return String.format("new C0EPacketClickWindow(%s,%s,%s,%s,%s,%s)", windowId, slotId, usedButton, mode, "item", actionNumber); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/wrappers/client/C0FPacketConfirmTransaction.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet.wrappers.client; 2 | 3 | import com.cubk.nsc2.packet.ClientPacketWrapper; 4 | import com.cubk.nsc2.packet.PacketData; 5 | import io.netty.buffer.ByteBuf; 6 | 7 | public class C0FPacketConfirmTransaction implements ClientPacketWrapper { 8 | public int windowId; 9 | public short uid; 10 | public boolean accepted; 11 | 12 | @Override 13 | public void parser(ByteBuf buf, PacketData packetData) { 14 | this.windowId = buf.readByte(); 15 | this.uid = buf.readShort(); 16 | this.accepted = buf.readByte() != 0; 17 | 18 | packetData.getDataList().add(new PacketData.Data(Integer.class, "windowId", windowId)); 19 | packetData.getDataList().add(new PacketData.Data(Short.class, "uid", uid)); 20 | packetData.getDataList().add(new PacketData.Data(Boolean.class, "accepted", accepted)); 21 | } 22 | 23 | @Override 24 | public String wrapToString() { 25 | return String.format("new C0FPacketConfirmTransaction(%s,%s,%s)", windowId, uid, accepted); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/wrappers/client/C10PacketCreativeInventoryAction.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet.wrappers.client; 2 | 3 | import com.cubk.nsc2.packet.ClientPacketWrapper; 4 | import com.cubk.nsc2.packet.PacketData; 5 | import com.cubk.nsc2.struct.ItemStack; 6 | import io.netty.buffer.ByteBuf; 7 | 8 | public class C10PacketCreativeInventoryAction implements ClientPacketWrapper { 9 | public int slotId; 10 | public ItemStack stack; 11 | 12 | @Override 13 | public void parser(ByteBuf buf, PacketData packetData) { 14 | this.slotId = buf.readShort(); 15 | this.stack = readItemStackFromBuffer(buf); 16 | packetData.getDataList().add(new PacketData.Data(Integer.class, "slotId", slotId)); 17 | packetData.getDataList().add(new PacketData.Data(ItemStack.class, "stack", stack)); 18 | } 19 | 20 | @Override 21 | public String wrapToString() { 22 | return String.format("new C10PacketCreativeInventoryAction(%s, %s)", slotId, stack != null ? stack.toString() : "null"); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/wrappers/client/C11PacketEnchantItem.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet.wrappers.client; 2 | 3 | import com.cubk.nsc2.packet.PacketData; 4 | import com.cubk.nsc2.packet.ClientPacketWrapper; 5 | import io.netty.buffer.ByteBuf; 6 | 7 | public class C11PacketEnchantItem implements ClientPacketWrapper { 8 | public int windowId; 9 | public int button; 10 | 11 | @Override 12 | public void parser(ByteBuf buf, PacketData packetData) { 13 | this.windowId = buf.readByte(); 14 | this.button = buf.readByte(); 15 | packetData.getDataList().add(new PacketData.Data(Integer.class, "windowId", windowId)); 16 | packetData.getDataList().add(new PacketData.Data(Integer.class, "button", button)); 17 | } 18 | 19 | @Override 20 | public String wrapToString() { 21 | return String.format("new C11PacketEnchantItem(%s, %s)", windowId, button); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/wrappers/client/C13PacketPlayerAbilities.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet.wrappers.client; 2 | 3 | import com.cubk.nsc2.packet.PacketData; 4 | import com.cubk.nsc2.packet.ClientPacketWrapper; 5 | import io.netty.buffer.ByteBuf; 6 | 7 | public class C13PacketPlayerAbilities implements ClientPacketWrapper { 8 | public boolean invulnerable; 9 | public boolean flying; 10 | public boolean allowFlying; 11 | public boolean creativeMode; 12 | public float flySpeed; 13 | public float walkSpeed; 14 | 15 | @Override 16 | public void parser(ByteBuf buf, PacketData packetData) { 17 | byte b0 = buf.readByte(); 18 | this.invulnerable = (b0 & 1) > 0; 19 | this.flying = (b0 & 2) > 0; 20 | this.allowFlying = (b0 & 4) > 0; 21 | this.creativeMode = (b0 & 8) > 0; 22 | this.flySpeed = buf.readFloat(); 23 | this.walkSpeed = buf.readFloat(); 24 | 25 | packetData.getDataList().add(new PacketData.Data(Boolean.class, "invulnerable", invulnerable)); 26 | packetData.getDataList().add(new PacketData.Data(Boolean.class, "flying", flying)); 27 | packetData.getDataList().add(new PacketData.Data(Boolean.class, "allowFlying", allowFlying)); 28 | packetData.getDataList().add(new PacketData.Data(Boolean.class, "creativeMode", creativeMode)); 29 | packetData.getDataList().add(new PacketData.Data(Float.class, "flySpeed", flySpeed)); 30 | packetData.getDataList().add(new PacketData.Data(Float.class, "walkSpeed", walkSpeed)); 31 | } 32 | 33 | @Override 34 | public String wrapToString() { 35 | return "Wrap你妈大逼自己看不懂是不是"; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/wrappers/client/C14PacketTabComplete.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet.wrappers.client; 2 | 3 | import com.cubk.nsc2.packet.ClientPacketWrapper; 4 | import com.cubk.nsc2.packet.PacketData; 5 | import com.cubk.nsc2.struct.Position; 6 | import io.netty.buffer.ByteBuf; 7 | 8 | public class C14PacketTabComplete implements ClientPacketWrapper { 9 | public String message; 10 | public Position targetBlock; 11 | 12 | @Override 13 | public void parser(ByteBuf buf, PacketData packetData) { 14 | this.message = readStringFromBuffer(buf, 32767); 15 | boolean flag = buf.readBoolean(); 16 | 17 | if (flag) { 18 | this.targetBlock = readPosition(buf); 19 | packetData.getDataList().add(new PacketData.Data(Position.class, "targetBlock", targetBlock)); 20 | } 21 | 22 | packetData.getDataList().add(new PacketData.Data(String.class, "message", message)); 23 | packetData.getDataList().add(new PacketData.Data(Boolean.class, "hasTargetBlock", flag)); 24 | } 25 | 26 | @Override 27 | public String wrapToString() { 28 | return "Wrap你妈大逼自己看不懂是不是"; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/wrappers/client/C17PacketCustomPayload.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet.wrappers.client; 2 | 3 | import com.cubk.nsc2.packet.ClientPacketWrapper; 4 | import com.cubk.nsc2.packet.PacketData; 5 | import io.netty.buffer.ByteBuf; 6 | 7 | public class C17PacketCustomPayload implements ClientPacketWrapper { 8 | public String channel; 9 | public ByteBuf data; 10 | 11 | @Override 12 | public void parser(ByteBuf buf, PacketData packetData) { 13 | this.channel = readStringFromBuffer(buf, 20); 14 | int length = buf.readableBytes(); 15 | 16 | if (length >= 0 && length <= 32767) { 17 | this.data = buf.readBytes(length).readSlice(length); // Retain the slice to prevent early release 18 | packetData.getDataList().add(new PacketData.Data(String.class, "channel", channel)); 19 | packetData.getDataList().add(new PacketData.Data(ByteBuf.class, "data", data)); 20 | } 21 | } 22 | 23 | @Override 24 | public String wrapToString() { 25 | return String.format("new C17PacketCustomPayload(\"%s\", %s)", channel, data); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/packet/wrappers/server/S12PacketEntityVelocity.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.packet.wrappers.server; 2 | 3 | import com.cubk.nsc2.packet.PacketData; 4 | import com.cubk.nsc2.packet.ServerPacketWrapper; 5 | import io.netty.buffer.ByteBuf; 6 | 7 | public class S12PacketEntityVelocity implements ServerPacketWrapper { 8 | public int entityID; 9 | public int motionX; 10 | public int motionY; 11 | public int motionZ; 12 | 13 | @Override 14 | public void parser(ByteBuf buf, PacketData packetData) { 15 | this.entityID = readVarIntFromBuffer(buf); 16 | this.motionX = buf.readShort(); 17 | this.motionY = buf.readShort(); 18 | this.motionZ = buf.readShort(); 19 | 20 | packetData.getDataList().add(new PacketData.Data(Integer.class, "entityId", entityID)); 21 | packetData.getDataList().add(new PacketData.Data(Integer.class, "motionX", motionX)); 22 | packetData.getDataList().add(new PacketData.Data(Integer.class, "motionY", motionY)); 23 | packetData.getDataList().add(new PacketData.Data(Integer.class, "motionZ", motionZ)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/plugin/Parser.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.plugin; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.JsonParseException; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.io.InputStreamReader; 10 | import java.util.Enumeration; 11 | import java.util.zip.ZipEntry; 12 | import java.util.zip.ZipFile; 13 | 14 | public class Parser { 15 | 16 | private PluginData data = null; 17 | 18 | public Parser(File file) { 19 | try { 20 | ZipFile zipFile = new ZipFile(file); 21 | 22 | Enumeration entries = zipFile.entries(); 23 | 24 | PluginData pluginJson = null; 25 | 26 | while (entries.hasMoreElements() && pluginJson == null) { 27 | ZipEntry entry = entries.nextElement(); 28 | 29 | if (!entry.isDirectory() && entry.getName().equals("plugin.json")) { 30 | InputStream stream = zipFile.getInputStream(entry); 31 | try { 32 | pluginJson = new Gson().fromJson(new InputStreamReader(stream), PluginData.class); 33 | } catch (JsonParseException jsonParseException) { 34 | throw new RuntimeException("Failed to parse JSON:", jsonParseException); 35 | } 36 | } 37 | } 38 | 39 | if (pluginJson == null) { 40 | zipFile.close(); 41 | throw new RuntimeException("Failed to find plugin.json in the root of the jar."); 42 | } 43 | 44 | zipFile.close(); 45 | this.data = pluginJson; 46 | } catch (IOException e) { 47 | throw new RuntimeException("Failed to open the jar as a zip:", e); 48 | } 49 | } 50 | 51 | public PluginData getObject() { 52 | return data; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/plugin/PluginAPI.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.plugin; 2 | 3 | 4 | import java.io.File; 5 | import java.util.Objects; 6 | import java.util.function.Consumer; 7 | 8 | public class PluginAPI { 9 | 10 | private static PluginLoader loader; 11 | private String outName; 12 | 13 | private PluginAPI(PluginLoader loader) { 14 | PluginAPI.loader = loader; 15 | } 16 | 17 | public static PluginAPI getApi(Consumer consumer, String outName) { 18 | consumer.accept(loader = new PluginLoader()); 19 | PluginAPI api = new PluginAPI(loader); 20 | api.outName = outName; 21 | return api; 22 | } 23 | 24 | public PluginLoader getLoader() { 25 | return loader; 26 | } 27 | 28 | public void loadAll(File folder) { 29 | try { 30 | if (!folder.exists()) 31 | folder.mkdir(); 32 | 33 | for (File fileIndex : Objects.requireNonNull(folder.listFiles())) { 34 | if (fileIndex.getName().endsWith(".jar")) { 35 | loader.load(fileIndex); 36 | System.out.println(outName + " " + "Loaded: " + fileIndex.getName()); 37 | } 38 | } 39 | } catch (NullPointerException e) { // 通常是没有这个文件夹 40 | 41 | } catch (Exception e) { 42 | e.printStackTrace(); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/plugin/PluginData.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.plugin; 2 | 3 | 4 | import lombok.Getter; 5 | 6 | @Getter 7 | public class PluginData { 8 | 9 | private final String main; 10 | private final String name; 11 | private final String version; 12 | 13 | public PluginData(String main, String name, String version) { 14 | this.main = main; 15 | this.name = name; 16 | this.version = version; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/plugin/PluginLoader.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.plugin; 2 | 3 | import com.cubk.nsc2.JavaPlugin; 4 | 5 | import java.io.File; 6 | import java.lang.reflect.Constructor; 7 | import java.lang.reflect.InvocationTargetException; 8 | import java.net.MalformedURLException; 9 | import java.net.URL; 10 | import java.net.URLClassLoader; 11 | import java.util.HashMap; 12 | 13 | public class PluginLoader { 14 | private final HashMap map = new HashMap<>(); 15 | 16 | public JavaPlugin load(File file) { 17 | if (!(file.getName().endsWith(".jar"))) throw new RuntimeException("File have to be a Jar! " + file.getName()); 18 | try { 19 | if (map.containsKey(file)) { 20 | throw new RuntimeException(file.getName() + " " + "Plugin already loaded."); 21 | } 22 | PluginData dataFile = new Parser(file).getObject(); 23 | ClassLoader loader = URLClassLoader.newInstance(new URL[]{file.toURI().toURL()}, getClass().getClassLoader()); 24 | Class clazz = Class.forName(dataFile.getMain(), true, loader); 25 | Class instanceClass = clazz.asSubclass(JavaPlugin.class); 26 | Constructor instanceClassConstructor = instanceClass.getConstructor(); 27 | JavaPlugin addon = instanceClassConstructor.newInstance(); 28 | addon.setDescriptionFile(dataFile); 29 | map.put(file, addon); 30 | addon.onLoad(); 31 | return addon; 32 | } catch (MalformedURLException e) { 33 | throw new RuntimeException("Failed to convert the file path to a URL.", e); 34 | } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | 35 | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { 36 | throw new RuntimeException("Failed to create a new instance of the addon.", e); 37 | } 38 | } 39 | 40 | 41 | public JavaPlugin unload(File file) { 42 | if (!(file.getName().endsWith(".jar"))) throw new RuntimeException("File have to be a Jar! " + file.getName()); 43 | if (!map.containsKey(file)) { 44 | throw new RuntimeException("Can't unload a addon that wasn't loaded in the first place."); 45 | } 46 | JavaPlugin addon = map.get(file); 47 | addon.onUnload(); 48 | map.remove(file); 49 | return addon; 50 | } 51 | 52 | public void reload(File file) { 53 | unload(file); 54 | load(file); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/struct/Constant.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.struct; 2 | 3 | import io.netty.util.AttributeKey; 4 | 5 | import java.lang.reflect.Constructor; 6 | import java.lang.reflect.Method; 7 | 8 | @SuppressWarnings("all") 9 | public class Constant { 10 | public static Method method_getNetHandler; 11 | public static Method method_getNetworkManager; 12 | public static Object object_theMinecraft; 13 | public static String name_writeData; 14 | public static Method method_getPacketId; 15 | public static AttributeKey object_attribute_key; 16 | public static Class class_EnumConnectionState; 17 | public static Constructor class_PacketBuffer; 18 | public static Class class_EnumPacketDirection; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/struct/EnumFacing.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.struct; 2 | 3 | import com.cubk.nsc2.util.MathHelper; 4 | 5 | public enum EnumFacing { 6 | DOWN, 7 | UP, 8 | NORTH, 9 | SOUTH, 10 | WEST, 11 | EAST; 12 | 13 | public static EnumFacing getFront(int index) { 14 | return values()[MathHelper.abs_int(index % values().length)]; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/struct/ItemStack.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.struct; 2 | 3 | public class ItemStack { 4 | 5 | public int id, amount, meta; 6 | 7 | public ItemStack(int itemIn, int amount, int meta) { 8 | this.id = itemIn; 9 | this.amount = amount; 10 | this.meta = meta; 11 | } 12 | 13 | @Override 14 | public String toString() { 15 | return "ItemStack{" + 16 | "id=" + id + 17 | ", amount=" + amount + 18 | ", meta=" + meta + 19 | '}'; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/struct/Position.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.struct; 2 | 3 | import com.cubk.nsc2.util.MathHelper; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | public class Position { 8 | private static final int NUM_X_BITS = 1 + MathHelper.calculateLogBaseTwo(MathHelper.roundUpToPowerOfTwo(30000000)); 9 | private static final int NUM_Z_BITS = NUM_X_BITS; 10 | private static final int NUM_Y_BITS = 64 - NUM_X_BITS - NUM_Z_BITS; 11 | private static final int Y_SHIFT = 0 + NUM_Z_BITS; 12 | private static final int X_SHIFT = Y_SHIFT + NUM_Y_BITS; 13 | 14 | private double x, y, z; 15 | 16 | public Position(double x, double y, double z) { 17 | this.x = x; 18 | this.y = y; 19 | this.z = z; 20 | } 21 | 22 | public void add(double x, double y, double z) { 23 | this.x += x; 24 | this.y += y; 25 | this.z += z; 26 | } 27 | 28 | public void add(Position position) { 29 | this.x += position.getX(); 30 | this.y += position.getY(); 31 | this.z += position.getZ(); 32 | } 33 | 34 | public static Position fromLong(long serialized) { 35 | int i = (int) (serialized << 64 - X_SHIFT - NUM_X_BITS >> 64 - NUM_X_BITS); 36 | int j = (int) (serialized << 64 - Y_SHIFT - NUM_Y_BITS >> 64 - NUM_Y_BITS); 37 | int k = (int) (serialized << 64 - NUM_Z_BITS >> 64 - NUM_Z_BITS); 38 | return new Position(i, j, k); 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return "Position{" + 44 | "x=" + x + 45 | ", y=" + y + 46 | ", z=" + z + 47 | '}'; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/struct/Vector3.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.struct; 2 | 3 | 4 | import lombok.Data; 5 | 6 | @Data 7 | public final class Vector3 { 8 | private float x; 9 | private float y; 10 | private float z; 11 | 12 | public Vector3(float f, float g, float h) { 13 | this.x = f; 14 | this.y = g; 15 | this.z = h; 16 | } 17 | 18 | public void add(float f, float g, float h) { 19 | this.x += f; 20 | this.y += g; 21 | this.z += h; 22 | } 23 | 24 | public void add(Vector3 vector3) { 25 | this.x += vector3.x; 26 | this.y += vector3.y; 27 | this.z += vector3.z; 28 | } 29 | } -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/struct/nbt/NBTBase.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.struct.nbt; 2 | 3 | import java.io.DataInput; 4 | import java.io.DataOutput; 5 | import java.io.IOException; 6 | 7 | public abstract class NBTBase { 8 | public static final String[] NBT_TYPES = new String[]{"END", "BYTE", "SHORT", "INT", "LONG", "FLOAT", "DOUBLE", "BYTE[]", "STRING", "LIST", "COMPOUND", "INT[]"}; 9 | 10 | /** 11 | * Write the actual data contents of the tag, implemented in NBT extension classes 12 | */ 13 | abstract void write(DataOutput output) throws IOException; 14 | 15 | public abstract void read(DataInput input, int depth, NBTSizeTracker sizeTracker) throws IOException; 16 | 17 | public abstract String toString(); 18 | 19 | /** 20 | * Gets the type byte for the tag. 21 | */ 22 | public abstract byte getId(); 23 | 24 | /** 25 | * Creates a new NBTBase object that corresponds with the passed in id. 26 | */ 27 | public static NBTBase createNewByType(byte id) { 28 | switch (id) { 29 | case 0: 30 | return new NBTTagEnd(); 31 | 32 | case 1: 33 | return new NBTTagByte(); 34 | 35 | case 2: 36 | return new NBTTagShort(); 37 | 38 | case 3: 39 | return new NBTTagInt(); 40 | 41 | case 4: 42 | return new NBTTagLong(); 43 | 44 | case 5: 45 | return new NBTTagFloat(); 46 | 47 | case 6: 48 | return new NBTTagDouble(); 49 | 50 | case 7: 51 | return new NBTTagByteArray(); 52 | 53 | case 8: 54 | return new NBTTagString(); 55 | 56 | case 9: 57 | return new NBTTagList(); 58 | 59 | case 10: 60 | return new NBTTagCompound(); 61 | 62 | case 11: 63 | return new NBTTagIntArray(); 64 | 65 | default: 66 | return null; 67 | } 68 | } 69 | 70 | /** 71 | * Creates a clone of the tag. 72 | */ 73 | public abstract NBTBase copy(); 74 | 75 | /** 76 | * Return whether this compound has no tags. 77 | */ 78 | public boolean hasNoTags() { 79 | return false; 80 | } 81 | 82 | public boolean equals(Object p_equals_1_) { 83 | if (!(p_equals_1_ instanceof NBTBase)) { 84 | return false; 85 | } else { 86 | NBTBase nbtbase = (NBTBase) p_equals_1_; 87 | return this.getId() == nbtbase.getId(); 88 | } 89 | } 90 | 91 | public int hashCode() { 92 | return this.getId(); 93 | } 94 | 95 | protected String getString() { 96 | return this.toString(); 97 | } 98 | 99 | public abstract static class NBTPrimitive extends NBTBase { 100 | public abstract long getLong(); 101 | 102 | public abstract int getInt(); 103 | 104 | public abstract short getShort(); 105 | 106 | public abstract byte getByte(); 107 | 108 | public abstract double getDouble(); 109 | 110 | public abstract float getFloat(); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/struct/nbt/NBTException.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.struct.nbt; 2 | 3 | public class NBTException extends Exception { 4 | public NBTException(String p_i45136_1_) { 5 | super(p_i45136_1_); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/struct/nbt/NBTSizeTracker.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.struct.nbt; 2 | 3 | public class NBTSizeTracker { 4 | public static final NBTSizeTracker INFINITE = new NBTSizeTracker(0L) { 5 | public void read(long bits) { 6 | } 7 | }; 8 | private final long max; 9 | private long read; 10 | 11 | public NBTSizeTracker(long max) { 12 | this.max = max; 13 | } 14 | 15 | /** 16 | * Tracks the reading of the given amount of bits(!) 17 | */ 18 | public void read(long bits) { 19 | this.read += bits / 8L; 20 | 21 | if (this.read > this.max) { 22 | throw new RuntimeException("Tried to read NBT tag that was too big; tried to allocate: " + this.read + "bytes where max allowed: " + this.max); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/struct/nbt/NBTTagByte.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.struct.nbt; 2 | 3 | import java.io.DataInput; 4 | import java.io.DataOutput; 5 | import java.io.IOException; 6 | 7 | public class NBTTagByte extends NBTBase.NBTPrimitive { 8 | /** 9 | * The byte value for the tag. 10 | */ 11 | private byte data; 12 | 13 | NBTTagByte() { 14 | } 15 | 16 | public NBTTagByte(byte data) { 17 | this.data = data; 18 | } 19 | 20 | /** 21 | * Write the actual data contents of the tag, implemented in NBT extension classes 22 | */ 23 | void write(DataOutput output) throws IOException { 24 | output.writeByte(this.data); 25 | } 26 | 27 | public void read(DataInput input, int depth, NBTSizeTracker sizeTracker) throws IOException { 28 | sizeTracker.read(72L); 29 | this.data = input.readByte(); 30 | } 31 | 32 | /** 33 | * Gets the type byte for the tag. 34 | */ 35 | public byte getId() { 36 | return (byte) 1; 37 | } 38 | 39 | public String toString() { 40 | return "" + this.data + "b"; 41 | } 42 | 43 | /** 44 | * Creates a clone of the tag. 45 | */ 46 | public NBTBase copy() { 47 | return new NBTTagByte(this.data); 48 | } 49 | 50 | public boolean equals(Object p_equals_1_) { 51 | if (super.equals(p_equals_1_)) { 52 | NBTTagByte nbttagbyte = (NBTTagByte) p_equals_1_; 53 | return this.data == nbttagbyte.data; 54 | } else { 55 | return false; 56 | } 57 | } 58 | 59 | public int hashCode() { 60 | return super.hashCode() ^ this.data; 61 | } 62 | 63 | public long getLong() { 64 | return (long) this.data; 65 | } 66 | 67 | public int getInt() { 68 | return this.data; 69 | } 70 | 71 | public short getShort() { 72 | return (short) this.data; 73 | } 74 | 75 | public byte getByte() { 76 | return this.data; 77 | } 78 | 79 | public double getDouble() { 80 | return (double) this.data; 81 | } 82 | 83 | public float getFloat() { 84 | return (float) this.data; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/struct/nbt/NBTTagByteArray.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.struct.nbt; 2 | 3 | import java.io.DataInput; 4 | import java.io.DataOutput; 5 | import java.io.IOException; 6 | import java.util.Arrays; 7 | 8 | public class NBTTagByteArray extends NBTBase { 9 | /** 10 | * The byte array stored in the tag. 11 | */ 12 | private byte[] data; 13 | 14 | NBTTagByteArray() { 15 | } 16 | 17 | public NBTTagByteArray(byte[] data) { 18 | this.data = data; 19 | } 20 | 21 | /** 22 | * Write the actual data contents of the tag, implemented in NBT extension classes 23 | */ 24 | void write(DataOutput output) throws IOException { 25 | output.writeInt(this.data.length); 26 | output.write(this.data); 27 | } 28 | 29 | public void read(DataInput input, int depth, NBTSizeTracker sizeTracker) throws IOException { 30 | sizeTracker.read(192L); 31 | int i = input.readInt(); 32 | sizeTracker.read((long) (8 * i)); 33 | this.data = new byte[i]; 34 | input.readFully(this.data); 35 | } 36 | 37 | /** 38 | * Gets the type byte for the tag. 39 | */ 40 | public byte getId() { 41 | return (byte) 7; 42 | } 43 | 44 | public String toString() { 45 | return "[" + this.data.length + " bytes]"; 46 | } 47 | 48 | /** 49 | * Creates a clone of the tag. 50 | */ 51 | public NBTBase copy() { 52 | byte[] abyte = new byte[this.data.length]; 53 | System.arraycopy(this.data, 0, abyte, 0, this.data.length); 54 | return new NBTTagByteArray(abyte); 55 | } 56 | 57 | public boolean equals(Object p_equals_1_) { 58 | return super.equals(p_equals_1_) ? Arrays.equals(this.data, ((NBTTagByteArray) p_equals_1_).data) : false; 59 | } 60 | 61 | public int hashCode() { 62 | return super.hashCode() ^ Arrays.hashCode(this.data); 63 | } 64 | 65 | public byte[] getByteArray() { 66 | return this.data; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/struct/nbt/NBTTagCompound.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.struct.nbt; 2 | 3 | import java.io.DataInput; 4 | import java.io.DataOutput; 5 | import java.io.IOException; 6 | import java.util.Map; 7 | import java.util.Map.Entry; 8 | import java.util.Set; 9 | import java.util.concurrent.ConcurrentHashMap; 10 | 11 | public class NBTTagCompound extends NBTBase { 12 | private Map tagMap = new ConcurrentHashMap<>(); 13 | 14 | private static void writeEntry(String name, NBTBase data, DataOutput output) throws IOException { 15 | output.writeByte(data.getId()); 16 | 17 | if (data.getId() != 0) { 18 | output.writeUTF(name); 19 | data.write(output); 20 | } 21 | } 22 | 23 | private static byte readType(DataInput input, NBTSizeTracker sizeTracker) throws IOException { 24 | return input.readByte(); 25 | } 26 | 27 | private static String readKey(DataInput input, NBTSizeTracker sizeTracker) throws IOException { 28 | return input.readUTF(); 29 | } 30 | 31 | static NBTBase readNBT(byte id, String key, DataInput input, int depth, NBTSizeTracker sizeTracker) throws IOException { 32 | NBTBase nbtbase = createNewByType(id); 33 | 34 | try { 35 | nbtbase.read(input, depth, sizeTracker); 36 | return nbtbase; 37 | } catch (IOException ioexception) { 38 | return new NBTBase() { 39 | @Override 40 | void write(DataOutput output) throws IOException { 41 | 42 | } 43 | 44 | @Override 45 | public void read(DataInput input, int depth, NBTSizeTracker sizeTracker) throws IOException { 46 | 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return null; 52 | } 53 | 54 | @Override 55 | public byte getId() { 56 | return 0; 57 | } 58 | 59 | @Override 60 | public NBTBase copy() { 61 | return null; 62 | } 63 | }; 64 | } 65 | } 66 | 67 | /** 68 | * Write the actual data contents of the tag, implemented in NBT extension classes 69 | */ 70 | void write(DataOutput output) throws IOException { 71 | for (String s : this.tagMap.keySet()) { 72 | NBTBase nbtbase = (NBTBase) this.tagMap.get(s); 73 | writeEntry(s, nbtbase, output); 74 | } 75 | 76 | output.writeByte(0); 77 | } 78 | 79 | public void read(DataInput input, int depth, NBTSizeTracker sizeTracker) throws IOException { 80 | sizeTracker.read(384L); 81 | 82 | if (depth > 512) { 83 | throw new RuntimeException("Tried to read NBT tag with too high complexity, depth > 512"); 84 | } else { 85 | this.tagMap.clear(); 86 | byte b0; 87 | 88 | while ((b0 = readType(input, sizeTracker)) != 0) { 89 | String s = readKey(input, sizeTracker); 90 | sizeTracker.read((long) (224 + 16 * s.length())); 91 | NBTBase nbtbase = readNBT(b0, s, input, depth + 1, sizeTracker); 92 | 93 | if (this.tagMap.put(s, nbtbase) != null) { 94 | sizeTracker.read(288L); 95 | } 96 | } 97 | } 98 | } 99 | 100 | public Set getKeySet() { 101 | return this.tagMap.keySet(); 102 | } 103 | 104 | /** 105 | * Gets the type byte for the tag. 106 | */ 107 | public byte getId() { 108 | return (byte) 10; 109 | } 110 | 111 | /** 112 | * Stores the given tag into the map with the given string key. This is mostly used to store tag lists. 113 | */ 114 | public void setTag(String key, NBTBase value) { 115 | this.tagMap.put(key, value); 116 | } 117 | 118 | /** 119 | * Stores a new NBTTagByte with the given byte value into the map with the given string key. 120 | */ 121 | public void setByte(String key, byte value) { 122 | this.tagMap.put(key, new NBTTagByte(value)); 123 | } 124 | 125 | /** 126 | * Stores a new NBTTagShort with the given short value into the map with the given string key. 127 | */ 128 | public void setShort(String key, short value) { 129 | this.tagMap.put(key, new NBTTagShort(value)); 130 | } 131 | 132 | /** 133 | * Stores a new NBTTagInt with the given integer value into the map with the given string key. 134 | */ 135 | public void setInteger(String key, int value) { 136 | this.tagMap.put(key, new NBTTagInt(value)); 137 | } 138 | 139 | /** 140 | * Stores a new NBTTagLong with the given long value into the map with the given string key. 141 | */ 142 | public void setLong(String key, long value) { 143 | this.tagMap.put(key, new NBTTagLong(value)); 144 | } 145 | 146 | /** 147 | * Stores a new NBTTagFloat with the given float value into the map with the given string key. 148 | */ 149 | public void setFloat(String key, float value) { 150 | this.tagMap.put(key, new NBTTagFloat(value)); 151 | } 152 | 153 | /** 154 | * Stores a new NBTTagDouble with the given double value into the map with the given string key. 155 | */ 156 | public void setDouble(String key, double value) { 157 | this.tagMap.put(key, new NBTTagDouble(value)); 158 | } 159 | 160 | /** 161 | * Stores a new NBTTagString with the given string value into the map with the given string key. 162 | */ 163 | public void setString(String key, String value) { 164 | this.tagMap.put(key, new NBTTagString(value)); 165 | } 166 | 167 | /** 168 | * Stores a new NBTTagByteArray with the given array as data into the map with the given string key. 169 | */ 170 | public void setByteArray(String key, byte[] value) { 171 | this.tagMap.put(key, new NBTTagByteArray(value)); 172 | } 173 | 174 | /** 175 | * Stores a new NBTTagIntArray with the given array as data into the map with the given string key. 176 | */ 177 | public void setIntArray(String key, int[] value) { 178 | this.tagMap.put(key, new NBTTagIntArray(value)); 179 | } 180 | 181 | /** 182 | * Stores the given boolean value as a NBTTagByte, storing 1 for true and 0 for false, using the given string key. 183 | */ 184 | public void setBoolean(String key, boolean value) { 185 | this.setByte(key, (byte) (value ? 1 : 0)); 186 | } 187 | 188 | /** 189 | * gets a generic tag with the specified name 190 | */ 191 | public NBTBase getTag(String key) { 192 | return (NBTBase) this.tagMap.get(key); 193 | } 194 | 195 | /** 196 | * Gets the ID byte for the given tag key 197 | */ 198 | public byte getTagId(String key) { 199 | NBTBase nbtbase = (NBTBase) this.tagMap.get(key); 200 | return nbtbase != null ? nbtbase.getId() : 0; 201 | } 202 | 203 | /** 204 | * Returns whether the given string has been previously stored as a key in the map. 205 | */ 206 | public boolean hasKey(String key) { 207 | return this.tagMap.containsKey(key); 208 | } 209 | 210 | public boolean hasKey(String key, int type) { 211 | int i = this.getTagId(key); 212 | 213 | if (i == type) { 214 | return true; 215 | } else if (type != 99) { 216 | if (i > 0) { 217 | ; 218 | } 219 | 220 | return false; 221 | } else { 222 | return i == 1 || i == 2 || i == 3 || i == 4 || i == 5 || i == 6; 223 | } 224 | } 225 | 226 | /** 227 | * Retrieves a byte value using the specified key, or 0 if no such key was stored. 228 | */ 229 | public byte getByte(String key) { 230 | try { 231 | return !this.hasKey(key, 99) ? 0 : ((NBTPrimitive) this.tagMap.get(key)).getByte(); 232 | } catch (ClassCastException var3) { 233 | return (byte) 0; 234 | } 235 | } 236 | 237 | /** 238 | * Retrieves a short value using the specified key, or 0 if no such key was stored. 239 | */ 240 | public short getShort(String key) { 241 | try { 242 | return !this.hasKey(key, 99) ? 0 : ((NBTPrimitive) this.tagMap.get(key)).getShort(); 243 | } catch (ClassCastException var3) { 244 | return (short) 0; 245 | } 246 | } 247 | 248 | /** 249 | * Retrieves an integer value using the specified key, or 0 if no such key was stored. 250 | */ 251 | public int getInteger(String key) { 252 | try { 253 | return !this.hasKey(key, 99) ? 0 : ((NBTPrimitive) this.tagMap.get(key)).getInt(); 254 | } catch (ClassCastException var3) { 255 | return 0; 256 | } 257 | } 258 | 259 | /** 260 | * Retrieves a long value using the specified key, or 0 if no such key was stored. 261 | */ 262 | public long getLong(String key) { 263 | try { 264 | return !this.hasKey(key, 99) ? 0L : ((NBTPrimitive) this.tagMap.get(key)).getLong(); 265 | } catch (ClassCastException var3) { 266 | return 0L; 267 | } 268 | } 269 | 270 | /** 271 | * Retrieves a float value using the specified key, or 0 if no such key was stored. 272 | */ 273 | public float getFloat(String key) { 274 | try { 275 | return !this.hasKey(key, 99) ? 0.0F : ((NBTPrimitive) this.tagMap.get(key)).getFloat(); 276 | } catch (ClassCastException var3) { 277 | return 0.0F; 278 | } 279 | } 280 | 281 | /** 282 | * Retrieves a double value using the specified key, or 0 if no such key was stored. 283 | */ 284 | public double getDouble(String key) { 285 | try { 286 | return !this.hasKey(key, 99) ? 0.0D : ((NBTPrimitive) this.tagMap.get(key)).getDouble(); 287 | } catch (ClassCastException var3) { 288 | return 0.0D; 289 | } 290 | } 291 | 292 | /** 293 | * Retrieves a string value using the specified key, or an empty string if no such key was stored. 294 | */ 295 | public String getString(String key) { 296 | try { 297 | return !this.hasKey(key, 8) ? "" : ((NBTBase) this.tagMap.get(key)).getString(); 298 | } catch (ClassCastException var3) { 299 | return ""; 300 | } 301 | } 302 | 303 | /** 304 | * Retrieves a byte array using the specified key, or a zero-length array if no such key was stored. 305 | */ 306 | public byte[] getByteArray(String key) { 307 | try { 308 | return !this.hasKey(key, 7) ? new byte[0] : ((NBTTagByteArray) this.tagMap.get(key)).getByteArray(); 309 | } catch (ClassCastException classcastexception) { 310 | throw new NullPointerException(this.createCrashReport(key, 7, classcastexception)); 311 | } 312 | } 313 | 314 | /** 315 | * Retrieves an int array using the specified key, or a zero-length array if no such key was stored. 316 | */ 317 | public int[] getIntArray(String key) { 318 | try { 319 | return !this.hasKey(key, 11) ? new int[0] : ((NBTTagIntArray) this.tagMap.get(key)).getIntArray(); 320 | } catch (ClassCastException classcastexception) { 321 | throw new NullPointerException(this.createCrashReport(key, 11, classcastexception)); 322 | } 323 | } 324 | 325 | /** 326 | * Retrieves a NBTTagCompound subtag matching the specified key, or a new empty NBTTagCompound if no such key was 327 | * stored. 328 | */ 329 | public NBTTagCompound getCompoundTag(String key) { 330 | try { 331 | return !this.hasKey(key, 10) ? new NBTTagCompound() : (NBTTagCompound) this.tagMap.get(key); 332 | } catch (ClassCastException classcastexception) { 333 | throw new NullPointerException(this.createCrashReport(key, 10, classcastexception)); 334 | } 335 | } 336 | 337 | /** 338 | * Gets the NBTTagList object with the given name. Args: name, NBTBase type 339 | */ 340 | public NBTTagList getTagList(String key, int type) { 341 | try { 342 | if (this.getTagId(key) != 9) { 343 | return new NBTTagList(); 344 | } else { 345 | NBTTagList nbttaglist = (NBTTagList) this.tagMap.get(key); 346 | return nbttaglist.tagCount() > 0 && nbttaglist.getTagType() != type ? new NBTTagList() : nbttaglist; 347 | } 348 | } catch (ClassCastException classcastexception) { 349 | throw new NullPointerException(this.createCrashReport(key, 9, classcastexception)); 350 | } 351 | } 352 | 353 | /** 354 | * Retrieves a boolean value using the specified key, or false if no such key was stored. This uses the getByte 355 | * method. 356 | */ 357 | public boolean getBoolean(String key) { 358 | return this.getByte(key) != 0; 359 | } 360 | 361 | /** 362 | * Remove the specified tag. 363 | */ 364 | public void removeTag(String key) { 365 | this.tagMap.remove(key); 366 | } 367 | 368 | public String toString() { 369 | StringBuilder stringbuilder = new StringBuilder("{"); 370 | 371 | for (Entry entry : this.tagMap.entrySet()) { 372 | if (stringbuilder.length() != 1) { 373 | stringbuilder.append(','); 374 | } 375 | 376 | stringbuilder.append((String) entry.getKey()).append(':').append(entry.getValue()); 377 | } 378 | 379 | return stringbuilder.append('}').toString(); 380 | } 381 | 382 | /** 383 | * Return whether this compound has no tags. 384 | */ 385 | public boolean hasNoTags() { 386 | return this.tagMap.isEmpty(); 387 | } 388 | 389 | /** 390 | * Create a crash report which indicates a NBT read error. 391 | */ 392 | private String createCrashReport(final String key, final int expectedType, ClassCastException ex) { 393 | return key; 394 | } 395 | 396 | /** 397 | * Creates a clone of the tag. 398 | */ 399 | public NBTBase copy() { 400 | NBTTagCompound nbttagcompound = new NBTTagCompound(); 401 | 402 | for (String s : this.tagMap.keySet()) { 403 | nbttagcompound.setTag(s, ((NBTBase) this.tagMap.get(s)).copy()); 404 | } 405 | 406 | return nbttagcompound; 407 | } 408 | 409 | public boolean equals(Object p_equals_1_) { 410 | if (super.equals(p_equals_1_)) { 411 | NBTTagCompound nbttagcompound = (NBTTagCompound) p_equals_1_; 412 | return this.tagMap.entrySet().equals(nbttagcompound.tagMap.entrySet()); 413 | } else { 414 | return false; 415 | } 416 | } 417 | 418 | public int hashCode() { 419 | return super.hashCode() ^ this.tagMap.hashCode(); 420 | } 421 | 422 | /** 423 | * Merges this NBTTagCompound with the given compound. Any sub-compounds are merged using the same methods, other 424 | * types of tags are overwritten from the given compound. 425 | */ 426 | public void merge(NBTTagCompound other) { 427 | for (String s : other.tagMap.keySet()) { 428 | NBTBase nbtbase = (NBTBase) other.tagMap.get(s); 429 | 430 | if (nbtbase.getId() == 10) { 431 | if (this.hasKey(s, 10)) { 432 | NBTTagCompound nbttagcompound = this.getCompoundTag(s); 433 | nbttagcompound.merge((NBTTagCompound) nbtbase); 434 | } else { 435 | this.setTag(s, nbtbase.copy()); 436 | } 437 | } else { 438 | this.setTag(s, nbtbase.copy()); 439 | } 440 | } 441 | } 442 | } 443 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/struct/nbt/NBTTagDouble.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.struct.nbt; 2 | 3 | import com.cubk.nsc2.util.MathHelper; 4 | 5 | import java.io.DataInput; 6 | import java.io.DataOutput; 7 | import java.io.IOException; 8 | 9 | public class NBTTagDouble extends NBTBase.NBTPrimitive { 10 | /** 11 | * The double value for the tag. 12 | */ 13 | private double data; 14 | 15 | NBTTagDouble() { 16 | } 17 | 18 | public NBTTagDouble(double data) { 19 | this.data = data; 20 | } 21 | 22 | /** 23 | * Write the actual data contents of the tag, implemented in NBT extension classes 24 | */ 25 | void write(DataOutput output) throws IOException { 26 | output.writeDouble(this.data); 27 | } 28 | 29 | public void read(DataInput input, int depth, NBTSizeTracker sizeTracker) throws IOException { 30 | sizeTracker.read(128L); 31 | this.data = input.readDouble(); 32 | } 33 | 34 | /** 35 | * Gets the type byte for the tag. 36 | */ 37 | public byte getId() { 38 | return (byte) 6; 39 | } 40 | 41 | public String toString() { 42 | return "" + this.data + "d"; 43 | } 44 | 45 | /** 46 | * Creates a clone of the tag. 47 | */ 48 | public NBTBase copy() { 49 | return new NBTTagDouble(this.data); 50 | } 51 | 52 | public boolean equals(Object p_equals_1_) { 53 | if (super.equals(p_equals_1_)) { 54 | NBTTagDouble nbttagdouble = (NBTTagDouble) p_equals_1_; 55 | return this.data == nbttagdouble.data; 56 | } else { 57 | return false; 58 | } 59 | } 60 | 61 | public int hashCode() { 62 | long i = Double.doubleToLongBits(this.data); 63 | return super.hashCode() ^ (int) (i ^ i >>> 32); 64 | } 65 | 66 | public long getLong() { 67 | return (long) Math.floor(this.data); 68 | } 69 | 70 | public int getInt() { 71 | return MathHelper.floor_double(this.data); 72 | } 73 | 74 | public short getShort() { 75 | return (short) (MathHelper.floor_double(this.data) & 65535); 76 | } 77 | 78 | public byte getByte() { 79 | return (byte) (MathHelper.floor_double(this.data) & 255); 80 | } 81 | 82 | public double getDouble() { 83 | return this.data; 84 | } 85 | 86 | public float getFloat() { 87 | return (float) this.data; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/struct/nbt/NBTTagEnd.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.struct.nbt; 2 | 3 | import java.io.DataInput; 4 | import java.io.DataOutput; 5 | import java.io.IOException; 6 | 7 | public class NBTTagEnd extends NBTBase { 8 | public void read(DataInput input, int depth, NBTSizeTracker sizeTracker) throws IOException { 9 | sizeTracker.read(64L); 10 | } 11 | 12 | /** 13 | * Write the actual data contents of the tag, implemented in NBT extension classes 14 | */ 15 | void write(DataOutput output) throws IOException { 16 | } 17 | 18 | /** 19 | * Gets the type byte for the tag. 20 | */ 21 | public byte getId() { 22 | return (byte) 0; 23 | } 24 | 25 | public String toString() { 26 | return "END"; 27 | } 28 | 29 | /** 30 | * Creates a clone of the tag. 31 | */ 32 | public NBTBase copy() { 33 | return new NBTTagEnd(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/struct/nbt/NBTTagFloat.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.struct.nbt; 2 | 3 | 4 | import com.cubk.nsc2.util.MathHelper; 5 | 6 | import java.io.DataInput; 7 | import java.io.DataOutput; 8 | import java.io.IOException; 9 | 10 | public class NBTTagFloat extends NBTBase.NBTPrimitive { 11 | /** 12 | * The float value for the tag. 13 | */ 14 | private float data; 15 | 16 | NBTTagFloat() { 17 | } 18 | 19 | public NBTTagFloat(float data) { 20 | this.data = data; 21 | } 22 | 23 | /** 24 | * Write the actual data contents of the tag, implemented in NBT extension classes 25 | */ 26 | void write(DataOutput output) throws IOException { 27 | output.writeFloat(this.data); 28 | } 29 | 30 | public void read(DataInput input, int depth, NBTSizeTracker sizeTracker) throws IOException { 31 | sizeTracker.read(96L); 32 | this.data = input.readFloat(); 33 | } 34 | 35 | /** 36 | * Gets the type byte for the tag. 37 | */ 38 | public byte getId() { 39 | return (byte) 5; 40 | } 41 | 42 | public String toString() { 43 | return "" + this.data + "f"; 44 | } 45 | 46 | /** 47 | * Creates a clone of the tag. 48 | */ 49 | public NBTBase copy() { 50 | return new NBTTagFloat(this.data); 51 | } 52 | 53 | public boolean equals(Object p_equals_1_) { 54 | if (super.equals(p_equals_1_)) { 55 | NBTTagFloat nbttagfloat = (NBTTagFloat) p_equals_1_; 56 | return this.data == nbttagfloat.data; 57 | } else { 58 | return false; 59 | } 60 | } 61 | 62 | public int hashCode() { 63 | return super.hashCode() ^ Float.floatToIntBits(this.data); 64 | } 65 | 66 | public long getLong() { 67 | return (long) this.data; 68 | } 69 | 70 | public int getInt() { 71 | return MathHelper.floor_float(this.data); 72 | } 73 | 74 | public short getShort() { 75 | return (short) (MathHelper.floor_float(this.data) & 65535); 76 | } 77 | 78 | public byte getByte() { 79 | return (byte) (MathHelper.floor_float(this.data) & 255); 80 | } 81 | 82 | public double getDouble() { 83 | return (double) this.data; 84 | } 85 | 86 | public float getFloat() { 87 | return this.data; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/struct/nbt/NBTTagInt.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.struct.nbt; 2 | 3 | import java.io.DataInput; 4 | import java.io.DataOutput; 5 | import java.io.IOException; 6 | 7 | public class NBTTagInt extends NBTBase.NBTPrimitive { 8 | /** 9 | * The integer value for the tag. 10 | */ 11 | private int data; 12 | 13 | NBTTagInt() { 14 | } 15 | 16 | public NBTTagInt(int data) { 17 | this.data = data; 18 | } 19 | 20 | /** 21 | * Write the actual data contents of the tag, implemented in NBT extension classes 22 | */ 23 | void write(DataOutput output) throws IOException { 24 | output.writeInt(this.data); 25 | } 26 | 27 | public void read(DataInput input, int depth, NBTSizeTracker sizeTracker) throws IOException { 28 | sizeTracker.read(96L); 29 | this.data = input.readInt(); 30 | } 31 | 32 | /** 33 | * Gets the type byte for the tag. 34 | */ 35 | public byte getId() { 36 | return (byte) 3; 37 | } 38 | 39 | public String toString() { 40 | return "" + this.data; 41 | } 42 | 43 | /** 44 | * Creates a clone of the tag. 45 | */ 46 | public NBTBase copy() { 47 | return new NBTTagInt(this.data); 48 | } 49 | 50 | public boolean equals(Object p_equals_1_) { 51 | if (super.equals(p_equals_1_)) { 52 | NBTTagInt nbttagint = (NBTTagInt) p_equals_1_; 53 | return this.data == nbttagint.data; 54 | } else { 55 | return false; 56 | } 57 | } 58 | 59 | public int hashCode() { 60 | return super.hashCode() ^ this.data; 61 | } 62 | 63 | public long getLong() { 64 | return (long) this.data; 65 | } 66 | 67 | public int getInt() { 68 | return this.data; 69 | } 70 | 71 | public short getShort() { 72 | return (short) (this.data & 65535); 73 | } 74 | 75 | public byte getByte() { 76 | return (byte) (this.data & 255); 77 | } 78 | 79 | public double getDouble() { 80 | return (double) this.data; 81 | } 82 | 83 | public float getFloat() { 84 | return (float) this.data; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/struct/nbt/NBTTagIntArray.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.struct.nbt; 2 | 3 | import java.io.DataInput; 4 | import java.io.DataOutput; 5 | import java.io.IOException; 6 | import java.util.Arrays; 7 | 8 | public class NBTTagIntArray extends NBTBase { 9 | /** 10 | * The array of saved integers 11 | */ 12 | private int[] intArray; 13 | 14 | NBTTagIntArray() { 15 | } 16 | 17 | public NBTTagIntArray(int[] p_i45132_1_) { 18 | this.intArray = p_i45132_1_; 19 | } 20 | 21 | /** 22 | * Write the actual data contents of the tag, implemented in NBT extension classes 23 | */ 24 | void write(DataOutput output) throws IOException { 25 | output.writeInt(this.intArray.length); 26 | 27 | for (int i = 0; i < this.intArray.length; ++i) { 28 | output.writeInt(this.intArray[i]); 29 | } 30 | } 31 | 32 | public void read(DataInput input, int depth, NBTSizeTracker sizeTracker) throws IOException { 33 | sizeTracker.read(192L); 34 | int i = input.readInt(); 35 | sizeTracker.read((long) (32 * i)); 36 | this.intArray = new int[i]; 37 | 38 | for (int j = 0; j < i; ++j) { 39 | this.intArray[j] = input.readInt(); 40 | } 41 | } 42 | 43 | /** 44 | * Gets the type byte for the tag. 45 | */ 46 | public byte getId() { 47 | return (byte) 11; 48 | } 49 | 50 | public String toString() { 51 | String s = "["; 52 | 53 | for (int i : this.intArray) { 54 | s = s + i + ","; 55 | } 56 | 57 | return s + "]"; 58 | } 59 | 60 | /** 61 | * Creates a clone of the tag. 62 | */ 63 | public NBTBase copy() { 64 | int[] aint = new int[this.intArray.length]; 65 | System.arraycopy(this.intArray, 0, aint, 0, this.intArray.length); 66 | return new NBTTagIntArray(aint); 67 | } 68 | 69 | public boolean equals(Object p_equals_1_) { 70 | return super.equals(p_equals_1_) ? Arrays.equals(this.intArray, ((NBTTagIntArray) p_equals_1_).intArray) : false; 71 | } 72 | 73 | public int hashCode() { 74 | return super.hashCode() ^ Arrays.hashCode(this.intArray); 75 | } 76 | 77 | public int[] getIntArray() { 78 | return this.intArray; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/struct/nbt/NBTTagList.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.struct.nbt; 2 | 3 | import java.io.DataInput; 4 | import java.io.DataOutput; 5 | import java.io.IOException; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public class NBTTagList extends NBTBase { 10 | private List tagList = new ArrayList<>(); 11 | 12 | /** 13 | * The type byte for the tags in the list - they must all be of the same type. 14 | */ 15 | private byte tagType = 0; 16 | 17 | /** 18 | * Write the actual data contents of the tag, implemented in NBT extension classes 19 | */ 20 | void write(DataOutput output) throws IOException { 21 | if (!this.tagList.isEmpty()) { 22 | this.tagType = ((NBTBase) this.tagList.get(0)).getId(); 23 | } else { 24 | this.tagType = 0; 25 | } 26 | 27 | output.writeByte(this.tagType); 28 | output.writeInt(this.tagList.size()); 29 | 30 | for (int i = 0; i < this.tagList.size(); ++i) { 31 | ((NBTBase) this.tagList.get(i)).write(output); 32 | } 33 | } 34 | 35 | public void read(DataInput input, int depth, NBTSizeTracker sizeTracker) throws IOException { 36 | sizeTracker.read(296L); 37 | 38 | if (depth > 512) { 39 | throw new RuntimeException("Tried to read NBT tag with too high complexity, depth > 512"); 40 | } else { 41 | this.tagType = input.readByte(); 42 | int i = input.readInt(); 43 | 44 | if (this.tagType == 0 && i > 0) { 45 | throw new RuntimeException("Missing type on ListTag"); 46 | } else { 47 | sizeTracker.read(32L * (long) i); 48 | this.tagList = newArrayListWithCapacity(i); 49 | 50 | for (int j = 0; j < i; ++j) { 51 | NBTBase nbtbase = NBTBase.createNewByType(this.tagType); 52 | nbtbase.read(input, depth + 1, sizeTracker); 53 | this.tagList.add(nbtbase); 54 | } 55 | } 56 | } 57 | } 58 | 59 | public static ArrayList newArrayListWithCapacity(int initialArraySize) { 60 | return new ArrayList(initialArraySize); 61 | } 62 | 63 | 64 | /** 65 | * Gets the type byte for the tag. 66 | */ 67 | public byte getId() { 68 | return (byte) 9; 69 | } 70 | 71 | public String toString() { 72 | StringBuilder stringbuilder = new StringBuilder("["); 73 | 74 | for (int i = 0; i < this.tagList.size(); ++i) { 75 | if (i != 0) { 76 | stringbuilder.append(','); 77 | } 78 | 79 | stringbuilder.append(i).append(':').append(this.tagList.get(i)); 80 | } 81 | 82 | return stringbuilder.append(']').toString(); 83 | } 84 | 85 | /** 86 | * Adds the provided tag to the end of the list. There is no check to verify this tag is of the same type as any 87 | * previous tag. 88 | */ 89 | public void appendTag(NBTBase nbt) { 90 | if (nbt.getId() == 0) { 91 | } else { 92 | if (this.tagType == 0) { 93 | this.tagType = nbt.getId(); 94 | } else if (this.tagType != nbt.getId()) { 95 | return; 96 | } 97 | 98 | this.tagList.add(nbt); 99 | } 100 | } 101 | 102 | /** 103 | * Set the given index to the given tag 104 | */ 105 | public void set(int idx, NBTBase nbt) { 106 | if (nbt.getId() == 0) { 107 | } else if (idx >= 0 && idx < this.tagList.size()) { 108 | if (this.tagType == 0) { 109 | this.tagType = nbt.getId(); 110 | } else if (this.tagType != nbt.getId()) { 111 | return; 112 | } 113 | 114 | this.tagList.set(idx, nbt); 115 | } else { 116 | } 117 | } 118 | 119 | /** 120 | * Removes a tag at the given index. 121 | */ 122 | public NBTBase removeTag(int i) { 123 | return (NBTBase) this.tagList.remove(i); 124 | } 125 | 126 | /** 127 | * Return whether this compound has no tags. 128 | */ 129 | public boolean hasNoTags() { 130 | return this.tagList.isEmpty(); 131 | } 132 | 133 | /** 134 | * Retrieves the NBTTagCompound at the specified index in the list 135 | */ 136 | public NBTTagCompound getCompoundTagAt(int i) { 137 | if (i >= 0 && i < this.tagList.size()) { 138 | NBTBase nbtbase = (NBTBase) this.tagList.get(i); 139 | return nbtbase.getId() == 10 ? (NBTTagCompound) nbtbase : new NBTTagCompound(); 140 | } else { 141 | return new NBTTagCompound(); 142 | } 143 | } 144 | 145 | public int[] getIntArrayAt(int i) { 146 | if (i >= 0 && i < this.tagList.size()) { 147 | NBTBase nbtbase = (NBTBase) this.tagList.get(i); 148 | return nbtbase.getId() == 11 ? ((NBTTagIntArray) nbtbase).getIntArray() : new int[0]; 149 | } else { 150 | return new int[0]; 151 | } 152 | } 153 | 154 | public double getDoubleAt(int i) { 155 | if (i >= 0 && i < this.tagList.size()) { 156 | NBTBase nbtbase = (NBTBase) this.tagList.get(i); 157 | return nbtbase.getId() == 6 ? ((NBTTagDouble) nbtbase).getDouble() : 0.0D; 158 | } else { 159 | return 0.0D; 160 | } 161 | } 162 | 163 | public float getFloatAt(int i) { 164 | if (i >= 0 && i < this.tagList.size()) { 165 | NBTBase nbtbase = (NBTBase) this.tagList.get(i); 166 | return nbtbase.getId() == 5 ? ((NBTTagFloat) nbtbase).getFloat() : 0.0F; 167 | } else { 168 | return 0.0F; 169 | } 170 | } 171 | 172 | /** 173 | * Retrieves the tag String value at the specified index in the list 174 | */ 175 | public String getStringTagAt(int i) { 176 | if (i >= 0 && i < this.tagList.size()) { 177 | NBTBase nbtbase = (NBTBase) this.tagList.get(i); 178 | return nbtbase.getId() == 8 ? nbtbase.getString() : nbtbase.toString(); 179 | } else { 180 | return ""; 181 | } 182 | } 183 | 184 | /** 185 | * Get the tag at the given position 186 | */ 187 | public NBTBase get(int idx) { 188 | return (NBTBase) (idx >= 0 && idx < this.tagList.size() ? (NBTBase) this.tagList.get(idx) : new NBTTagEnd()); 189 | } 190 | 191 | /** 192 | * Returns the number of tags in the list. 193 | */ 194 | public int tagCount() { 195 | return this.tagList.size(); 196 | } 197 | 198 | /** 199 | * Creates a clone of the tag. 200 | */ 201 | public NBTBase copy() { 202 | NBTTagList nbttaglist = new NBTTagList(); 203 | nbttaglist.tagType = this.tagType; 204 | 205 | for (NBTBase nbtbase : this.tagList) { 206 | NBTBase nbtbase1 = nbtbase.copy(); 207 | nbttaglist.tagList.add(nbtbase1); 208 | } 209 | 210 | return nbttaglist; 211 | } 212 | 213 | public boolean equals(Object p_equals_1_) { 214 | if (super.equals(p_equals_1_)) { 215 | NBTTagList nbttaglist = (NBTTagList) p_equals_1_; 216 | 217 | if (this.tagType == nbttaglist.tagType) { 218 | return this.tagList.equals(nbttaglist.tagList); 219 | } 220 | } 221 | 222 | return false; 223 | } 224 | 225 | public int hashCode() { 226 | return super.hashCode() ^ this.tagList.hashCode(); 227 | } 228 | 229 | public int getTagType() { 230 | return this.tagType; 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/struct/nbt/NBTTagLong.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.struct.nbt; 2 | 3 | import java.io.DataInput; 4 | import java.io.DataOutput; 5 | import java.io.IOException; 6 | 7 | public class NBTTagLong extends NBTBase.NBTPrimitive { 8 | /** 9 | * The long value for the tag. 10 | */ 11 | private long data; 12 | 13 | NBTTagLong() { 14 | } 15 | 16 | public NBTTagLong(long data) { 17 | this.data = data; 18 | } 19 | 20 | /** 21 | * Write the actual data contents of the tag, implemented in NBT extension classes 22 | */ 23 | void write(DataOutput output) throws IOException { 24 | output.writeLong(this.data); 25 | } 26 | 27 | public void read(DataInput input, int depth, NBTSizeTracker sizeTracker) throws IOException { 28 | sizeTracker.read(128L); 29 | this.data = input.readLong(); 30 | } 31 | 32 | /** 33 | * Gets the type byte for the tag. 34 | */ 35 | public byte getId() { 36 | return (byte) 4; 37 | } 38 | 39 | public String toString() { 40 | return "" + this.data + "L"; 41 | } 42 | 43 | /** 44 | * Creates a clone of the tag. 45 | */ 46 | public NBTBase copy() { 47 | return new NBTTagLong(this.data); 48 | } 49 | 50 | public boolean equals(Object p_equals_1_) { 51 | if (super.equals(p_equals_1_)) { 52 | NBTTagLong nbttaglong = (NBTTagLong) p_equals_1_; 53 | return this.data == nbttaglong.data; 54 | } else { 55 | return false; 56 | } 57 | } 58 | 59 | public int hashCode() { 60 | return super.hashCode() ^ (int) (this.data ^ this.data >>> 32); 61 | } 62 | 63 | public long getLong() { 64 | return this.data; 65 | } 66 | 67 | public int getInt() { 68 | return (int) (this.data & -1L); 69 | } 70 | 71 | public short getShort() { 72 | return (short) ((int) (this.data & 65535L)); 73 | } 74 | 75 | public byte getByte() { 76 | return (byte) ((int) (this.data & 255L)); 77 | } 78 | 79 | public double getDouble() { 80 | return (double) this.data; 81 | } 82 | 83 | public float getFloat() { 84 | return (float) this.data; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/struct/nbt/NBTTagShort.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.struct.nbt; 2 | 3 | import java.io.DataInput; 4 | import java.io.DataOutput; 5 | import java.io.IOException; 6 | 7 | public class NBTTagShort extends NBTBase.NBTPrimitive { 8 | /** 9 | * The short value for the tag. 10 | */ 11 | private short data; 12 | 13 | public NBTTagShort() { 14 | } 15 | 16 | public NBTTagShort(short data) { 17 | this.data = data; 18 | } 19 | 20 | /** 21 | * Write the actual data contents of the tag, implemented in NBT extension classes 22 | */ 23 | void write(DataOutput output) throws IOException { 24 | output.writeShort(this.data); 25 | } 26 | 27 | public void read(DataInput input, int depth, NBTSizeTracker sizeTracker) throws IOException { 28 | sizeTracker.read(80L); 29 | this.data = input.readShort(); 30 | } 31 | 32 | /** 33 | * Gets the type byte for the tag. 34 | */ 35 | public byte getId() { 36 | return (byte) 2; 37 | } 38 | 39 | public String toString() { 40 | return "" + this.data + "s"; 41 | } 42 | 43 | /** 44 | * Creates a clone of the tag. 45 | */ 46 | public NBTBase copy() { 47 | return new NBTTagShort(this.data); 48 | } 49 | 50 | public boolean equals(Object p_equals_1_) { 51 | if (super.equals(p_equals_1_)) { 52 | NBTTagShort nbttagshort = (NBTTagShort) p_equals_1_; 53 | return this.data == nbttagshort.data; 54 | } else { 55 | return false; 56 | } 57 | } 58 | 59 | public int hashCode() { 60 | return super.hashCode() ^ this.data; 61 | } 62 | 63 | public long getLong() { 64 | return (long) this.data; 65 | } 66 | 67 | public int getInt() { 68 | return this.data; 69 | } 70 | 71 | public short getShort() { 72 | return this.data; 73 | } 74 | 75 | public byte getByte() { 76 | return (byte) (this.data & 255); 77 | } 78 | 79 | public double getDouble() { 80 | return (double) this.data; 81 | } 82 | 83 | public float getFloat() { 84 | return (float) this.data; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/struct/nbt/NBTTagString.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.struct.nbt; 2 | 3 | import java.io.DataInput; 4 | import java.io.DataOutput; 5 | import java.io.IOException; 6 | 7 | public class NBTTagString extends NBTBase { 8 | /** 9 | * The string value for the tag (cannot be empty). 10 | */ 11 | private String data; 12 | 13 | public NBTTagString() { 14 | this.data = ""; 15 | } 16 | 17 | public NBTTagString(String data) { 18 | this.data = data; 19 | 20 | if (data == null) { 21 | throw new IllegalArgumentException("Empty string not allowed"); 22 | } 23 | } 24 | 25 | /** 26 | * Write the actual data contents of the tag, implemented in NBT extension classes 27 | */ 28 | void write(DataOutput output) throws IOException { 29 | output.writeUTF(this.data); 30 | } 31 | 32 | public void read(DataInput input, int depth, NBTSizeTracker sizeTracker) throws IOException { 33 | sizeTracker.read(288L); 34 | this.data = input.readUTF(); 35 | sizeTracker.read((long) (16 * this.data.length())); 36 | } 37 | 38 | /** 39 | * Gets the type byte for the tag. 40 | */ 41 | public byte getId() { 42 | return (byte) 8; 43 | } 44 | 45 | public String toString() { 46 | return "\"" + this.data.replace("\"", "\\\"") + "\""; 47 | } 48 | 49 | /** 50 | * Creates a clone of the tag. 51 | */ 52 | public NBTBase copy() { 53 | return new NBTTagString(this.data); 54 | } 55 | 56 | /** 57 | * Return whether this compound has no tags. 58 | */ 59 | public boolean hasNoTags() { 60 | return this.data.isEmpty(); 61 | } 62 | 63 | public boolean equals(Object p_equals_1_) { 64 | if (!super.equals(p_equals_1_)) { 65 | return false; 66 | } else { 67 | NBTTagString nbttagstring = (NBTTagString) p_equals_1_; 68 | return this.data == null && nbttagstring.data == null || this.data != null && this.data.equals(nbttagstring.data); 69 | } 70 | } 71 | 72 | public int hashCode() { 73 | return super.hashCode() ^ this.data.hashCode(); 74 | } 75 | 76 | public String getString() { 77 | return this.data; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/transformer/Transformer.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.transformer; 2 | 3 | import org.objectweb.asm.Opcodes; 4 | import org.objectweb.asm.tree.ClassNode; 5 | 6 | public interface Transformer extends Opcodes { 7 | void handle(ClassNode classNode); 8 | 9 | String getTarget(); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/transformer/TransformerManager.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.transformer; 2 | 3 | import com.cubk.nsc2.Agent; 4 | import com.cubk.nsc2.transformer.transformers.BootstrapTransformer; 5 | import org.objectweb.asm.ClassReader; 6 | import org.objectweb.asm.ClassWriter; 7 | import org.objectweb.asm.tree.ClassNode; 8 | 9 | import java.io.File; 10 | import java.io.FileOutputStream; 11 | import java.lang.instrument.ClassFileTransformer; 12 | import java.lang.instrument.IllegalClassFormatException; 13 | import java.security.ProtectionDomain; 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | public class TransformerManager implements ClassFileTransformer { 18 | 19 | private final List transformers = new ArrayList<>(); 20 | 21 | public TransformerManager() { 22 | transformers.add(new BootstrapTransformer()); 23 | 24 | //retransformClasses(); 25 | } 26 | 27 | public void retransformClasses() { 28 | for (Transformer transformer : transformers) { 29 | try { 30 | Class target = Class.forName(transformer.getTarget().replace("/", ".")); 31 | System.out.println("[NSC] Transforming: " + target.getName()); 32 | Agent.instrumentation.retransformClasses(target); 33 | } catch (Exception e) { 34 | e.printStackTrace(); 35 | } 36 | } 37 | } 38 | 39 | @Override 40 | public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { 41 | for (Transformer transformer : transformers) { 42 | if (transformer.getTarget().equals(className)) { 43 | 44 | byte[] data = classfileBuffer; 45 | try { 46 | ClassNode classNode = new ClassNode(); 47 | ClassReader reader = new ClassReader(classfileBuffer); 48 | reader.accept(classNode, 0); 49 | 50 | transformer.handle(classNode); 51 | 52 | ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS); 53 | classNode.accept(classWriter); 54 | 55 | data = classWriter.toByteArray(); 56 | 57 | transformers.remove(transformer); 58 | File file = new File("NSC_" + classNode.name.replace("/", ".") + ".class"); 59 | FileOutputStream fos = new FileOutputStream(file); 60 | fos.write(data); 61 | fos.close(); 62 | } catch (Exception e) { 63 | e.printStackTrace(); 64 | } 65 | return data; 66 | } 67 | } 68 | return classfileBuffer; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/transformer/transformers/BootstrapTransformer.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.transformer.transformers; 2 | 3 | import com.cubk.nsc2.gui.AddressSwapperFrame; 4 | import com.cubk.nsc2.transformer.Transformer; 5 | import io.netty.bootstrap.AbstractBootstrap; 6 | import io.netty.bootstrap.Bootstrap; 7 | import io.netty.channel.ChannelFuture; 8 | import org.objectweb.asm.tree.*; 9 | 10 | import java.lang.reflect.Method; 11 | import java.net.InetSocketAddress; 12 | import java.net.SocketAddress; 13 | 14 | public class BootstrapTransformer implements Transformer { 15 | 16 | public static ChannelFuture connectHook(Bootstrap bootstrap, SocketAddress remoteAddress) { 17 | if (remoteAddress instanceof InetSocketAddress) { 18 | InetSocketAddress address = (InetSocketAddress) remoteAddress; 19 | 20 | if (AddressSwapperFrame.getUse().isSelected()) { 21 | if (address.getHostName().startsWith(AddressSwapperFrame.getOriginalHostField().getText())) { 22 | remoteAddress = new InetSocketAddress(AddressSwapperFrame.getTargetServerField().getText(), Integer.parseInt(AddressSwapperFrame.getTargetPortField().getText())); 23 | } 24 | } 25 | 26 | try { 27 | Method localAddressMethod = AbstractBootstrap.class.getDeclaredMethod("localAddress"); 28 | localAddressMethod.setAccessible(true); 29 | SocketAddress localAddress = (SocketAddress) localAddressMethod.invoke(bootstrap); 30 | 31 | Method doConnectMethod = Bootstrap.class.getDeclaredMethod("doConnect", SocketAddress.class, SocketAddress.class); 32 | doConnectMethod.setAccessible(true); 33 | return (ChannelFuture) doConnectMethod.invoke(bootstrap, remoteAddress, localAddress); 34 | } catch (Exception e) { 35 | e.printStackTrace(); 36 | return null; 37 | } 38 | } 39 | return null; 40 | } 41 | 42 | @Override 43 | public void handle(ClassNode classNode) { 44 | for (MethodNode methodNode : classNode.methods) { 45 | if (methodNode.name.equals("connect") && methodNode.desc.equals("(Ljava/net/SocketAddress;)Lio/netty/channel/ChannelFuture;")) { 46 | InsnList instructions = methodNode.instructions; 47 | 48 | instructions.clear(); 49 | 50 | instructions.add(new VarInsnNode(ALOAD, 0)); 51 | instructions.add(new VarInsnNode(ALOAD, 1)); 52 | instructions.add(new MethodInsnNode(INVOKESTATIC, BootstrapTransformer.class.getName().replace(".", "/"), "connectHook", "(Lio/netty/bootstrap/Bootstrap;Ljava/net/SocketAddress;)Lio/netty/channel/ChannelFuture;", false)); 53 | instructions.add(new InsnNode(ARETURN)); 54 | 55 | methodNode.instructions = instructions; 56 | } 57 | } 58 | } 59 | 60 | @Override 61 | public String getTarget() { 62 | return "io/netty/bootstrap/Bootstrap"; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/util/MathHelper.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.util; 2 | 3 | import java.util.Random; 4 | import java.util.UUID; 5 | 6 | public class MathHelper { 7 | public static final float SQRT_2 = sqrt_float(2.0F); 8 | private static final int SIN_BITS = 12; 9 | private static final int SIN_MASK = 4095; 10 | private static final int SIN_COUNT = 4096; 11 | private static final int SIN_COUNT_D4 = 1024; 12 | public static final float PI = MathUtil.roundToFloat(Math.PI); 13 | public static final float PI2 = MathUtil.roundToFloat((Math.PI * 2D)); 14 | public static final float PId2 = MathUtil.roundToFloat((Math.PI / 2D)); 15 | private static final float radToIndex = MathUtil.roundToFloat(651.8986469044033D); 16 | public static final float deg2Rad = MathUtil.roundToFloat(0.017453292519943295D); 17 | private static final float[] SIN_TABLE_FAST = new float[4096]; 18 | public static boolean fastMath = false; 19 | 20 | /** 21 | * A table of sin values computed from 0 (inclusive) to 2*pi (exclusive), with steps of 2*PI / 65536. 22 | */ 23 | private static final float[] SIN_TABLE = new float[65536]; 24 | 25 | /** 26 | * Though it looks like an array, this is really more like a mapping. Key (index of this array) is the upper 5 bits 27 | * of the result of multiplying a 32-bit unsigned integer by the B(2, 5) De Bruijn sequence 0x077CB531. Value 28 | * (value stored in the array) is the unique index (from the right) of the leftmost one-bit in a 32-bit unsigned 29 | * integer that can cause the upper 5 bits to get that value. Used for highly optimized "find the log-base-2 of 30 | * this number" calculations. 31 | */ 32 | private static final int[] multiplyDeBruijnBitPosition; 33 | private static final double field_181163_d; 34 | private static final double[] field_181164_e; 35 | private static final double[] field_181165_f; 36 | 37 | static { 38 | for (int i = 0; i < 65536; ++i) { 39 | SIN_TABLE[i] = (float) Math.sin((double) i * Math.PI * 2.0D / 65536.0D); 40 | } 41 | 42 | for (int j = 0; j < SIN_TABLE_FAST.length; ++j) { 43 | SIN_TABLE_FAST[j] = MathUtil.roundToFloat(Math.sin((double) j * Math.PI * 2.0D / 4096.0D)); 44 | } 45 | 46 | multiplyDeBruijnBitPosition = new int[]{0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9}; 47 | field_181163_d = Double.longBitsToDouble(4805340802404319232L); 48 | field_181164_e = new double[257]; 49 | field_181165_f = new double[257]; 50 | 51 | for (int k = 0; k < 257; ++k) { 52 | double d0 = (double) k / 256.0D; 53 | double d1 = Math.asin(d0); 54 | field_181165_f[k] = Math.cos(d1); 55 | field_181164_e[k] = d1; 56 | } 57 | } 58 | 59 | /** 60 | * sin looked up in a table 61 | */ 62 | public static float sin(float p_76126_0_) { 63 | return fastMath ? SIN_TABLE_FAST[(int) (p_76126_0_ * radToIndex) & 4095] : SIN_TABLE[(int) (p_76126_0_ * 10430.378F) & 65535]; 64 | } 65 | 66 | /** 67 | * cos looked up in the sin table with the appropriate offset 68 | */ 69 | public static float cos(float value) { 70 | return fastMath ? SIN_TABLE_FAST[(int) (value * radToIndex + 1024.0F) & 4095] : SIN_TABLE[(int) (value * 10430.378F + 16384.0F) & 65535]; 71 | } 72 | 73 | public static float sqrt_float(float value) { 74 | return (float) Math.sqrt((double) value); 75 | } 76 | 77 | public static float sqrt_double(double value) { 78 | return (float) Math.sqrt(value); 79 | } 80 | 81 | /** 82 | * Returns the greatest integer less than or equal to the float argument 83 | */ 84 | public static int floor_float(float value) { 85 | int i = (int) value; 86 | return value < (float) i ? i - 1 : i; 87 | } 88 | 89 | /** 90 | * returns par0 cast as an int, and no greater than Integer.MAX_VALUE-1024 91 | */ 92 | public static int truncateDoubleToInt(double value) { 93 | return (int) (value + 1024.0D) - 1024; 94 | } 95 | 96 | /** 97 | * Returns the greatest integer less than or equal to the double argument 98 | */ 99 | public static int floor_double(double value) { 100 | int i = (int) value; 101 | return value < (double) i ? i - 1 : i; 102 | } 103 | 104 | /** 105 | * Long version of floor_double 106 | */ 107 | public static long floor_double_long(double value) { 108 | long i = (long) value; 109 | return value < (double) i ? i - 1L : i; 110 | } 111 | 112 | public static int func_154353_e(double value) { 113 | return (int) (value >= 0.0D ? value : -value + 1.0D); 114 | } 115 | 116 | public static float abs(float value) { 117 | return value >= 0.0F ? value : -value; 118 | } 119 | 120 | /** 121 | * Returns the unsigned value of an int. 122 | */ 123 | public static int abs_int(int value) { 124 | return value >= 0 ? value : -value; 125 | } 126 | 127 | public static int ceiling_float_int(float value) { 128 | int i = (int) value; 129 | return value > (float) i ? i + 1 : i; 130 | } 131 | 132 | public static int ceiling_double_int(double value) { 133 | int i = (int) value; 134 | return value > (double) i ? i + 1 : i; 135 | } 136 | 137 | /** 138 | * Returns the value of the first parameter, clamped to be within the lower and upper limits given by the second and 139 | * third parameters. 140 | */ 141 | public static int clamp_int(int num, int min, int max) { 142 | return num < min ? min : (num > max ? max : num); 143 | } 144 | 145 | /** 146 | * Returns the value of the first parameter, clamped to be within the lower and upper limits given by the second and 147 | * third parameters 148 | */ 149 | public static float clamp_float(float num, float min, float max) { 150 | return num < min ? min : (num > max ? max : num); 151 | } 152 | 153 | public static double clamp_double(double num, double min, double max) { 154 | return num < min ? min : (num > max ? max : num); 155 | } 156 | 157 | public static double denormalizeClamp(double lowerBnd, double upperBnd, double slide) { 158 | return slide < 0.0D ? lowerBnd : (slide > 1.0D ? upperBnd : lowerBnd + (upperBnd - lowerBnd) * slide); 159 | } 160 | 161 | /** 162 | * Maximum of the absolute value of two numbers. 163 | */ 164 | public static double abs_max(double p_76132_0_, double p_76132_2_) { 165 | if (p_76132_0_ < 0.0D) { 166 | p_76132_0_ = -p_76132_0_; 167 | } 168 | 169 | if (p_76132_2_ < 0.0D) { 170 | p_76132_2_ = -p_76132_2_; 171 | } 172 | 173 | return p_76132_0_ > p_76132_2_ ? p_76132_0_ : p_76132_2_; 174 | } 175 | 176 | /** 177 | * Buckets an integer with specifed bucket sizes. Args: i, bucketSize 178 | */ 179 | public static int bucketInt(int p_76137_0_, int p_76137_1_) { 180 | return p_76137_0_ < 0 ? -((-p_76137_0_ - 1) / p_76137_1_) - 1 : p_76137_0_ / p_76137_1_; 181 | } 182 | 183 | public static int getRandomIntegerInRange(Random p_76136_0_, int p_76136_1_, int p_76136_2_) { 184 | return p_76136_1_ >= p_76136_2_ ? p_76136_1_ : p_76136_0_.nextInt(p_76136_2_ - p_76136_1_ + 1) + p_76136_1_; 185 | } 186 | 187 | public static float randomFloatClamp(Random p_151240_0_, float p_151240_1_, float p_151240_2_) { 188 | return p_151240_1_ >= p_151240_2_ ? p_151240_1_ : p_151240_0_.nextFloat() * (p_151240_2_ - p_151240_1_) + p_151240_1_; 189 | } 190 | 191 | public static double getRandomDoubleInRange(Random p_82716_0_, double p_82716_1_, double p_82716_3_) { 192 | return p_82716_1_ >= p_82716_3_ ? p_82716_1_ : p_82716_0_.nextDouble() * (p_82716_3_ - p_82716_1_) + p_82716_1_; 193 | } 194 | 195 | public static double average(long[] values) { 196 | long i = 0L; 197 | 198 | for (long j : values) { 199 | i += j; 200 | } 201 | 202 | return (double) i / (double) values.length; 203 | } 204 | 205 | public static boolean epsilonEquals(float p_180185_0_, float p_180185_1_) { 206 | return abs(p_180185_1_ - p_180185_0_) < 1.0E-5F; 207 | } 208 | 209 | public static int normalizeAngle(int p_180184_0_, int p_180184_1_) { 210 | return (p_180184_0_ % p_180184_1_ + p_180184_1_) % p_180184_1_; 211 | } 212 | 213 | /** 214 | * the angle is reduced to an angle between -180 and +180 by mod, and a 360 check 215 | */ 216 | public static float wrapAngleTo180_float(float value) { 217 | value = value % 360.0F; 218 | 219 | if (value >= 180.0F) { 220 | value -= 360.0F; 221 | } 222 | 223 | if (value < -180.0F) { 224 | value += 360.0F; 225 | } 226 | 227 | return value; 228 | } 229 | 230 | /** 231 | * the angle is reduced to an angle between -180 and +180 by mod, and a 360 check 232 | */ 233 | public static double wrapAngleTo180_double(double value) { 234 | value = value % 360.0D; 235 | 236 | if (value >= 180.0D) { 237 | value -= 360.0D; 238 | } 239 | 240 | if (value < -180.0D) { 241 | value += 360.0D; 242 | } 243 | 244 | return value; 245 | } 246 | 247 | /** 248 | * parses the string as integer or returns the second parameter if it fails 249 | */ 250 | public static int parseIntWithDefault(String p_82715_0_, int p_82715_1_) { 251 | try { 252 | return Integer.parseInt(p_82715_0_); 253 | } catch (Throwable var3) { 254 | return p_82715_1_; 255 | } 256 | } 257 | 258 | /** 259 | * parses the string as integer or returns the second parameter if it fails. this value is capped to par2 260 | */ 261 | public static int parseIntWithDefaultAndMax(String p_82714_0_, int p_82714_1_, int p_82714_2_) { 262 | return Math.max(p_82714_2_, parseIntWithDefault(p_82714_0_, p_82714_1_)); 263 | } 264 | 265 | /** 266 | * parses the string as double or returns the second parameter if it fails. 267 | */ 268 | public static double parseDoubleWithDefault(String p_82712_0_, double p_82712_1_) { 269 | try { 270 | return Double.parseDouble(p_82712_0_); 271 | } catch (Throwable var4) { 272 | return p_82712_1_; 273 | } 274 | } 275 | 276 | public static double parseDoubleWithDefaultAndMax(String p_82713_0_, double p_82713_1_, double p_82713_3_) { 277 | return Math.max(p_82713_3_, parseDoubleWithDefault(p_82713_0_, p_82713_1_)); 278 | } 279 | 280 | /** 281 | * Returns the input value rounded up to the next highest power of two. 282 | */ 283 | public static int roundUpToPowerOfTwo(int value) { 284 | int i = value - 1; 285 | i = i | i >> 1; 286 | i = i | i >> 2; 287 | i = i | i >> 4; 288 | i = i | i >> 8; 289 | i = i | i >> 16; 290 | return i + 1; 291 | } 292 | 293 | /** 294 | * Is the given value a power of two? (1, 2, 4, 8, 16, ...) 295 | */ 296 | private static boolean isPowerOfTwo(int value) { 297 | return value != 0 && (value & value - 1) == 0; 298 | } 299 | 300 | /** 301 | * Uses a B(2, 5) De Bruijn sequence and a lookup table to efficiently calculate the log-base-two of the given 302 | * value. Optimized for cases where the input value is a power-of-two. If the input value is not a power-of-two, 303 | * then subtract 1 from the return value. 304 | */ 305 | private static int calculateLogBaseTwoDeBruijn(int value) { 306 | value = isPowerOfTwo(value) ? value : roundUpToPowerOfTwo(value); 307 | return multiplyDeBruijnBitPosition[(int) ((long) value * 125613361L >> 27) & 31]; 308 | } 309 | 310 | /** 311 | * Efficiently calculates the floor of the base-2 log of an integer value. This is effectively the index of the 312 | * highest bit that is set. For example, if the number in binary is 0...100101, this will return 5. 313 | */ 314 | public static int calculateLogBaseTwo(int value) { 315 | return calculateLogBaseTwoDeBruijn(value) - (isPowerOfTwo(value) ? 0 : 1); 316 | } 317 | 318 | public static int roundUp(int p_154354_0_, int p_154354_1_) { 319 | if (p_154354_1_ == 0) { 320 | return 0; 321 | } else if (p_154354_0_ == 0) { 322 | return p_154354_1_; 323 | } else { 324 | if (p_154354_0_ < 0) { 325 | p_154354_1_ *= -1; 326 | } 327 | 328 | int i = p_154354_0_ % p_154354_1_; 329 | return i == 0 ? p_154354_0_ : p_154354_0_ + p_154354_1_ - i; 330 | } 331 | } 332 | 333 | public static int func_180183_b(float p_180183_0_, float p_180183_1_, float p_180183_2_) { 334 | return func_180181_b(floor_float(p_180183_0_ * 255.0F), floor_float(p_180183_1_ * 255.0F), floor_float(p_180183_2_ * 255.0F)); 335 | } 336 | 337 | public static int func_180181_b(int p_180181_0_, int p_180181_1_, int p_180181_2_) { 338 | int i = (p_180181_0_ << 8) + p_180181_1_; 339 | i = (i << 8) + p_180181_2_; 340 | return i; 341 | } 342 | 343 | public static int func_180188_d(int p_180188_0_, int p_180188_1_) { 344 | int i = (p_180188_0_ & 16711680) >> 16; 345 | int j = (p_180188_1_ & 16711680) >> 16; 346 | int k = (p_180188_0_ & 65280) >> 8; 347 | int l = (p_180188_1_ & 65280) >> 8; 348 | int i1 = (p_180188_0_ & 255) >> 0; 349 | int j1 = (p_180188_1_ & 255) >> 0; 350 | int k1 = (int) ((float) i * (float) j / 255.0F); 351 | int l1 = (int) ((float) k * (float) l / 255.0F); 352 | int i2 = (int) ((float) i1 * (float) j1 / 255.0F); 353 | return p_180188_0_ & -16777216 | k1 << 16 | l1 << 8 | i2; 354 | } 355 | 356 | public static double func_181162_h(double p_181162_0_) { 357 | return p_181162_0_ - Math.floor(p_181162_0_); 358 | } 359 | 360 | public static long getCoordinateRandom(int x, int y, int z) { 361 | long i = (long) (x * 3129871) ^ (long) z * 116129781L ^ (long) y; 362 | i = i * i * 42317861L + i * 11L; 363 | return i; 364 | } 365 | 366 | public static UUID getRandomUuid(Random rand) { 367 | long i = rand.nextLong() & -61441L | 16384L; 368 | long j = rand.nextLong() & 4611686018427387903L | Long.MIN_VALUE; 369 | return new UUID(i, j); 370 | } 371 | 372 | public static double func_181160_c(double p_181160_0_, double p_181160_2_, double p_181160_4_) { 373 | return (p_181160_0_ - p_181160_2_) / (p_181160_4_ - p_181160_2_); 374 | } 375 | 376 | public static double atan2(double p_181159_0_, double p_181159_2_) { 377 | double d0 = p_181159_2_ * p_181159_2_ + p_181159_0_ * p_181159_0_; 378 | 379 | if (Double.isNaN(d0)) { 380 | return Double.NaN; 381 | } else { 382 | boolean flag = p_181159_0_ < 0.0D; 383 | 384 | if (flag) { 385 | p_181159_0_ = -p_181159_0_; 386 | } 387 | 388 | boolean flag1 = p_181159_2_ < 0.0D; 389 | 390 | if (flag1) { 391 | p_181159_2_ = -p_181159_2_; 392 | } 393 | 394 | boolean flag2 = p_181159_0_ > p_181159_2_; 395 | 396 | if (flag2) { 397 | double d1 = p_181159_2_; 398 | p_181159_2_ = p_181159_0_; 399 | p_181159_0_ = d1; 400 | } 401 | 402 | double d9 = func_181161_i(d0); 403 | p_181159_2_ = p_181159_2_ * d9; 404 | p_181159_0_ = p_181159_0_ * d9; 405 | double d2 = field_181163_d + p_181159_0_; 406 | int i = (int) Double.doubleToRawLongBits(d2); 407 | double d3 = field_181164_e[i]; 408 | double d4 = field_181165_f[i]; 409 | double d5 = d2 - field_181163_d; 410 | double d6 = p_181159_0_ * d4 - p_181159_2_ * d5; 411 | double d7 = (6.0D + d6 * d6) * d6 * 0.16666666666666666D; 412 | double d8 = d3 + d7; 413 | 414 | if (flag2) { 415 | d8 = (Math.PI / 2D) - d8; 416 | } 417 | 418 | if (flag1) { 419 | d8 = Math.PI - d8; 420 | } 421 | 422 | if (flag) { 423 | d8 = -d8; 424 | } 425 | 426 | return d8; 427 | } 428 | } 429 | 430 | public static double func_181161_i(double p_181161_0_) { 431 | double d0 = 0.5D * p_181161_0_; 432 | long i = Double.doubleToRawLongBits(p_181161_0_); 433 | i = 6910469410427058090L - (i >> 1); 434 | p_181161_0_ = Double.longBitsToDouble(i); 435 | p_181161_0_ = p_181161_0_ * (1.5D - d0 * p_181161_0_ * p_181161_0_); 436 | return p_181161_0_; 437 | } 438 | 439 | public static int hsvToRGB(float p_181758_0_, float p_181758_1_, float p_181758_2_) { 440 | int i = (int) (p_181758_0_ * 6.0F) % 6; 441 | float f = p_181758_0_ * 6.0F - (float) i; 442 | float f1 = p_181758_2_ * (1.0F - p_181758_1_); 443 | float f2 = p_181758_2_ * (1.0F - f * p_181758_1_); 444 | float f3 = p_181758_2_ * (1.0F - (1.0F - f) * p_181758_1_); 445 | float f4; 446 | float f5; 447 | float f6; 448 | 449 | switch (i) { 450 | case 0: 451 | f4 = p_181758_2_; 452 | f5 = f3; 453 | f6 = f1; 454 | break; 455 | 456 | case 1: 457 | f4 = f2; 458 | f5 = p_181758_2_; 459 | f6 = f1; 460 | break; 461 | 462 | case 2: 463 | f4 = f1; 464 | f5 = p_181758_2_; 465 | f6 = f3; 466 | break; 467 | 468 | case 3: 469 | f4 = f1; 470 | f5 = f2; 471 | f6 = p_181758_2_; 472 | break; 473 | 474 | case 4: 475 | f4 = f3; 476 | f5 = f1; 477 | f6 = p_181758_2_; 478 | break; 479 | 480 | case 5: 481 | f4 = p_181758_2_; 482 | f5 = f1; 483 | f6 = f2; 484 | break; 485 | 486 | default: 487 | throw new RuntimeException("Something went wrong when converting from HSV to RGB. Input was " + p_181758_0_ + ", " + p_181758_1_ + ", " + p_181758_2_); 488 | } 489 | 490 | int j = clamp_int((int) (f4 * 255.0F), 0, 255); 491 | int k = clamp_int((int) (f5 * 255.0F), 0, 255); 492 | int l = clamp_int((int) (f6 * 255.0F), 0, 255); 493 | return j << 16 | k << 8 | l; 494 | } 495 | } 496 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/util/MathUtil.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.util; 2 | 3 | public class MathUtil { 4 | public static final float PI = (float) Math.PI; 5 | public static final float PI2 = ((float) Math.PI * 2F); 6 | public static final float PId2 = ((float) Math.PI / 2F); 7 | private static final float[] ASIN_TABLE = new float[65536]; 8 | 9 | static { 10 | for (int i = 0; i < 65536; ++i) { 11 | ASIN_TABLE[i] = (float) Math.asin((double) i / 32767.5D - 1.0D); 12 | } 13 | 14 | for (int j = -1; j < 2; ++j) { 15 | ASIN_TABLE[(int) (((double) j + 1.0D) * 32767.5D) & 65535] = (float) Math.asin((double) j); 16 | } 17 | } 18 | 19 | public static float asin(float value) { 20 | return ASIN_TABLE[(int) ((double) (value + 1.0F) * 32767.5D) & 65535]; 21 | } 22 | 23 | public static float acos(float value) { 24 | return ((float) Math.PI / 2F) - ASIN_TABLE[(int) ((double) (value + 1.0F) * 32767.5D) & 65535]; 25 | } 26 | 27 | public static int getAverage(int[] vals) { 28 | if (vals.length <= 0) { 29 | return 0; 30 | } else { 31 | int i = getSum(vals); 32 | int j = i / vals.length; 33 | return j; 34 | } 35 | } 36 | 37 | public static int getSum(int[] vals) { 38 | if (vals.length <= 0) { 39 | return 0; 40 | } else { 41 | int i = 0; 42 | 43 | for (int j = 0; j < vals.length; ++j) { 44 | int k = vals[j]; 45 | i += k; 46 | } 47 | 48 | return i; 49 | } 50 | } 51 | 52 | public static int roundDownToPowerOfTwo(int val) { 53 | int i = MathHelper.roundUpToPowerOfTwo(val); 54 | return val == i ? i : i / 2; 55 | } 56 | 57 | public static boolean equalsDelta(float f1, float f2, float delta) { 58 | return Math.abs(f1 - f2) <= delta; 59 | } 60 | 61 | public static float toDeg(float angle) { 62 | return angle * 180.0F / MathHelper.PI; 63 | } 64 | 65 | public static float toRad(float angle) { 66 | return angle / 180.0F * MathHelper.PI; 67 | } 68 | 69 | public static float roundToFloat(double d) { 70 | return (float) ((double) Math.round(d * 1.0E8D) / 1.0E8D); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/cubk/nsc2/util/TimerUtil.java: -------------------------------------------------------------------------------- 1 | package com.cubk.nsc2.util; 2 | 3 | public class TimerUtil { 4 | public long lastMS = System.currentTimeMillis(); 5 | public long time; 6 | 7 | public void reset() { 8 | lastMS = System.currentTimeMillis(); 9 | } 10 | 11 | public boolean hasTimeElapsed(long time, boolean reset) { 12 | if (System.currentTimeMillis() - lastMS > time) { 13 | if (reset) reset(); 14 | return true; 15 | } 16 | 17 | return false; 18 | } 19 | 20 | public long elapsed() { 21 | return System.currentTimeMillis() - lastMS; 22 | } 23 | 24 | public boolean hasTimeElapsed(long time) { 25 | this.time = time; 26 | return System.currentTimeMillis() - lastMS > this.time; 27 | } 28 | 29 | public long getTime() { 30 | return System.currentTimeMillis() - lastMS; 31 | } 32 | 33 | public void setTime(long time) { 34 | lastMS = time; 35 | } 36 | 37 | public static final class CPSDelay { 38 | private final TimerUtil timerUtils = new TimerUtil(); 39 | 40 | public boolean shouldAttack(int cps) { 41 | int aps = 20 / cps; 42 | return timerUtils.hasTimeElapsed(50 * aps, true); 43 | } 44 | 45 | public void reset() { 46 | timerUtils.reset(); 47 | } 48 | } 49 | } 50 | --------------------------------------------------------------------------------