    public static RequestTarget createWithoutValidation(
            RequestTargetForm form, @Nullable String scheme, @Nullable String authority,
            String path, String pathWithMatrixVariables, @Nullable String query, @Nullable String fragment) {
        return new DefaultRequestTarget(
                form, scheme, authority, path, pathWithMatrixVariables, query, fragment);
    }


    private static RequestTarget slowAbsoluteFormForClient(String reqTarget, int authorityPos) {
        // Extract scheme and authority while looking for path.
        final URI schemeAndAuthority;
        final String scheme = reqTarget.substring(0, authorityPos - 3);
        final int nextPos = findNextComponent(reqTarget, authorityPos);
        final String authority;
        if (nextPos < 0) {
            // Found no other components after authority
            authority = reqTarget.substring(authorityPos);
        } else {
            // Path, query or fragment exists.
            authority = reqTarget.substring(authorityPos, nextPos);
        }

        // Reject a URI with an empty authority.
        if (authority.isEmpty()) {
            return null;
        }

        // Normalize scheme and authority.
        schemeAndAuthority = normalizeSchemeAndAuthority(scheme, authority);
        if (schemeAndAuthority == null) {
            // Invalid scheme or authority.
            return null;
        }

        if (nextPos < 0) {
            return new DefaultRequestTarget(RequestTargetForm.ABSOLUTE,
                                            schemeAndAuthority.getScheme(),
                                            schemeAndAuthority.getRawAuthority(),
                                            "/",
                                            "/", null,
                                            null);
        }

        return slowForClient(reqTarget, schemeAndAuthority, nextPos);
    }


    public String maybePathWithMatrixVariables() {
        return maybePathWithMatrixVariables;
    }


    public static String removeMatrixVariables(String path) {
        int semicolonIndex = path.indexOf(';');
        if (semicolonIndex < 0) {
            return path;
        }
        if (semicolonIndex == 0 || path.charAt(semicolonIndex - 1) == '/') {
            // Invalid matrix variable e.g. /;a=b/foo
            return null;
        }
        int subStringStartIndex = 0;
        try (TemporaryThreadLocals threadLocals = TemporaryThreadLocals.acquire()) {
            final StringBuilder sb = threadLocals.stringBuilder();
            for (;;) {
                sb.append(path, subStringStartIndex, semicolonIndex);
                final int slashIndex = path.indexOf('/', semicolonIndex + 1);
                if (slashIndex < 0) {
                    return sb.toString();
                }
                subStringStartIndex = slashIndex;
                semicolonIndex = path.indexOf(';', subStringStartIndex + 1);
                if (semicolonIndex < 0) {
                    sb.append(path, subStringStartIndex, path.length());
                    return sb.toString();
                }
                if (path.charAt(semicolonIndex - 1) == '/') {
                    // Invalid matrix variable e.g. /prefix/;a=b/foo
                    return null;
                }
            }
        }
    }


    public static String mappedPath(ServiceRequestContext ctx) {
        final RequestTarget requestTarget = ctx.routingContext().requestTarget();
        final String pathWithMatrixVariables = requestTarget.maybePathWithMatrixVariables();
        if (pathWithMatrixVariables.equals(ctx.path())) {
            return ctx.mappedPath();
        }
        // The request path contains matrix variables. e.g. "/foo/bar/users;name=alice"

        final String prefix = ctx.path().substring(0, ctx.path().length() - ctx.mappedPath().length());
        // The prefix is now `/foo/bar`
        if (!pathWithMatrixVariables.startsWith(prefix)) {
            // The request path has matrix variables in the wrong place. e.g. "/foo;name=alice/bar/users"
            return null;
        }
        final String mappedPath = pathWithMatrixVariables.substring(prefix.length());
        if (mappedPath.charAt(0) != '/') {
            // Again, the request path has matrix variables in the wrong place. e.g. "/foo/bar;/users"
            return null;
        }
        return mappedPath;
    }


    private ExactPathMapping(String prefix, String exactPath) {
        if (!Flags.allowSemicolonInPathComponent()) {
            checkArgument(prefix.indexOf(';') < 0, "prefix: %s (expected not to have a ';')", prefix);
            checkArgument(exactPath.indexOf(';') < 0, "exactPath: %s (expected not to have a ';')", exactPath);
        }
        this.prefix = prefix;
        this.exactPath = ensureAbsolutePath(exactPath, "exactPath");
        paths = ImmutableList.of(exactPath, exactPath);
    }


    PrefixPathMapping(String prefix, boolean stripPrefix) {
        checkArgument(Flags.allowSemicolonInPathComponent() || prefix.indexOf(';') < 0,
                      "prefix: %s (expected not to have a ';')", prefix);
        prefix = ensureAbsolutePath(prefix, "prefix");
        if (!prefix.endsWith("/")) {
            prefix += '/';
        }

        this.prefix = prefix;
        this.stripPrefix = stripPrefix;
        final String triePath = prefix + '*';
        paths = ImmutableList.of(prefix, triePath);
        pathPattern = triePath;
        strVal = PREFIX + prefix + " (stripPrefix: " + stripPrefix + ')';
    }


    default RoutingContext withPath(String path) {
        requireNonNull(path, "path");
        final RequestTarget oldReqTarget = requestTarget();
        final RequestTarget newReqTarget =
                DefaultRequestTarget.createWithoutValidation(
                        oldReqTarget.form(),
                        oldReqTarget.scheme(),
                        oldReqTarget.authority(),
                        removeMatrixVariables(path),
                        path,
                        oldReqTarget.query(),
                        oldReqTarget.fragment());

        return new RoutingContextWrapper(this) {
            @Override
            public RequestTarget requestTarget() {
                return newReqTarget;
            }
        };
    }


    private static RequestTarget forServer(String rawPath, boolean allowSemicolonInPathComponent) {
        final RequestTarget res = DefaultRequestTarget.forServer(rawPath, allowSemicolonInPathComponent, false);
        if (res != null) {
            logger.info("forServer({}) => path: {}, query: {}", rawPath, res.path(), res.query());
        } else {
            logger.info("forServer({}) => null", rawPath);
        }
        return res;
    }


    void testRemoveMatrixVariables() {
        assertThat(removeMatrixVariables("/foo")).isEqualTo("/foo");
        assertThat(removeMatrixVariables("/foo;")).isEqualTo("/foo");
        assertThat(removeMatrixVariables("/foo/")).isEqualTo("/foo/");
        assertThat(removeMatrixVariables("/foo/bar")).isEqualTo("/foo/bar");
        assertThat(removeMatrixVariables("/foo/bar;")).isEqualTo("/foo/bar");
        assertThat(removeMatrixVariables("/foo/bar/")).isEqualTo("/foo/bar/");
        assertThat(removeMatrixVariables("/foo;/bar")).isEqualTo("/foo/bar");
        assertThat(removeMatrixVariables("/foo;/bar;")).isEqualTo("/foo/bar");
        assertThat(removeMatrixVariables("/foo;/bar/")).isEqualTo("/foo/bar/");
        assertThat(removeMatrixVariables("/foo;a=b/bar")).isEqualTo("/foo/bar");
        assertThat(removeMatrixVariables("/foo;a=b/bar;")).isEqualTo("/foo/bar");
        assertThat(removeMatrixVariables("/foo;a=b/bar/")).isEqualTo("/foo/bar/");
        assertThat(removeMatrixVariables("/foo;a=b/bar/baz")).isEqualTo("/foo/bar/baz");
        assertThat(removeMatrixVariables("/foo;a=b/bar/baz;")).isEqualTo("/foo/bar/baz");
        assertThat(removeMatrixVariables("/foo;a=b/bar/baz/")).isEqualTo("/foo/bar/baz/");
        assertThat(removeMatrixVariables("/foo;a=b/bar;/baz")).isEqualTo("/foo/bar/baz");
        assertThat(removeMatrixVariables("/foo;a=b/bar;/baz;")).isEqualTo("/foo/bar/baz");
        assertThat(removeMatrixVariables("/foo;a=b/bar;/baz/")).isEqualTo("/foo/bar/baz/");
        assertThat(removeMatrixVariables("/foo;a=b/bar;c=d/baz")).isEqualTo("/foo/bar/baz");
        assertThat(removeMatrixVariables("/foo;a=b/bar;c=d/baz;")).isEqualTo("/foo/bar/baz");
        assertThat(removeMatrixVariables("/foo;a=b/bar;c=d/baz/")).isEqualTo("/foo/bar/baz/");

        // Invalid
        assertThat(removeMatrixVariables("/;a=b")).isNull();
        assertThat(removeMatrixVariables("/prefix/;a=b")).isNull();
    }


    void reserveSemicolonWhenAllowed() {
        // '%3B' is decoded into ';' when allowSemicolonInPathComponent is true.
        assertAccepted(forServer("/abc%3B?a=%3B", true), "/abc;", "a=%3B");
        assertAccepted(forServer("/abc%3B?a=%3B"), "/abc%3B", "a=%3B");

        assertAccepted(forServer("/abc%3B", true), "/abc;");
        assertAccepted(forServer("/abc%3B"), "/abc%3B");

        // Client always decodes '%3B' into ';'.
        assertAccepted(forClient("/abc%3B?a=%3B"), "/abc;", "a=%3B");
    }


    void serverShouldRemoveMatrixVariablesWhenNotAllowed() {
        // Not allowed
        assertAccepted(forServer("/;a=b?c=d;e=f"), "/", "c=d;e=f");
        // Allowed.
        assertAccepted(forServer("/;a=b?c=d;e=f", true), "/;a=b", "c=d;e=f");
        // '%3B' should never be decoded into ';'.
        assertAccepted(forServer("/%3B?a=b%3Bc=d"), "/%3B", "a=b%3Bc=d");
    }


    void shouldReserveQuestionMark() throws URISyntaxException {
        // '%3F' must not be decoded into '?'.
        assertAccepted(forServer("/abc%3F.json?a=%3F"), "/abc%3F.json", "a=%3F");
        assertAccepted(forClient("/abc%3F.json?a=%3F"), "/abc%3F.json", "a=%3F");
    }


    void stripMatrixVariables() throws InterruptedException {
        final AggregatedHttpResponse response = server.blockingWebClient().get("/foo;a=b");
        assertThat(response.headers().status()).isSameAs(HttpStatus.OK);
        final ServiceRequestContextCaptor captor = server.requestContextCaptor();
        final ServiceRequestContext sctx = captor.poll();
        assertThat(sctx.path()).isEqualTo("/foo");
        assertThat(sctx.routingContext().requestTarget().maybePathWithMatrixVariables())
                .isEqualTo("/foo;a=b");
    }


    static final ServerExtension server = new ServerExtension() {
        @Override
        protected void configure(ServerBuilder sb) throws Exception {
            sb.service("/foo", (ctx, req) -> HttpResponse.of(200));
        }
    };


    void notAllowSemicolon() {
        assertThatThrownBy(() -> Route.builder().path("/foo;")).isInstanceOf(
                IllegalArgumentException.class);
        assertThatThrownBy(() -> Route.builder().path("/foo/{bar};")).isInstanceOf(
                IllegalArgumentException.class);
        assertThatThrownBy(() -> Route.builder().path("/bar/:baz;")).isInstanceOf(
                IllegalArgumentException.class);
        assertThatThrownBy(() -> Route.builder().path("exact:/:foo/bar;")).isInstanceOf(
                IllegalArgumentException.class);
        assertThatThrownBy(() -> Route.builder().path("prefix:/bar/baz;")).isInstanceOf(
                IllegalArgumentException.class);
    }


    public void exceptionHandler() {
        throw new BaseException("exception handler");
    }


    public void customException() {
        throw new CustomException();
    }


    public ResponseEntity<Map<String, Object>> onBaseException(Throwable t) {
        final Map<String, Object> body = ImmutableMap.<String, Object>builder()
                                                     .put("status", HttpStatus.INTERNAL_SERVER_ERROR.value())
                                                     .put("message", t.getMessage())
                                                     .build();
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(body);
    }


        BaseException(String message) {
            super(message);
        }


    public void runtimeException() {
        throw new RuntimeException("runtime exception");
    }


    public void globalExceptionHandler() {
        throw new GlobalBaseException("global exception handler");
    }


    GlobalBaseException(String message) {
        super(message);
    }


    public ResponseEntity<Map<String, Object>> onGlobalBaseException(Throwable t) {
        final String message = t.getMessage();
        final Map<String, Object> body = ImmutableMap.of("status", HttpStatus.INTERNAL_SERVER_ERROR.value(),
                                                         "message", message);
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(body);
    }


    public Greeting(String content) {
        this.content = content;
    }


    public String getContent() {
        return content;
    }


    public ResponseEntity<Greeting> greetingSync(
            @RequestParam(value = "name", defaultValue = "World") String name) {
        return ResponseEntity.ok(new Greeting(String.format(template, name)));
    }


    List<Integer> findPet(
            @MatrixVariable(name = "q", pathVar = "ownerId") int q1,
            @MatrixVariable(name = "q", pathVar = "petId") int q2) {
        return ImmutableList.of(q1, q2);
    }


        JettyServletWebServerFactory jettyServletWebServerFactory(
                ObjectProvider<JettyServerCustomizer> serverCustomizers) {
            final JettyServletWebServerFactory factory = new ArmeriaJettyServletWebServerFactory();
            factory.getServerCustomizers().addAll(serverCustomizers.orderedStream().toList());
            return factory;
        }


        protected JettyWebServer getJettyWebServer(Server server) {
            return new JettyWebServer(server, true);
        }


    public static void main(String[] args) {
        SpringApplication.run(SpringJettyApplication.class, args);
    }


    public ArmeriaServerConfigurator armeriaTomcat(WebServerApplicationContext applicationContext) {
        final WebServer webServer = applicationContext.getWebServer();
        if (webServer instanceof JettyWebServer) {
            final Server jettyServer = ((JettyWebServer) webServer).getServer();

            return serverBuilder -> serverBuilder.service("prefix:/jetty/api/rest/v1",
                                                          JettyService.of(jettyServer));
        }
        return serverBuilder -> {};
    }


    private static void assertUpStatus(AggregatedHttpResponse res) throws IOException {
        assertThat(res.status()).isEqualTo(HttpStatus.OK);
        assertThat(res.contentType().toString()).isEqualTo("application/vnd.spring-boot.actuator.v3+json");

        final Map<String, Object> values = OBJECT_MAPPER.readValue(res.content().array(), JSON_MAP);
        assertThat(values).containsEntry("status", "UP");
    }


    void additionalPath() throws Exception {
        String path = "/internal/actuator/health/foo";
        assertUpStatus(managementClient.get(path).aggregate().join());
        assertThat(armeriaClient.get(path).aggregate().join().status()).isSameAs(HttpStatus.NOT_FOUND);

        path = "/internal/actuator/health/bar";
        assertUpStatus(managementClient.get(path).aggregate().join());
        assertThat(armeriaClient.get(path).aggregate().join().status()).isSameAs(HttpStatus.NOT_FOUND);

        path = "/foohealth";
        assertUpStatus(managementClient.get(path).aggregate().join());
        assertThat(armeriaClient.get(path).aggregate().join().status()).isSameAs(HttpStatus.NOT_FOUND);

        // barhealth is bound to Armeria port.
        path = "/barhealth";
        assertThat(managementClient.get(path).aggregate().join().status()).isSameAs(HttpStatus.NOT_FOUND);
        assertUpStatus(armeriaClient.get(path).aggregate().join());
    }


    void setUp() {
        managementClient = WebClient.builder("http://127.0.0.1:" + managementPort).build();
        armeriaClient = WebClient.builder("http://127.0.0.1:" + armeriaPort).build();
    }


    void testHealth() throws Exception {
        final AggregatedHttpResponse res = managementClient.get("/internal/actuator/health").aggregate().join();
        assertUpStatus(res);
    }


private static final TypeReference<Map<String, Object>> JSON_MAP = new TypeReference<>() {};


    void shouldReturnFormattedMessage(String path, int status, String message) throws Exception {
        final ResponseEntity<String> response =
                restTemplate.getForEntity(jettyBaseUrlPath(port) + path, String.class);
        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.valueOf(status));
        assertThatJson(response.getBody()).node("status").isEqualTo(status);
        assertThatJson(response.getBody()).node("message").isEqualTo(message);
    }


    private static String jettyBaseUrlPath(int port) {
        return "http://localhost:" + port + JETTY_BASE_PATH;
    }


    void wrongMatrixVariables() throws Exception {
        final WebClient client = WebClient.of("http://127.0.0.1:" + port);
        AggregatedHttpResponse response = client.blocking().get(
                JETTY_BASE_PATH + ";/owners/42;q=11/pets/21;q=22");
        assertThat(response.status()).isSameAs(HttpStatus.BAD_REQUEST);

        response = client.blocking().get("/jetty;wrong=place/api/rest/v1/owners/42;q=11/pets/21;q=22");
        assertThat(response.status()).isSameAs(HttpStatus.BAD_REQUEST);
    }


    void matrixVariablesPreserved() throws Exception {
        final WebClient client = WebClient.of("http://127.0.0.1:" + port);
        final AggregatedHttpResponse response = client.blocking().get(
                JETTY_BASE_PATH + "/owners/42;q=11/pets/21;q=22");
        assertThat(response.contentUtf8()).isEqualTo("[11,22]");
    }


    void greetingShouldReturn404() throws Exception {
        assertThat(restTemplate.getForEntity("http://localhost:" + httpPort + JETTY_BASE_PATH + "/greet",
                                             Void.class)
                               .getStatusCode().value()).isEqualByComparingTo(404);
    }


    void contextLoads() {
        assertThat(greetingController).isNotNull();
    }


    public void init() throws Exception {
        httpPort = server.activePorts()
                         .values()
                         .stream()
                         .filter(ServerPort::hasHttp)
                         .findAny()
                         .get()
                         .localAddress()
                         .getPort();
    }


    void greetingShouldReturnDefaultMessage() throws Exception {
        assertThat(restTemplate.getForObject("http://localhost:" + httpPort + JETTY_BASE_PATH + "/greeting",
                                             String.class))
                .contains("Hello, World!");
    }


    void greetingShouldReturnUsersMessage() throws Exception {
        assertThat(restTemplate.getForObject("http://localhost:" + httpPort +
                                             JETTY_BASE_PATH + "/greeting?name=Armeria",
                                             String.class))
                .contains("Hello, Armeria!");
    }


    List<Integer> findPet(
            @MatrixVariable(name = "q", pathVar = "ownerId") int q1,
            @MatrixVariable(name = "q", pathVar = "petId") int q2) {
        return ImmutableList.of(q1, q2);
    }


    void wrongMatrixVariables() throws Exception {
        final WebClient client = WebClient.of("http://127.0.0.1:" + port);
        AggregatedHttpResponse response = client.blocking().get(
                TOMCAT_BASE_PATH + ";/owners/42;q=11/pets/21;q=22");
        assertThat(response.status()).isSameAs(HttpStatus.BAD_REQUEST);

        response = client.blocking().get("/tomcat;wrong=place/api/rest/v1/owners/42;q=11/pets/21;q=22");
        assertThat(response.status()).isSameAs(HttpStatus.BAD_REQUEST);
    }


    void matrixVariablesPreserved() throws Exception {
        final WebClient client = WebClient.of("http://127.0.0.1:" + port);
        final AggregatedHttpResponse response = client.blocking().get(
                TOMCAT_BASE_PATH + "/owners/42;q=11/pets/21;q=22");
        assertThat(response.contentUtf8()).isEqualTo("[11,22]");
    }


    private static void fillRequest(
            ServiceRequestContext ctx, AggregatedHttpRequest aReq, Request jReq, String mappedPath) {
        DispatcherTypeUtil.setRequestType(jReq);
        jReq.setAsyncSupported(true, null);
        jReq.setSecure(ctx.sessionProtocol().isTls());
        jReq.setMetaData(toRequestMetadata(ctx, aReq, mappedPath));
        final HttpHeaders trailers = aReq.trailers();
        if (!trailers.isEmpty()) {
            final HttpField[] httpFields = trailers.stream()
                                                   .map(e -> new HttpField(e.getKey().toString(), e.getValue()))
                                                   .toArray(HttpField[]::new);
            jReq.setTrailerHttpFields(HttpFields.from(httpFields));
        }
    }


    private static MetaData.Request toRequestMetadata(ServiceRequestContext ctx, AggregatedHttpRequest aReq,
                                                      String mappedPath) {
        // Construct the HttpURI
        final StringBuilder uriBuf = new StringBuilder();
        final RequestHeaders aHeaders = aReq.headers();

        uriBuf.append(ctx.sessionProtocol().isTls() ? "https" : "http");
        uriBuf.append("://");
        uriBuf.append(aHeaders.authority());

        final RequestTarget requestTarget = ctx.routingContext().requestTarget();
        if (requestTarget.query() != null) {
            mappedPath = mappedPath + '?' + requestTarget.query();
        }
        uriBuf.append(mappedPath);

        final HttpURI uri = HttpURI.build(HttpURI.build(uriBuf.toString()))
                                   .asImmutable();
        final HttpField[] fields = aHeaders.stream().map(header -> {
            final AsciiString k = header.getKey();
            final String v = header.getValue();
            if (k.charAt(0) != ':') {
                return new HttpField(k.toString(), v);
            }
            if (HttpHeaderNames.AUTHORITY.equals(k) && !aHeaders.contains(HttpHeaderNames.HOST)) {
                // Convert `:authority` to `host`.
                return new HttpField(HttpHeaderNames.HOST.toString(), v);
            }
            return null;
        }).filter(Objects::nonNull).toArray(HttpField[]::new);
        final HttpFields jHeaders = HttpFields.from(fields);

        return new MetaData.Request(aHeaders.method().name(), uri,
                                    ctx.sessionProtocol().isMultiplex() ? HttpVersion.HTTP_2
                                                                        : HttpVersion.HTTP_1_1,
                                    jHeaders, aReq.content().length());
    }


    ArmeriaServerHttpRequest(ServiceRequestContext ctx,
                             HttpRequest req,
                             DataBufferFactoryWrapper<?> factoryWrapper) {
        super(uri(ctx, req), null, springHeaders(req.headers()));
        this.ctx = requireNonNull(ctx, "ctx");
        this.req = req;

        body = Flux.from(req).cast(HttpData.class).map(factoryWrapper::toDataBuffer)
                   // Guarantee that the context is accessible from a controller method
                   // when a user specify @RequestBody in order to convert a request body into an object.
                   .publishOn(Schedulers.fromExecutor(ctx.eventLoop()));
    }


    private static URI uri(ServiceRequestContext ctx, HttpRequest req) {
        final String scheme = req.scheme();
        final String authority = req.authority();
        // Server side Armeria HTTP request always has the scheme and authority.
        assert scheme != null;
        assert authority != null;
        final RequestTarget requestTarget = ctx.routingContext().requestTarget();
        String path = requestTarget.maybePathWithMatrixVariables();
        if (requestTarget.query() != null) {
            path = path + '?' + requestTarget.query();
        }
        return URI.create(scheme + "://" + authority + path);
    }


            Flux<Integer> findPet(
                    @MatrixVariable(name = "q", pathVar = "ownerId") int q1,
                    @MatrixVariable(name = "q", pathVar = "petId") int q2) {
                return Flux.just(q1, q2);
            }


    void foo() throws Exception {
        final WebClient client = WebClient.of("http://127.0.0.1:" + port);
        final AggregatedHttpResponse response = client.blocking().get("/owners/42;q=11/pets/21;q=22");
        assertThat(response.contentUtf8()).isEqualTo("[11,22]");
    }


	public GuiCraftingPipe(EntityPlayer player, IInventory dummyInventory, BaseLogicCrafting logic, boolean isAdvancedSat, boolean isSplitedCrafting) {
		super(null);
		_player = player;
		this.isAdvancedSat = isAdvancedSat;
		this.isSplitedCrafting = isSplitedCrafting;

		if(!isAdvancedSat && !isSplitedCrafting) {
			xSize = 177;
			ySize = 187;
		} else {
			xSize = 177;
			ySize = 187 + 30;
		}

		DummyContainer dummy = new DummyContainer(player.inventory, dummyInventory);
		dummy.addNormalSlotsForPlayerInventory(8, ySize - 82);

		//Input slots
        for(int l = 0; l < 9; l++) {
        	dummy.addDummySlot(l, 8 + l * 18, 18);
        }

		//Output slot
        if(!isAdvancedSat) {
        	dummy.addDummySlot(9, 85, 55);
        } else {
        	dummy.addDummySlot(9, 85, 105);
        }

        this.inventorySlots = dummy;
		_logic = logic;
		buttonarray = new GuiButton[6];
		normalButtonArray = new GuiButton[6];
		advancedSatButtonArray = new GuiButton[9][2];
		for(int i=0;i<9;i++) {
			advancedSatButtonArray[i] = new GuiButton[2];
		}
	}

The product deserializes untrusted data without sufficiently verifying that the resulting data will be valid.


	public void initGui() {
		super.initGui();

		if(!isAdvancedSat) {
			controlList.add(normalButtonArray[0] = new SmallGuiButton(0, (width-xSize) / 2 + 155, (height - ySize) / 2 + 50, 10,10, ">"));
			controlList.add(normalButtonArray[1] = new SmallGuiButton(1, (width-xSize) / 2 + 120, (height - ySize) / 2 + 50, 10,10, "<"));
		}
		if(!isAdvancedSat) {
			controlList.add(normalButtonArray[2] = new SmallGuiButton(3, (width-xSize) / 2 + 39, (height - ySize) / 2 + 50, 37,10, "Import"));
			controlList.add(normalButtonArray[3] = new SmallGuiButton(4, (width-xSize) / 2 + 6, (height - ySize) / 2 + 50, 28,10, "Open"));
			for(int i = 0; i < 6; i++) {
				controlList.add(buttonarray[i] = new SmallGuiButton(5 + i, (width-xSize) / 2 + 12 + 18 * i, (height - ySize) / 2 + 30, 10,10, ">"));
				buttonarray[i].drawButton = false;
			}
			controlList.add(normalButtonArray[4] = new SmallGuiButton(20, (width-xSize) / 2 + 155, (height - ySize) / 2 + 85, 10,10, ">"));
			controlList.add(normalButtonArray[5] = new SmallGuiButton(21, (width-xSize) / 2 + 120, (height - ySize) / 2 + 85, 10,10, "<"));
		} else {
			for(int i=0;i<9;i++) {
				controlList.add(advancedSatButtonArray[i][0] = new SmallGuiButton(30 + i, (width-xSize) / 2 + 10 + 18 * i, (height - ySize) / 2 + 40, 15,10, "/\\"));
				controlList.add(advancedSatButtonArray[i][1] = new SmallGuiButton(40 + i, (width-xSize) / 2 + 10 + 18 * i, (height - ySize) / 2 + 70, 15,10, "\\/"));
			}
			controlList.add(normalButtonArray[2] = new SmallGuiButton(3, (width-xSize) / 2 + 39, (height - ySize) / 2 + 100, 37,10, "Import"));
			controlList.add(normalButtonArray[3] = new SmallGuiButton(4, (width-xSize) / 2 + 6, (height - ySize) / 2 + 100, 28,10, "Open"));
			controlList.add(normalButtonArray[4] = new SmallGuiButton(20, (width-xSize) / 2 + 155, (height - ySize) / 2 + 105, 10,10, ">"));
			controlList.add(normalButtonArray[5] = new SmallGuiButton(21, (width-xSize) / 2 + 120, (height - ySize) / 2 + 105, 10,10, "<"));
		}
	}


	protected void actionPerformed(GuiButton guibutton) {
		if(5 <= guibutton.id && guibutton.id < 11) {
			_logic.handleStackMove(guibutton.id - 5);
		}
		if(30 <= guibutton.id && guibutton.id < 40) {
			_logic.setNextSatellite(_player, guibutton.id - 30);
		}
		if(40 <= guibutton.id && guibutton.id < 50) {
			_logic.setPrevSatellite(_player, guibutton.id - 40);
		}
		switch(guibutton.id){
		case 0:
			_logic.setNextSatellite(_player);
			return;
		case 1:
			_logic.setPrevSatellite(_player);
			return;
		/*case 2:
			_logic.paintPathToSatellite();
			return;*/
		case 3:
			_logic.importFromCraftingTable(_player);
			return;
		case 4:
			_logic.openAttachedGui(_player);
			return;
		case 20:
			_logic.priorityUp(_player);
			return;
		case 21:
			_logic.priorityDown(_player);
			return;
		default:
			super.actionPerformed(guibutton);
			return;
		}
	}


	protected void drawGuiContainerBackgroundLayer(float f, int x, int y) {
		BasicGuiHelper.drawGuiBackGround(mc, guiLeft, guiTop, guiLeft + xSize, guiTop + ySize, zLevel, true, true, true, true, true);

		if(!isAdvancedSat) {
			drawRect(guiLeft + 116, guiTop + 4, guiLeft + 170, guiTop + 70, 0xff8B8B8B);
		}

		for(int i=0; i<9;i++) {
			BasicGuiHelper.drawSlotBackground(mc, guiLeft + 7 + (18*i), guiTop + 17);
		}
		if(!isAdvancedSat) {
			BasicGuiHelper.drawBigSlotBackground(mc, guiLeft + 80, guiTop + 50);
		} else {
			BasicGuiHelper.drawBigSlotBackground(mc, guiLeft + 80, guiTop + 100);
		}
		BasicGuiHelper.drawPlayerInventoryBackground(mc, guiLeft + 8, guiTop + ySize - 82);

		if(!isAdvancedSat) {
			for(int count=36; count<42;count++) {
				Slot slot = inventorySlots.getSlot(count);
				if(slot != null && slot.getStack() != null && slot.getStack().getMaxStackSize() < 2) {
					drawRect(guiLeft + 18 + (18 * (count-36)), guiTop + 18, guiLeft + 18 + (18 * (count-36)) + 16, guiTop + 18 + 16, 0xFFFF0000);
					buttonarray[count - 36].drawButton = true;
				} else {
					buttonarray[count - 36].drawButton = false;
				}
			}
		}
	}


	protected void drawGuiContainerForegroundLayer(int par1, int par2) {
		fontRenderer.drawString("Inputs", 18, 7, 0x404040);
		fontRenderer.drawString("Inventory", 10, ySize - 93, 0x404040);

		if(!isAdvancedSat) {
			fontRenderer.drawString("Output", 77, 40, 0x404040);
			fontRenderer.drawString("Satellite", 123, 7, 0x404040);
			if (_logic.satelliteId == 0) {
				fontRenderer.drawString("Off", 135, 52, 0x404040);
			} else {
				fontRenderer.drawString(""+_logic.satelliteId , 146 - fontRenderer.getStringWidth(""+_logic.satelliteId) , 52, 0x404040);
			}
			fontRenderer.drawString("Priority:" , 123 , 75, 0x404040);
			fontRenderer.drawString(""+_logic.priority , 143 - (fontRenderer.getStringWidth(""+_logic.priority) / 2) , 87, 0x404040);
		} else {
			for(int i=0; i<9;i++) {
				if (_logic.advancedSatelliteIdArray[i] == 0) {
					fontRenderer.drawString("Off", 10 + (i * 18), 57, 0x404040);
				} else {
					fontRenderer.drawString(""+_logic.advancedSatelliteIdArray[i] , 20 - fontRenderer.getStringWidth(""+_logic.advancedSatelliteIdArray[i]) + (i * 18), 57, 0x404040);
				}
			}
			fontRenderer.drawString("Output", 77, 90, 0x404040);
			fontRenderer.drawString("Priority:" , 123 , 95, 0x404040);
			fontRenderer.drawString(""+_logic.priority , 143 - (fontRenderer.getStringWidth(""+_logic.priority) / 2) , 107, 0x404040);
		}
	}


	public void loadUpgrades() {
		registerUpgrade(SNEAKY_UP, "Sneaky Upgrade (UP)", SneakyUpgradeUP.class);
		registerUpgrade(SNEAKY_DOWN, "Sneaky Upgrade (DOWN)", SneakyUpgradeDOWN.class);
		registerUpgrade(SNEAKY_NORTH, "Sneaky Upgrade (NORTH)", SneakyUpgradeNORTH.class);
		registerUpgrade(SNEAKY_SOUTH, "Sneaky Upgrade (SOUTH)", SneakyUpgradeSOUTH.class);
		registerUpgrade(SNEAKY_EAST, "Sneaky Upgrade (EAST)", SneakyUpgradeEAST.class);
		registerUpgrade(SNEAKY_WEST, "Sneaky Upgrade (WEST)", SneakyUpgradeWEST.class);
		registerUpgrade(CONNECTION_UP, "Disconnection Upgrade (UP)", ConnectionUpgradeUP.class, 9 * 16 + 7);
		registerUpgrade(CONNECTION_DOWN, "Disconnection Upgrade (DOWN)", ConnectionUpgradeDOWN.class, 9 * 16 + 8);
		registerUpgrade(CONNECTION_NORTH, "Disconnection Upgrade (NORTH)", ConnectionUpgradeNORTH.class, 9 * 16 + 9);
		registerUpgrade(CONNECTION_SOUTH, "Disconnection Upgrade (SOUTH)", ConnectionUpgradeSOUTH.class, 9 * 16 + 10);
		registerUpgrade(CONNECTION_EAST, "Disconnection Upgrade (EAST)", ConnectionUpgradeEAST.class, 9 * 16 + 11);
		registerUpgrade(CONNECTION_WEST, "Disconnection Upgrade (WEST)", ConnectionUpgradeWEST.class, 9 * 16 + 12);
		registerUpgrade(SPEED, "Item Speed Upgrade", SpeedUpgrade.class, 9 * 16 + 6);
		registerUpgrade(ADVANCED_SAT_CRAFTINGPIPE, "Advanced Satellite Upgrade", AdvancedSatelliteUpgrade.class, 9 * 16 + 13);
		registerUpgrade(SAT_DISTRIBUTING_CRAFTER, "Split Crafting Upgrade (Crafter)", SplitCraftingCrafterUpgrade.class, 9 * 16 + 14);
		registerUpgrade(SAT_DISTRIBUTING_SATELITE, "Split Crafting Upgrade (Satellite)", SplitCraftingSatelliteUpgrade.class, 9 * 16 + 15);
	}


	public IRouter getSatelliteRouter(int x, int y) {
		if(x == -1 && y == -1) {
			for (final BaseLogicSatellite satellite : BaseLogicSatellite.AllSatellites) {
				if (satellite.satelliteId == satelliteId) {
					CoreRoutedPipe satPipe = satellite.getRoutedPipe();
					if(satPipe == null || satPipe.stillNeedReplace() || satPipe.getRouter() == null)
						continue;
					return satPipe.getRouter();
				}
			}
		} else if(y == -1) {
			for (final BaseLogicSatellite satellite : BaseLogicSatellite.AllSatellites) {
				if (satellite.satelliteId == advancedSatelliteIdArray[x]) {
					CoreRoutedPipe satPipe = satellite.getRoutedPipe();
					if(satPipe == null || satPipe.stillNeedReplace() || satPipe.getRouter() == null)
						continue;
					return satPipe.getRouter();
				}
			}
		} else {
			//TODO
		}
		return null;
	}


	public void setNextSatellite(EntityPlayer player) {
		if (MainProxy.isClient(player.worldObj)) {
			final PacketCoordinates packet = new PacketCoordinates(NetworkConstants.CRAFTING_PIPE_NEXT_SATELLITE, xCoord, yCoord, zCoord);
			MainProxy.sendPacketToServer(packet.getPacket());
		} else {
			satelliteId = getNextConnectSatelliteId(false, -1, -1);
			final PacketPipeInteger packet = new PacketPipeInteger(NetworkConstants.CRAFTING_PIPE_SATELLITE_ID, xCoord, yCoord, zCoord, satelliteId);
			MainProxy.sendPacketToPlayer(packet.getPacket(), (Player)player);
		}

	}


	public void setSatelliteId(int satelliteId, int x, int y) {
		if(x == -1 && y == -1) {
			this.satelliteId = satelliteId;
		} else if(y == -1) {
			advancedSatelliteIdArray[x] = satelliteId;
		} else {
			//TODO
		}
	}


	protected int getNextConnectSatelliteId(boolean prev, int x, int y) {
		final List<ExitRoute> routes = getRoutedPipe().getRouter().getIRoutersByCost();
		int closestIdFound = prev ? 0 : Integer.MAX_VALUE;
		for (final BaseLogicSatellite satellite : BaseLogicSatellite.AllSatellites) {
			CoreRoutedPipe satPipe = satellite.getRoutedPipe();
			if(satPipe == null || satPipe.stillNeedReplace() || satPipe.getRouter() == null)
				continue;
			IRouter satRouter = satPipe.getRouter();
			for (ExitRoute route:routes){
				if (route.destination == satRouter) {
					if(x == -1 && y == -1) {
						if (!prev && satellite.satelliteId > satelliteId && satellite.satelliteId < closestIdFound) {
							closestIdFound = satellite.satelliteId;
						} else if (prev && satellite.satelliteId < satelliteId && satellite.satelliteId > closestIdFound) {
							closestIdFound = satellite.satelliteId;
						}
					} else if(y == -1) {
						if (!prev && satellite.satelliteId > advancedSatelliteIdArray[x] && satellite.satelliteId < closestIdFound) {
							closestIdFound = satellite.satelliteId;
						} else if (prev && satellite.satelliteId < advancedSatelliteIdArray[x] && satellite.satelliteId > closestIdFound) {
							closestIdFound = satellite.satelliteId;
						}
					} else {
						//TODO
					}
				}
			}
		}
		if (closestIdFound == Integer.MAX_VALUE) {
			if(x == -1 && y == -1) {
				return satelliteId;
			} else if(y == -1) {
				return advancedSatelliteIdArray[x];
			} else {
				//TODO
			}
		}

		return closestIdFound;

	}


	public void onWrenchClicked(EntityPlayer entityplayer) {
		if (MainProxy.isServer(entityplayer.worldObj)) {
			MainProxy.sendPacketToPlayer(new GuiArgumentPacket(GuiIDs.GUI_CRAFTINGPIPE_ID, new Object[]{((CoreRoutedPipe)this.container.pipe).getUpgradeManager().isAdvancedSatelliteCrafter(), ((CoreRoutedPipe)this.container.pipe).getUpgradeManager().isSatelliteCraftingCrafter()}).getPacket(),  (Player) entityplayer);
			entityplayer.openGui(LogisticsPipes.instance, GuiIDs.GUI_CRAFTINGPIPE_ID, worldObj, xCoord, yCoord, zCoord);
		}
	}


	public void setPrevSatellite(EntityPlayer player) {
		if (MainProxy.isClient(player.worldObj)) {
			final PacketCoordinates packet = new PacketCoordinates(NetworkConstants.CRAFTING_PIPE_PREV_SATELLITE, xCoord, yCoord, zCoord);
			MainProxy.sendPacketToServer(packet.getPacket());
		} else {
			satelliteId = getNextConnectSatelliteId(true, -1, -1);
			final PacketPipeInteger packet = new PacketPipeInteger(NetworkConstants.CRAFTING_PIPE_SATELLITE_ID, xCoord, yCoord, zCoord, satelliteId);
			MainProxy.sendPacketToPlayer(packet.getPacket(), (Player)player);
		}
	}


	public void setNextSatellite(EntityPlayer player, int i) {
		if (MainProxy.isClient(player.worldObj)) {
			final PacketCoordinates packet = new PacketPipeInteger(NetworkConstants.CRAFTING_PIPE_NEXT_SATELLITE_ADVANCED, xCoord, yCoord, zCoord, i);
			MainProxy.sendPacketToServer(packet.getPacket());
		} else {
			advancedSatelliteIdArray[i] = getNextConnectSatelliteId(false, i, -1);
			final PacketModuleInteger packet = new PacketModuleInteger(NetworkConstants.CRAFTING_PIPE_SATELLITE_ID_ADVANCED, xCoord, yCoord, zCoord, i, advancedSatelliteIdArray[i]);
			MainProxy.sendPacketToPlayer(packet.getPacket(), (Player)player);
		}
	}


	public boolean isSatelliteConnected() {
		final List<ExitRoute> routes = getRoutedPipe().getRouter().getIRoutersByCost();
		if(!((CoreRoutedPipe)this.container.pipe).getUpgradeManager().isAdvancedSatelliteCrafter()) {
			if(satelliteId == 0) return true;
			for (final BaseLogicSatellite satellite : BaseLogicSatellite.AllSatellites) {
				if (satellite.satelliteId == satelliteId) {
					CoreRoutedPipe satPipe = satellite.getRoutedPipe();
					if(satPipe == null || satPipe.stillNeedReplace() || satPipe.getRouter() == null)
						continue;
					IRouter satRouter = satPipe.getRouter();
					for (ExitRoute route:routes) {
						if (route.destination == satRouter) {
							return true;
						}
					}
				}
			}
		} else {
			boolean foundAll = true;
			for(int i=0;i<9;i++) {
				boolean foundOne = false;
				if(advancedSatelliteIdArray[i] == 0) {
					continue;
				}
				for (final BaseLogicSatellite satellite : BaseLogicSatellite.AllSatellites) {
					if (satellite.satelliteId == advancedSatelliteIdArray[i]) {
						CoreRoutedPipe satPipe = satellite.getRoutedPipe();
						if(satPipe == null || satPipe.stillNeedReplace() || satPipe.getRouter() == null)
							continue;
						IRouter satRouter = satPipe.getRouter();
						for (ExitRoute route:routes) {
							if (route.destination == satRouter) {
								foundOne = true;
								break;
							}
						}
					}
				}
				foundAll &= foundOne;
			}
			return foundAll;
		}
		return false;
	}


	public void setPrevSatellite(EntityPlayer player, int i) {
		if (MainProxy.isClient(player.worldObj)) {
			final PacketCoordinates packet = new PacketPipeInteger(NetworkConstants.CRAFTING_PIPE_PREV_SATELLITE_ADVANCED, xCoord, yCoord, zCoord, i);
			MainProxy.sendPacketToServer(packet.getPacket());
		} else {
			advancedSatelliteIdArray[i] = getNextConnectSatelliteId(true, i, -1);
			final PacketModuleInteger packet = new PacketModuleInteger(NetworkConstants.CRAFTING_PIPE_SATELLITE_ID_ADVANCED, xCoord, yCoord, zCoord, i, advancedSatelliteIdArray[i]);
			MainProxy.sendPacketToPlayer(packet.getPacket(), (Player)player);
		}
	}


	public Pair<Integer, Integer> getBestReply(LiquidStack stack, IRouter sourceRouter, List<Integer> jamList) {
		for (ExitRoute candidateRouter : sourceRouter.getIRoutersByCost()){
			if(!candidateRouter.containsFlag(PipeRoutingConnectionType.canRouteTo)) continue;
			if(candidateRouter.destination.getSimpleID() == sourceRouter.getSimpleID()) continue;
			if(jamList.contains(candidateRouter.destination.getSimpleID())) continue;

			if (candidateRouter.destination.getPipe() == null || !candidateRouter.destination.getPipe().isEnabled()) continue;
			CoreRoutedPipe pipe = candidateRouter.destination.getPipe();

			if(!(pipe instanceof ILiquidSink)) continue;

			int amount = ((ILiquidSink)pipe).sinkAmount(stack);
			if(amount > 0) {
				Pair<Integer, Integer> result = new Pair<Integer, Integer>(candidateRouter.destination.getSimpleID(), amount);
				return result;
			}
		}
		Pair<Integer, Integer> result = new Pair<Integer, Integer>(0, 0);
		return result;
	}


	private static void onCraftingPipeSetSatellite(PacketPipeInteger packet) {
		final TileGenericPipe pipe = getPipe(FMLClientHandler.instance().getClient().theWorld, packet.posX, packet.posY, packet.posZ);
		if (pipe == null) {
			return;
		}

		if (!(pipe.pipe.logic instanceof BaseLogicCrafting)) {
			return;
		}

		((BaseLogicCrafting) pipe.pipe.logic).setSatelliteId(packet.integer, -1, -1);
	}


	private static void onCraftingPipeSetSatelliteAdvanced(PacketModuleInteger packet) {
		final TileGenericPipe pipe = getPipe(FMLClientHandler.instance().getClient().theWorld, packet.posX, packet.posY, packet.posZ);
		if (pipe == null) {
			return;
		}

		if (!(pipe.pipe.logic instanceof BaseLogicCrafting)) {
			return;
		}

		((BaseLogicCrafting) pipe.pipe.logic).setSatelliteId(packet.integer, packet.slot, -1);
	}


	private static void onCraftingPipeNextSatelliteAdvanced(EntityPlayerMP player, PacketPipeInteger packet) {
		final TileGenericPipe pipe = getPipe(player.worldObj, packet.posX, packet.posY, packet.posZ);
		if (pipe == null) {
			return;
		}

		if (!(pipe.pipe.logic instanceof BaseLogicCrafting)) {
			return;
		}

		((BaseLogicCrafting) pipe.pipe.logic).setNextSatellite(player, packet.integer);
	}


	private static void onCraftingPipePrevSatelliteAdvanced(EntityPlayerMP player, PacketPipeInteger packet) {
		final TileGenericPipe pipe = getPipe(player.worldObj, packet.posX, packet.posY, packet.posZ);
		if (pipe == null) {
			return;
		}

		if (!(pipe.pipe.logic instanceof BaseLogicCrafting)) {
			return;
		}

		((BaseLogicCrafting) pipe.pipe.logic).setPrevSatellite(player, packet.integer);
	}


	public void readData(DataInputStream data) throws IOException {
		guiID = data.readInt();
		int size = data.readInt();
		args = new Object[size];
		for(int i=0; i < size;i++) {
			int arraySize = data.readInt();
			byte[] bytes = new byte[arraySize];
			data.read(bytes);
			ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
			ObjectInput in = null;
			in = new ObjectInputStream(bis);
			try {
				Object o = in.readObject();
				args[i] = o;
			} catch (ClassNotFoundException e) {
				throw new UnsupportedOperationException(e);
			}
		}
	}


	public int getID() {
		return NetworkConstants.GUI_ARGUMENT_PACKET;
	}


	public void writeData(DataOutputStream data) throws IOException {
		data.writeInt(guiID);
		data.writeInt(args.length);
		for(int i=0; i<args.length;i++) {
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			ObjectOutput out = null;
			out = new ObjectOutputStream(bos);
			out.writeObject(args[i]);
			byte[] bytes = bos.toByteArray();
			data.writeInt(bytes.length);
			data.write(bytes);
		}
	}


	public GuiArgumentPacket() {
		super();
	}


	public GuiArgumentPacket(int Id, Object... arg) {
		super();
		args = arg;
		guiID = Id;
	}


	public CraftingTemplate addCrafting() {

		if (!isEnabled()){
			return null;
		}

		BaseLogicCrafting craftingLogic = (BaseLogicCrafting) this.logic;
		ItemStack stack = craftingLogic.getCraftedItem();
		if (stack == null) return null;

		IRequestItems[] target = new IRequestItems[9];
		for(int i=0;i<9;i++) {
			target[i] = this;
		}

		boolean hasSatellite = craftingLogic.isSatelliteConnected();
		if(!hasSatellite) return null;
		if(!getUpgradeManager().isAdvancedSatelliteCrafter()) {
			if(craftingLogic.satelliteId != 0) {
				IRequestItems sat = (IRequestItems)craftingLogic.getSatelliteRouter(-1, -1).getPipe();
				for(int i=6;i<9;i++) {
					target[i] = sat;
				}
			}
		} else {
			for(int i=0;i<9;i++) {
				if(craftingLogic.advancedSatelliteIdArray[i] != 0) {
					target[i] = (IRequestItems)craftingLogic.getSatelliteRouter(i, -1).getPipe();
				}
			}
		}

		CraftingTemplate template = new CraftingTemplate(ItemIdentifierStack.GetFromStack(stack), this, craftingLogic.priority);

		//Check all materials
		for (int i = 0; i < 9; i++){
			ItemStack resourceStack = craftingLogic.getMaterials(i);
			if (resourceStack == null || resourceStack.stackSize == 0) continue;
			template.addRequirement(ItemIdentifierStack.GetFromStack(resourceStack), target[i]);

		}
		return template;
	}


	public Set<ItemIdentifier> getSpecificInterests() {
		Set<ItemIdentifier> l1 = new TreeSet<ItemIdentifier>();;
		for(Pair<TileEntity, ForgeDirection> pair:getAdjacentTanks(false)) {
			ILiquidTank[] tanks = ((ITankContainer)pair.getValue1()).getTanks(pair.getValue2().getOpposite());
			for(ILiquidTank tank:tanks) {
				LiquidStack liquid;
				if((liquid = tank.getLiquid()) != null && liquid.itemID != 0) {
					LiquidIdentifier ident = LiquidIdentifier.get(liquid);
					l1.add(ident.getItemIdentifier());
				}
			}
		}
		return l1;
	}


	public boolean isAllowed(CoreRoutedPipe pipe) {
		return pipe instanceof PipeItemsCraftingLogistics;
	}


	public boolean needsUpdate() {
		return false;
	}


	public boolean isAllowed(CoreRoutedPipe pipe) {
		return true;
	}


	public boolean isAllowed(CoreRoutedPipe pipe) {
		return pipe instanceof PipeItemsSatelliteLogistics;
	}


	public boolean isSatelliteCraftingCrafter() {
		return isSatelliteCraftingCrafter;
	}


	public DummyContainer getDummyContainer(EntityPlayer player) {
		DummyContainer dummy = new DummyContainer(player.inventory, inv);
		dummy.addNormalSlotsForPlayerInventory(8, 60);

		//Pipe slots
	    for(int pipeSlot = 0; pipeSlot < 8; pipeSlot++){
	    	dummy.addRestrictedSlot(pipeSlot, inv, 8 + pipeSlot * 18, 18, new ISlotCheck() {
				@Override
				public boolean isStackAllowed(ItemStack itemStack) {
					if(itemStack == null) return false;
					if(itemStack.itemID == LogisticsPipes.UpgradeItem.itemID) {
						if(!LogisticsPipes.UpgradeItem.getUpgradeForItem(itemStack, null).isAllowed(pipe)) return false;
					} else {
						return false;
					}
					return true;
				}
	    	});
	    }
    	dummy.addRestrictedSlot(8, inv, 8 + 8 * 18, 18, new ISlotCheck() {
			@Override
			public boolean isStackAllowed(ItemStack itemStack) {
				if(itemStack == null) return false;
				if(itemStack.itemID != LogisticsPipes.LogisticsItemCard.itemID) return false;
				if(itemStack.getItemDamage() != LogisticsItemCard.SEC_CARD) return false;
				return true;
			}
    	});
	    return dummy;
	}


	public void InventoryChanged(SimpleInventory inventory) {
		boolean needUpdate = false;
		for(int i=0;i<inv.getSizeInventory() - 1;i++) {
			ItemStack item = inv.getStackInSlot(i);
			if(item != null) {
				needUpdate |= updateModule(i);
			} else if(item == null && upgrades[i] != null) {
				needUpdate |= removeUpgrade(i);
			}
		}
		//update sneaky direction, speed upgrade count and disconnection
		sneakyOrientation = ForgeDirection.UNKNOWN;
		speedUpgradeCount = 0;
		isAdvancedCrafter = false;
		isSatelliteCraftingSatellite = false;
		isSatelliteCraftingCrafter = false;
		disconnectedSides.clear();
		for(int i=0;i<upgrades.length;i++) {
			IPipeUpgrade upgrade = upgrades[i];
			if(upgrade instanceof SneakyUpgrade && sneakyOrientation == ForgeDirection.UNKNOWN) {
				sneakyOrientation = ((SneakyUpgrade) upgrade).getSneakyOrientation();
			} else if(upgrade instanceof SpeedUpgrade) {
				speedUpgradeCount += inv.getStackInSlot(i).stackSize;
			} else if(upgrade instanceof ConnectionUpgrade) {
				disconnectedSides.add(((ConnectionUpgrade)upgrade).getSide());
			} else if(upgrade instanceof SplitCraftingCrafterUpgrade) {
				isSatelliteCraftingCrafter = true;
			} else if(upgrade instanceof SplitCraftingSatelliteUpgrade) {
				isSatelliteCraftingSatellite = true;
			} else if(upgrade instanceof AdvancedSatelliteUpgrade) {
				isAdvancedCrafter = true;
			}
		}
		if(needUpdate) {
			pipe.connectionUpdate();
		}
	}


	public boolean tryIserting(World world, EntityPlayer entityplayer) {
		if(entityplayer.getCurrentEquippedItem() != null && entityplayer.getCurrentEquippedItem().itemID == LogisticsPipes.UpgradeItem.itemID && LogisticsPipes.UpgradeItem.getUpgradeForItem(entityplayer.getCurrentEquippedItem(), null).isAllowed(pipe)) {
			if(MainProxy.isClient(world)) return true;
			for(int i=0;i<inv.getSizeInventory() - 1;i++) {
				ItemStack item = inv.getStackInSlot(i);
				if(item == null) {
					inv.setInventorySlotContents(i, entityplayer.getCurrentEquippedItem().splitStack(1));
					InventoryChanged(inv);
					return true;
				} else if(item.getItemDamage() == entityplayer.getCurrentEquippedItem().getItemDamage()) {
					if(item.stackSize < inv.getInventoryStackLimit()) {
						item.stackSize++;
						entityplayer.getCurrentEquippedItem().splitStack(1);
						return true;
					}
				}
			}
		}
		if(entityplayer.getCurrentEquippedItem() != null && entityplayer.getCurrentEquippedItem().itemID == LogisticsPipes.LogisticsItemCard.itemID && entityplayer.getCurrentEquippedItem().getItemDamage() == LogisticsItemCard.SEC_CARD) {
			if(MainProxy.isClient(world)) return true;
			if(inv.getStackInSlot(8) == null) {
				inv.setInventorySlotContents(8, entityplayer.getCurrentEquippedItem().copy());
				inv.getStackInSlot(8).stackSize = 1;
				entityplayer.getCurrentEquippedItem().splitStack(1);
				return true;
			}
		}
		return false;
	}


	public boolean isSatelliteCraftingSatellite() {
		return isSatelliteCraftingSatellite;
	}


	public boolean isAdvancedSatelliteCrafter() {
		return isAdvancedCrafter;
	}


    public static void drawBigSlotBackground(Minecraft mc, int x, int y) {
		int i = mc.renderEngine.getTexture("/logisticspipes/gui/slot-big.png");
		GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
		mc.renderEngine.bindTexture(i);

		Tessellator var9 = Tessellator.instance;
        var9.startDrawingQuads();
        var9.addVertexWithUV(x		, y + 26	, (double)zLevel, 0	, 1);
        var9.addVertexWithUV(x + 26	, y + 26	, (double)zLevel, 1	, 1);
        var9.addVertexWithUV(x + 26	, y			, (double)zLevel, 1	, 0);
        var9.addVertexWithUV(x		, y			, (double)zLevel, 0	, 0);
        var9.draw();
    }


	public void writeToLPData(LPDataOutput output) {
		output.writeLongArray(amountRecorded);
		output.writeInt(arrayPos);
		output.writeItemIdentifier(item);
	}


	public void readFromLPData(LPDataInput input) {
		amountRecorded = input.readLongArray();
		arrayPos = input.readInt();
		item = input.readItemIdentifier();
	}


	public void setUseNewRenderer(boolean flag) {
		useNewRenderer = flag;
	}


	public void readData(LPDataInput input) {
		useNewRenderer = input.readBoolean();
		useFallbackRenderer = input.readBoolean();
		renderPipeDistance = input.readInt();
		renderPipeContentDistance = input.readInt();
		isUninitialised = false;
	}


	public void writeData(LPDataOutput output) {
		output.writeBoolean(useNewRenderer);
		output.writeBoolean(useFallbackRenderer);
		output.writeInt(renderPipeDistance);
		output.writeInt(renderPipeContentDistance);
	}


	public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
		super.handlerAdded(ctx);
		ctx.attr(PacketHandler.INBOUNDPACKETTRACKER).set(new ThreadLocal<>());
	}


	private static void onPacketData(ModernPacket packet, final EntityPlayer player) {
		try {
			packet.processPacket(player);
			if (LPConstants.DEBUG) {
				PacketHandler.debugMap.remove(packet.getDebugId());
			}
		} catch (DelayPacketException e) {
			if (packet.retry() && MainProxy.isClient(player.getEntityWorld())) {
				SimpleServiceLocator.clientBufferHandler.queueFailedPacket(packet, player);
			} else if (LPConstants.DEBUG) {
				LogisticsPipes.log.error(packet.getClass().getName());
				LogisticsPipes.log.error(packet.toString());
				e.printStackTrace();
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}


	public static void onPacketData(final LPDataInput data, final EntityPlayer player) {
		if (player == null) {
			return;
		}
		final int packetID = data.readShort();
		final ModernPacket packet = PacketHandler.packetlist.get(packetID).template();
		packet.setDebugId(data.readInt());
		packet.readData(data);
		PacketHandler.onPacketData(packet, player);
	}


		InboundModernPacketWrapper(ModernPacket p, EntityPlayer e) {
			packet = p;
			player = e;
		}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeBoolean(flag);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		flag = input.readBoolean();
	}


	public BooleanModuleCoordinatesGuiProvider(int id) {
		super(id);
	}


	public void writeData(LPDataOutput output) {

		output.writeInt(posX);
		output.writeInt(posY);
		output.writeInt(posZ);
	}


	public void readData(LPDataInput input) {

		posX = input.readInt();
		posY = input.readInt();
		posZ = input.readInt();

	}


	public CoordinatesGuiProvider(int id) {
		super(id);
	}


	public CoordinatesPopupGuiProvider(int id) {
		super(id);
	}


public void writeData(LPDataOutput output) {}


public void readData(LPDataInput input) {}


	public void readData(LPDataInput input) {
		super.readData(input);
		slot = input.readEnum(ModulePositionType.class);
		positionInt = input.readInt();
	}


	public ModuleCoordinatesGuiProvider(int id) {
		super(id);
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeEnum(slot);
		output.writeInt(positionInt);
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeInt(invSlot);
	}


	public ModuleInHandGuiProvider(int id) {
		super(id);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		invSlot = input.readInt();
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		nbt = input.readNBTTagCompound();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeNBTTagCompound(nbt);
	}


	public UpgradeCoordinatesGuiProvider(int id) {
		super(id);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		positionInt = input.readInt();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeInt(positionInt);
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeBitSet(getFlags());
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		setFlags(input.readBitSet());
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeBoolean(flag);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		flag = input.readBoolean();
	}


	public void readData(LPDataInput input) {

		posX = input.readInt();
		posY = input.readInt();
		posZ = input.readInt();

	}


	public CoordinatesPacket(int id) {
		super(id);
	}


	public void writeData(LPDataOutput output) {

		output.writeInt(posX);
		output.writeInt(posY);
		output.writeInt(posZ);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		direction = input.readForgeDirection();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeForgeDirection(direction);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		setInteger2(input.readInt());
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeInt(getInteger2());
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeInt(getInteger());
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		setInteger(input.readInt());
	}


	public void readData(LPDataInput input) {
		setInteger(input.readInt());
	}


	public void writeData(LPDataOutput output) {
		output.writeInt(getInteger());
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);

		if (inventory != null) {
			output.writeByte(STACK_MARKER);
			output.writeInt(inventory.getSizeInventory());
			for (int i = 0; i < inventory.getSizeInventory(); i++) {
				output.writeItemStack(inventory.getStackInSlot(i));
			}
		} else if (stackList != null) {
			output.writeByte(STACK_MARKER);
			output.writeCollection(stackList, LPDataOutput::writeItemStack);
		} else if (identList != null) {
			output.writeByte(IDENT_MARKER);
			output.writeCollection(identList, LPDataOutput::writeItemIdentifierStack);
		} else if (identSet != null) {
			output.writeByte(IDENT_MARKER);
			output.writeCollection(identSet, LPDataOutput::writeItemIdentifierStack);
		} else {
			throw new IllegalStateException("Wont send packet without content");
		}
	}


	public void readData(LPDataInput input) {
		super.readData(input);

		byte marker = input.readByte();
		if (marker == STACK_MARKER) {
			stackList = input.readLinkedList(LPDataInput::readItemStack);
		} else if (marker == IDENT_MARKER) {
			identList = input.readLinkedList(LPDataInput::readItemIdentifierStack);
		} else {
			throw new UnsupportedOperationException("Unknown marker: " + marker);
		}
	}


	public void readData(LPDataInput input) {
		super.readData(input);

		final int itemID = input.readInt();
		if (itemID != 0) {
			int stackSize = input.readInt();
			int damage = input.readInt();
			setStack(new ItemStack(Item.getItemById(itemID), stackSize, damage));
			getStack().setTagCompound(input.readNBTTagCompound());
		} else {
			setStack(null);
		}
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		if (getStack() != null) {
			output.writeInt(Item.getIdFromItem(getStack().getItem()));
			output.writeInt(getStack().stackSize);
			output.writeInt(getStack().getItemDamage());
			output.writeNBTTagCompound(getStack().getTagCompound());
		} else {
			output.writeInt(0);
		}
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeCollection(list, this);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		list = input.readArrayList(this);
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeBoolean(type != null);
		if (type != null) {
			output.writeEnum(type);
			output.writeInt(positionInt);
		}
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		if (input.readBoolean()) {
			type = input.readEnum(ModulePositionType.class);
			positionInt = input.readInt();
		}
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeNBTTagCompound(tag);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		tag = input.readNBTTagCompound();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeItemIdentifierStack(stack);
		output.writeInt(dimension);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		stack = input.readItemIdentifierStack();
		dimension = input.readInt();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeUTF(getString());
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		setString(input.readUTF());
	}


	public void readData(LPDataInput input) {
		int size = input.readInt();
		for (int i = 0; i < size; i++) {
			getStringList().add(input.readUTF());
		}
	}


	public void writeData(LPDataOutput output) {
		output.writeInt(getStringList().size());
		for (int i = 0; i < getStringList().size(); i++) {
			output.writeUTF(getStringList().get(i));
		}
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		targetType = input.readItemIdentifier();
		if (input.readBoolean()) {
			for (int i = 0; i < 9; i++) {
				ignore_dmg[i] = input.readBoolean();
				ignore_nbt[i] = input.readBoolean();
				use_od[i] = input.readBoolean();
				use_category[i] = input.readBoolean();
			}
		}
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeItemIdentifier(targetType);
		output.writeBoolean(isFuzzy);
		if (isFuzzy) {
			for (int i = 0; i < 9; i++) {
				output.writeBoolean(ignore_dmg[i]);
				output.writeBoolean(ignore_nbt[i]);
				output.writeBoolean(use_od[i]);
				output.writeBoolean(use_category[i]);
			}
		}
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeCollection(trackingList, (output1, object) -> object.writeToLPData(output1));

	}


	public void readData(LPDataInput input) {
		super.readData(input);
		trackingList = input.readArrayList(data1 -> {
			TrackingTask object = new TrackingTask();
			object.readFromLPData(data1);
			return object;
		});
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		dir = input.readForgeDirection();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeForgeDirection(dir);
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeIntArray(amount);
		output.writeBoolean(cleanupExclude);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		amount = input.readIntArray();
		cleanupExclude = input.readBoolean();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeBoolean(patternUpgarde);
		output.writeIntArray(slotArray);
		output.writeBoolean(isLimit);
		output.writeInt(mode);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		patternUpgarde = input.readBoolean();
		slotArray = input.readIntArray();
		isLimit = input.readBoolean();
		mode = input.readInt();
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		areItemsIncluded = input.readBoolean();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeBoolean(areItemsIncluded);
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeInt(extractorMode);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		extractorMode = input.readInt();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeInt(timeOut);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		timeOut = input.readInt();
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		isAdvancedSat = input.readBoolean();
		liquidCrafter = input.readInt();
		amount = input.readIntArray();
		hasByproductExtractor = input.readBoolean();
		isFuzzy = input.readBoolean();
		cleanupSize = input.readInt();
		cleanupExclude = input.readBoolean();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeBoolean(isAdvancedSat);
		output.writeInt(liquidCrafter);
		output.writeIntArray(amount);
		output.writeBoolean(hasByproductExtractor);
		output.writeBoolean(isFuzzy);
		output.writeInt(cleanupSize);
		output.writeBoolean(cleanupExclude);
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeForgeDirection(sneakyOrientation);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		sneakyOrientation = input.readForgeDirection();
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		isDefaultRoute = input.readBoolean();
		hasFuzzyUpgrade = input.readBoolean();
		ignoreData = input.readBitSet();
		ignoreNBT = input.readBitSet();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeBoolean(isDefaultRoute);
		output.writeBoolean(hasFuzzyUpgrade);
		output.writeBitSet(ignoreData);
		output.writeBitSet(ignoreNBT);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		exclude = input.readBoolean();
		extractorMode = input.readInt();
		isActive = input.readBoolean();
		sneakyOrientation = input.readForgeDirection();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeBoolean(exclude);
		output.writeInt(extractorMode);
		output.writeBoolean(isActive);
		output.writeForgeDirection(sneakyOrientation);
	}


public void writeData(LPDataOutput output) {}


public void readData(LPDataInput input) {}


	public void writeData(LPDataOutput output) {
		output.writeByteArray(content);
	}


	public void readData(LPDataInput input) {
		content = input.readByteArray();
	}


	public void readData(LPDataInput input) {
		enumSet = EnumSet.noneOf(CraftingDependency.class);
		for (CraftingDependency type : CraftingDependency.values()) {
			if (input.readBoolean()) {
				enumSet.add(type);
			}
		}
	}


	public void writeData(LPDataOutput output) {
		for (CraftingDependency type : CraftingDependency.values()) {
			output.writeBoolean(enumSet.contains(type));
		}
	}


	public void readData(LPDataInput input) {
		throw new RuntimeException("This packet should never be used");
	}


	public void writeData(LPDataOutput output) {
		throw new RuntimeException("This packet should never be used");
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);

		output.writeInt(content.length);

		for (int i = 0; i < content.length; i++) {
			final ItemStack itemstack = content[i];

			if (itemstack != null) {
				output.writeByte(i);
				output.writeInt(Item.getIdFromItem(itemstack.getItem()));
				output.writeInt(itemstack.stackSize);
				output.writeInt(itemstack.getItemDamage());
				output.writeNBTTagCompound(itemstack.getTagCompound());
			}
		}
		output.writeByte(-1); // mark packet end
	}


	public void readData(LPDataInput input) {
		super.readData(input);

		content = new ItemStack[input.readInt()];

		byte index = input.readByte();

		while (index != -1) { // read until the end
			final int itemID = input.readInt();
			int stackSize = input.readInt();
			int damage = input.readInt();
			ItemStack stack = new ItemStack(Item.getItemById(itemID), stackSize, damage);
			stack.setTagCompound(input.readNBTTagCompound());
			content[index] = stack;
			index = input.readByte(); // read the next slot
		}
	}


	public void readData(LPDataInput input) {
		LogisticsPipes.getClientPlayerConfig().readData(input);
	}


	public void writeData(LPDataOutput output) {
		config.writeData(output);
	}


	public void readData(LPDataInput input) {
		config = new PlayerConfig(null);
		config.readData(input);
	}


	public void readData(LPDataInput input) {
		ident = input.readItemIdentifierStack().getItem();
		name = input.readUTF();
	}


	public void writeData(LPDataOutput output) {
		output.writeItemIdentifierStack(ident.makeStack(0));
		output.writeUTF(name);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		item = input.readItemIdentifier();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeItemIdentifier(item);
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeBoolean(down);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		down = input.readBoolean();
	}


	public CraftingCycleRecipe(int id) {
		super(id);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		targetType = input.readItemIdentifier();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeItemIdentifier(targetType);
	}


	public CraftingSetType(int id) {
		super(id);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		length = input.readFloat();
		dir = input.readForgeDirection();
		color = input.readInt();
		reverse = input.readBoolean();
		renderBall = input.readBoolean();
		remove = input.readBoolean();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeFloat(length);
		output.writeForgeDirection(dir);
		output.writeInt(color);
		output.writeBoolean(reverse);
		output.writeBoolean(renderBall);
		output.writeBoolean(remove);
	}


	public PowerPacketLaser(int id) {
		super(id);
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeDouble(getDouble());
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		setDouble(input.readDouble());
	}


	public void readData(LPDataInput input) {
		identList = input.readArrayList(LPDataInput::readItemIdentifierStack);
	}


	public void writeData(LPDataOutput output) {
		output.writeCollection(identList, LPDataOutput::writeItemIdentifierStack);
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeLong(uuid.getMostSignificantBits());
		output.writeLong(uuid.getLeastSignificantBits());
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		uuid = new UUID(input.readLong(), input.readLong());
	}


	public void writeData(LPDataOutput output) {
		output.writeInt(buttonID);
		super.writeData(output);
	}


	public void readData(LPDataInput input) {
		buttonID = input.readInt();
		super.readData(input);
	}


public void readData(LPDataInput input) {}


public void writeData(LPDataOutput output) {}


	public void readData(LPDataInput input) {
		super.readData(input);
		mode = input.readBoolean();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeBoolean(mode);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		pipeId = input.readInt();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeInt(pipeId);
	}


	public void writeData(LPDataOutput output) {
		output.writeInt(windowID);
		output.writeUTF(line);
	}


	public void readData(LPDataInput input) {
		windowID = input.readInt();
		line = input.readUTF();
	}


	public void writeData(LPDataOutput output) {
		output.writeInt(windowID);
		output.writeUTF(title);
	}


	public void readData(LPDataInput input) {
		windowID = input.readInt();
		title = input.readUTF();
	}


	public void writeData(LPDataOutput output) {
		output.writeInt(windowID);
		output.writeCollection(status, new IWriteListObject<StatusEntry>() {

			@Override
			public void writeObject(LPDataOutput output, StatusEntry entry) {
				output.writeUTF(entry.name);
				output.writeBoolean(entry.subEntry != null);
				if (entry.subEntry != null) {
					output.writeCollection(entry.subEntry, this);
				}
			}
		});
	}


	public void readData(LPDataInput input) {
		windowID = input.readInt();
		status = input.readArrayList(new IReadListObject<StatusEntry>() {

			@Override
			public StatusEntry readObject(LPDataInput input) {
				StatusEntry status = new StatusEntry();
				status.name = input.readUTF();
				if (input.readBoolean()) {
					status.subEntry = input.readArrayList(this);
				}
				return status;
			}
		});
	}


	public void processPacket(EntityPlayer player) {
		MovingObjectPosition box = FMLClientHandler.instance().getClient().objectMouseOver;
		if (box == null) {
			MainProxy.sendPacketToServer(PacketHandler.getPacket(DebugTargetResponse.class).setMode(DebugTargetResponse.TargetMode.None));
		} else if (box.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) {
			MainProxy.sendPacketToServer(PacketHandler.getPacket(DebugTargetResponse.class).setMode(DebugTargetResponse.TargetMode.Block)
					.setAdditions(new int[] { box.blockX, box.blockY, box.blockZ }));
		} else if (box.typeOfHit == MovingObjectPosition.MovingObjectType.ENTITY) {
			MainProxy.sendPacketToServer(PacketHandler.getPacket(DebugTargetResponse.class).setMode(DebugTargetResponse.TargetMode.Entity)
					.setAdditions(new int[] { box.entityHit.getEntityId() }));
		}
	}


	public void writeData(LPDataOutput output) {
		output.writeByteArray(payload);
		output.writeInt(identifier);
	}


	public void readData(LPDataInput input) {
		payload = input.readByteArray();
		identifier = input.readInt();
	}


	public void writeData(LPDataOutput output) {
		output.writeUTF(getName());
		output.writeInt(getIdentification());
	}


	public void readData(LPDataInput input) {
		setName(input.readUTF());
		setIdentification(input.readInt());
	}


	public DebugTargetResponse(int id) {
		super(id);
	}


	public void readData(LPDataInput input) {
		mode = TargetMode.values()[input.readByte()];
		additions = input.readIntArray();
	}


	public void writeData(LPDataOutput output) {
		output.writeByte(mode.ordinal());
		output.writeIntArray(additions);
	}


	public void writeData(LPDataOutput output) {
		output.writeInt(slotId);
		output.writeItemIdentifierStack(ItemIdentifierStack.getFromStack(stack));
		output.writeInt(button);
	}


	public void readData(LPDataInput input) {
		slotId = input.readInt();
		stack = input.readItemIdentifierStack().makeNormalStack();
		button = input.readInt();
	}


	public void writeData(LPDataOutput output) {
		output.writeInt(slotNumber);
		output.writeBitSet(flags);
	}


	public void readData(LPDataInput input) {
		slotNumber = input.readInt();
		flags = input.readBitSet();
	}


	public void readData(LPDataInput input) {
		guiID = input.readInt();
		windowID = input.readInt();
		guiData = input.readByteArray();
	}


	public void writeData(LPDataOutput output) {
		output.writeInt(guiID);
		output.writeInt(windowID);
		output.writeByteArray(guiData);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		guiID = input.readInt();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeInt(getGuiID());
	}


	public GuiReopenPacket(int id) {
		super(id);
	}


public void writeData(LPDataOutput output) {}


public void readData(LPDataInput input) {}


	public void readData(LPDataInput input) {
		buttonId = input.readInt();
		state = input.readBoolean();
		slot = input.readInt();
	}


	public void writeData(LPDataOutput output) {
		output.writeInt(buttonId);
		output.writeBoolean(state);
		output.writeInt(slot);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		mode = input.readInt();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeInt(mode);
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeInt(integer2);
		output.writeInt(integer3);
		output.writeInt(integer4);
		if (string1 == null) {
			string1 = "";
		}
		output.writeUTF(string1);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		integer2 = input.readInt();
		integer3 = input.readInt();
		integer4 = input.readInt();
		string1 = input.readUTF();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeBoolean(isDefault);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		isDefault = input.readBoolean();
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		nbt = input.readNBTTagCompound();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeNBTTagCompound(nbt);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		isLimited = input.readBoolean();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeBoolean(isLimited);
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeInt(timeOut);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		timeOut = input.readInt();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeInt(sinkSize);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		sinkSize = input.readInt();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeInt(pos);
		if (pos != -1) {
			output.writeBoolean(isNBT);
		} else {
			output.writeBitSet(ignoreData);
			output.writeBitSet(ignoreNBT);
		}
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		pos = input.readInt();
		if (pos != -1) {
			isNBT = input.readBoolean();
		} else {
			ignoreData = input.readBitSet();
			ignoreNBT = input.readBitSet();
		}
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeBoolean(hasPatternUpgrade);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		hasPatternUpgrade = input.readBoolean();
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		targetPos = input.readSet(LPDataInput::readLPPosition);
		subTypes = input.readArrayList(data1 -> data1.readEnum(CoreMultiBlockPipe.SubBlockTypeForShare.class));
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeCollection(targetPos, LPDataOutput::writeLPPosition);
		output.writeCollection(subTypes, LPDataOutput::writeEnum);
	}


	public MultiBlockCoordinatesPacket(int id) {
		super(id);
	}


	public void writeData(LPDataOutput output) {
		output.writeCollection(used, LPDataOutput::writeResource);
		output.writeCollection(missing, LPDataOutput::writeResource);
		// ToDo: ???
		output.writeByte(0);
	}


	public void readData(LPDataInput input) {
		used = input.readArrayList(LPDataInput::readResource);
		missing = input.readArrayList(LPDataInput::readResource);
	}


	public void writeData(LPDataOutput output) {
		output.writeCollection(items, LPDataOutput::writeResource);
		output.writeBoolean(isFlag());
	}


	public void readData(LPDataInput input) {
		items = input.readArrayList(LPDataInput::readResource);
		setFlag(input.readBoolean());
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeResource(stack);
		output.writeLinkedLogisticsOrderList(orders);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		stack = input.readResource();
		orders = input.readLinkedLogisticsOrderList();
	}


public void readData(LPDataInput input) {}


public void writeData(LPDataOutput output) {}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeIntArray(amount);
		output.writeIntArray(liquidSatelliteIdArray);
		output.writeInt(liquidSatelliteId);
		output.writeInt(satelliteId);
		output.writeIntArray(advancedSatelliteIdArray);
		output.writeInt(priority);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		amount = input.readIntArray();
		liquidSatelliteIdArray = input.readIntArray();
		liquidSatelliteId = input.readInt();
		satelliteId = input.readInt();
		advancedSatelliteIdArray = input.readIntArray();
		priority = input.readInt();
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		content = input.readArrayList(input1 -> {
			GuiRecipeImport.Canidates can = new GuiRecipeImport.Canidates(new TreeSet<>());
			can.order = input1.readArrayList(LPDataInput::readItemIdentifierStack);
			return can;
		});
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeCollection(content, (data, object) -> data.writeCollection(object.order,
				(IWriteListObject<ItemIdentifierStack>) LPDataOutput::writeItemIdentifierStack));
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		if (input.readBoolean()) {
			stack = input.readItemIdentifierStack();
		}
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		if (stack == null) {
			output.writeBoolean(false);
		} else {
			output.writeBoolean(true);
			output.writeItemIdentifierStack(stack);
		}
	}


	public Triplet<ItemIdentifierStack, Pair<Integer /* Time */, Integer /* BufferCounter */>, LPTravelingItemServer> readObject(LPDataInput input) {
		return new Triplet<>(input.readItemIdentifierStack(), null, null);
	}


	public void writeObject(LPDataOutput output,
			Triplet<ItemIdentifierStack, Pair<Integer /* Time */, Integer /* BufferCounter */>, LPTravelingItemServer> object) {
		output.writeItemIdentifierStack(object.getValue1());
	}


	public void readData(LPDataInput input) {
		response = input.readArrayList(LPDataInput::readInt);
	}


	public void writeData(LPDataOutput output) {
		output.writeCollection(response, LPDataOutput::writeInt);
	}


	public ParticleFX(int id) {
		super(id);
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeInt(particles.size());
		for (ParticleCount pc : particles) {
			output.writeByte(pc.getParticle().ordinal());
			output.writeInt(pc.getAmount());
		}
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		int nparticles = input.readInt();
		particles = new ArrayList<>(nparticles);
		for (int i = 0; i < nparticles; i++) {
			int particle = input.readByte();
			int amount = input.readInt();
			particles.add(new ParticleCount(Particles.values()[particle], amount));
		}
	}


	public PipeContentPacket(int id) {
		super(id);
	}


	public void readData(LPDataInput input) {
		item = input.readItemIdentifierStack();
		travelId = input.readInt();
	}


	public void writeData(LPDataOutput output) {
		output.writeItemIdentifierStack(item);
		output.writeInt(travelId);
	}


	public void readData(LPDataInput input) {
		isServer = input.readBoolean();
	}


	public void writeData(LPDataOutput output) {
		output.writeBoolean(isServer);
	}


	public PipeFluidUpdate(int id) {
		super(id);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		bits = input.readBitSet();
		for (int i = 0; i < renderCache.length; i++) {
			if (bits.get(i)) {
				renderCache[i] = new FluidStack(FluidRegistry.getFluid(input.readInt()), input.readInt(), input.readNBTTagCompound());
			}
		}
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		for (int i = 0; i < renderCache.length; i++) {
			bits.set(i, renderCache[i] != null);
		}
		output.writeBitSet(bits);
		for (FluidStack aRenderCache : renderCache) {
			if (aRenderCache != null) {
				output.writeInt(FluidRegistry.getFluidID(aRenderCache.getFluid()));
				output.writeInt(aRenderCache.amount);
				output.writeNBTTagCompound(aRenderCache.tag);
			}
		}
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		for (LogisticsOrder order : manager) {
			output.writeByte(1);
			output.writeOrderInfo(order);
		}
		output.writeByte(0);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		clientOrder = new LinkedList<>();
		while (input.readByte() == 1) {
			clientOrder.add(input.readOrderInfo());
		}
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeBoolean(start);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		start = input.readBoolean();
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		travelId = input.readInt();
		speed = input.readFloat();
		position = input.readFloat();
		this.input = input.readForgeDirection();
		output = input.readForgeDirection();
		yaw = input.readFloat();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeInt(travelId);
		output.writeFloat(speed);
		output.writeFloat(position);
		output.writeForgeDirection(input);
		output.writeForgeDirection(this.output);
		output.writeFloat(yaw);
	}


	public PipeSignTypes(int id) {
		super(id);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		types = input.readArrayList(LPDataInput::readInt);
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeCollection(types, LPDataOutput::writeInt);
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);

		IClientState[] clientStates = new IClientState[] { renderState, coreState, bcPluggableState, pipe };
		byte[][] clientStateBuffers = new byte[][] { bytesRenderState, bytesCoreState, bytesBCPluggableState, bytesPipe };
		for (int i = 0; i < clientStates.length; i++) {
			clientStateBuffers[i] = LPDataIOWrapper.collectData(clientStates[i]::writeData);
			output.writeByteArray(clientStateBuffers[i]);
		}
	}


	public void readData(LPDataInput input) {
		super.readData(input);

		bytesRenderState = input.readByteArray();
		bytesCoreState = input.readByteArray();
		bytesBCPluggableState = input.readByteArray();
		bytesPipe = input.readByteArray();
	}


	public void processPacket(EntityPlayer player) {
		LogisticsTileGenericPipe pipe = this.getPipe(player.getEntityWorld());
		if (pipe == null) {
			return;
		}
		LPDataIOWrapper.provideData(bytesRenderState, pipe.renderState::readData);
		LPDataIOWrapper.provideData(bytesCoreState, pipe.coreState::readData);
		LPDataIOWrapper.provideData(bytesBCPluggableState, pipe.bcPlugableState::readData);
		pipe.afterStateUpdated();
		LPDataIOWrapper.provideData(bytesPipe, pipe.pipe::readData);
	}


	public void readData(LPDataInput input) {
		while (input.readBoolean()) {
			lasers.add(new LaserData().readData(input));
		}
	}


	public void writeData(LPDataOutput output) {
		for (LaserData laser : lasers) {
			output.writeBoolean(true);
			laser.writeData(output);
		}
		output.writeBoolean(false);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		tagetPosX = input.readInt();
		tagetPosY = input.readInt();
		tagetPosZ = input.readInt();
		slot = input.readInt();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeInt(tagetPosX);
		output.writeInt(tagetPosY);
		output.writeInt(tagetPosZ);
		output.writeInt(slot);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		inventorySlot = input.readInt();
		slot = input.readInt();
		pipePosX = input.readInt();
		pipePosY = input.readInt();
		pipePosZ = input.readInt();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeInt(inventorySlot);
		output.writeInt(slot);
		output.writeInt(pipePosX);
		output.writeInt(pipePosY);
		output.writeInt(pipePosZ);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		slot = input.readInt();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeInt(slot);
	}


	public void writeData(LPDataOutput output) {
		initData();
		super.writeData(output);
		output.writeInt(stat_session_sent);
		output.writeInt(stat_session_recieved);
		output.writeInt(stat_session_relayed);
		output.writeLong(stat_lifetime_sent);
		output.writeLong(stat_lifetime_recieved);
		output.writeLong(stat_lifetime_relayed);
		output.writeInt(server_routing_table_size);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		stat_session_sent = input.readInt();
		stat_session_recieved = input.readInt();
		stat_session_relayed = input.readInt();
		stat_lifetime_sent = input.readLong();
		stat_lifetime_recieved = input.readLong();
		stat_lifetime_relayed = input.readLong();
		server_routing_table_size = input.readInt();
	}


	public void processPacket(EntityPlayer player) {
		MovingObjectPosition box = FMLClientHandler.instance().getClient().objectMouseOver;
		if (box == null) {
			MainProxy.sendPacketToServer(PacketHandler.getPacket(RoutingUpdateTargetResponse.class).setMode(TargetMode.None));
		} else if (box.typeOfHit == MovingObjectType.BLOCK) {
			MainProxy.sendPacketToServer(PacketHandler.getPacket(RoutingUpdateTargetResponse.class).setMode(TargetMode.Block)
					.setAdditions(new int[] { box.blockX, box.blockY, box.blockZ }));
		} else if (box.typeOfHit == MovingObjectType.ENTITY) {
			MainProxy.sendPacketToServer(PacketHandler.getPacket(RoutingUpdateTargetResponse.class).setMode(TargetMode.Entity)
					.setAdditions(new int[] { box.entityHit.getEntityId() }));
		}
	}


public void readData(LPDataInput input) {}


public void writeData(LPDataOutput output) {}


	public void readData(LPDataInput input) {
		exitRoute = input.readExitRoute(MainProxy.getClientMainWorld());
	}


	public void writeData(LPDataOutput output) {
		output.writeExitRoute(exitRoute);
	}


	public void readData(LPDataInput input) {
		msg = new ExitRoute[input.readInt()];
		for (int i = 0; i < msg.length; i++) {
			msg[i] = input.readExitRoute(MainProxy.getClientMainWorld());
		}
	}


	public void writeData(LPDataOutput output) {
		output.writeInt(msg.length);
		for (ExitRoute element : msg) {
			output.writeExitRoute(element);
		}
	}


	public void writeData(LPDataOutput output) {
		output.writeEnumSet(set, PipeRoutingConnectionType.class);
		output.writeLPPosition(pos);
	}


	public void readData(LPDataInput input) {
		set = input.readEnumSet(PipeRoutingConnectionType.class);
		pos = input.readLPPosition();
	}


	public void readData(LPDataInput input) {
		pos = input.readLPPosition();
		filterPositions = new EnumMap<>(PipeRoutingConnectionType.class);
		short id;
		while ((id = input.readShort()) != -1) {
			PipeRoutingConnectionType type = PipeRoutingConnectionType.values[id];
			List<List<DoubleCoordinates>> typeFilters = new ArrayList<>();
			int length;
			while ((length = input.readShort()) != -1) {
				List<DoubleCoordinates> linkedFilter = new ArrayList<>();
				for (int i = 0; i < length; i++) {
					linkedFilter.add(input.readLPPosition());
				}
				typeFilters.add(linkedFilter);
			}
			filterPositions.put(type, typeFilters);
		}
	}


	public void writeData(LPDataOutput output) {
		output.writeLPPosition(pos);
		for (PipeRoutingConnectionType type : filters.keySet()) {
			output.writeShort(type.ordinal());
			for (List<IFilter> linkedFilter : filters.get(type)) {
				output.writeShort(linkedFilter.size());
				for (IFilter filter : linkedFilter) {
					output.writeLPPosition(filter.getLPPosition());
				}
			}
			output.writeShort(-1);
		}
		output.writeShort(-1);
	}


	public RoutingUpdateTargetResponse(int id) {
		super(id);
	}


	public void processPacket(final EntityPlayer player) {
		if (mode == TargetMode.None) {
			player.addChatMessage(new ChatComponentText(ChatColor.RED + "No Target Found"));
		} else if (mode == TargetMode.Block) {
			int x = additions[0];
			int y = additions[1];
			int z = additions[2];
			player.addChatMessage(new ChatComponentText("Checking Block at: x:" + x + " y:" + y + " z:" + z));
			Block id = player.worldObj.getBlock(x, y, z);
			player.addChatMessage(new ChatComponentText("Found Block with Id: " + Block.getIdFromBlock(id)));
			final TileEntity tile = player.worldObj.getTileEntity(x, y, z);
			if (tile == null) {
				player.addChatMessage(new ChatComponentText(ChatColor.RED + "No TileEntity found"));
			} else if (!(tile instanceof LogisticsTileGenericPipe)) {
				player.addChatMessage(new ChatComponentText(ChatColor.RED + "No LogisticsTileGenericPipe found"));
			} else if (!(((LogisticsTileGenericPipe) tile).pipe instanceof CoreRoutedPipe)) {
				player.addChatMessage(new ChatComponentText(ChatColor.RED + "No CoreRoutedPipe found"));
			} else {
				LPChatListener.addTask(() -> {
					player.addChatMessage(new ChatComponentText(ChatColor.GREEN + "Starting RoutingTable debug update."));
					DebugController.instance(player).debug(((ServerRouter) ((CoreRoutedPipe) ((LogisticsTileGenericPipe) tile).pipe).getRouter()));
					MainProxy.sendPacketToPlayer(PacketHandler.getPacket(OpenChatGui.class), player);
					return true;
				}, player);
				player.addChatMessage(new ChatComponentText(
						ChatColor.AQUA + "Start RoutingTable debug update ? " + ChatColor.RESET + "<" + ChatColor.GREEN + "yes" + ChatColor.RESET + "/"
								+ ChatColor.RED + "no" + ChatColor.RESET + ">"));
				MainProxy.sendPacketToPlayer(PacketHandler.getPacket(OpenChatGui.class), player);
			}
		} else if (mode == TargetMode.Entity) {
			player.addChatMessage(new ChatComponentText(ChatColor.RED + "Entity not allowed"));
		}
	}


	public void readData(LPDataInput input) {
		mode = TargetMode.values()[input.readByte()];
		additions = input.readIntArray();
	}


	public void writeData(LPDataOutput output) {
		output.writeByte(mode.ordinal());
		output.writeIntArray(additions);
	}


	public void writeData(LPDataOutput output) {
		output.writeInt(satID);
		super.writeData(output);
	}


	public void readData(LPDataInput input) {
		satID = input.readInt();
		super.readData(input);
	}


	public void readData(LPDataInput input) {
		super.readData(input);
		side = input.readForgeDirection();
	}


	public void writeData(LPDataOutput output) {
		super.writeData(output);
		output.writeForgeDirection(side);
	}


	public boolean getTurtleConnect() {
		if (container instanceof LogisticsTileGenericPipe) {
			return container.getTurtleConnect();
		}
		return false;
	}


	public void readData(LPDataInput input) {
		isOpaqueClientSide = input.readBoolean();
	}


	public void setTurtleConnect(Boolean flag) {
		if (container instanceof LogisticsTileGenericPipe) {
			container.setTurtleConnect(flag);
		}
	}


	public void writeData(LPDataOutput output) {
		output.writeBoolean(isOpaque());
	}


		public void readData(LPDataInput input) {
			pipeId = input.readInt();

		}


	public void setTurtleConnect(boolean flag) {
		SimpleServiceLocator.ccProxy.setTurtleConnect(flag, this);
	}


		public void writeData(LPDataOutput output) {
			output.writeInt(pipeId);

		}


	public void writeData(LPDataOutput output) {
		if (orientation == null) {
			output.writeBoolean(false);
		} else {
			output.writeBoolean(true);
			output.writeEnum(orientation);
		}
	}


		public void rotatePositions(IPositionRotateble set) {
			renderOrientation.rotatePositions(set);
		}


		public void setOnPipe(CoreMultiBlockPipe pipe) {
			((HSTubeCurve) pipe).orientation = this;
		}


	public void readData(LPDataInput input) {
		if (input.readBoolean()) {
			orientation = input.readEnum(CurveOrientation.class);
		}
	}


		TubeGainRenderOrientation(ForgeDirection dir) {
			this.dir = dir;
		}


		public void rotatePositions(IPositionRotateble set) {
			renderOrientation.rotateOrientation(set);
		}


		public void setOnPipe(CoreMultiBlockPipe pipe) {
			((HSTubeGain) pipe).orientation = this;
		}


		public void rotateOrientation(IPositionRotateble set) {
			if (this == EAST) {
				set.rotateRight();
			} else if (this == WEST) {
				set.rotateLeft();
			} else if (this == SOUTH) {
				set.rotateLeft();
				set.rotateLeft();
			}
		}


	public void readData(LPDataInput input) {
		if (input.readBoolean()) {
			orientation = input.readEnum(TubeGainOrientation.class);
		}
	}


		TubeGainOrientation(TubeGainRenderOrientation render, DoubleCoordinates off, ForgeDirection dir) {
			renderOrientation = render;
			offset = off;
			this.dir = dir;
		}


	public void readData(LPDataInput input) {
		if (input.readBoolean()) {
			orientation = input.readEnum(TubeLineOrientation.class);
		}
	}


    Group createNew(String name, String description, int organizationId) {
        AffectedRowCountAndKey<Integer> insert = groupRepository.insert(name, description, organizationId);
        return groupRepository.getById(insert.getKey());
    }

Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.


    public Optional<GroupModification> update(int listId, GroupModification modification) {

        if(groupRepository.getOptionalById(listId).isEmpty() || CollectionUtils.isEmpty(modification.getItems())) {
            return Optional.empty();
        }

        List<String> existingValues = groupRepository.getAllValuesIncludingNotActive(listId);
        List<GroupMemberModification> notPresent = modification.getItems().stream()
            .filter(i -> i.getId() == null && !existingValues.contains(i.getValue().strip().toLowerCase()))
            .distinct()
            .collect(Collectors.toList());

        if(!notPresent.isEmpty()) {
            var insertResult = insertMembers(listId, notPresent);
            if(!insertResult.isSuccess()) {
                var error = Objects.requireNonNull(insertResult.getFirstErrorOrNull());
                throw new DuplicateGroupItemException(error.getDescription());
            }
        }
        groupRepository.update(listId, modification.getName(), modification.getDescription());
        return loadComplete(listId);
    }


    default int[] insert(int groupId, List<GroupMemberModification> members) {
        MapSqlParameterSource[] params = members.stream()
            .map(i -> new MapSqlParameterSource("groupId", groupId).addValue("value", i.getValue().toLowerCase()).addValue("description", i.getDescription()))
            .toArray(MapSqlParameterSource[]::new);

        return getNamedParameterJdbcTemplate().batchUpdate("insert into group_member(a_group_id_fk, value, description) values(:groupId, :value, :description)", params);
    }


  public static String pathOffset(String path, RoutingContext context) {
    final Route route = context.currentRoute();

    // cannot make any assumptions
    if (route == null) {
      return path;
    }

    if (!route.isExactPath()) {
      final String rest = context.pathParam("*");
      if (rest != null) {
        // normalize
        if (rest.length() > 0) {
          if (rest.charAt(0) == '/') {
            return rest;
          } else {
            return "/" + rest;
          }
        } else {
          return "/";
        }
      }
    }
    int prefixLen = 0;
    String mountPoint = context.mountPoint();
    if (mountPoint != null) {
      prefixLen = mountPoint.length();
      // special case we need to verify if a trailing slash  is present and exclude
      if (mountPoint.charAt(mountPoint.length() - 1) == '/') {
        prefixLen--;
      }
    }
    // we can only safely skip the route path if there are no variables or regex
    if (!route.isRegexPath()) {
      String routePath = route.getPath();
      if (routePath != null) {
        prefixLen += routePath.length();
        // special case we need to verify if a trailing slash  is present and exclude
        if (routePath.charAt(routePath.length() - 1) == '/') {
          prefixLen--;
        }
      }
    }
    return prefixLen != 0 ? path.substring(prefixLen) : path;
  }

Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.


	protected void onInitialize() {
		super.onInitialize();

		IModel<String> valueModel = new AbstractReadOnlyModel<String>() {

			@Override
			public String getObject() {
				return getUser().getAccessToken();
			}

		};
		add(new TextField<String>("value", valueModel) {

			@Override
			protected String[] getInputTypes() {
				return new String[] {"password"};
			}

		});

		add(new CopyToClipboardLink("copy", valueModel));

		add(new Link<Void>("regenerate") {

			@Override
			public void onClick() {
				getUser().setAccessToken(RandomStringUtils.randomAlphanumeric(User.ACCESS_TOKEN_LEN));
				OneDev.getInstance(UserManager.class).save(getUser());
				Session.get().success("Access token regenerated");
				setResponsePage(getPage());
			}

		}.add(new ConfirmClickModifier("This will invalidate current token and generate a new one, do you want to continue?")));
	}

Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG)

The product uses a Pseudo-Random Number Generator (PRNG) in a security context, but the PRNG's algorithm is not cryptographically strong.