import eagler github
This commit is contained in:
parent
fb30047d17
commit
6582c3d7dc
624
CREDITS
Normal file
624
CREDITS
Normal file
|
@ -0,0 +1,624 @@
|
|||
|
||||
EaglercraftX Developers
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
lax1dude:
|
||||
|
||||
- Creator of Eaglercraft
|
||||
- Wrote HW accelerated OpenGL 1.3 emulator
|
||||
- Wrote all desktop emulation code
|
||||
- Ported the Minecraft 1.8 client src to TeaVM
|
||||
- Wrote EaglercraftXBungee
|
||||
- Wrote the patch and build system
|
||||
|
||||
ayunami2000:
|
||||
|
||||
- Many bug fixes
|
||||
- Added resource packs
|
||||
- Added screen recording
|
||||
- Created the replit
|
||||
|
||||
|
||||
|
||||
Code used within EaglercraftX
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Project Name: TeaVM
|
||||
Project Author: Alexey Andreev
|
||||
Project URL: https://teavm.org/
|
||||
|
||||
Used For: Compiling Java to JS, JRE implementation
|
||||
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Project Name: LWJGL 3
|
||||
Project Author: Spasi
|
||||
Project URL: https://www.lwjgl.org
|
||||
|
||||
Used For: OpenGL, OpenAL, and GLFW bindings in desktop debug runtime
|
||||
|
||||
* Copyright (c) 2012-present Lightweight Java Game Library
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name Lightweight Java Game Library nor the names of
|
||||
* its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Project Name: ANGLE
|
||||
Project Author: Google
|
||||
Project URL: https://angleproject.org/
|
||||
|
||||
Used For: OpenGL ES 3.0 emulation in desktop debug runtime
|
||||
|
||||
* Copyright 2018 The ANGLE Project Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* Neither the name of TransGaming Inc., Google Inc., 3DLabs Inc.
|
||||
* Ltd., nor the names of their contributors may be used to endorse
|
||||
* or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Project Name: java-diff-utils
|
||||
Project Author: Google, forked by wumpz
|
||||
Project URL: https://java-diff-utils.github.io/java-diff-utils/
|
||||
|
||||
Used For: generating and applying patch files in build system
|
||||
|
||||
* Copyright 2009-2017 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Project Name: Google Guava
|
||||
Project Author: Google
|
||||
Project URL: https://github.com/google/guava
|
||||
|
||||
Used For: It's a dependency for Minecraft 1.8
|
||||
|
||||
* Copyright (C) 2011 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Project Name: javax.annotation
|
||||
Project Author: Oracle Inc.
|
||||
Project URL: ??
|
||||
|
||||
Used For: Dependency for Google Guava
|
||||
|
||||
* Copyright (c) 2005-2018 Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* The contents of this file are subject to the terms of either the GNU
|
||||
* General Public License Version 2 only ("GPL") or the Common Development
|
||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
||||
* may not use this file except in compliance with the License. You can
|
||||
* obtain a copy of the License at
|
||||
* https://oss.oracle.com/licenses/CDDL+GPL-1.1
|
||||
* or LICENSE.txt. See the License for the specific
|
||||
* language governing permissions and limitations under the License.
|
||||
*
|
||||
* When distributing the software, include this License Header Notice in each
|
||||
* file and include the License file at LICENSE.txt.
|
||||
*
|
||||
* GPL Classpath Exception:
|
||||
* Oracle designates this particular file as subject to the "Classpath"
|
||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
||||
* file that accompanied this code.
|
||||
*
|
||||
* Modifications:
|
||||
* If applicable, add the following below the License Header, with the fields
|
||||
* enclosed by brackets [] replaced by your own identifying information:
|
||||
* "Portions Copyright [year] [name of copyright owner]"
|
||||
*
|
||||
* Contributor(s):
|
||||
* If you wish your version of this file to be governed by only the CDDL or
|
||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
||||
* elects to include this software in this distribution under the [CDDL or GPL
|
||||
* Version 2] license." If you don't indicate a single choice of license, a
|
||||
* recipient has the option to distribute your version of this file under
|
||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
||||
* only if the new code is made subject to such option by the copyright
|
||||
* holder.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Project Name: Apache Commons Lang
|
||||
Project Author: Apache Software Foundation
|
||||
Project URL: https://commons.apache.org/proper/commons-lang/
|
||||
|
||||
Used For: It's a dependency for Minecraft 1.8
|
||||
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Project Name: Apache Commons IO
|
||||
Project Author: Apache Software Foundation
|
||||
Project URL: https://commons.apache.org/proper/commons-io/
|
||||
|
||||
Used For: simplifying file IO in build system
|
||||
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Project Name: Apache Commons CSV
|
||||
Project Author: Apache Software Foundation
|
||||
Project URL: https://commons.apache.org/proper/commons-csv/
|
||||
|
||||
Used For: loading mod coder pack config files in build system
|
||||
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Project Name: JSON-java
|
||||
Project Author: Sean Leary (stleary)
|
||||
Project URL: https://github.com/stleary/JSON-java
|
||||
|
||||
Used For: JSON serialization and parsing in client and build system
|
||||
|
||||
* Public domain.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Project Name: Eclipse IDE Java Formatter
|
||||
Project Author: Eclipse Foundation
|
||||
Project URL: https://www.eclipse.org/
|
||||
|
||||
Used For: Formatting source code in build system before making diffs
|
||||
|
||||
* License is here: https://www.eclipse.org/legal/epl-2.0/
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Project Name: ObjectWeb ASM
|
||||
Project Author: OW2
|
||||
Project URL: https://asm.ow2.io/
|
||||
|
||||
Used For: parsing method signatures in build system
|
||||
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Project Name: Bouncy Castle Crypto
|
||||
Project Author: The Legion of the Bouncy Castle
|
||||
Project URL: https://www.bouncycastle.org/java.html
|
||||
|
||||
Used For: MD5, SHA-1, SHA-256 implementations
|
||||
|
||||
* Copyright (c) 2000-2021 The Legion of the Bouncy Castle Inc. (https://www.bouncycastle.org)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Project Name: Apache Harmony JRE
|
||||
Project Author: Apache Software Foundation
|
||||
Project URL: https://harmony.apache.org/
|
||||
|
||||
Used For: TeaVM compatible String.format implementation
|
||||
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Project Name: Apache Commons Codec
|
||||
Project Author: Apache Software Foundation
|
||||
Project URL: https://commons.apache.org/proper/commons-codec/
|
||||
|
||||
Used For: Base64 encoder/decoder implementation
|
||||
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Project Name: JZlib
|
||||
Project Author: ymnk, JCraft Inc.
|
||||
Project URL: http://www.jcraft.com/jzlib/
|
||||
|
||||
Used For: Deflate and GZIP implementations in client
|
||||
|
||||
* Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The names of the authors may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
* INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Project Name: Java-WebSocket
|
||||
Project Author: Nathan Rajlich (TooTallNate)
|
||||
Project URL: http://tootallnate.github.io/Java-WebSocket
|
||||
|
||||
Used For: WebSockets in desktop runtime
|
||||
|
||||
* Copyright (c) 2010-2020 Nathan Rajlich
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Project Name: Netty
|
||||
Project Author: Netty Project
|
||||
Project URL: https://netty.io/
|
||||
|
||||
Used For: 'ByteBuf' classes implementations for Minecraft 1.8's networking engine
|
||||
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License, version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License. You may obtain a
|
||||
* copy of the License at:
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Project Name: 3D Sound System
|
||||
Project Author: Paul Lamb
|
||||
Project URL: http://www.paulscode.com/forum/index.php?topic=4.0
|
||||
|
||||
Used For: Audio in desktop runtime
|
||||
|
||||
* SoundSystem License:
|
||||
*
|
||||
* You are free to use this library for any purpose, commercial or
|
||||
* otherwise. You may modify this library or source code, and distribute it any
|
||||
* way you like, provided the following conditions are met:
|
||||
*
|
||||
* 1) You must abide by the conditions of the aforementioned LWJGL License.
|
||||
*
|
||||
* 2) You may not falsely claim to be the author of this library or any
|
||||
* unmodified portion of it.
|
||||
*
|
||||
* 3) You may not copyright this library or a modified version of it and then
|
||||
* sue me for copyright infringement.
|
||||
*
|
||||
* 4) If you modify the source code, you must clearly document the changes made
|
||||
* before redistributing the modified source code, so other users know it is not
|
||||
* the original code.
|
||||
*
|
||||
* 5) You are not required to give me credit for this library in any derived
|
||||
* work, but if you do, you must also mention my website:
|
||||
* http://www.paulscode.com
|
||||
*
|
||||
* 6) I the author will not be responsible for any damages (physical, financial,
|
||||
* or otherwise) caused by the use if this library or any part of it.
|
||||
*
|
||||
* 7) I the author do not guarantee, warrant, or make any representations,
|
||||
* either expressed or implied, regarding the use of this library or any part of
|
||||
* it.
|
||||
*
|
||||
* Author: Paul Lamb
|
||||
* http://www.paulscode.com
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Project Name: JOrbis
|
||||
Project Author: ymnk, JCraft Inc.
|
||||
Project URL: http://www.jcraft.com/jorbis/
|
||||
|
||||
Used For: Audio in desktop runtime
|
||||
|
||||
* JOrbis
|
||||
* Copyright (C) 2000 ymnk, JCraft,Inc.
|
||||
*
|
||||
* Written by: 2000 ymnk<ymnk@jcraft.com>
|
||||
*
|
||||
* Many thanks to
|
||||
* Monty <monty@xiph.org> and
|
||||
* The XIPHOPHORUS Company http://www.xiph.org/ .
|
||||
* JOrbis has been based on their awesome works, Vorbis codec.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public License
|
||||
* as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Project Name: sqlite-jdbc
|
||||
Project Author: Taro L. Saito (xerial)
|
||||
Project URL: https://github.com/xerial/sqlite-jdbc
|
||||
|
||||
Used For: Default skin cache and authentication JDBC driver in EaglerXBungee
|
||||
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Project Name: fix-webm-duration
|
||||
Project Author: Yury Sitnikov
|
||||
Project URL: https://github.com/yusitnikov/fix-webm-duration
|
||||
|
||||
Used For: Post-processing screen recordings to add durations to the file headers
|
||||
|
||||
* The MIT license
|
||||
*
|
||||
* Copyright (c) 2018 Yury Sitnikov
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Make sure you also update the copy of this file in "sources/resources/assets/eagler/CREDITS"
|
||||
|
||||
The content of both files should match, but not include this notice in the resources one
|
3
CompileLatestClient.sh
Executable file
3
CompileLatestClient.sh
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
java -cp "buildtools/BuildTools.jar" net.lax1dude.eaglercraft.v1_8.buildtools.gui.CompileLatestClientGUI
|
||||
rm -rf "##TEAVM.TMP##"
|
247
LICENSE
247
LICENSE
|
@ -1,201 +1,64 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
|
||||
1. Definitions.
|
||||
WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES NORMALLY
|
||||
FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED TO SHARE,
|
||||
DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE SOFTWARE IN THIS
|
||||
REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
Prohibited sharing, distribution, and repurposing these files includes but is not
|
||||
limited to: Publicly sharing or distributing any significant portion, modified or
|
||||
unmodified, of any source code files produced by the buildtools commands without
|
||||
minification or obfuscation, with the exception of patch files. Publicly
|
||||
repurposing, without permission, the source code for any file which is a part of
|
||||
the Eaglercraft runtime, as in any additional source files required for output of
|
||||
buildtools commands to run on a specific platform. Publicly repurposing, without
|
||||
permission, any resource file found in the project's default resource pack that
|
||||
does not exist in vanilla Minecraft resource packs. And, additionally, publicly
|
||||
repurposing, without permission, any data produced by the act of compiling or
|
||||
converting the files described in these previous three cases, besides the compiled
|
||||
or minified application (the 'game') itself.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
Prohibited commercial use includes selling access to any files or data (including
|
||||
the game itself) contained or produced by this repository, requiring the direct
|
||||
forced viewing of advertisement presented when a user attempts to load a compiled
|
||||
version of this project (or follow a hyperlink to the project's source or files
|
||||
derived from it, examples include using adfoc.us or adf.ly on your site), and
|
||||
selling content in any form that can only be accessed through the use of this
|
||||
project or files produced by or derived from it. Making a pay-to-win multiplayer
|
||||
server, for example, would be prohibited under these terms.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
Malicious use includes creating and/or distributing modified versions of the
|
||||
game's 1.8 client (often referred to as "hacked clients") which give you an unfair
|
||||
advantage on multiplayer servers, creating and/or distributing modified clients
|
||||
which allow you to exploit bugs in EaglercraftXBungee or Eagler-compatible server
|
||||
software, creating and/or distributing modified clients which allow you to exploit
|
||||
bugs in Minecraft servers or Minecraft-compatible server software, or creating
|
||||
and/or distributing modified clients which allow you to exploit bugs in portions of
|
||||
any other software used in companion with EaglerXBungee or on an Eagler-compatible
|
||||
server (e.g. VIAaaS, NGINX, Caddy)
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
Distribution of any file or a product of compilation or conversion covered by this
|
||||
document must retain all existing copyright notices found within the file and
|
||||
folders before any modifications were made.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
BY VIOLATING THESE TERMS YOU AGREE TO A BLOCK/BAN FROM ALL SOURCES OF DOCUMENTATION
|
||||
AND SUPPORT FOR THIS PROJECT, PERMISSION TO USE THESE FILES WAS GIVEN TO YOU IN
|
||||
GOOD FAITH THAT THE WORK WILL NOT BE ABUSED, AND VIOLATING THIS AGREEMENT IS A
|
||||
DEMONSTRATION OF A LACK OF RESPECT AND GOOD INTENTIONS ON BEHALF OF YOUR EFFORTS TO
|
||||
LEARN HOW TO USE THESE TOOLS CORRECTLY AND IS JUSTIFICATION FOR YOUR EXCLUSION FROM
|
||||
ANY AND ALL SOURCES OF DOCUMENTATION OR SUPPORT THAT WILL ASSIST YOU TO CONTINUE TO
|
||||
VIOLATE THESE TERMS
|
||||
|
|
68
README.md
68
README.md
|
@ -1 +1,67 @@
|
|||
# Resent-1.8
|
||||
# EaglercraftX 1.8
|
||||
|
||||
### Play real Minecraft 1.8 in your browser, currently only supports multiplayer
|
||||
|
||||
![EaglercraftX 1.8 Screenshot Main Menu](https://g.deev.is/eaglercraft/eaglerx-480p.png)
|
||||
|
||||
## ATTENTION MOJANG/MICROSOFT EMPLOYEE ASSIGNED TO STALK ME:
|
||||
|
||||
### THIS REPOSITORY DOES NOT CONTAIN YOUR INTELLECTUAL PROPERTY
|
||||
|
||||
### FILING A FALSE DMCA IS ILLEGAL AND IMMORAL
|
||||
|
||||
### This repository contains:
|
||||
|
||||
- **Utilities to decompile Minecraft 1.8 and apply patch files to it**
|
||||
- **Source code to provide the LWJGL keyboard, mouse, and OpenGL APIs in a browser**
|
||||
- **Source code for an OpenGL 1.3 emulator built on top of WebGL 2.0**
|
||||
- **Patch files to mod the Minecraft 1.8 source code to make it browser compatible**
|
||||
- **Browser-modified portions of Minecraft 1.8's open-source dependencies**
|
||||
- **Plugins for Minecraft servers to allow the eagler client to connect to them**
|
||||
|
||||
### This repository does NOT contain:
|
||||
|
||||
- **Any portion of the decompiled Minecraft 1.8 source code or resources**
|
||||
- **Any portion of Mod Coder Pack and it's config files**
|
||||
- **Data that can be used alone to reconstruct portions of the game's source code**
|
||||
- **Code configured by default to allow users to play without owning a copy of Minecraft**
|
||||
|
||||
## Getting Started:
|
||||
|
||||
### To compile the latest version of the client, on Windows:
|
||||
|
||||
1. Make sure you have at least Java 11 installed and added to your PATH
|
||||
2. Download (clone) this repository to your computer
|
||||
3. Double click `CompileLatestClient.bat`, a GUI resembling a classic windows installer should open
|
||||
4. Follow the steps shown to you in the new window to finish compiling
|
||||
|
||||
### To compile the latest version of the client, on Linux/macOS:
|
||||
|
||||
1. Make sure you have at least Java 11 installed
|
||||
2. Download (clone) this repository to your computer
|
||||
3. Open a terminal in the folder the repository was cloned to
|
||||
4. Type `chmod +x CompileLatestClient.sh` and hit enter
|
||||
5. Type `./CompileLatestClient.sh` and hit enter, a GUI resembling a classic windows installer should open
|
||||
6. Follow the steps shown to you in the new window to finish compiling
|
||||
|
||||
## Making a Server:
|
||||
|
||||
**EaglercraftX 1.8's server is a BungeeCord/Waterfall PLUGIN, not an entire "fork" of bungeecord like the 1.5 Eaglerbungee was, and I can't believe I have to clarify this too but the EaglerXBungee 1.8 plugin is not compatible with the old 1.5 bungee, you must migrate to the latest version of official BungeeCord/Waterfall to use it**
|
||||
|
||||
Simply set up the latest version of BungeeCord or Waterfall and download [EaglerXBungee-Latest.jar](https://gitlab.com/lax1dude/eaglercraftx-1.8/-/raw/main/gateway/EaglercraftXBungee/EaglerXBungee-Latest.jar) and place it in the plugins directory.
|
||||
|
||||
Then to actually log in to the server with Eaglercraft, first join your server using vanilla Minecraft Java Edition 1.8 and run the new `/eagler` command to set a password. Then leave the server and switch to your EaglercraftX client.
|
||||
|
||||
Set your EaglercraftX username to the same username as the vanilla minecraft account you set the password with, then when you try to join your server it will present you with a login screen where you can enter the password you set. If the password is correct it will let you join the server.
|
||||
|
||||
**NOTE: If you set `online_mode` to `false` on BungeeCord/Waterfall's config.yml, the password system will be disabled and you will be able to join with any username without setting a password like Eaglercraft 1.5. This should only ever be used for testing.**
|
||||
|
||||
A config guide will be added here too eventually
|
||||
|
||||
## Contributing:
|
||||
|
||||
This part of the guide is incomplete
|
||||
|
||||
## Developing a Client:
|
||||
|
||||
There is currently no system in place to make forks of 1.8 and merge commits made to the patch files in this repository with the patch files or workspace of the fork, you're on your own if you try to keep a fork of this repo for reasons other than to contribute to it
|
||||
|
|
2
build_clean_tmp.sh
Executable file
2
build_clean_tmp.sh
Executable file
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
java -jar buildtools/BuildTools.jar clean
|
2
build_help.sh
Executable file
2
build_help.sh
Executable file
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
java -jar buildtools/BuildTools.jar help
|
2
build_init.sh
Executable file
2
build_init.sh
Executable file
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
java -jar buildtools/BuildTools.jar init
|
2
build_make_pullrequest.sh
Executable file
2
build_make_pullrequest.sh
Executable file
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
java -jar buildtools/BuildTools.jar pullrequest
|
2
build_make_unpatched.sh
Executable file
2
build_make_unpatched.sh
Executable file
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
java -jar buildtools/BuildTools.jar unpatched
|
2
build_make_workspace.sh
Executable file
2
build_make_workspace.sh
Executable file
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
java -jar buildtools/BuildTools.jar workspace
|
2
build_merge_direct.sh
Executable file
2
build_merge_direct.sh
Executable file
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
java -jar buildtools/BuildTools.jar merge_direct
|
2
build_merge_pullrequest.sh
Executable file
2
build_merge_pullrequest.sh
Executable file
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
java -jar buildtools/BuildTools.jar merge
|
2
build_test_pullrequest.sh
Executable file
2
build_test_pullrequest.sh
Executable file
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
java -jar buildtools/BuildTools.jar pullrequest_test
|
BIN
buildtools/BuildTools.jar
Normal file
BIN
buildtools/BuildTools.jar
Normal file
Binary file not shown.
BIN
buildtools/Java11Check.jar
Normal file
BIN
buildtools/Java11Check.jar
Normal file
Binary file not shown.
4
buildtools/MAINFEST-README-PLEASE.txt
Normal file
4
buildtools/MAINFEST-README-PLEASE.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
|
||||
when you export the BuildTools source as a jar you must copy the "MANIFEST.MF" file in this directory into the "META-INF" directory inside the JAR!!
|
||||
|
||||
reasons: limitations in eclipse/intellij, lazyness
|
4
buildtools/MANIFEST.MF
Normal file
4
buildtools/MANIFEST.MF
Normal file
|
@ -0,0 +1,4 @@
|
|||
Manifest-Version: 1.0
|
||||
Main-Class: net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildTools
|
||||
Class-Path: Java11Check.jar deps/asm-signature.jar deps/commons-csv-1.9.0.jar deps/commons-io-2.11.0.jar deps/eclipse-formatter.jar deps/java-diff-utils-4.11.jar deps/json-20220320.jar
|
||||
|
BIN
buildtools/TeaVMBridge.jar
Normal file
BIN
buildtools/TeaVMBridge.jar
Normal file
Binary file not shown.
BIN
buildtools/deps/asm-signature.jar
Normal file
BIN
buildtools/deps/asm-signature.jar
Normal file
Binary file not shown.
BIN
buildtools/deps/commons-csv-1.9.0-javadoc.jar
Normal file
BIN
buildtools/deps/commons-csv-1.9.0-javadoc.jar
Normal file
Binary file not shown.
BIN
buildtools/deps/commons-csv-1.9.0.jar
Normal file
BIN
buildtools/deps/commons-csv-1.9.0.jar
Normal file
Binary file not shown.
BIN
buildtools/deps/commons-io-2.11.0-javadoc.jar
Normal file
BIN
buildtools/deps/commons-io-2.11.0-javadoc.jar
Normal file
Binary file not shown.
BIN
buildtools/deps/commons-io-2.11.0.jar
Normal file
BIN
buildtools/deps/commons-io-2.11.0.jar
Normal file
Binary file not shown.
BIN
buildtools/deps/eclipse-formatter.jar
Normal file
BIN
buildtools/deps/eclipse-formatter.jar
Normal file
Binary file not shown.
BIN
buildtools/deps/java-diff-utils-4.11-javadoc.jar
Normal file
BIN
buildtools/deps/java-diff-utils-4.11-javadoc.jar
Normal file
Binary file not shown.
BIN
buildtools/deps/java-diff-utils-4.11.jar
Normal file
BIN
buildtools/deps/java-diff-utils-4.11.jar
Normal file
Binary file not shown.
BIN
buildtools/deps/json-20220320-javadoc.jar
Normal file
BIN
buildtools/deps/json-20220320-javadoc.jar
Normal file
Binary file not shown.
BIN
buildtools/deps/json-20220320.jar
Normal file
BIN
buildtools/deps/json-20220320.jar
Normal file
Binary file not shown.
BIN
buildtools/production-favicon.png
Normal file
BIN
buildtools/production-favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
48
buildtools/production-index-ext.html
Normal file
48
buildtools/production-index-ext.html
Normal file
|
@ -0,0 +1,48 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content="Play minecraft 1.8 in your browser" />
|
||||
<meta name="keywords" content="eaglercraft, eaglercraftx, minecraft, 1.8, 1.8.8" />
|
||||
<title>EaglercraftX 1.8</title>
|
||||
<meta property="og:locale" content="en-US" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content="EaglercraftX 1.8" />
|
||||
<meta property="og:description" content="Play minecraft 1.8 in your browser" />
|
||||
<meta property="og:image" content="favicon.png" />
|
||||
<link type="image/png" rel="shortcut icon" href="favicon.png" />
|
||||
<script type="text/javascript" src="classes.js"></script>
|
||||
<script type="text/javascript" src="fix-webm-duration.js"></script>
|
||||
<script type="text/javascript">
|
||||
"use strict";
|
||||
window.addEventListener("load", () => {
|
||||
if(document.location.href.startsWith("file:")) {
|
||||
alert("HTTP please, do not open this file locally, run a local HTTP server and load it via HTTP");
|
||||
}else {
|
||||
var opts = window.eaglercraftXOpts;
|
||||
|
||||
if(typeof opts === "function") window.eaglercraftXOpts = opts = opts();
|
||||
if(typeof opts === "undefined") window.eaglercraftXOpts = opts = {};
|
||||
|
||||
if(!opts.container) opts.container = "game_frame";
|
||||
if(!opts.assetsURI) opts.assetsURI = "assets.epk";
|
||||
if(!opts.localesURI) opts.localesURI = "lang/";
|
||||
|
||||
if(!opts.joinServer) {
|
||||
var q = window.location.search;
|
||||
if(typeof q === "string" && q.startsWith("?")) {
|
||||
q = new URLSearchParams(q);
|
||||
var s = q.get("server");
|
||||
if(s) opts.joinServer = s;
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body style="margin:0px;width:100vw;height:100vh;overflow:hidden;" id="game_frame">
|
||||
</body>
|
||||
</html>
|
52
buildtools/production-index.html
Normal file
52
buildtools/production-index.html
Normal file
|
@ -0,0 +1,52 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content="Play minecraft 1.8 in your browser" />
|
||||
<meta name="keywords" content="eaglercraft, eaglercraftx, minecraft, 1.8, 1.8.8" />
|
||||
<title>EaglercraftX 1.8</title>
|
||||
<meta property="og:locale" content="en-US" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content="EaglercraftX 1.8" />
|
||||
<meta property="og:description" content="Play minecraft 1.8 in your browser" />
|
||||
<meta property="og:image" content="favicon.png" />
|
||||
<link type="image/png" rel="shortcut icon" href="favicon.png" />
|
||||
<script type="text/javascript" src="classes.js"></script>
|
||||
<script type="text/javascript" src="fix-webm-duration.js"></script>
|
||||
<script type="text/javascript">
|
||||
"use strict";
|
||||
window.addEventListener("load", () => {
|
||||
if(document.location.href.startsWith("file:")) {
|
||||
alert("HTTP please, do not open this file locally, run a local HTTP server and load it via HTTP");
|
||||
}else {
|
||||
|
||||
// %%%%%%%%% launch options %%%%%%%%%%%%
|
||||
|
||||
window.eaglercraftXOpts = {
|
||||
container: "game_frame",
|
||||
assetsURI: "assets.epk",
|
||||
localesURI: "lang/",
|
||||
servers: [
|
||||
/* example: { addr: "ws://localhost:8081/", name: "Local test server" } */
|
||||
]
|
||||
};
|
||||
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
var q = window.location.search;
|
||||
if(typeof q === "string" && q.startsWith("?")) {
|
||||
q = new URLSearchParams(q);
|
||||
var s = q.get("server");
|
||||
if(s) window.eaglercraftXOpts.joinServer = s;
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body style="margin:0px;width:100vw;height:100vh;overflow:hidden;" id="game_frame">
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,167 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.diff.MergePullRequest;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.diff.PullRequestTask;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.CreateUnpatched;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.InitTask;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.SetupWorkspace;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.TaskClean;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class EaglerBuildTools {
|
||||
|
||||
public static File repositoryRoot = new File(".");
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Eaglercraft 1.8 Build Tools");
|
||||
System.out.println("Copyright (c) 2022 LAX1DUDE");
|
||||
System.out.println();
|
||||
|
||||
if(!System.getProperty("eaglercraft.isJava11", "false").equalsIgnoreCase("true")) {
|
||||
try {
|
||||
if (!(boolean) Class
|
||||
.forName("net.lax1dude.eaglercraft.v1_8.buildtools.Java11Check", true,
|
||||
new URLClassLoader(new URL[] { (new File("buildtools/Java11Check.jar")).toURI().toURL() }))
|
||||
.getMethod("classLoadCheck").invoke(null)) {
|
||||
throw new RuntimeException("wtf?");
|
||||
}
|
||||
}catch(Throwable t) {
|
||||
System.err.println("ERROR: A minimum of Java 11 is required to run this tool!");
|
||||
System.err.println();
|
||||
System.err.println("You are using Java " + System.getProperty("java.version"));
|
||||
System.err.println();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(args.length == 0 || (args.length == 1 && args[0].equalsIgnoreCase("help"))) {
|
||||
System.out.println("Options:");
|
||||
System.out.println(" help - displays this message");
|
||||
System.out.println(" init - decompiles 1.8.8 and applies the main repo's patch files");
|
||||
System.out.println(" workspace - creates a dev workspace with a gradle project to compile the source");
|
||||
System.out.println(" pullrequest - scans changes in the dev workspace and creates patch files for pull requests");
|
||||
System.out.println(" pullrequest_test - makes new workspace and re-applies the patches in 'pullrequest'");
|
||||
System.out.println(" unpatched - creates a zip file with the vanilla minecraft source without patches");
|
||||
System.out.println(" merge - merges the patch files in the pullrequest folder with the repo's main patch files");
|
||||
System.out.println(" merge_direct - merges changes in the dev workspace with the repo's main patch files");
|
||||
System.out.println(" clean - delete init and pullrequest directories, keeps dev workspace");
|
||||
System.out.println();
|
||||
}else if(args.length == 1 && args[0].equalsIgnoreCase("init")) {
|
||||
LicensePrompt.display();
|
||||
System.out.println("Running task '" + args[0] + "':");
|
||||
System.out.println();
|
||||
if(InitTask.initTask()) {
|
||||
System.out.println();
|
||||
System.out.println("Task Complete.");
|
||||
System.out.println();
|
||||
}else {
|
||||
System.err.println();
|
||||
System.err.println("Task Failed!");
|
||||
System.err.println();
|
||||
}
|
||||
}else if(args.length == 1 && args[0].equalsIgnoreCase("workspace")) {
|
||||
System.out.println("Running task '" + args[0] + "':");
|
||||
System.out.println();
|
||||
if(SetupWorkspace.setupWorkspace()) {
|
||||
System.out.println();
|
||||
System.out.println("Task Complete.");
|
||||
System.out.println();
|
||||
}else {
|
||||
System.err.println();
|
||||
System.err.println("Task Failed!");
|
||||
System.err.println();
|
||||
}
|
||||
}else if(args.length == 1 && args[0].equalsIgnoreCase("pullrequest")) {
|
||||
System.out.println("Running task '" + args[0] + "':");
|
||||
System.out.println();
|
||||
if(PullRequestTask.pullRequest()) {
|
||||
System.out.println();
|
||||
System.out.println("Task Complete.");
|
||||
System.out.println();
|
||||
}else {
|
||||
System.err.println();
|
||||
System.err.println("Task Failed!");
|
||||
System.err.println();
|
||||
}
|
||||
}else if(args.length == 1 && args[0].equalsIgnoreCase("pullrequest_test")) {
|
||||
System.out.println("Running task '" + args[0] + "':");
|
||||
System.out.println();
|
||||
if(SetupWorkspace.pullRequestTest()) {
|
||||
System.out.println();
|
||||
System.out.println("Task Complete.");
|
||||
System.out.println();
|
||||
}else {
|
||||
System.err.println();
|
||||
System.err.println("Task Failed!");
|
||||
System.err.println();
|
||||
}
|
||||
}else if(args.length == 1 && args[0].equalsIgnoreCase("unpatched")) {
|
||||
System.out.println("Running task '" + args[0] + "':");
|
||||
System.out.println();
|
||||
if(CreateUnpatched.createUnpatched()) {
|
||||
System.out.println();
|
||||
System.out.println("Task Complete.");
|
||||
System.out.println();
|
||||
}else {
|
||||
System.err.println();
|
||||
System.err.println("Task Failed!");
|
||||
System.err.println();
|
||||
}
|
||||
}else if(args.length == 1 && args[0].equalsIgnoreCase("merge")) {
|
||||
System.out.println("Running task '" + args[0] + "':");
|
||||
System.out.println();
|
||||
if(MergePullRequest.mergeTask()) {
|
||||
System.out.println();
|
||||
System.out.println("Task Complete.");
|
||||
System.out.println();
|
||||
}else {
|
||||
System.err.println();
|
||||
System.err.println("Task Failed!");
|
||||
System.err.println();
|
||||
}
|
||||
}else if(args.length == 1 && args[0].equalsIgnoreCase("merge_direct")) {
|
||||
System.out.println("Running task '" + args[0] + "':");
|
||||
System.out.println();
|
||||
if(MergePullRequest.mergeDirect()) {
|
||||
System.out.println();
|
||||
System.out.println("Task Complete.");
|
||||
System.out.println();
|
||||
}else {
|
||||
System.err.println();
|
||||
System.err.println("Task Failed!");
|
||||
System.err.println();
|
||||
}
|
||||
}else if(args.length == 1 && args[0].equalsIgnoreCase("clean")) {
|
||||
System.out.println("Running task '" + args[0] + "':");
|
||||
System.out.println();
|
||||
if(TaskClean.taskClean()) {
|
||||
System.out.println();
|
||||
System.out.println("Task Complete.");
|
||||
System.out.println();
|
||||
}else {
|
||||
System.err.println();
|
||||
System.err.println("Task Failed!");
|
||||
System.err.println();
|
||||
}
|
||||
}else {
|
||||
System.err.println("Invalid arguments!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,183 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class EaglerBuildToolsConfig {
|
||||
|
||||
public static File temporary_directory = new File(System.getProperty("user.home"), ".eaglercraft_1.8_buildtools");
|
||||
private static boolean temporary_directory_isInit = false;
|
||||
private static boolean temporary_directory_mentioned = false;
|
||||
|
||||
public static File workspace_directory = new File("../eaglercraft_1.8_workspace");
|
||||
private static boolean workspace_directory_isInit = false;
|
||||
private static boolean workspace_directory_mentioned = false;
|
||||
|
||||
private static boolean config_file_loaded = false;
|
||||
|
||||
public static final File configFile = new File("./buildtools_config.json");
|
||||
|
||||
public static void load() {
|
||||
if(configFile.exists()) {
|
||||
try(FileInputStream is = new FileInputStream(configFile)) {
|
||||
byte[] r = new byte[(int)configFile.length()];
|
||||
is.read(r);
|
||||
is.close();
|
||||
String jsonTxt = new String(r, StandardCharsets.UTF_8);
|
||||
JSONObject obj = new JSONObject(jsonTxt);
|
||||
String path = obj.optString("temporary_directory", null);
|
||||
if(path != null) {
|
||||
temporary_directory = new File(path);
|
||||
temporary_directory_isInit = true;
|
||||
}
|
||||
path = obj.optString("workspace_directory", null);
|
||||
if(path != null) {
|
||||
workspace_directory = new File(path);
|
||||
workspace_directory_isInit = true;
|
||||
}
|
||||
}catch(Throwable ex) {
|
||||
System.err.println("Failed to read config!");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void save() {
|
||||
JSONObject obj = new JSONObject();
|
||||
if(temporary_directory_isInit) obj.put("temporary_directory", temporary_directory.getAbsolutePath());
|
||||
if(workspace_directory_isInit) obj.put("workspace_directory", workspace_directory.getAbsoluteFile());
|
||||
try(FileOutputStream os = new FileOutputStream(configFile)) {
|
||||
os.write(obj.toString(4).getBytes(StandardCharsets.UTF_8));
|
||||
os.close();
|
||||
}catch(IOException e) {
|
||||
System.err.println("Failed to write config!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void mentionConfigPath() {
|
||||
System.out.println("Edit '" + configFile.getName() + "' to change");
|
||||
}
|
||||
|
||||
public static File getTemporaryDirectory() {
|
||||
if(!config_file_loaded) {
|
||||
load();
|
||||
config_file_loaded = true;
|
||||
}
|
||||
if(!temporary_directory_isInit) {
|
||||
File f = temporary_directory;
|
||||
System.out.println();
|
||||
System.out.println("Using temporary directory: " + f.getAbsolutePath());
|
||||
temporary_directory_mentioned = true;
|
||||
f = askIfChangeIsWanted(f);
|
||||
temporary_directory = f;
|
||||
temporary_directory_isInit = true;
|
||||
while(!temporary_directory.isDirectory() && !temporary_directory.mkdirs()) {
|
||||
System.err.println("Failed to create: " + f.getAbsolutePath());
|
||||
temporary_directory = askIfChangeIsWanted(f);
|
||||
}
|
||||
save();
|
||||
System.out.println();
|
||||
return temporary_directory;
|
||||
}else {
|
||||
if(!temporary_directory_mentioned) {
|
||||
System.out.println("Using temporary directory: " + temporary_directory.getAbsolutePath());
|
||||
temporary_directory_mentioned = true;
|
||||
while(!temporary_directory.isDirectory() && !temporary_directory.mkdirs()) {
|
||||
System.err.println("Failed to create: " + temporary_directory.getAbsolutePath());
|
||||
temporary_directory = askIfChangeIsWanted(temporary_directory);
|
||||
}
|
||||
mentionConfigPath();
|
||||
}
|
||||
return temporary_directory;
|
||||
}
|
||||
}
|
||||
|
||||
public static File getWorkspaceDirectory() {
|
||||
if(!config_file_loaded) {
|
||||
load();
|
||||
config_file_loaded = true;
|
||||
}
|
||||
if(!workspace_directory_isInit) {
|
||||
File f = workspace_directory;
|
||||
System.out.println();
|
||||
System.out.println("Using workspace directory: " + f.getAbsolutePath());
|
||||
workspace_directory_mentioned = true;
|
||||
f = askIfChangeIsWanted(f);
|
||||
workspace_directory = f;
|
||||
workspace_directory_isInit = true;
|
||||
while(!workspace_directory.isDirectory() && !workspace_directory.mkdirs()) {
|
||||
System.err.println("Failed to create: " + f.getAbsolutePath());
|
||||
workspace_directory = askIfChangeIsWanted(f);
|
||||
}
|
||||
save();
|
||||
System.out.println();
|
||||
return workspace_directory;
|
||||
}else {
|
||||
if(!workspace_directory_mentioned) {
|
||||
System.out.println("Using workspace directory: " + workspace_directory.getAbsolutePath());
|
||||
workspace_directory_mentioned = true;
|
||||
while(!workspace_directory.isDirectory() && !workspace_directory.mkdirs()) {
|
||||
System.err.println("Failed to create: " + workspace_directory.getAbsolutePath());
|
||||
workspace_directory = askIfChangeIsWanted(workspace_directory);
|
||||
}
|
||||
mentionConfigPath();
|
||||
}
|
||||
return workspace_directory;
|
||||
}
|
||||
}
|
||||
|
||||
public static File askIfChangeIsWanted(File in) {
|
||||
System.out.println("Would you like to change this directory?");
|
||||
System.out.println("Enter 'Y' for yes or 'N' for no: ");
|
||||
String l = "N";
|
||||
|
||||
try {
|
||||
l = (new BufferedReader(new InputStreamReader(System.in))).readLine();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
|
||||
if(l != null && ((l = l.trim()).equalsIgnoreCase("y") || l.equalsIgnoreCase("yes"))) {
|
||||
System.out.println();
|
||||
System.out.println("Type a new filename or hit 'Enter' to browse: ");
|
||||
try {
|
||||
l = (new BufferedReader(new InputStreamReader(System.in))).readLine();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
if(l != null && (l = l.trim()).length() > 0) {
|
||||
in = new File(l);
|
||||
}else {
|
||||
File f = FileChooserTool.load(true);
|
||||
if(f == null) {
|
||||
System.out.println("You hit cancel on the file chooser, the directory '" + in.getAbsolutePath() + "' will be used.");
|
||||
in = askIfChangeIsWanted(in);
|
||||
}else {
|
||||
in = f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JFrame;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class FileChooserTool {
|
||||
|
||||
public static final JFileChooser fc = new JFileChooser();
|
||||
|
||||
public static File load(boolean directory) {
|
||||
fc.setFileSelectionMode(directory ? JFileChooser.DIRECTORIES_ONLY : JFileChooser.FILES_ONLY);
|
||||
fc.setMultiSelectionEnabled(false);
|
||||
fc.setFileHidingEnabled(false);
|
||||
fc.setDialogTitle("Eaglercraft Buildtools");
|
||||
JFrame parent = new JFrame();
|
||||
parent.setBounds(0, 0, 50, 50);
|
||||
parent.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
parent.setAlwaysOnTop(true);
|
||||
parent.setTitle("File Chooser");
|
||||
parent.setLocationRelativeTo(null);
|
||||
parent.setVisible(true);
|
||||
if(fc.showOpenDialog(parent) == JFileChooser.APPROVE_OPTION) {
|
||||
parent.dispose();
|
||||
return fc.getSelectedFile();
|
||||
}else {
|
||||
parent.dispose();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class LicensePrompt {
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println();
|
||||
display();
|
||||
}
|
||||
|
||||
public static void display() {
|
||||
System.out.println("WARNING: You must agree to the LICENSE before running this command");
|
||||
System.out.println();
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(LicensePrompt.class.getResourceAsStream("/lang/LICENSE_console_wrapped.txt"), StandardCharsets.UTF_8))) {
|
||||
String line;
|
||||
while((line = reader.readLine()) != null) {
|
||||
if(line.equals("<press enter>")) {
|
||||
pressEnter();
|
||||
}else {
|
||||
System.out.println(line);
|
||||
}
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
System.err.println();
|
||||
System.err.println("ERROR: could not display license text");
|
||||
System.err.println("Please read the \"LICENSE\" file before using this software");
|
||||
System.err.println();
|
||||
pressEnter();
|
||||
}
|
||||
}
|
||||
|
||||
private static void pressEnter() {
|
||||
System.out.println();
|
||||
System.out.println("(press ENTER to continue)");
|
||||
while(true) {
|
||||
try {
|
||||
if(System.in.read() == '\n') {
|
||||
break;
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
throw new RuntimeException("Unexpected IOException reading STDIN", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,447 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.decompiler;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.signature.SignatureReader;
|
||||
import org.objectweb.asm.signature.SignatureVisitor;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class LocalVariableGenerator extends SignatureVisitor {
|
||||
|
||||
public static final Map<Character,String> primitiveNames = new HashMap();
|
||||
public static final Set<String> illegalVariableNames = new HashSet();
|
||||
|
||||
static {
|
||||
|
||||
primitiveNames.put('Z', "Flag");
|
||||
primitiveNames.put('C', "Char");
|
||||
primitiveNames.put('B', "Byte");
|
||||
primitiveNames.put('S', "Short");
|
||||
primitiveNames.put('I', "Int");
|
||||
primitiveNames.put('F', "Float");
|
||||
primitiveNames.put('J', "Long");
|
||||
primitiveNames.put('D', "Double");
|
||||
primitiveNames.put('V', "Void");
|
||||
|
||||
illegalVariableNames.addAll(Arrays.asList(
|
||||
"abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class",
|
||||
"continue", "const", "default", "do", "double", "else", "enum", "exports", "extends",
|
||||
"final", "finally", "float", "for", "goto", "if", "implements", "import",
|
||||
"instanceof", "int", "interface", "long", "native", "new", "package", "private",
|
||||
"protected", "public", "return", "short", "static", "strictfp", "super", "switch",
|
||||
"synchronized", "this", "throw", "throws", "transient", "try", "var", "void",
|
||||
"volatile", "while", "string"
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
private String baseClass = null;
|
||||
private boolean isArray = false;
|
||||
private String typeParam1 = null;
|
||||
private boolean typeParam1IsArray = false;
|
||||
private String typeParam2 = null;
|
||||
private boolean typeParam2IsArray = false;
|
||||
|
||||
public static final SignatureVisitor nopVisitor = new SignatureVisitor(Opcodes.ASM5) {};
|
||||
|
||||
LocalVariableGenerator() {
|
||||
super(Opcodes.ASM5);
|
||||
}
|
||||
|
||||
public static String createName(String sig) {
|
||||
SignatureReader rd = new SignatureReader(sig);
|
||||
LocalVariableGenerator gen = new LocalVariableGenerator();
|
||||
rd.acceptType(gen);
|
||||
return gen.getResult();
|
||||
}
|
||||
|
||||
private String removePath(String in) {
|
||||
int idx = in.lastIndexOf('/');
|
||||
int idx2 = in.lastIndexOf('$');
|
||||
if(idx2 > idx && idx2 != in.length() - 1) {
|
||||
idx = idx2;
|
||||
}
|
||||
if(idx != -1) {
|
||||
in = in.substring(idx + 1);
|
||||
}
|
||||
if(in.length() == 0 || Character.isDigit(in.charAt(0))) {
|
||||
in = "obj" + in;
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
String getResult() {
|
||||
String rt;
|
||||
if(baseClass == null) {
|
||||
rt = "Object";
|
||||
}else {
|
||||
rt = removePath(baseClass);
|
||||
}
|
||||
if(typeParam1 == null && typeParam2 == null) {
|
||||
if(isArray) {
|
||||
rt = "ArrayOf" + rt;
|
||||
}
|
||||
}else {
|
||||
if(isArray) {
|
||||
rt = rt + "Array";
|
||||
}
|
||||
}
|
||||
if(typeParam1 != null && typeParam2 == null) {
|
||||
if(typeParam1IsArray) {
|
||||
typeParam1 = typeParam1 + "Array";
|
||||
}
|
||||
rt = rt + "Of" + removePath(typeParam1);
|
||||
}else if(typeParam1 != null && typeParam2 != null) {
|
||||
if(typeParam1IsArray) {
|
||||
typeParam1 = typeParam1 + "Array";
|
||||
}
|
||||
if(typeParam2IsArray) {
|
||||
typeParam2 = typeParam2 + "Array";
|
||||
}
|
||||
rt = rt + "Of" + removePath(typeParam1) + "And" + removePath(typeParam2);
|
||||
}
|
||||
return rt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitArrayType() {
|
||||
if(baseClass == null) {
|
||||
isArray = true;
|
||||
return new ArrayTypeVisitor();
|
||||
}else {
|
||||
return nopVisitor;
|
||||
}
|
||||
}
|
||||
|
||||
private class ArrayTypeVisitor extends SignatureVisitor {
|
||||
|
||||
protected ArrayTypeVisitor() {
|
||||
super(Opcodes.ASM5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBaseType(char descriptor) {
|
||||
if(baseClass == null) {
|
||||
baseClass = primitiveNames.get(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassType(String name) {
|
||||
if(baseClass == null) {
|
||||
baseClass = name;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitArrayType() {
|
||||
if(baseClass == null) {
|
||||
baseClass = "array";
|
||||
}
|
||||
return nopVisitor;
|
||||
}
|
||||
|
||||
@Override public SignatureVisitor visitClassBound() { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitExceptionType() { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitInterface() { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitInterfaceBound() { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitParameterType() { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitTypeArgument(char wildcard) { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitReturnType() { return nopVisitor; }
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBaseType(char descriptor) {
|
||||
if(baseClass == null) {
|
||||
baseClass = primitiveNames.get(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitClassBound() {
|
||||
//System.out.println("class: " + this);
|
||||
return nopVisitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassType(String name) {
|
||||
//System.out.println("classType: " + name);
|
||||
if(baseClass == null) {
|
||||
baseClass = name;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitExceptionType() {
|
||||
return nopVisitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFormalTypeParameter(String name) {
|
||||
//System.out.println("formalTypeParam: " + name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClassType(String name) {
|
||||
//System.out.println("innerClassType: " + name);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitInterface() {
|
||||
return nopVisitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitInterfaceBound() {
|
||||
return nopVisitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitParameterType() {
|
||||
return nopVisitor;
|
||||
}
|
||||
|
||||
private class TypeParamVisitor extends SignatureVisitor {
|
||||
|
||||
private boolean hasVisited = false;
|
||||
private final int firstOrSecond;
|
||||
|
||||
protected TypeParamVisitor(int firstOrSecond) {
|
||||
super(Opcodes.ASM5);
|
||||
this.firstOrSecond = firstOrSecond;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBaseType(char descriptor) {
|
||||
if(!hasVisited) {
|
||||
if(firstOrSecond == 1) {
|
||||
if(typeParam1 == null) {
|
||||
typeParam1 = primitiveNames.get(descriptor);
|
||||
}
|
||||
}else if(firstOrSecond == 2) {
|
||||
if(typeParam2 == null) {
|
||||
typeParam2 = primitiveNames.get(descriptor);
|
||||
}
|
||||
}
|
||||
hasVisited = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassType(String name) {
|
||||
if(!hasVisited) {
|
||||
if(firstOrSecond == 1) {
|
||||
if(typeParam1 == null) {
|
||||
typeParam1 = name;
|
||||
}
|
||||
}else if(firstOrSecond == 2) {
|
||||
if(typeParam2 == null) {
|
||||
typeParam2 = name;
|
||||
}
|
||||
}
|
||||
hasVisited = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitArrayType() {
|
||||
if(!hasVisited) {
|
||||
if(firstOrSecond == 1) {
|
||||
if(typeParam1 == null) {
|
||||
typeParam1IsArray = true;
|
||||
return new TypeParamArrayVisitor();
|
||||
}
|
||||
}else if(firstOrSecond == 2) {
|
||||
if(typeParam2 == null) {
|
||||
typeParam2IsArray = true;
|
||||
return new TypeParamArrayVisitor();
|
||||
}
|
||||
}
|
||||
}
|
||||
return nopVisitor;
|
||||
}
|
||||
|
||||
private class TypeParamArrayVisitor extends SignatureVisitor {
|
||||
|
||||
protected TypeParamArrayVisitor() {
|
||||
super(Opcodes.ASM5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBaseType(char descriptor) {
|
||||
if(!hasVisited) {
|
||||
if(firstOrSecond == 1) {
|
||||
if(typeParam1 == null) {
|
||||
typeParam1 = primitiveNames.get(descriptor);
|
||||
}
|
||||
}else if(firstOrSecond == 2) {
|
||||
if(typeParam2 == null) {
|
||||
typeParam2 = primitiveNames.get(descriptor);
|
||||
}
|
||||
}
|
||||
hasVisited = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassType(String name) {
|
||||
if(!hasVisited) {
|
||||
if(firstOrSecond == 1) {
|
||||
if(typeParam1 == null) {
|
||||
typeParam1 = name;
|
||||
}
|
||||
}else if(firstOrSecond == 2) {
|
||||
if(typeParam2 == null) {
|
||||
typeParam2 = name;
|
||||
}
|
||||
}
|
||||
hasVisited = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitArrayType() {
|
||||
if(!hasVisited) {
|
||||
if(firstOrSecond == 1) {
|
||||
if(typeParam1 == null) {
|
||||
typeParam1 = "array";
|
||||
}
|
||||
}else if(firstOrSecond == 2) {
|
||||
if(typeParam2 == null) {
|
||||
typeParam2 = "array";
|
||||
}
|
||||
}
|
||||
hasVisited = true;
|
||||
}
|
||||
return nopVisitor;
|
||||
}
|
||||
|
||||
@Override public SignatureVisitor visitClassBound() { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitExceptionType() { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitInterface() { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitInterfaceBound() { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitParameterType() { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitTypeArgument(char wildcard) { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitReturnType() { return nopVisitor; }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitReturnType() {
|
||||
return nopVisitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitSuperclass() {
|
||||
return nopVisitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeArgument() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitTypeArgument(char wildcard) {
|
||||
if(typeParam1 == null) {
|
||||
return new TypeParamVisitor(1);
|
||||
}else if(typeParam2 == null) {
|
||||
return new TypeParamVisitor(2);
|
||||
}else {
|
||||
return nopVisitor;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeVariable(String name) {
|
||||
|
||||
}
|
||||
|
||||
public static String nextLocalVariableNameFromString(Map<String,Integer> tmpLocalsMap, String signature, String pfx) {
|
||||
String str = signature.length() == 1 ? primitiveNames.get(signature.charAt(0)) : null;
|
||||
if(str == null) {
|
||||
str = LocalVariableGenerator.createName(signature);
|
||||
}
|
||||
String ls = str.toLowerCase();
|
||||
Integer i = tmpLocalsMap.get(ls);
|
||||
if(i == null) {
|
||||
tmpLocalsMap.put(ls, 1);
|
||||
if(Character.isDigit(str.charAt(str.length() - 1))) {
|
||||
str = str + "_1";
|
||||
}else {
|
||||
str = illegalVariableNames.contains(str.toLowerCase()) ? str + "1" : str;
|
||||
}
|
||||
}else {
|
||||
int ii = i.intValue() + 1;
|
||||
tmpLocalsMap.put(ls, ii);
|
||||
if(Character.isDigit(str.charAt(str.length() - 1)) || str.contains("And") || str.length() > 16) {
|
||||
str = str + "_" + ii;
|
||||
}else {
|
||||
str = str + ii;
|
||||
}
|
||||
}
|
||||
return pfx == null ? camelCase(str) : pfx + str;
|
||||
}
|
||||
|
||||
public static String nextLocalVariableName(Map<String,Integer> tmpLocalsMap, LocalVariableGenerator signature, String pfx) {
|
||||
String str = signature.getResult();
|
||||
String ls = str.toLowerCase();
|
||||
Integer i = tmpLocalsMap.get(ls);
|
||||
if(i == null) {
|
||||
tmpLocalsMap.put(ls, 1);
|
||||
if(Character.isDigit(str.charAt(str.length() - 1))) {
|
||||
str = str + "_1";
|
||||
}else {
|
||||
str = illegalVariableNames.contains(str.toLowerCase()) ? str + "1" : str;
|
||||
}
|
||||
}else {
|
||||
int ii = i.intValue() + 1;
|
||||
tmpLocalsMap.put(ls, ii);
|
||||
if(Character.isDigit(str.charAt(str.length() - 1)) || str.contains("And") || str.length() > 16) {
|
||||
str = str + "_" + ii;
|
||||
}else {
|
||||
str = str + ii;
|
||||
}
|
||||
}
|
||||
return pfx == null ? camelCase(str) : pfx + str;
|
||||
}
|
||||
|
||||
public static String camelCase(String in) {
|
||||
if(in == null || in.length() <= 0) {
|
||||
return "name";
|
||||
}else {
|
||||
if(in.length() > 1 && Character.isUpperCase(in.charAt(0)) && Character.isUpperCase(in.charAt(1))) {
|
||||
return "var" + in;
|
||||
}else {
|
||||
return in.substring(0, 1).toLowerCase() + in.substring(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.decompiler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.signature.SignatureReader;
|
||||
import org.objectweb.asm.signature.SignatureVisitor;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class ParameterSplitter extends SignatureVisitor {
|
||||
|
||||
protected ParameterSplitter() {
|
||||
super(Opcodes.ASM5);
|
||||
}
|
||||
|
||||
protected static final ArrayList<LocalVariableGenerator> ret = new ArrayList();
|
||||
protected static final HashMap<String,Integer> usedLocals = new HashMap();
|
||||
|
||||
public static int getParameterArray(String sig, String[] input) {
|
||||
SignatureReader rd = new SignatureReader(sig);
|
||||
ParameterSplitter pms = new ParameterSplitter();
|
||||
ret.clear();
|
||||
usedLocals.clear();
|
||||
rd.accept(pms);
|
||||
int l = ret.size();
|
||||
if(l > input.length) {
|
||||
l = input.length;
|
||||
}
|
||||
int c = 0;
|
||||
for(int i = 0; i < l; ++i) {
|
||||
if(input[i] == null) {
|
||||
input[i] = LocalVariableGenerator.nextLocalVariableName(usedLocals, ret.get(i), "par");
|
||||
++c;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
public static String[] getParameterSigArray(String sig, String pfx) {
|
||||
SignatureReader rd = new SignatureReader(sig);
|
||||
ParameterSplitter pms = new ParameterSplitter();
|
||||
ret.clear();
|
||||
usedLocals.clear();
|
||||
rd.accept(pms);
|
||||
String[] r = new String[ret.size()];
|
||||
for(int i = 0; i < r.length; ++i) {
|
||||
r[i] = LocalVariableGenerator.nextLocalVariableName(usedLocals, ret.get(i), pfx);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitParameterType() {
|
||||
LocalVariableGenerator lv = new LocalVariableGenerator();
|
||||
ret.add(lv);
|
||||
return lv;
|
||||
}
|
||||
|
||||
@Override public SignatureVisitor visitClassBound() { return LocalVariableGenerator.nopVisitor; }
|
||||
@Override public SignatureVisitor visitExceptionType() { return LocalVariableGenerator.nopVisitor; }
|
||||
@Override public SignatureVisitor visitInterface() { return LocalVariableGenerator.nopVisitor; }
|
||||
@Override public SignatureVisitor visitInterfaceBound() { return LocalVariableGenerator.nopVisitor; }
|
||||
@Override public SignatureVisitor visitTypeArgument(char wildcard) { return LocalVariableGenerator.nopVisitor; }
|
||||
@Override public SignatureVisitor visitReturnType() { return LocalVariableGenerator.nopVisitor; }
|
||||
@Override public SignatureVisitor visitArrayType() { return LocalVariableGenerator.nopVisitor; }
|
||||
@Override public void visitBaseType(char descriptor) { }
|
||||
@Override public void visitClassType(String name) { }
|
||||
@Override public void visitEnd() { }
|
||||
@Override public void visitFormalTypeParameter(String name) { }
|
||||
@Override public void visitInnerClassType(String name) { }
|
||||
@Override public SignatureVisitor visitSuperclass() { return LocalVariableGenerator.nopVisitor; }
|
||||
@Override public void visitTypeArgument() { }
|
||||
@Override public void visitTypeVariable(String name) { }
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,416 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.gui;
|
||||
|
||||
import java.awt.Desktop;
|
||||
import java.awt.EventQueue;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildTools;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.gui.TeaVMBinaries.MissingJARsException;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.DecompileMinecraft;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.FFMPEG;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.InitMCP;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.teavm.TeaVMBridge;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.teavm.TeaVMBridge.TeaVMClassLoadException;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.teavm.TeaVMBridge.TeaVMRuntimeException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class CompileLatestClientGUI {
|
||||
|
||||
public static CompileLatestClientFrame frame = null;
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println();
|
||||
System.out.println("Launching client compiler wizard...");
|
||||
System.out.println("Copyright (c) 2022 lax1dude");
|
||||
System.out.println();
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
|
||||
| UnsupportedLookAndFeelException e) {
|
||||
System.err.println("Could not set system look and feel: " + e.toString());
|
||||
}
|
||||
if(!System.getProperty("eaglercraft.isJava11", "false").equalsIgnoreCase("true")) {
|
||||
try {
|
||||
if (!(boolean) Class
|
||||
.forName("net.lax1dude.eaglercraft.v1_8.buildtools.Java11Check", true,
|
||||
new URLClassLoader(new URL[] { (new File("buildtools/Java11Check.jar")).toURI().toURL() }))
|
||||
.getMethod("classLoadCheck").invoke(null)) {
|
||||
throw new RuntimeException("wtf?");
|
||||
}
|
||||
}catch(Throwable t) {
|
||||
JOptionPane.showMessageDialog(null, "Error: Java 11 is required to run this program", "Unsupported JRE", JOptionPane.ERROR_MESSAGE);
|
||||
System.exit(-1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
frame = new CompileLatestClientFrame();
|
||||
frame.frmCompileLatestClient.setLocationRelativeTo(null);
|
||||
frame.frmCompileLatestClient.setVisible(true);
|
||||
System.out.println("you eagler");
|
||||
System.out.println();
|
||||
frame.launchLogUpdateThread();
|
||||
System.setOut(new PrintStream(new ConsoleRedirector(false)));
|
||||
System.setErr(new PrintStream(new ConsoleRedirector(true)));
|
||||
if(JavaC.jdkHome == null) {
|
||||
if(JOptionPane.showConfirmDialog(frame.frmCompileLatestClient, "Error: A JDK is required to run this program!\nYou are currently running on a JRE\nDo you have a JDK installed that you would like to use instead?", "Unsupported JRE", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
|
||||
JOptionPane.showMessageDialog(frame.frmCompileLatestClient, "You need at least JDK 8 to compile EaglercraftX 1.8!\nSelect the path to the installation you want to use", "Unsupported JRE", JOptionPane.INFORMATION_MESSAGE);
|
||||
JFileChooser fileChooser = new JFileChooser((new File(System.getProperty("java.home"))).getParentFile());
|
||||
fileChooser.setMultiSelectionEnabled(false);
|
||||
fileChooser.setFileHidingEnabled(false);
|
||||
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||
while(true) {
|
||||
if(fileChooser.showOpenDialog(frame.frmCompileLatestClient) == JFileChooser.APPROVE_OPTION) {
|
||||
File f = fileChooser.getSelectedFile();
|
||||
if(JavaC.windows ? (new File(f, "bin/javac.exe")).exists() : (new File(f, "bin/javac")).canExecute()) {
|
||||
break;
|
||||
}else {
|
||||
if(JOptionPane.showConfirmDialog(frame.frmCompileLatestClient, "Could not find a java compiler in this directory!\nWould you like to try again?", "Unsupported JRE", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
JOptionPane.showMessageDialog(frame.frmCompileLatestClient, "Please install JDK 8 or newer to continue", "Unsupported JRE", JOptionPane.ERROR_MESSAGE);
|
||||
System.exit(-1);
|
||||
return;
|
||||
}
|
||||
JavaC.jdkHome = fileChooser.getSelectedFile();
|
||||
JOptionPane.showMessageDialog(frame.frmCompileLatestClient, "The JDK \"" + JavaC.jdkHome.getAbsolutePath() + "\" will be used to compile EaglercraftX", "Unsupported JRE", JOptionPane.INFORMATION_MESSAGE);
|
||||
}else {
|
||||
JOptionPane.showMessageDialog(frame.frmCompileLatestClient, "Please install a JDK and re-launch this program", "Unsupported JRE", JOptionPane.ERROR_MESSAGE);
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
frame.scrollPane_LicenseText.getVerticalScrollBar().setValue(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static class CompileFailureException extends RuntimeException {
|
||||
public CompileFailureException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
public CompileFailureException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
}
|
||||
|
||||
public static void runCompiler() {
|
||||
try {
|
||||
runCompiler0();
|
||||
}catch(CompileFailureException t) {
|
||||
System.out.println();
|
||||
System.err.println("Error: " + t.getMessage());
|
||||
t.printStackTrace();
|
||||
frame.finishCompiling(true, t.getMessage());
|
||||
return;
|
||||
}catch(Throwable t) {
|
||||
System.out.println();
|
||||
System.err.println("Error: unhandled exception caught while compiling!");
|
||||
t.printStackTrace();
|
||||
frame.finishCompiling(true, t.toString());
|
||||
return;
|
||||
}
|
||||
if(!frame.finished) {
|
||||
System.out.println();
|
||||
System.err.println("Error: compilation finished with unknown status!");
|
||||
frame.finishCompiling(true, "Compilation finished with unknown status");
|
||||
}
|
||||
}
|
||||
|
||||
private static void runCompiler0() throws Throwable {
|
||||
File repositoryFolder = new File(frame.textField_RepositoryPath.getText().trim());
|
||||
EaglerBuildTools.repositoryRoot = repositoryFolder;
|
||||
File modCoderPack = new File(frame.textField_ModCoderPack.getText().trim());
|
||||
File minecraftJar = new File(frame.textField_JarFilePath.getText().trim());
|
||||
File assetsIndex = new File(frame.textField_AssetsIndexJSON.getText().trim());
|
||||
File outputDirectory = new File(frame.textField_OutputDirectory.getText().trim());
|
||||
File temporaryDirectory = new File(outputDirectory, "build");
|
||||
|
||||
File[] existingOutput = outputDirectory.listFiles();
|
||||
if(existingOutput.length > 0) {
|
||||
System.out.println("Deleting existing files from the output directory...");
|
||||
try {
|
||||
for(int i = 0; i < existingOutput.length; ++i) {
|
||||
File f = existingOutput[i];
|
||||
if(f.isDirectory()) {
|
||||
FileUtils.deleteDirectory(f);
|
||||
}else {
|
||||
if(!f.delete()) {
|
||||
throw new IOException("Could not delete: " + f.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}catch(IOException t) {
|
||||
throw new CompileFailureException("Could not delete old output directory: " + t.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
File mcpDataTMP = new File(temporaryDirectory, "ModCoderPack");
|
||||
File minecraftSrcTmp = new File(temporaryDirectory, "MinecraftSrc");
|
||||
|
||||
String ffmpeg = frame.chckbxUsePathFFmpeg.isSelected() ? "" : frame.textField_pathToFFmpeg.getText().trim();
|
||||
if(ffmpeg.length() == 0) {
|
||||
FFMPEG.foundFFMPEG = "ffmpeg";
|
||||
}else {
|
||||
FFMPEG.foundFFMPEG = ffmpeg;
|
||||
}
|
||||
|
||||
String mavenRepositoryURL = frame.getRepositoryURL();
|
||||
File mavenRepositoryFolder = null;
|
||||
if(mavenRepositoryURL == null) {
|
||||
mavenRepositoryFolder = new File(frame.textField_MavenRepoLocal.getText().trim());
|
||||
}
|
||||
|
||||
boolean generateOfflineDownload = frame.chckbxOutputOfflineDownload.isSelected();
|
||||
boolean keepTemporaryFiles = frame.chckbxKeepTemporaryFiles.isSelected();
|
||||
|
||||
if(!mcpDataTMP.isDirectory() && !mcpDataTMP.mkdirs()) {
|
||||
throw new CompileFailureException("Error: failed to create \"" + mcpDataTMP.getAbsolutePath() + "\"!");
|
||||
}
|
||||
|
||||
if(!InitMCP.initTask(modCoderPack, mcpDataTMP)) {
|
||||
throw new CompileFailureException("Error: could not initialize MCP from \"" + modCoderPack.getAbsolutePath() + "\"!");
|
||||
}
|
||||
|
||||
if(!minecraftSrcTmp.isDirectory() && !minecraftSrcTmp.mkdirs()) {
|
||||
throw new CompileFailureException("Error: failed to create \"" + minecraftSrcTmp.getAbsolutePath() + "\"!");
|
||||
}
|
||||
|
||||
if(!DecompileMinecraft.decompileMinecraft(mcpDataTMP, minecraftJar, minecraftSrcTmp, assetsIndex, false)) {
|
||||
throw new CompileFailureException("Error: could not decompile and patch 1.8.8.jar from \"" + minecraftJar.getAbsolutePath() + "\"!");
|
||||
}
|
||||
|
||||
try {
|
||||
FileUtils.copyFile(new File(repositoryFolder, "patches/minecraft/output_license.txt"), new File(temporaryDirectory, "MinecraftSrc/LICENSE"));
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Error: failed to write LICENSE in temporary directory!");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
if(frame.rdbtnMavenRepoLocal.isSelected()) {
|
||||
System.out.println("TeaVM JARs will be loaded from: " + frame.textField_MavenRepoLocal.getText());
|
||||
}else {
|
||||
String url = frame.getRepositoryURL();
|
||||
System.out.println("TeaVM JARs will be downloaded from repository: " + url);
|
||||
System.out.println();
|
||||
try {
|
||||
TeaVMBinaries.downloadFromMaven(url, new File("##TEAVM.TMP##"));
|
||||
}catch(MissingJARsException ex) {
|
||||
throw new CompileFailureException(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
int compileResultCode;
|
||||
File compiledResultClasses = new File(temporaryDirectory, "classes");
|
||||
|
||||
try {
|
||||
try {
|
||||
compileResultCode = JavaC.runJavaC(new File(minecraftSrcTmp, "minecraft_src_javadoc.jar"),
|
||||
compiledResultClasses, temporaryDirectory, TeaVMBinaries.getTeaVMRuntimeClasspath(),
|
||||
new File(repositoryFolder, "sources/main/java"), new File(repositoryFolder, "sources/teavm/java"));
|
||||
}catch(IOException ex) {
|
||||
throw new CompileFailureException("failed to run javac compiler! " + ex.toString(), ex);
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
if(compileResultCode == 0) {
|
||||
System.out.println("Java compiler completed successfully");
|
||||
}else {
|
||||
throw new CompileFailureException("failed to run javac compiler! exit code " + compileResultCode + ", check log");
|
||||
}
|
||||
}finally {
|
||||
File extractedSrcTmp = new File(temporaryDirectory, "MinecraftSrc/src_javadoc_tmp");
|
||||
if(extractedSrcTmp.exists()) {
|
||||
System.out.println();
|
||||
System.out.println("Deleting temporary directory: " + extractedSrcTmp.getAbsolutePath());
|
||||
try {
|
||||
FileUtils.deleteDirectory(extractedSrcTmp);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Failed to delete temporary directory!");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Preparing arguments for TeaVM...");
|
||||
|
||||
if(!TeaVMBinaries.tryLoadTeaVMBridge()) {
|
||||
System.err.println("Failed to locate TeaVMBridge.jar, you can specify it's path manually by adding the JVM argument \"-Deaglercraft.TeaVMBridge=<path>\"");
|
||||
throw new CompileFailureException("Failed to locate TeaVMBridge.jar!");
|
||||
}
|
||||
|
||||
Map<String, Object> teavmArgs = new HashMap();
|
||||
|
||||
List<String> teavmClassPath = new ArrayList();
|
||||
teavmClassPath.add(compiledResultClasses.getAbsolutePath());
|
||||
teavmClassPath.addAll(Arrays.asList(TeaVMBinaries.getTeaVMRuntimeClasspath()));
|
||||
teavmArgs.put("classPathEntries", teavmClassPath);
|
||||
|
||||
teavmArgs.put("entryPointName", "main");
|
||||
teavmArgs.put("mainClass", "net.lax1dude.eaglercraft.v1_8.internal.teavm.MainClass");
|
||||
teavmArgs.put("minifying", true);
|
||||
teavmArgs.put("optimizationLevel", "ADVANCED");
|
||||
teavmArgs.put("targetDirectory", outputDirectory.getAbsolutePath());
|
||||
teavmArgs.put("generateSourceMaps", true);
|
||||
teavmArgs.put("targetFileName", "classes.js");
|
||||
|
||||
System.out.println();
|
||||
|
||||
boolean teavmStatus;
|
||||
try {
|
||||
teavmStatus = TeaVMBridge.compileTeaVM(teavmArgs);
|
||||
}catch(TeaVMClassLoadException ex) {
|
||||
throw new CompileFailureException("Failed to link TeaVM jar files! Did you select the wrong jar?", ex);
|
||||
}catch(TeaVMRuntimeException ex) {
|
||||
throw new CompileFailureException("Failed to run TeaVM! Check log", ex);
|
||||
}
|
||||
|
||||
if(!teavmStatus) {
|
||||
frame.finishCompiling(true, "TeaVM reported problems, check the log");
|
||||
return;
|
||||
}
|
||||
|
||||
File epkCompiler = new File(repositoryFolder, "sources/setup/workspace_template/desktopRuntime/CompileEPK.jar");
|
||||
|
||||
if(!epkCompiler.exists()) {
|
||||
throw new CompileFailureException("EPKCompiler JAR file is missing: " + epkCompiler.getAbsolutePath());
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Writing default index.html...");
|
||||
|
||||
FileUtils.copyFile(new File(repositoryFolder, "buildtools/production-index.html"), new File(outputDirectory, "index.html"));
|
||||
FileUtils.copyFile(new File(repositoryFolder, "buildtools/production-favicon.png"), new File(outputDirectory, "favicon.png"));
|
||||
FileUtils.copyFile(new File(repositoryFolder, "sources/setup/workspace_template/javascript/fix-webm-duration.js"), new File(outputDirectory, "fix-webm-duration.js"));
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Running EPKCompiler on assets...");
|
||||
|
||||
EPKCompiler.compilerMain(epkCompiler, new String[] {
|
||||
((new File(minecraftSrcTmp, "minecraft_res_patch.jar")).getAbsolutePath() + System.getProperty("path.separator") +
|
||||
(new File(repositoryFolder, "sources/resources")).getAbsolutePath()), (new File(outputDirectory, "assets.epk")).getAbsolutePath() });
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Running EPKCompiler on languages.zip...");
|
||||
|
||||
EPKCompiler.compilerMain(epkCompiler, new String[] {
|
||||
(new File(minecraftSrcTmp, "minecraft_languages.zip")).getAbsolutePath(),
|
||||
(new File(temporaryDirectory, "languages.epk")).getAbsolutePath() });
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Creating languages directory...");
|
||||
File langDirectory = new File(outputDirectory, "lang");
|
||||
|
||||
byte[] copyBuffer = new byte[16384];
|
||||
int i;
|
||||
try(ZipInputStream zis = new ZipInputStream(new FileInputStream(new File(minecraftSrcTmp, "minecraft_languages.zip")))) {
|
||||
ZipEntry etr;
|
||||
while((etr = zis.getNextEntry()) != null) {
|
||||
if(!etr.isDirectory()) {
|
||||
File phile = new File(langDirectory, etr.getName());
|
||||
File parent = phile.getParentFile();
|
||||
if(!parent.exists() && !parent.mkdirs()) {
|
||||
throw new IOException("Could not create directory: " + parent.getAbsolutePath());
|
||||
}
|
||||
try(FileOutputStream os = new FileOutputStream(phile)) {
|
||||
while((i = zis.read(copyBuffer)) != -1) {
|
||||
os.write(copyBuffer, 0, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
if(generateOfflineDownload) {
|
||||
System.out.println("Running offline download generator...");
|
||||
System.out.println();
|
||||
File offlineDownloadGenerator = new File(repositoryFolder, "sources/setup/workspace_template/desktopRuntime/MakeOfflineDownload.jar");
|
||||
MakeOfflineDownload.compilerMain(offlineDownloadGenerator, new String[] {
|
||||
(new File(repositoryFolder, "sources/setup/workspace_template/javascript/OfflineDownloadTemplate.txt")).getAbsolutePath(),
|
||||
(new File(outputDirectory, "classes.js")).getAbsolutePath() + System.getProperty("path.separator")
|
||||
+ (new File(outputDirectory, "fix-webm-duration.js")).getAbsolutePath(),
|
||||
(new File(outputDirectory, "assets.epk")).getAbsolutePath(),
|
||||
(new File(outputDirectory, "EaglercraftX_1.8_Offline_en_US.html")).getAbsolutePath(),
|
||||
(new File(outputDirectory, "EaglercraftX_1.8_Offline_International.html")).getAbsolutePath(),
|
||||
(new File(outputDirectory, "build/languages.epk")).getAbsolutePath()
|
||||
});
|
||||
}
|
||||
|
||||
System.out.println("Releasing external ClassLoader(s)...");
|
||||
System.out.println();
|
||||
|
||||
TeaVMBridge.free();
|
||||
EPKCompiler.free();
|
||||
|
||||
if(generateOfflineDownload) {
|
||||
MakeOfflineDownload.free();
|
||||
}
|
||||
|
||||
if(!keepTemporaryFiles) {
|
||||
System.out.println("Cleaning up temporary files...");
|
||||
try {
|
||||
FileUtils.deleteDirectory(temporaryDirectory);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Failed to delete temporary directory: " + temporaryDirectory.getAbsolutePath());
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Client build successful! Check the output directory for your files");
|
||||
|
||||
try {
|
||||
Desktop.getDesktop().open(outputDirectory);
|
||||
}catch(Throwable t) {
|
||||
}
|
||||
|
||||
frame.finishCompiling(false, "");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.gui;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class ConsoleRedirector extends OutputStream {
|
||||
|
||||
private final OutputStream stdout;
|
||||
private final boolean err;
|
||||
|
||||
public ConsoleRedirector(boolean err) {
|
||||
stdout = err ? System.err : System.out;
|
||||
this.err = err;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int o, int l) throws IOException {
|
||||
stdout.write(b, o, l);
|
||||
String append = new String(b, o, l, StandardCharsets.US_ASCII);
|
||||
if(err) {
|
||||
CompileLatestClientGUI.frame.logError(append);
|
||||
}else {
|
||||
CompileLatestClientGUI.frame.logInfo(append);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
stdout.write(b);
|
||||
write0(b);
|
||||
}
|
||||
|
||||
private void write0(int b) throws IOException {
|
||||
char c = (char)b;
|
||||
if(c != '\r') {
|
||||
if(err && c != '\n') {
|
||||
CompileLatestClientGUI.frame.logError(new String(new char[] { c }));
|
||||
}else {
|
||||
CompileLatestClientGUI.frame.logInfo(new String(new char[] { c }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.gui;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class EPKCompiler {
|
||||
|
||||
private static File currentJarFile = null;
|
||||
private static URLClassLoader classLoader = null;
|
||||
private static Method mainMethod = null;
|
||||
|
||||
public static void compilerMain(File jarFile, String[] args) throws InvocationTargetException {
|
||||
if(currentJarFile != null && !currentJarFile.equals(jarFile)) {
|
||||
throw new IllegalArgumentException("Cannot load two different EPKCompiler versions into the same runtime");
|
||||
}
|
||||
if(mainMethod == null) {
|
||||
currentJarFile = jarFile;
|
||||
try {
|
||||
if(classLoader == null) {
|
||||
classLoader = new URLClassLoader(new URL[] { jarFile.toURI().toURL() }, ClassLoader.getSystemClassLoader());
|
||||
}
|
||||
Class epkCompilerMain = classLoader.loadClass("CompilePackage");
|
||||
mainMethod = epkCompilerMain.getDeclaredMethod("main", String[].class);
|
||||
} catch (MalformedURLException | SecurityException e) {
|
||||
throw new IllegalArgumentException("Illegal EPKCompiler JAR path!", e);
|
||||
} catch (ClassNotFoundException | NoSuchMethodException e) {
|
||||
throw new IllegalArgumentException("EPKCompiler JAR does not contain main class: 'CompilePackage'", e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
mainMethod.invoke(null, new Object[] { args });
|
||||
} catch (IllegalAccessException | IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException("EPKCompiler JAR does not contain valid 'main' method", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void free() {
|
||||
if(classLoader != null) {
|
||||
try {
|
||||
classLoader.close();
|
||||
classLoader = null;
|
||||
} catch (IOException e) {
|
||||
System.err.println("Memory leak, failed to release EPKCompiler ClassLoader!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,223 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.gui;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class JavaC {
|
||||
|
||||
public static final boolean windows;
|
||||
|
||||
public static File jdkHome;
|
||||
|
||||
public static final List<String> compilerFlags = Arrays.asList(
|
||||
"-Xlint:-unchecked", "-Xlint:-options", "-Xlint:-deprecation",
|
||||
"-source", "1.8", "-target", "1.8"
|
||||
);
|
||||
|
||||
private static int debugSourceFileCount = 0;
|
||||
|
||||
public static int runJavaC(File mcSourceJar, File outputDirectory, File tmpDirectory, String[] teavmClasspath,
|
||||
File... eaglerSourceDirs) throws IOException {
|
||||
|
||||
if(!outputDirectory.exists() && !outputDirectory.mkdirs()) {
|
||||
throw new IOException("Could not create output directory: " + outputDirectory.getAbsolutePath());
|
||||
}
|
||||
|
||||
if(!tmpDirectory.exists() && !tmpDirectory.mkdirs()) {
|
||||
throw new IOException("Could not create temporary directory: " + outputDirectory.getAbsolutePath());
|
||||
}
|
||||
|
||||
File minecraftSrcTmp = new File(tmpDirectory, "MinecraftSrc/src_javadoc_tmp");
|
||||
|
||||
if(!minecraftSrcTmp.exists() && !minecraftSrcTmp.mkdirs()) {
|
||||
throw new IOException("Could not create temporary directory: " + minecraftSrcTmp.getAbsolutePath());
|
||||
}
|
||||
|
||||
debugSourceFileCount = 0;
|
||||
|
||||
File argFile = new File(tmpDirectory, "sourceFiles.txt");
|
||||
try(PrintWriter writer = new PrintWriter(new FileWriter(argFile))) {
|
||||
|
||||
System.out.println("Extracting decompiled source...");
|
||||
|
||||
byte[] copyBuffer = new byte[16384];
|
||||
int copyBufferLen;
|
||||
try(ZipInputStream zis = new ZipInputStream(new FileInputStream(mcSourceJar))) {
|
||||
ZipEntry etr;
|
||||
while((etr = zis.getNextEntry()) != null && !etr.isDirectory()) {
|
||||
String n = etr.getName();
|
||||
if(n.endsWith(".java")) {
|
||||
File writeTo = new File(minecraftSrcTmp, n);
|
||||
File parent = writeTo.getParentFile();
|
||||
if(!parent.exists() && !parent.mkdirs()) {
|
||||
throw new IOException("Could not create temporary directory: " + parent.getAbsolutePath());
|
||||
}
|
||||
try(OutputStream os = new FileOutputStream(writeTo)) {
|
||||
while((copyBufferLen = zis.read(copyBuffer)) != -1) {
|
||||
os.write(copyBuffer, 0, copyBufferLen);
|
||||
}
|
||||
}
|
||||
writer.println("\"" + writeTo.getAbsolutePath().replace('\\', '/') + "\"");
|
||||
++debugSourceFileCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Scanning source folder paths...");
|
||||
|
||||
for(int i = 0; i < eaglerSourceDirs.length; ++i) {
|
||||
discoverSourceFiles(eaglerSourceDirs[i], writer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
List<String> commandBuilder = new ArrayList();
|
||||
|
||||
if(windows) {
|
||||
commandBuilder.add((new File(jdkHome, "bin/javac.exe")).getAbsolutePath());
|
||||
}else {
|
||||
commandBuilder.add((new File(jdkHome, "bin/javac")).getAbsolutePath());
|
||||
}
|
||||
|
||||
commandBuilder.addAll(compilerFlags);
|
||||
|
||||
String pathSeparator = System.getProperty("path.separator");
|
||||
|
||||
commandBuilder.add("-classpath");
|
||||
commandBuilder.add(String.join(pathSeparator, teavmClasspath));
|
||||
|
||||
commandBuilder.add("-sourcepath");
|
||||
|
||||
StringBuilder sourcePathBuilder = new StringBuilder();
|
||||
sourcePathBuilder.append(mcSourceJar.getAbsolutePath());
|
||||
|
||||
for(int i = 0; i < eaglerSourceDirs.length; ++i) {
|
||||
sourcePathBuilder.append(pathSeparator).append(eaglerSourceDirs[i].getAbsolutePath());
|
||||
}
|
||||
|
||||
commandBuilder.add(sourcePathBuilder.toString());
|
||||
|
||||
commandBuilder.add("-d");
|
||||
commandBuilder.add(outputDirectory.getAbsolutePath());
|
||||
|
||||
commandBuilder.add("@" + argFile.getAbsolutePath());
|
||||
|
||||
System.out.println();
|
||||
for(int i = 0, l = commandBuilder.size(); i < l; ++i) {
|
||||
String e = commandBuilder.get(i);
|
||||
if(e.indexOf(' ') != -1) {
|
||||
System.out.print("\"" + e + "\"");
|
||||
}else {
|
||||
System.out.print(e);
|
||||
}
|
||||
System.out.print(' ');
|
||||
}
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
System.out.println("Compiling " + debugSourceFileCount + " source files...");
|
||||
|
||||
ProcessBuilder procBuilder = new ProcessBuilder(commandBuilder);
|
||||
procBuilder.directory(tmpDirectory);
|
||||
Process javacProcess = procBuilder.start();
|
||||
|
||||
InputStream stdout = javacProcess.getInputStream();
|
||||
InputStream stderr = javacProcess.getErrorStream();
|
||||
byte[] readBuffer = new byte[128];
|
||||
int j;
|
||||
boolean tick;
|
||||
|
||||
do {
|
||||
tick = false;
|
||||
|
||||
j = stdout.available();
|
||||
if(j > 0) {
|
||||
if(j > 128) {
|
||||
j = 128;
|
||||
}
|
||||
stdout.read(readBuffer, 0, j);
|
||||
System.out.write(readBuffer, 0, j);
|
||||
tick = true;
|
||||
}
|
||||
|
||||
j = stderr.available();
|
||||
if(j > 0) {
|
||||
if(j > 128) {
|
||||
j = 128;
|
||||
}
|
||||
stderr.read(readBuffer, 0, j);
|
||||
System.err.write(readBuffer, 0, j);
|
||||
tick = true;
|
||||
}
|
||||
|
||||
if(!tick) {
|
||||
try {
|
||||
Thread.sleep(10l);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
|
||||
}while(javacProcess.isAlive());
|
||||
|
||||
while(true) {
|
||||
try {
|
||||
return javacProcess.waitFor();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void discoverSourceFiles(File folder, PrintWriter printWriter) throws IOException {
|
||||
File[] files = folder.listFiles();
|
||||
for(int i = 0; i < files.length; ++i) {
|
||||
File f = files[i];
|
||||
String name = f.getAbsolutePath();
|
||||
if(f.isDirectory()) {
|
||||
discoverSourceFiles(f, printWriter);
|
||||
}else {
|
||||
if(name.endsWith(".java")) {
|
||||
printWriter.println("\"" + name.replace('\\', '/') + "\"");
|
||||
++debugSourceFileCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
windows = System.getProperty("os.name").toLowerCase().contains("windows");
|
||||
String javac = windows ? "javac.exe" : "javac";
|
||||
File jdkHomeProp = new File(System.getProperty("java.home"));
|
||||
if((new File(jdkHomeProp, "bin/" + javac)).isFile()) {
|
||||
jdkHome = jdkHomeProp;
|
||||
}else if((new File(jdkHomeProp, "../bin/" + javac)).isFile()) {
|
||||
jdkHome = jdkHomeProp.getParentFile();
|
||||
}else {
|
||||
jdkHome = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.gui;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class MakeOfflineDownload {
|
||||
|
||||
private static File currentJarFile = null;
|
||||
private static URLClassLoader classLoader = null;
|
||||
private static Method mainMethod = null;
|
||||
|
||||
public static void compilerMain(File jarFile, String[] args) throws InvocationTargetException {
|
||||
if(currentJarFile != null && !currentJarFile.equals(jarFile)) {
|
||||
throw new IllegalArgumentException("Cannot load two different MakeOfflineDownload versions into the same runtime");
|
||||
}
|
||||
if(mainMethod == null) {
|
||||
currentJarFile = jarFile;
|
||||
try {
|
||||
if(classLoader == null) {
|
||||
classLoader = new URLClassLoader(new URL[] { jarFile.toURI().toURL() }, ClassLoader.getSystemClassLoader());
|
||||
}
|
||||
Class epkCompilerMain = classLoader.loadClass("net.lax1dude.eaglercraft.v1_8.buildtools.workspace.MakeOfflineDownload");
|
||||
mainMethod = epkCompilerMain.getDeclaredMethod("main", String[].class);
|
||||
} catch (MalformedURLException | SecurityException e) {
|
||||
throw new IllegalArgumentException("Illegal MakeOfflineDownload JAR path!", e);
|
||||
} catch (ClassNotFoundException | NoSuchMethodException e) {
|
||||
throw new IllegalArgumentException("MakeOfflineDownload JAR does not contain main class: 'net.lax1dude.eaglercraft.v1_8.buildtools.workspace.MakeOfflineDownload'", e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
mainMethod.invoke(null, new Object[] { args });
|
||||
} catch (IllegalAccessException | IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException("MakeOfflineDownload JAR does not contain valid 'main' method", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void free() {
|
||||
if(classLoader != null) {
|
||||
try {
|
||||
classLoader.close();
|
||||
classLoader = null;
|
||||
} catch (IOException e) {
|
||||
System.err.println("Memory leak, failed to release MakeOfflineDownload ClassLoader!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,422 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.gui;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class TeaVMBinaries {
|
||||
|
||||
public static final String teavmCoreJar = "teavm-core-0.6.1.jar";
|
||||
public static final String teavmCoreMaven = "org/teavm/teavm-core/0.6.1/teavm-core-0.6.1.jar";
|
||||
public static File teavmCore = null;
|
||||
|
||||
public static final String teavmCliJar = "teavm-cli-0.6.1.jar";
|
||||
public static final String teavmCliMaven = "org/teavm/teavm-cli/0.6.1/teavm-cli-0.6.1.jar";
|
||||
public static File teavmCli = null;
|
||||
|
||||
public static final String teavmToolingJar = "teavm-tooling-0.6.1.jar";
|
||||
public static final String teavmToolingMaven = "org/teavm/teavm-tooling/0.6.1/teavm-tooling-0.6.1.jar";
|
||||
public static File teavmTooling = null;
|
||||
|
||||
public static final String teavmPlatformJar = "teavm-platform-0.6.1.jar";
|
||||
public static final String teavmPlatformMaven = "org/teavm/teavm-platform/0.6.1/teavm-platform-0.6.1.jar";
|
||||
public static File teavmPlatform = null;
|
||||
|
||||
public static final String teavmClasslibJar = "teavm-classlib-0.6.1.jar";
|
||||
public static final String teavmClasslibMaven = "org/teavm/teavm-classlib/0.6.1/teavm-classlib-0.6.1.jar";
|
||||
public static File teavmClasslib = null;
|
||||
|
||||
public static final String teavmInteropJar = "teavm-interop-0.6.1.jar";
|
||||
public static final String teavmInteropMaven = "org/teavm/teavm-interop/0.6.1/teavm-interop-0.6.1.jar";
|
||||
public static File teavmInterop = null;
|
||||
|
||||
public static final String teavmJSOJar = "teavm-jso-0.6.1.jar";
|
||||
public static final String teavmJSOMaven = "org/teavm/teavm-jso/0.6.1/teavm-jso-0.6.1.jar";
|
||||
public static File teavmJSO = null;
|
||||
|
||||
public static final String teavmJSOApisJar = "teavm-jso-apis-0.6.1.jar";
|
||||
public static final String teavmJSOApisMaven = "org/teavm/teavm-jso-apis/0.6.1/teavm-jso-apis-0.6.1.jar";
|
||||
public static File teavmJSOApis = null;
|
||||
|
||||
public static final String teavmJSOImplJar = "teavm-jso-impl-0.6.1.jar";
|
||||
public static final String teavmJSOImplMaven = "org/teavm/teavm-jso-impl/0.6.1/teavm-jso-impl-0.6.1.jar";
|
||||
public static File teavmJSOImpl = null;
|
||||
|
||||
public static final String teavmMetaprogrammingAPIJar = "teavm-metaprogramming-api-0.6.1.jar";
|
||||
public static final String teavmMetaprogrammingAPIMaven = "org/teavm/teavm-metaprogramming-api/0.6.1/teavm-metaprogramming-api-0.6.1.jar";
|
||||
public static File teavmMetaprogrammingAPI = null;
|
||||
|
||||
public static final String teavmMetaprogrammingImplJar = "teavm-metaprogramming-impl-0.6.1.jar";
|
||||
public static final String teavmMetaprogrammingImplMaven = "org/teavm/teavm-metaprogramming-impl/0.6.1/teavm-metaprogramming-impl-0.6.1.jar";
|
||||
public static File teavmMetaprogrammingImpl = null;
|
||||
|
||||
public static final String teavmJodaTimeJar = "joda-time-2.7.jar";
|
||||
public static final String teavmJodaTimeMaven = "joda-time/joda-time/2.7/joda-time-2.7.jar";
|
||||
public static File teavmJodaTime = null;
|
||||
|
||||
public static final String teavmJZLIBJar = "jzlib-1.1.3.jar";
|
||||
public static final String teavmJZLIBMaven = "com/jcraft/jzlib/1.1.3/jzlib-1.1.3.jar";
|
||||
public static File teavmJZLIB = null;
|
||||
|
||||
public static File teavmBridge = null;
|
||||
|
||||
public static class MissingJARsException extends RuntimeException {
|
||||
|
||||
public final List<String> jars;
|
||||
|
||||
public MissingJARsException(String msg, List<String> jars) {
|
||||
super(msg);
|
||||
this.jars = jars;
|
||||
}
|
||||
|
||||
public MissingJARsException(List<String> jars) {
|
||||
this("The following JAR files were not found: " + String.join(", ", jars), jars);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void downloadFromMaven(String url, File outputDir) throws MissingJARsException {
|
||||
teavmCore = teavmPlatform = teavmClasslib = teavmInterop = teavmJSO =
|
||||
teavmJSOApis = teavmJSOImpl = teavmMetaprogrammingAPI = teavmMetaprogrammingImpl =
|
||||
teavmJodaTime = teavmJZLIB = teavmTooling = teavmCli = null;
|
||||
|
||||
if(url.lastIndexOf('/') != url.length() - 1) {
|
||||
url += "/";
|
||||
}
|
||||
|
||||
String urlConc = url + teavmCoreMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmCoreJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmCore = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmCliMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmCliJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmCli = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmToolingMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmToolingJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmTooling = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmPlatformMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmPlatformJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmPlatform = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmClasslibMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmClasslibJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmClasslib = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmInteropMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmInteropJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmInterop = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmJSOMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmJSOJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmJSO = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmJSOApisMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmJSOApisJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmJSOApis = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmJSOImplMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmJSOImplJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmJSOImpl = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmMetaprogrammingAPIMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmMetaprogrammingAPIJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmMetaprogrammingAPI = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmMetaprogrammingImplMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmMetaprogrammingImplJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmMetaprogrammingImpl = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmJodaTimeMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmJodaTimeJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmJodaTime = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmJZLIBMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmJZLIBJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmJZLIB = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void loadFromDirectory(File directory) throws MissingJARsException {
|
||||
teavmCore = teavmPlatform = teavmClasslib = teavmInterop = teavmJSO =
|
||||
teavmJSOApis = teavmJSOImpl = teavmMetaprogrammingAPI = teavmMetaprogrammingImpl =
|
||||
teavmJodaTime = teavmJZLIB = teavmTooling = teavmCli = null;
|
||||
discoverJars(directory);
|
||||
List<String> missingJars = new ArrayList();
|
||||
if(teavmCore == null) {
|
||||
missingJars.add(teavmCoreJar);
|
||||
}
|
||||
if(teavmCli == null) {
|
||||
missingJars.add(teavmCliJar);
|
||||
}
|
||||
if(teavmTooling == null) {
|
||||
missingJars.add(teavmToolingJar);
|
||||
}
|
||||
if(teavmPlatform == null) {
|
||||
missingJars.add(teavmPlatformJar);
|
||||
}
|
||||
if(teavmClasslib == null) {
|
||||
missingJars.add(teavmClasslibJar);
|
||||
}
|
||||
if(teavmInterop == null) {
|
||||
missingJars.add(teavmInteropJar);
|
||||
}
|
||||
if(teavmJSO == null) {
|
||||
missingJars.add(teavmJSOJar);
|
||||
}
|
||||
if(teavmJSOApis == null) {
|
||||
missingJars.add(teavmJSOApisJar);
|
||||
}
|
||||
if(teavmJSOImpl == null) {
|
||||
missingJars.add(teavmJSOImplJar);
|
||||
}
|
||||
if(teavmMetaprogrammingAPI == null) {
|
||||
missingJars.add(teavmMetaprogrammingAPIJar);
|
||||
}
|
||||
if(teavmMetaprogrammingImpl == null) {
|
||||
missingJars.add(teavmMetaprogrammingImplJar);
|
||||
}
|
||||
if(teavmJodaTime == null) {
|
||||
missingJars.add(teavmJodaTimeJar);
|
||||
}
|
||||
if(teavmJZLIB == null) {
|
||||
missingJars.add(teavmJZLIBJar);
|
||||
}
|
||||
if(missingJars.size() > 0) {
|
||||
throw new MissingJARsException(missingJars);
|
||||
}
|
||||
}
|
||||
|
||||
private static void discoverJars(File dir) {
|
||||
File[] files = dir.listFiles();
|
||||
for(int i = 0; i < files.length; ++i) {
|
||||
File f = files[i];
|
||||
if(f.isDirectory()) {
|
||||
discoverJars(f);
|
||||
}else {
|
||||
String n = f.getName();
|
||||
switch(n) {
|
||||
case teavmCoreJar:
|
||||
teavmCore = f;
|
||||
break;
|
||||
case teavmCliJar:
|
||||
teavmCli = f;
|
||||
break;
|
||||
case teavmToolingJar:
|
||||
teavmTooling = f;
|
||||
break;
|
||||
case teavmPlatformJar:
|
||||
teavmPlatform = f;
|
||||
break;
|
||||
case teavmClasslibJar:
|
||||
teavmClasslib = f;
|
||||
break;
|
||||
case teavmInteropJar:
|
||||
teavmInterop = f;
|
||||
break;
|
||||
case teavmJSOJar:
|
||||
teavmJSO = f;
|
||||
break;
|
||||
case teavmJSOApisJar:
|
||||
teavmJSOApis = f;
|
||||
break;
|
||||
case teavmJSOImplJar:
|
||||
teavmJSOImpl = f;
|
||||
break;
|
||||
case teavmMetaprogrammingAPIJar:
|
||||
teavmMetaprogrammingAPI = f;
|
||||
break;
|
||||
case teavmMetaprogrammingImplJar:
|
||||
teavmMetaprogrammingImpl = f;
|
||||
break;
|
||||
case teavmJodaTimeJar:
|
||||
teavmJodaTime = f;
|
||||
break;
|
||||
case teavmJZLIBJar:
|
||||
teavmJZLIB = f;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void copyURLToFileCheck404(String urlIn, File fileOut) throws IOException {
|
||||
System.out.println("downloading: " + urlIn);
|
||||
URL url;
|
||||
try {
|
||||
url = new URL(urlIn);
|
||||
}catch(MalformedURLException ex) {
|
||||
throw new IOException("Invalid URL: " + urlIn, ex);
|
||||
}
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setConnectTimeout(5000);
|
||||
connection.setReadTimeout(5000);
|
||||
int respCode = connection.getResponseCode();
|
||||
if(respCode != 200) {
|
||||
connection.disconnect();
|
||||
throw new IOException("Recieved response code: " + respCode);
|
||||
}
|
||||
try (InputStream stream = connection.getInputStream()) {
|
||||
FileUtils.copyInputStreamToFile(stream, fileOut);
|
||||
}finally {
|
||||
connection.disconnect(); // is this required?
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean tryLoadTeaVMBridge() {
|
||||
String override = System.getProperty("eaglercraft.TeaVMBridge");
|
||||
File teavmBridgeCheck;
|
||||
if(override != null) {
|
||||
teavmBridgeCheck = new File(override);
|
||||
}else {
|
||||
try {
|
||||
teavmBridgeCheck = new File(new File(URLDecoder.decode(
|
||||
TeaVMBinaries.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath(),
|
||||
"UTF-8")).getParent(), "TeaVMBridge.jar");
|
||||
} catch (URISyntaxException | UnsupportedEncodingException e) {
|
||||
System.err.println("Failed to locate TeaVMBridge.jar relative to BuildTools jar!");
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(teavmBridgeCheck.exists()) {
|
||||
teavmBridge = teavmBridgeCheck;
|
||||
return true;
|
||||
}else {
|
||||
System.err.println("File does not exist: " + teavmBridgeCheck.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static File[] getTeaVMCompilerClasspath() {
|
||||
return new File[] { teavmCore, teavmCli, teavmTooling, teavmInterop, teavmMetaprogrammingAPI, teavmBridge };
|
||||
}
|
||||
|
||||
public static String[] getTeaVMRuntimeClasspath() {
|
||||
return new String[] {
|
||||
teavmJodaTime.getAbsolutePath(), teavmJZLIB.getAbsolutePath(), teavmClasslib.getAbsolutePath(),
|
||||
teavmInterop.getAbsolutePath(), teavmJSO.getAbsolutePath(), teavmJSOApis.getAbsolutePath(),
|
||||
teavmJSOImpl.getAbsolutePath(), teavmMetaprogrammingAPI.getAbsolutePath(),
|
||||
teavmMetaprogrammingImpl.getAbsolutePath(), teavmPlatform.getAbsolutePath()
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,612 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.gui.headless;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildTools;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.LicensePrompt;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.gui.EPKCompiler;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.gui.JavaC;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.gui.MakeOfflineDownload;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.gui.TeaVMBinaries;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.gui.CompileLatestClientGUI.CompileFailureException;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.gui.TeaVMBinaries.MissingJARsException;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.DecompileMinecraft;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.FFMPEG;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.InitMCP;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.teavm.TeaVMBridge;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.teavm.TeaVMBridge.TeaVMClassLoadException;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.teavm.TeaVMBridge.TeaVMRuntimeException;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.util.FileReaderUTF;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.util.FileWriterUTF;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class CompileLatestClientHeadless {
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Launching client compiler...");
|
||||
System.out.println("Copyright (c) 2022 lax1dude");
|
||||
System.out.println();
|
||||
|
||||
boolean yes = false;
|
||||
String configPath = null;
|
||||
|
||||
if(args.length == 1) {
|
||||
configPath = args[0];
|
||||
}else if(args.length == 2 && (yes = args[0].equalsIgnoreCase("-y"))) {
|
||||
configPath = args[1];
|
||||
}else {
|
||||
System.err.println("Usage: java -jar BuildTools.jar [-y] <config file>");
|
||||
System.err.println();
|
||||
System.exit(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println("Loading config file: " + configPath);
|
||||
System.out.println();
|
||||
|
||||
File configFile = new File(configPath);
|
||||
String configSrc;
|
||||
try {
|
||||
configSrc = FileUtils.readFileToString(configFile, StandardCharsets.UTF_8);
|
||||
}catch(FileNotFoundException ex) {
|
||||
ex.printStackTrace();
|
||||
System.err.println();
|
||||
System.err.println("ERROR: File '" + configFile.getAbsolutePath() + "' does not exist!");
|
||||
System.err.println();
|
||||
System.exit(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
JSONObject configJSON;
|
||||
try {
|
||||
configJSON = new JSONObject(configSrc);
|
||||
}catch(JSONException ex) {
|
||||
System.err.println("ERROR: Could not parse '" + configFile.getName() + "' as JSON!");
|
||||
System.err.println();
|
||||
System.err.println(ex.toString());
|
||||
System.err.println();
|
||||
System.exit(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
File repositoryFolder;
|
||||
File modCoderPack;
|
||||
File minecraftJar;
|
||||
File assetsIndex;
|
||||
File outputDirectory;
|
||||
File temporaryDirectory;
|
||||
String ffmpeg = "ffmpeg";
|
||||
String mavenURL = null;
|
||||
File mavenLocal = null;
|
||||
File productionIndex = null;
|
||||
File productionFavicon = null;
|
||||
List<String> addScripts = null;
|
||||
List<String> removeScripts = null;
|
||||
List<String> injectInOfflineScripts = null;
|
||||
boolean generateOffline;
|
||||
File offlineTemplate = null;
|
||||
boolean keepTemporaryFiles;
|
||||
boolean writeSourceMap = false;
|
||||
boolean minifying = true;
|
||||
try {
|
||||
repositoryFolder = new File(configJSON.optString("repositoryFolder", "."));
|
||||
modCoderPack = new File(configJSON.getString("modCoderPack"));
|
||||
minecraftJar = new File(configJSON.getString("minecraftJar"));
|
||||
assetsIndex = new File(configJSON.getString("assetsIndex"));
|
||||
outputDirectory = new File(configJSON.getString("outputDirectory"));
|
||||
String tmpDir = configJSON.optString("temporaryDirectory");
|
||||
temporaryDirectory = tmpDir == null ? new File(outputDirectory, "build") : new File(tmpDir);
|
||||
ffmpeg = configJSON.optString("ffmpeg", ffmpeg);
|
||||
if(ffmpeg.length() == 0) {
|
||||
ffmpeg = "ffmpeg";
|
||||
}
|
||||
String prodIndex = configJSON.optString("productionIndex");
|
||||
if(prodIndex != null) {
|
||||
productionIndex = new File(prodIndex);
|
||||
String prodFavicon = configJSON.optString("productionFavicon");
|
||||
if(prodFavicon != null) {
|
||||
productionFavicon = new File(prodFavicon);
|
||||
}
|
||||
JSONArray scripts = configJSON.optJSONArray("addScripts");
|
||||
if(scripts != null) {
|
||||
int l = scripts.length();
|
||||
if(l > 0) {
|
||||
addScripts = new ArrayList(l);
|
||||
for(int i = 0; i < l; ++i) {
|
||||
addScripts.add(scripts.getString(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
scripts = configJSON.optJSONArray("removeScripts");
|
||||
if(scripts != null) {
|
||||
int l = scripts.length();
|
||||
if(l > 0) {
|
||||
removeScripts = new ArrayList(l);
|
||||
for(int i = 0; i < l; ++i) {
|
||||
removeScripts.add(scripts.getString(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
scripts = configJSON.optJSONArray("injectInOffline");
|
||||
if(scripts != null) {
|
||||
int l = scripts.length();
|
||||
if(l > 0) {
|
||||
injectInOfflineScripts = new ArrayList(l);
|
||||
for(int i = 0; i < l; ++i) {
|
||||
injectInOfflineScripts.add(scripts.getString(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mavenURL = configJSON.optString("mavenURL");
|
||||
mavenLocal = new File(configJSON.getString("mavenLocal"));
|
||||
generateOffline = configJSON.optBoolean("generateOfflineDownload", false);
|
||||
if(generateOffline) {
|
||||
offlineTemplate = new File(configJSON.getString("offlineDownloadTemplate"));
|
||||
}
|
||||
keepTemporaryFiles = configJSON.optBoolean("keepTemporaryFiles", false);
|
||||
writeSourceMap = configJSON.optBoolean("writeSourceMap", false);
|
||||
minifying = configJSON.optBoolean("minifying", true);
|
||||
}catch(JSONException ex) {
|
||||
System.err.println("CONFIG ERROR: " + ex.toString());
|
||||
System.err.println();
|
||||
System.exit(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println("Loaded config successfully:");
|
||||
System.out.println();
|
||||
System.out.println(" - Repository Folder: " + repositoryFolder.getAbsolutePath().replace('\\', '/'));
|
||||
System.out.println(" - Mod Coder Pack: " + modCoderPack.getAbsolutePath().replace('\\', '/'));
|
||||
System.out.println(" - Minecraft 1.8.8: " + minecraftJar.getAbsolutePath().replace('\\', '/'));
|
||||
System.out.println(" - Assets Index 1.8: " + assetsIndex.getAbsolutePath().replace('\\', '/'));
|
||||
System.out.println(" - Temporary Directory: " + temporaryDirectory.getAbsolutePath().replace('\\', '/'));
|
||||
System.out.println(" - Output Directory: " + outputDirectory.getAbsolutePath().replace('\\', '/'));
|
||||
System.out.println(" - FFmpeg Executable: " + ffmpeg.replace('\\', '/'));
|
||||
System.out.println(" - Maven Repo URL: " + mavenURL);
|
||||
System.out.println(" - Maven Local Dir: " + mavenLocal.getAbsolutePath().replace('\\', '/'));
|
||||
System.out.println(" - Production Index: " + (productionIndex == null ? "null" : productionIndex.getAbsolutePath().replace('\\', '/')));
|
||||
System.out.println(" - Production Favicon: " + (productionFavicon == null ? "null" : productionFavicon.getAbsolutePath().replace('\\', '/')));
|
||||
System.out.println(" - Generate Offline: " + generateOffline);
|
||||
System.out.println(" - Offline Template: " + (offlineTemplate == null ? "null" : offlineTemplate.getAbsolutePath().replace('\\', '/')));
|
||||
System.out.println(" - Inject in Offline: " + (injectInOfflineScripts == null ? "[ ]" : "[ " + String.join(", ", injectInOfflineScripts).replace('\\', '/') + " ]"));
|
||||
System.out.println(" - Minifying: " + minifying);
|
||||
System.out.println(" - Write Source Map: " + writeSourceMap);
|
||||
System.out.println(" - Keep Temp Files: " + keepTemporaryFiles);
|
||||
System.out.println(" - Add Scripts: " + (addScripts == null ? "[ ]" : "[ " + String.join(", ", addScripts).replace('\\', '/') + " ]"));
|
||||
System.out.println(" - Remove Scripts: " + (removeScripts == null ? "[ ]" : "[ " + String.join(", ", removeScripts).replace('\\', '/') + " ]"));
|
||||
System.out.println();
|
||||
|
||||
if(!yes) {
|
||||
System.out.println();
|
||||
LicensePrompt.display();
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
EaglerBuildTools.repositoryRoot = repositoryFolder;
|
||||
|
||||
try {
|
||||
if(!outputDirectory.isDirectory() && !outputDirectory.mkdirs()) {
|
||||
throw new CompileFailureException("Could not create output directory!");
|
||||
}
|
||||
|
||||
File[] existingOutput = outputDirectory.listFiles();
|
||||
if(existingOutput.length > 0) {
|
||||
|
||||
if(!yes) {
|
||||
System.out.print("Output directory has existing files, would you like to delete them? [y/n] ");
|
||||
String str = (new BufferedReader(new InputStreamReader(System.in))).readLine();
|
||||
System.out.println();
|
||||
if(!str.equalsIgnoreCase("y") && !str.equalsIgnoreCase("yes")) {
|
||||
System.out.println("Build cancelled.");
|
||||
System.out.println();
|
||||
System.exit(-1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Deleting existing files from the output directory...");
|
||||
|
||||
try {
|
||||
for(int i = 0; i < existingOutput.length; ++i) {
|
||||
File f = existingOutput[i];
|
||||
if(f.isDirectory()) {
|
||||
FileUtils.deleteDirectory(f);
|
||||
}else {
|
||||
if(!f.delete()) {
|
||||
throw new IOException("Could not delete: " + f.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}catch(IOException t) {
|
||||
throw new CompileFailureException("Could not delete old output directory: " + t.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
File mcpDataTMP = new File(temporaryDirectory, "ModCoderPack");
|
||||
File minecraftSrcTmp = new File(temporaryDirectory, "MinecraftSrc");
|
||||
|
||||
if(ffmpeg.length() == 0) {
|
||||
FFMPEG.foundFFMPEG = "ffmpeg";
|
||||
}else {
|
||||
FFMPEG.foundFFMPEG = ffmpeg;
|
||||
}
|
||||
|
||||
if(!mcpDataTMP.isDirectory() && !mcpDataTMP.mkdirs()) {
|
||||
throw new CompileFailureException("Error: failed to create \"" + mcpDataTMP.getAbsolutePath() + "\"!");
|
||||
}
|
||||
|
||||
if(!InitMCP.initTask(modCoderPack, mcpDataTMP)) {
|
||||
throw new CompileFailureException("Error: could not initialize MCP from \"" + modCoderPack.getAbsolutePath() + "\"!");
|
||||
}
|
||||
|
||||
if(!minecraftSrcTmp.isDirectory() && !minecraftSrcTmp.mkdirs()) {
|
||||
throw new CompileFailureException("Error: failed to create \"" + minecraftSrcTmp.getAbsolutePath() + "\"!");
|
||||
}
|
||||
|
||||
if(!DecompileMinecraft.decompileMinecraft(mcpDataTMP, minecraftJar, minecraftSrcTmp, assetsIndex, false)) {
|
||||
throw new CompileFailureException("Error: could not decompile and patch 1.8.8.jar from \"" + minecraftJar.getAbsolutePath() + "\"!");
|
||||
}
|
||||
|
||||
try {
|
||||
FileUtils.copyFile(new File(repositoryFolder, "patches/minecraft/output_license.txt"), new File(temporaryDirectory, "MinecraftSrc/LICENSE"));
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Error: failed to write LICENSE in temporary directory!");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
if(mavenURL == null) {
|
||||
System.out.println("TeaVM JARs will be loaded from: " + mavenLocal.getAbsolutePath());
|
||||
System.out.println();
|
||||
try {
|
||||
TeaVMBinaries.loadFromDirectory(mavenLocal);
|
||||
}catch(MissingJARsException ex) {
|
||||
throw new CompileFailureException(ex.getMessage());
|
||||
}
|
||||
}else {
|
||||
System.out.println("TeaVM JARs will be downloaded from repository: " + mavenURL);
|
||||
System.out.println();
|
||||
try {
|
||||
TeaVMBinaries.downloadFromMaven(mavenURL, mavenLocal);
|
||||
}catch(MissingJARsException ex) {
|
||||
throw new CompileFailureException(ex.getMessage());
|
||||
}
|
||||
System.out.println();
|
||||
System.out.println("Notice: make sure to delete \"" + mavenLocal.getAbsolutePath() + "\" when the compiler is finished, it will not be deleted automatically");
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
int compileResultCode;
|
||||
File compiledResultClasses = new File(temporaryDirectory, "classes");
|
||||
|
||||
try {
|
||||
try {
|
||||
compileResultCode = JavaC.runJavaC(new File(minecraftSrcTmp, "minecraft_src_javadoc.jar"),
|
||||
compiledResultClasses, temporaryDirectory, TeaVMBinaries.getTeaVMRuntimeClasspath(),
|
||||
new File(repositoryFolder, "sources/main/java"), new File(repositoryFolder, "sources/teavm/java"));
|
||||
}catch(IOException ex) {
|
||||
throw new CompileFailureException("failed to run javac compiler! " + ex.toString(), ex);
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
if(compileResultCode == 0) {
|
||||
System.out.println("Java compiler completed successfully");
|
||||
}else {
|
||||
throw new CompileFailureException("failed to run javac compiler! exit code " + compileResultCode + ", check log");
|
||||
}
|
||||
}finally {
|
||||
File extractedSrcTmp = new File(temporaryDirectory, "MinecraftSrc/src_javadoc_tmp");
|
||||
if(extractedSrcTmp.exists()) {
|
||||
System.out.println();
|
||||
System.out.println("Deleting temporary directory: " + extractedSrcTmp.getAbsolutePath());
|
||||
try {
|
||||
FileUtils.deleteDirectory(extractedSrcTmp);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Failed to delete temporary directory!");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Preparing arguments for TeaVM...");
|
||||
|
||||
if(!TeaVMBinaries.tryLoadTeaVMBridge()) {
|
||||
System.err.println("Failed to locate TeaVMBridge.jar, you can specify it's path manually by adding the JVM argument \"-Deaglercraft.TeaVMBridge=<path>\"");
|
||||
throw new CompileFailureException("Failed to locate TeaVMBridge.jar!");
|
||||
}
|
||||
|
||||
Map<String, Object> teavmArgs = new HashMap();
|
||||
|
||||
List<String> teavmClassPath = new ArrayList();
|
||||
teavmClassPath.add(compiledResultClasses.getAbsolutePath());
|
||||
teavmClassPath.addAll(Arrays.asList(TeaVMBinaries.getTeaVMRuntimeClasspath()));
|
||||
teavmArgs.put("classPathEntries", teavmClassPath);
|
||||
|
||||
teavmArgs.put("entryPointName", "main");
|
||||
teavmArgs.put("mainClass", "net.lax1dude.eaglercraft.v1_8.internal.teavm.MainClass");
|
||||
teavmArgs.put("minifying", minifying);
|
||||
teavmArgs.put("optimizationLevel", "ADVANCED");
|
||||
teavmArgs.put("targetDirectory", outputDirectory.getAbsolutePath());
|
||||
teavmArgs.put("generateSourceMaps", writeSourceMap);
|
||||
teavmArgs.put("targetFileName", "classes.js");
|
||||
|
||||
System.out.println();
|
||||
|
||||
boolean teavmStatus;
|
||||
try {
|
||||
teavmStatus = TeaVMBridge.compileTeaVM(teavmArgs);
|
||||
}catch(TeaVMClassLoadException ex) {
|
||||
throw new CompileFailureException("Failed to link TeaVM jar files! Did you select the wrong jar?", ex);
|
||||
}catch(TeaVMRuntimeException ex) {
|
||||
throw new CompileFailureException("Failed to run TeaVM! Check log", ex);
|
||||
}
|
||||
|
||||
if(!teavmStatus) {
|
||||
System.out.println("TeaVM reported problems, check the log");
|
||||
System.out.println();
|
||||
System.exit(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
File epkCompiler = new File(repositoryFolder, "sources/setup/workspace_template/desktopRuntime/CompileEPK.jar");
|
||||
|
||||
if(!epkCompiler.exists()) {
|
||||
throw new CompileFailureException("EPKCompiler JAR file is missing: " + epkCompiler.getAbsolutePath());
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Writing index.html...");
|
||||
System.out.println();
|
||||
|
||||
String faviconExt = null;
|
||||
if(productionFavicon != null) {
|
||||
faviconExt = productionFavicon.getName();
|
||||
int i = faviconExt.lastIndexOf('.');
|
||||
if(i != -1) {
|
||||
faviconExt = faviconExt.substring(i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
try(BufferedReader indexReader = new BufferedReader(new FileReaderUTF(productionIndex));
|
||||
PrintWriter indexWriter = new PrintWriter(new FileWriterUTF(new File(outputDirectory, "index.html")))) {
|
||||
String line;
|
||||
while((line = indexReader.readLine()) != null) {
|
||||
String trim = line.trim();
|
||||
if(trim.startsWith("<link")) {
|
||||
if(trim.contains("rel=\"shortcut icon\"")) {
|
||||
if(faviconExt != null) {
|
||||
String contentType = "image/png";
|
||||
switch(faviconExt) {
|
||||
case "png":
|
||||
break;
|
||||
case "jpg":
|
||||
case "jpeg":
|
||||
contentType = "image/jpeg";
|
||||
break;
|
||||
case "ico":
|
||||
contentType = "image/x-icon";
|
||||
break;
|
||||
case "gif":
|
||||
contentType = "image/gif";
|
||||
break;
|
||||
case "bmp":
|
||||
contentType = "image/bmp";
|
||||
break;
|
||||
case "webp":
|
||||
contentType = "image/webp";
|
||||
break;
|
||||
default:
|
||||
System.err.println();
|
||||
System.err.println("WARNING: favicon extension '" + faviconExt + "' is unknown, defaulting to image/png MIME type");
|
||||
System.err.println();
|
||||
break;
|
||||
}
|
||||
indexWriter.println(line.replace("favicon.png", "favicon." + faviconExt).replace("image/png", contentType));
|
||||
System.out.println("Setting favicon <link> href to \"favicon." + faviconExt + "\", MIME type \"" + contentType + "\" in index.html");
|
||||
}else {
|
||||
System.out.println("Removed favicon <link> from index.html, no favicon configured");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(trim.startsWith("<meta")) {
|
||||
if(trim.contains("property=\"og:image\"")) {
|
||||
if(faviconExt != null) {
|
||||
indexWriter.println(line.replace("favicon.png", "favicon." + faviconExt));
|
||||
System.out.println("Setting og:image <link> href to \"favicon." + faviconExt + "\"");
|
||||
}else {
|
||||
System.out.println("Removed og:image <meta> tag in index.html, no favicon configured");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(trim.startsWith("<script")) {
|
||||
int idx = line.indexOf("src=\"");
|
||||
int idx2 = line.indexOf('"', idx + 5);
|
||||
String srcSubStr = line.substring(idx + 5, idx2);
|
||||
if(addScripts != null && srcSubStr.equals("classes.js")) {
|
||||
for(int i = 0, l = addScripts.size(); i < l; ++i) {
|
||||
String addSrc = addScripts.get(i);
|
||||
indexWriter.println(line.replace("classes.js", addSrc));
|
||||
System.out.println("Added <script> tag with src \"" + addSrc + "\" to index.html");
|
||||
}
|
||||
}
|
||||
if(removeScripts != null && removeScripts.contains(srcSubStr)) {
|
||||
System.out.println("Removed <script> tag with src \"" + srcSubStr + "\" from index.html");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
indexWriter.println(line);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
if(productionFavicon != null) {
|
||||
FileUtils.copyFile(productionFavicon, new File(outputDirectory, "favicon." + faviconExt));
|
||||
}
|
||||
|
||||
FileUtils.copyFile(new File(repositoryFolder, "sources/setup/workspace_template/javascript/fix-webm-duration.js"), new File(outputDirectory, "fix-webm-duration.js"));
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Running EPKCompiler on assets...");
|
||||
|
||||
EPKCompiler.compilerMain(epkCompiler, new String[] {
|
||||
((new File(minecraftSrcTmp, "minecraft_res_patch.jar")).getAbsolutePath() + System.getProperty("path.separator") +
|
||||
(new File(repositoryFolder, "sources/resources")).getAbsolutePath()), (new File(outputDirectory, "assets.epk")).getAbsolutePath() });
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Running EPKCompiler on languages.zip...");
|
||||
|
||||
EPKCompiler.compilerMain(epkCompiler, new String[] {
|
||||
(new File(minecraftSrcTmp, "minecraft_languages.zip")).getAbsolutePath(),
|
||||
(new File(temporaryDirectory, "languages.epk")).getAbsolutePath() });
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Creating languages directory...");
|
||||
File langDirectory = new File(outputDirectory, "lang");
|
||||
|
||||
byte[] copyBuffer = new byte[16384];
|
||||
int i;
|
||||
try(ZipInputStream zis = new ZipInputStream(new FileInputStream(new File(minecraftSrcTmp, "minecraft_languages.zip")))) {
|
||||
ZipEntry etr;
|
||||
while((etr = zis.getNextEntry()) != null) {
|
||||
if(!etr.isDirectory()) {
|
||||
File phile = new File(langDirectory, etr.getName());
|
||||
File parent = phile.getParentFile();
|
||||
if(!parent.exists() && !parent.mkdirs()) {
|
||||
throw new IOException("Could not create directory: " + parent.getAbsolutePath());
|
||||
}
|
||||
try(FileOutputStream os = new FileOutputStream(phile)) {
|
||||
while((i = zis.read(copyBuffer)) != -1) {
|
||||
os.write(copyBuffer, 0, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
if(generateOffline) {
|
||||
System.out.println("Running offline download generator...");
|
||||
System.out.println();
|
||||
File offlineTemplateArg = offlineTemplate;
|
||||
if(injectInOfflineScripts != null) {
|
||||
offlineTemplateArg = new File(temporaryDirectory, "offline_download_template.txt");
|
||||
try(BufferedReader indexReader = new BufferedReader(new FileReaderUTF(offlineTemplate));
|
||||
PrintWriter indexWriter = new PrintWriter(new FileWriterUTF(offlineTemplateArg))) {
|
||||
String line;
|
||||
while((line = indexReader.readLine()) != null) {
|
||||
if(line.contains("${classes_js}")) {
|
||||
for(int j = 0, l = injectInOfflineScripts.size(); j < l; ++j) {
|
||||
File injectFile = new File(injectInOfflineScripts.get(j));
|
||||
String injectName = injectFile.getAbsolutePath();
|
||||
String injectNameName = injectFile.getName();
|
||||
System.out.println("Adding file to offline download template: " + injectName);
|
||||
indexWriter.println("// %%%%%%%%% " + injectNameName + " %%%%%%%%%");
|
||||
indexWriter.println();
|
||||
try(BufferedReader insertReader = new BufferedReader(new FileReaderUTF(injectFile))) {
|
||||
String line2;
|
||||
while((line2 = insertReader.readLine()) != null) {
|
||||
indexWriter.println(line2);
|
||||
}
|
||||
}
|
||||
indexWriter.println();
|
||||
char[] percents = new char[20 + injectNameName.length()];
|
||||
for(int k = 0; k < percents.length; ++k) {
|
||||
percents[k] = '%';
|
||||
}
|
||||
indexWriter.print("// ");
|
||||
indexWriter.println(percents);
|
||||
indexWriter.println();
|
||||
indexWriter.println();
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
indexWriter.println(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
File offlineDownloadGenerator = new File(repositoryFolder, "sources/setup/workspace_template/desktopRuntime/MakeOfflineDownload.jar");
|
||||
MakeOfflineDownload.compilerMain(offlineDownloadGenerator, new String[] {
|
||||
offlineTemplateArg.getAbsolutePath(),
|
||||
(new File(outputDirectory, "classes.js")).getAbsolutePath() + System.getProperty("path.separator")
|
||||
+ (new File(outputDirectory, "fix-webm-duration.js")).getAbsolutePath(),
|
||||
(new File(outputDirectory, "assets.epk")).getAbsolutePath(),
|
||||
(new File(outputDirectory, "EaglercraftX_1.8_Offline_en_US.html")).getAbsolutePath(),
|
||||
(new File(outputDirectory, "EaglercraftX_1.8_Offline_International.html")).getAbsolutePath(),
|
||||
(new File(temporaryDirectory, "languages.epk")).getAbsolutePath()
|
||||
});
|
||||
}
|
||||
|
||||
System.out.println("Releasing external ClassLoader(s)...");
|
||||
System.out.println();
|
||||
|
||||
TeaVMBridge.free();
|
||||
EPKCompiler.free();
|
||||
|
||||
if(generateOffline) {
|
||||
MakeOfflineDownload.free();
|
||||
}
|
||||
|
||||
if(!keepTemporaryFiles) {
|
||||
System.out.println("Cleaning up temporary files...");
|
||||
try {
|
||||
FileUtils.deleteDirectory(temporaryDirectory);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Failed to delete temporary directory: " + temporaryDirectory.getAbsolutePath());
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Client build successful! Check the output directory for your files");
|
||||
|
||||
}catch(CompileFailureException ex) {
|
||||
System.out.println();
|
||||
System.err.println("COMPILATION FAILED: " + ex.getMessage());
|
||||
System.out.println();
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.diff;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import com.github.difflib.patch.Patch;
|
||||
import com.github.difflib.patch.PatchFailedException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class ApplyPatchesToZip {
|
||||
|
||||
public static final int patchContextLength = 3;
|
||||
|
||||
public static void applyPatches(File zipIn, File unpatchedZipIn, File patchesIn, File zipOut, boolean compress, boolean useECR) throws Throwable {
|
||||
if(!patchesIn.isDirectory()) {
|
||||
FileUtils.copyFile(zipIn, zipOut);
|
||||
return;
|
||||
}
|
||||
Map<String,byte[]> jarEntriesUnpatched;
|
||||
if(unpatchedZipIn != null) {
|
||||
System.out.println("Loading files from '" + unpatchedZipIn.getName() + "'...");
|
||||
try(FileInputStream is = new FileInputStream(unpatchedZipIn)) {
|
||||
jarEntriesUnpatched = JARMemoryCache.loadJAR(is);
|
||||
}
|
||||
}else {
|
||||
jarEntriesUnpatched = new WeakHashMap();
|
||||
}
|
||||
Map<String,byte[]> jarEntriesPatched;
|
||||
if(zipIn != null) {
|
||||
System.out.println("Loading files from '" + zipIn.getName() + "'...");
|
||||
try(FileInputStream is = new FileInputStream(zipIn)) {
|
||||
jarEntriesPatched = JARMemoryCache.loadJAR(is);
|
||||
}
|
||||
}else {
|
||||
jarEntriesPatched = new WeakHashMap();
|
||||
}
|
||||
System.out.println("Patching files in '" + zipIn.getName() + "'...");
|
||||
final Map<String,byte[]> jarEntries = new HashMap();
|
||||
jarEntries.putAll(jarEntriesUnpatched);
|
||||
jarEntries.putAll(jarEntriesPatched);
|
||||
DiffSet diffs = new DiffSet();
|
||||
int totalLoad = diffs.loadFolder(patchesIn, useECR, useECR ? new DiffSet.SourceProvider() {
|
||||
@Override
|
||||
public List<String> getSource(String filename) throws IOException {
|
||||
byte[] etr = jarEntries.get(filename);
|
||||
if(etr == null) {
|
||||
throw new FileNotFoundException("Could not find source for: " + filename);
|
||||
}
|
||||
return Lines.linesList(new String(etr, StandardCharsets.UTF_8));
|
||||
}
|
||||
} : null);
|
||||
System.out.println(" loaded " + totalLoad + " patch files from the repo");
|
||||
System.out.println(" patching files...");
|
||||
System.out.print(" ");
|
||||
|
||||
int cnt = 0;
|
||||
int crtCnt = 0;
|
||||
int delCnt = 0;
|
||||
int repCnt = 0;
|
||||
int pthCnt = 0;
|
||||
try(ZipOutputStream jarOut = new ZipOutputStream(new FileOutputStream(zipOut))) {
|
||||
jarOut.setLevel(compress ? 5 : 0);
|
||||
jarOut.putNextEntry(new ZipEntry("META-INF/MANIFEST.MF"));
|
||||
jarOut.write("Manifest-Version: 1.0\nCreated-By: Eaglercraft BuildTools\n".getBytes(StandardCharsets.UTF_8));
|
||||
String nm;
|
||||
for(Entry<String,byte[]> et : jarEntries.entrySet()) {
|
||||
nm = et.getKey();
|
||||
if(!nm.startsWith("META-INF")) {
|
||||
Object op = diffs.diffs.get(nm);
|
||||
if(op != null) {
|
||||
if(op instanceof DiffSet.DeleteFunction) {
|
||||
++delCnt;
|
||||
continue;
|
||||
}else if(op instanceof DiffSet.ReplaceFunction) {
|
||||
jarOut.putNextEntry(new ZipEntry(nm));
|
||||
IOUtils.write(((DiffSet.ReplaceFunction)op).file, jarOut);
|
||||
++repCnt;
|
||||
}else if(op instanceof Patch<?>) {
|
||||
jarOut.putNextEntry(new ZipEntry(nm));
|
||||
List<String> lines = Lines.linesList(new String(et.getValue(), "UTF-8"));
|
||||
try {
|
||||
lines = ((Patch<String>)op).applyTo(lines);
|
||||
}catch(PatchFailedException ptch) {
|
||||
throw new IOException("Could not patch file \"" + nm + "\"!", ptch);
|
||||
}
|
||||
IOUtils.writeLines(lines, null, jarOut, "UTF-8");
|
||||
++pthCnt;
|
||||
}else {
|
||||
// ?
|
||||
}
|
||||
++cnt;
|
||||
if(cnt % 75 == 74) {
|
||||
System.out.print(".");
|
||||
}
|
||||
}else {
|
||||
if(jarEntriesPatched.containsKey(nm)) {
|
||||
jarOut.putNextEntry(new ZipEntry(nm));
|
||||
IOUtils.write(et.getValue(), jarOut);
|
||||
++cnt;
|
||||
if(cnt % 75 == 74) {
|
||||
System.out.print(".");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for(Entry<String,byte[]> etr : diffs.recreate.entrySet()) {
|
||||
jarOut.putNextEntry(new ZipEntry(etr.getKey()));
|
||||
IOUtils.write(etr.getValue(), jarOut);
|
||||
++crtCnt;
|
||||
++cnt;
|
||||
if(cnt % 75 == 74) {
|
||||
System.out.print(".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Patched " + pthCnt + " files");
|
||||
System.out.println("Restored " + crtCnt + " files");
|
||||
System.out.println("Replaced " + repCnt + " files");
|
||||
System.out.println("Deleted " + delCnt + " files");
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.diff;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import com.github.difflib.UnifiedDiffUtils;
|
||||
import com.github.difflib.patch.Patch;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class DiffSet {
|
||||
|
||||
public static class DeleteFunction {
|
||||
private DeleteFunction() {
|
||||
}
|
||||
}
|
||||
|
||||
public static class ReplaceFunction {
|
||||
public final byte[] file;
|
||||
private ReplaceFunction(byte[] file) {
|
||||
this.file = file;
|
||||
}
|
||||
}
|
||||
|
||||
public static final DeleteFunction deleteFunction = new DeleteFunction();
|
||||
|
||||
public final Map<String,Object> diffs;
|
||||
public final Map<String,byte[]> recreate;
|
||||
|
||||
public DiffSet() {
|
||||
diffs = new HashMap();
|
||||
recreate = new HashMap();
|
||||
}
|
||||
|
||||
private static final Pattern editPattern = Pattern.compile(".*\\.edit(\\.[^\\.\\/\\\\]+)?$");
|
||||
private static final Pattern replacePattern = Pattern.compile(".*\\.replace(\\.[^\\.\\/\\\\]+)?$");
|
||||
private static final Pattern deletePattern = Pattern.compile(".*\\.delete(\\.[^\\.\\/\\\\]+)?$");
|
||||
private static final Pattern recreatePattern = Pattern.compile(".*\\.recreate(\\.[^\\.\\/\\\\]+)?$");
|
||||
|
||||
public int loadFolder(File pathIn, boolean useECR, SourceProvider ecrContextProvider) throws IOException {
|
||||
String baseAbsolutePath = pathIn.getAbsolutePath();
|
||||
int total = 0;
|
||||
|
||||
File del = new File(pathIn, "delete.txt");
|
||||
if(del.isFile()) {
|
||||
Collection<String> cl = FileUtils.readLines(del, "UTF-8");
|
||||
for(String s : cl) {
|
||||
s = s.trim();
|
||||
s = s.replace('\\', '/');
|
||||
if(!s.startsWith("#")) {
|
||||
if(s.startsWith("/")) {
|
||||
s = s.substring(1);
|
||||
}
|
||||
diffs.put(s, deleteFunction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Collection<File> fl = FileUtils.listFiles(pathIn, null, true);
|
||||
Iterator<File> fi = fl.iterator();
|
||||
while(fi.hasNext()) {
|
||||
File f = fi.next();
|
||||
String fName = f.getAbsolutePath().replace(baseAbsolutePath, "").replace('\\', '/');
|
||||
if(fName.startsWith("/")) {
|
||||
fName = fName.substring(1);
|
||||
}
|
||||
if(editPattern.matcher(fName).matches()) {
|
||||
try {
|
||||
String nm = removeExt(fName, "edit");
|
||||
Patch<String> pth;
|
||||
if(useECR) {
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8))) {
|
||||
pth = EaglerContextRedacted.readContextRestricted(ecrContextProvider.getSource(nm), reader);
|
||||
}
|
||||
}else {
|
||||
List<String> phile = FileUtils.readLines(f, "UTF-8");
|
||||
pth = UnifiedDiffUtils.parseUnifiedDiff(phile);
|
||||
}
|
||||
if(pth == null) {
|
||||
throw new IOException("Invalid DIFF file!");
|
||||
}
|
||||
diffs.put(nm, pth);
|
||||
++total;
|
||||
}catch(Throwable ex) {
|
||||
System.err.println("ERROR: could not read '" + fName + "'!");
|
||||
}
|
||||
}else if(replacePattern.matcher(fName).matches()) {
|
||||
try {
|
||||
diffs.put(removeExt(fName, "replace"), new ReplaceFunction(FileUtils.readFileToByteArray(f)));
|
||||
++total;
|
||||
}catch(Throwable ex) {
|
||||
System.err.println("ERROR: could not read '" + fName + "'!");
|
||||
}
|
||||
}else if(deletePattern.matcher(fName).matches()) {
|
||||
diffs.put(removeExt(fName, "delete"), deleteFunction);
|
||||
++total;
|
||||
}else if(recreatePattern.matcher(fName).matches()) {
|
||||
try {
|
||||
String str = removeExt(fName, "recreate");
|
||||
recreate.put(str, FileUtils.readFileToByteArray(f));
|
||||
diffs.remove(str);
|
||||
++total;
|
||||
}catch(Throwable ex) {
|
||||
System.err.println("ERROR: could not read '" + fName + "'!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
private static String removeExt(String fn, String ext) {
|
||||
int end = fn.lastIndexOf("." + ext);
|
||||
if(end != -1) {
|
||||
return fn.substring(0, end) + fn.substring(end + ext.length() + 1, fn.length());
|
||||
}else {
|
||||
return fn;
|
||||
}
|
||||
}
|
||||
|
||||
public static interface SourceProvider {
|
||||
List<String> getSource(String filename) throws IOException;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,256 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.diff;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import com.github.difflib.patch.AbstractDelta;
|
||||
import com.github.difflib.patch.ChangeDelta;
|
||||
import com.github.difflib.patch.Chunk;
|
||||
import com.github.difflib.patch.DeleteDelta;
|
||||
import com.github.difflib.patch.DeltaType;
|
||||
import com.github.difflib.patch.InsertDelta;
|
||||
import com.github.difflib.patch.Patch;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class EaglerContextRedacted {
|
||||
|
||||
public static void writeContextRedacted(Patch<String> patch, PrintWriter output) {
|
||||
Date theDate = new Date();
|
||||
|
||||
output.println();
|
||||
output.println("# Eagler Context Redacted Diff");
|
||||
output.println("# Copyright (c) " + (new SimpleDateFormat("yyyy")).format(theDate) + " lax1dude. All rights reserved.");
|
||||
output.println();
|
||||
output.println("# Version: 1.0");
|
||||
output.println("# Author: lax1dude");
|
||||
output.println();
|
||||
|
||||
List<AbstractDelta<String>> deltas = patch.getDeltas();
|
||||
delta_itr: for(int i = 0, l = deltas.size(); i < l; ++i) {
|
||||
AbstractDelta<String> delta = deltas.get(i);
|
||||
|
||||
DeltaType type = delta.getType();
|
||||
String blockType;
|
||||
String blockPrefix;
|
||||
switch(type) {
|
||||
case CHANGE:
|
||||
blockType = "> CHANGE";
|
||||
blockPrefix = "~ ";
|
||||
break;
|
||||
case DELETE:
|
||||
blockType = "> DELETE";
|
||||
blockPrefix = "- ";
|
||||
break;
|
||||
case EQUAL:
|
||||
continue delta_itr;
|
||||
case INSERT:
|
||||
blockType = "> INSERT";
|
||||
blockPrefix = "+ ";
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid type " + type + " for delta " + i);
|
||||
}
|
||||
|
||||
Chunk<String> source = delta.getSource();
|
||||
int sourcePos = source.getPosition();
|
||||
int sourceLen = source.getLines().size();
|
||||
|
||||
Chunk<String> target = delta.getTarget();
|
||||
int targetPos = target.getPosition();
|
||||
List<String> linesToWrite = target.getLines();
|
||||
int targetLen = linesToWrite.size();
|
||||
|
||||
output.println(blockType + " " + targetPos + (targetLen > 0 ? " : " + (targetPos + targetLen) : "") + " @ "
|
||||
+ sourcePos + (sourceLen > 0 ? " : " + (sourcePos + sourceLen) : ""));
|
||||
|
||||
output.println();
|
||||
|
||||
if(targetLen > 0) {
|
||||
for(int j = 0, ll = linesToWrite.size(); j < ll; ++j) {
|
||||
output.println(blockPrefix + linesToWrite.get(j));
|
||||
}
|
||||
|
||||
output.println();
|
||||
}
|
||||
}
|
||||
|
||||
output.println("> EOF");
|
||||
}
|
||||
|
||||
public static Patch<String> readContextRestricted(List<String> context, BufferedReader reader) throws IOException {
|
||||
Patch<String> newPatch = new Patch();
|
||||
|
||||
DeltaType currentDeltaType = null;
|
||||
int sourceStart = 0;
|
||||
int sourceLen = 0;
|
||||
int targetStart = 0;
|
||||
int targetLen = 0;
|
||||
List<String> targetLines = null;
|
||||
|
||||
String line;
|
||||
readLinesLoop: while((line = reader.readLine()) != null) {
|
||||
if(line.length() < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(line.charAt(1) != ' ') {
|
||||
throw new IOException("Unknown line type: " + line.substring(0, 2));
|
||||
}
|
||||
|
||||
char lineType = line.charAt(0);
|
||||
String value = line.substring(2);
|
||||
|
||||
switch(lineType) {
|
||||
case '#':
|
||||
int idx = value.indexOf(':');
|
||||
if(idx > 0) {
|
||||
String k = value.substring(0, idx).trim().toLowerCase();
|
||||
if(k.equals("version")) {
|
||||
String v = value.substring(idx + 1).trim();
|
||||
if(!v.equals("1.0")) {
|
||||
throw new IOException("Unsupported format version: " + v);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '>':
|
||||
|
||||
String[] split = value.trim().split("[\\s]+");
|
||||
|
||||
if(split.length == 1 && split[0].equals("EOF")) {
|
||||
break readLinesLoop;
|
||||
}
|
||||
|
||||
if(split.length < 4 ||
|
||||
!((split[2].equals("@") && (split.length == 4 || (split.length == 6 && split[4].equals(":")))) ||
|
||||
(split[2].equals(":") && ((split.length == 6 && split[4].equals("@")) || (split.length == 8 && split[4].equals("@") && split[6].equals(":")))))) {
|
||||
throw new IOException("Invalid block: [ " + String.join(" ", split) + " ]");
|
||||
}
|
||||
|
||||
if(currentDeltaType != null) {
|
||||
newPatch.addDelta(makeDelta(currentDeltaType, sourceStart, sourceLen, targetStart, targetLen, context, targetLines));
|
||||
}
|
||||
|
||||
switch(split[0]) {
|
||||
case "CHANGE":
|
||||
currentDeltaType = DeltaType.CHANGE;
|
||||
break;
|
||||
case "DELETE":
|
||||
currentDeltaType = DeltaType.DELETE;
|
||||
break;
|
||||
case "INSERT":
|
||||
currentDeltaType = DeltaType.INSERT;
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Unknown line block: " + split[0]);
|
||||
}
|
||||
|
||||
targetLines = null;
|
||||
|
||||
targetStart = parseInt(split[1]);
|
||||
|
||||
if(split[2].equals(":")) {
|
||||
targetLen = parseInt(split[3]) - targetStart;
|
||||
sourceStart = parseInt(split[5]);
|
||||
if(split.length == 8) {
|
||||
sourceLen = parseInt(split[7]) - sourceStart;
|
||||
}else {
|
||||
sourceLen = 0;
|
||||
}
|
||||
}else {
|
||||
targetLen = 0;
|
||||
sourceStart = parseInt(split[3]);
|
||||
if(split.length == 6) {
|
||||
sourceLen = parseInt(split[5]) - sourceStart;
|
||||
}else {
|
||||
sourceLen = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '~':
|
||||
if(currentDeltaType != DeltaType.CHANGE) {
|
||||
throw new IOException("Read an unexpected CHANGE line in a " + currentDeltaType + " block: " + line);
|
||||
}else {
|
||||
if(targetLines == null) targetLines = new ArrayList();
|
||||
targetLines.add(value);
|
||||
}
|
||||
break;
|
||||
case '-':
|
||||
if(currentDeltaType != DeltaType.DELETE) {
|
||||
throw new IOException("Read an unexpected DELETE line in a " + currentDeltaType + " block: " + line);
|
||||
}else {
|
||||
if(targetLines == null) targetLines = new ArrayList();
|
||||
targetLines.add(value);
|
||||
}
|
||||
break;
|
||||
case '+':
|
||||
if(currentDeltaType != DeltaType.INSERT) {
|
||||
throw new IOException("Read an unexpected INSERT line in a " + currentDeltaType + " block: " + line);
|
||||
}else {
|
||||
if(targetLines == null) targetLines = new ArrayList();
|
||||
targetLines.add(value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Unknown line type: " + lineType);
|
||||
}
|
||||
}
|
||||
|
||||
if(currentDeltaType != null) {
|
||||
newPatch.addDelta(makeDelta(currentDeltaType, sourceStart, sourceLen, targetStart, targetLen, context, targetLines));
|
||||
}
|
||||
|
||||
return newPatch;
|
||||
}
|
||||
|
||||
private static int parseInt(String str) throws IOException {
|
||||
try {
|
||||
return Integer.parseInt(str);
|
||||
}catch(NumberFormatException ex) {
|
||||
throw new IOException("Value is not a valid integer: \"" + str + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
private static AbstractDelta<String> makeDelta(DeltaType deltaType, int sourceStart, int sourceLen,
|
||||
int targetStart, int targetLen, List<String> context, List<String> targetLines) throws IOException {
|
||||
List<String> sourceLines = new ArrayList(sourceLen);
|
||||
for(int i = 0; i < sourceLen; ++i) {
|
||||
sourceLines.add(context.get(sourceStart + i));
|
||||
}
|
||||
if(targetLines == null) {
|
||||
targetLines = new ArrayList(0);
|
||||
}
|
||||
if(targetLen != targetLines.size()) {
|
||||
throw new IOException("" + deltaType + " block at sourceStart " + sourceStart + " is " + targetLen
|
||||
+ " lines long but only " + targetLines.size() + " lines were read!");
|
||||
}
|
||||
switch(deltaType) {
|
||||
case CHANGE:
|
||||
return new ChangeDelta(new Chunk(sourceStart, sourceLines), new Chunk(targetStart, targetLines));
|
||||
case DELETE:
|
||||
return new DeleteDelta(new Chunk(sourceStart, sourceLines), new Chunk(targetStart, targetLines));
|
||||
case INSERT:
|
||||
return new InsertDelta(new Chunk(sourceStart, sourceLines), new Chunk(targetStart, targetLines));
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid delta type: " + deltaType);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.diff;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class JARMemoryCache {
|
||||
|
||||
public static Map<String,byte[]> loadJAR(InputStream is) throws IOException {
|
||||
Map<String,byte[]> ret = new HashMap();
|
||||
ZipInputStream isz = new ZipInputStream(is);
|
||||
ZipEntry et;
|
||||
while((et = isz.getNextEntry()) != null) {
|
||||
if(!et.isDirectory()) {
|
||||
String n = et.getName();
|
||||
if(n.startsWith("/")) {
|
||||
n = n.substring(1);
|
||||
}
|
||||
if(!n.startsWith("META-INF")) {
|
||||
byte[] data = IOUtils.toByteArray(isz);
|
||||
ret.put(n, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.diff;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class Lines {
|
||||
|
||||
public static final Pattern splitPattern = Pattern.compile("(\\r\\n|\\n|\\r)");
|
||||
|
||||
public static String[] linesArray(String input) {
|
||||
return splitPattern.split(input);
|
||||
}
|
||||
|
||||
public static List<String> linesList(String input) {
|
||||
return Arrays.asList(splitPattern.split(input));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,529 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.diff;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import com.github.difflib.DiffUtils;
|
||||
import com.github.difflib.UnifiedDiffUtils;
|
||||
import com.github.difflib.patch.Patch;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildToolsConfig;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.CSVMappings;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.InsertJavaDoc;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.SetupWorkspace;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class MergePullRequest {
|
||||
|
||||
public static boolean mergeTask() {
|
||||
try {
|
||||
return mergeTask0();
|
||||
}catch(Throwable t) {
|
||||
System.err.println();
|
||||
System.err.println("Exception encountered while running task 'merge'!");
|
||||
t.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean mergeTask0() throws Throwable {
|
||||
File pullRequestDir = new File("pullrequest");
|
||||
|
||||
if(!pullRequestDir.isDirectory() || FileUtils.isEmptyDirectory(pullRequestDir)) {
|
||||
System.err.println("ERROR: the 'pullrequest' directory does not exist or is empty, aborting merge because there's nothing to merge");
|
||||
return false;
|
||||
}
|
||||
|
||||
if((new File(pullRequestDir, "merged.txt")).exists()) {
|
||||
System.err.println("ERROR: the 'pullrequest' directory has already been merged, aborting merge because there's nothing to merge");
|
||||
System.err.println("To override, delete 'merged.txt' from the folder.");
|
||||
return false;
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Warning: running 'merge' is a command only intended to be used");
|
||||
System.out.println("by the repository's owner, it will perminantly incorporate all");
|
||||
System.out.println("changes in the 'pullrequest' directory into this repository's");
|
||||
System.out.println("patch file directory!");
|
||||
System.out.println();
|
||||
System.out.println("Doing so will make it impossible to reliably create any future");
|
||||
System.out.println("pull requests back to this project's main repository, unless the");
|
||||
System.out.println("main repository has merged the same pull request into it's patch");
|
||||
System.out.println("file directory too.");
|
||||
System.out.println();
|
||||
System.out.println("Back up the current state of the patch file directory in a local");
|
||||
System.out.println("commit or branch to allow you to undo any unintentional changes");
|
||||
System.out.println("made to the directory as a result of running this command.");
|
||||
System.out.println();
|
||||
System.out.print("Do you really want to do this? [Y/n]: ");
|
||||
|
||||
String ret = "n";
|
||||
try {
|
||||
ret = (new BufferedReader(new InputStreamReader(System.in))).readLine();
|
||||
}catch(IOException ex) {
|
||||
// ?
|
||||
}
|
||||
ret = ret.toLowerCase();
|
||||
if(!ret.startsWith("y")) {
|
||||
System.out.println();
|
||||
System.out.println("OKAY THANK GOD, crisis averted!");
|
||||
System.out.println();
|
||||
System.out.println("Thank the author of this tool kindly for providing this check.");
|
||||
return true;
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Warning: close all programs that may have files or folders open");
|
||||
System.out.println("in the repository or the merge could fail catastrophically");
|
||||
System.out.println();
|
||||
System.out.println("This folder: " + (new File(".")).getAbsolutePath());
|
||||
System.out.println();
|
||||
System.out.println("Check for any file explorer windows displaying the contents of a");
|
||||
System.out.println("file or folder in this directory.");
|
||||
System.out.println();
|
||||
System.out.println("Close any programs with files open someplace in this folder.");
|
||||
System.out.println();
|
||||
System.out.println("If merging fails, revert all changes in this directory with git");
|
||||
System.out.println("or a backup, re-run 'init', then run 'pullrequest' and 'merge'");
|
||||
System.out.println();
|
||||
System.out.print("Did you close everything? [Y/n]: ");
|
||||
|
||||
ret = "n";
|
||||
try {
|
||||
ret = (new BufferedReader(new InputStreamReader(System.in))).readLine();
|
||||
}catch(IOException ex) {
|
||||
// ?
|
||||
}
|
||||
ret = ret.toLowerCase();
|
||||
if(!ret.startsWith("y")) {
|
||||
System.out.println();
|
||||
System.out.println("OKAY THANK GOD, crisis averted!");
|
||||
System.out.println();
|
||||
System.out.println("Thank the author of this tool kindly for providing this check.");
|
||||
return true;
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
File temporaryDirectory = EaglerBuildToolsConfig.getTemporaryDirectory();
|
||||
System.out.println();
|
||||
|
||||
File pullRequestToSrc = new File(pullRequestDir, "source");
|
||||
File pullRequestToRes = new File(pullRequestDir, "resources");
|
||||
|
||||
boolean prSrcExist = pullRequestToSrc.isDirectory() && !FileUtils.isEmptyDirectory(pullRequestToSrc);
|
||||
boolean prResExist = pullRequestToRes.isDirectory() && !FileUtils.isEmptyDirectory(pullRequestToRes);
|
||||
|
||||
if(!prSrcExist && !prResExist) {
|
||||
System.err.println("ERROR: the 'pullrequest' directory does not exist or is empty, aborting merge because there's nothing to merge");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(prSrcExist) {
|
||||
File tmpOriginalUnpatched = new File(temporaryDirectory, "MinecraftSrc/minecraft_src.jar");
|
||||
if(!tmpOriginalUnpatched.isFile()) {
|
||||
System.err.println("ERROR: file '" + tmpOriginalUnpatched.getName() + "' was not found!");
|
||||
System.err.println("Run the 'init' task again to re-generate it");
|
||||
return false;
|
||||
}
|
||||
|
||||
File tmpOriginal = new File(temporaryDirectory, "MinecraftSrc/minecraft_src_patch.jar");
|
||||
if(!tmpOriginal.isFile()) {
|
||||
System.err.println("ERROR: file '" + tmpOriginal.getName() + "' was not found!");
|
||||
System.err.println("Run the 'init' task again to re-generate it");
|
||||
return false;
|
||||
}
|
||||
|
||||
File tmpMerged = new File(temporaryDirectory, "MinecraftSrc/minecraft_src_merge.jar");
|
||||
File tmpMergedDiffs = new File(temporaryDirectory, "MinecraftSrc/minecraft_src_merge_diffs.zip");
|
||||
|
||||
System.out.println("Applying pull request to '" + tmpOriginal.getName() + "'...");
|
||||
System.out.println();
|
||||
ApplyPatchesToZip.applyPatches(tmpOriginal, tmpOriginalUnpatched, pullRequestToSrc, tmpMerged, true, false);
|
||||
|
||||
try {
|
||||
createMergeDiffs(tmpMerged, tmpOriginalUnpatched, tmpMergedDiffs);
|
||||
}catch(Throwable t) {
|
||||
tmpMerged.delete();
|
||||
throw t;
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
File patchOut = new File("./patches/minecraft");
|
||||
File patchTmpOut = new File("./patches.bak/minecraft");
|
||||
if(patchOut.exists()) {
|
||||
System.out.println("Backing up '" + patchOut.getAbsolutePath() + "'...");
|
||||
try {
|
||||
FileUtils.deleteDirectory(patchTmpOut);
|
||||
FileUtils.moveDirectory(patchOut, patchTmpOut);
|
||||
}catch(Throwable t) {
|
||||
tmpMerged.delete();
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
|
||||
FileUtils.copyFile(new File(patchTmpOut, "output_license.txt"), new File(patchOut, "output_license.txt"));
|
||||
|
||||
System.out.println("Extracting '" + tmpMergedDiffs + "' to 'patches/minecraft'...");
|
||||
int cnt = SetupWorkspace.extractJarTo(tmpMergedDiffs, patchOut);
|
||||
|
||||
if(!tmpMergedDiffs.delete()) {
|
||||
System.err.println("ERROR: could not delete '" + tmpMergedDiffs.getName() + "'!");
|
||||
}
|
||||
|
||||
System.out.println("Wrote " + cnt + " files.");
|
||||
|
||||
System.out.println("Copying '" + tmpMerged.getName() + "' to '" + tmpOriginal.getName() + "'...");
|
||||
|
||||
if((tmpOriginal.exists() && !tmpOriginal.delete()) || !tmpMerged.renameTo(tmpOriginal)) {
|
||||
System.err.println("ERROR: could not copy '" + tmpMerged.getName() + "' to '" + tmpOriginal.getName() + "'!");
|
||||
System.err.println("Run the 'init' task again before proceeding");
|
||||
tmpOriginal.delete();
|
||||
}else {
|
||||
File javadocOut = new File(temporaryDirectory, "MinecraftSrc/minecraft_src_javadoc.jar");
|
||||
CSVMappings comments = new CSVMappings();
|
||||
if(!InsertJavaDoc.processSource(tmpOriginal, javadocOut, new File(temporaryDirectory, "ModCoderPack"), comments)) {
|
||||
System.err.println();
|
||||
System.err.println("ERROR: Could not create javadoc!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(tmpMerged.exists()) {
|
||||
tmpMerged.delete();
|
||||
}
|
||||
|
||||
System.out.println("Deleting backup folder...");
|
||||
|
||||
try {
|
||||
FileUtils.deleteDirectory(patchTmpOut);
|
||||
}catch(Throwable t) {
|
||||
System.err.println("ERROR: could not delete 'patches.bak/minecraft'!");
|
||||
System.err.println(t.toString());
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
}
|
||||
|
||||
if(prResExist) {
|
||||
File tmpOriginalUnpatched = new File(temporaryDirectory, "MinecraftSrc/minecraft_res.jar");
|
||||
if(!tmpOriginalUnpatched.isFile()) {
|
||||
System.err.println("ERROR: file '" + tmpOriginalUnpatched.getName() + "' was not found!");
|
||||
System.err.println("Run the 'init' task again to re-generate it");
|
||||
return false;
|
||||
}
|
||||
|
||||
File tmpOriginal = new File(temporaryDirectory, "MinecraftSrc/minecraft_res_patch.jar");
|
||||
if(!tmpOriginal.isFile()) {
|
||||
System.err.println("ERROR: file '" + tmpOriginal.getName() + "' was not found!");
|
||||
System.err.println("Run the 'init' task again to re-generate it");
|
||||
return false;
|
||||
}
|
||||
|
||||
File tmpMerged = new File(temporaryDirectory, "MinecraftSrc/minecraft_res_merge.jar");
|
||||
File tmpMergedDiffs = new File(temporaryDirectory, "MinecraftSrc/minecraft_res_merge_diffs.zip");
|
||||
|
||||
System.out.println("Applying pull request to '" + tmpOriginal.getName() + "'...");
|
||||
System.out.println();
|
||||
ApplyPatchesToZip.applyPatches(tmpOriginal, tmpOriginalUnpatched, pullRequestToRes, tmpMerged, true, false);
|
||||
|
||||
try {
|
||||
createMergeDiffs(tmpMerged, tmpOriginalUnpatched, tmpMergedDiffs);
|
||||
}catch(Throwable t) {
|
||||
tmpMerged.delete();
|
||||
throw t;
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
File patchOut = new File("./patches/resources");
|
||||
File patchTmpOut = new File("./patches.bak/resources");
|
||||
if(patchOut.exists()) {
|
||||
System.out.println("Backing up '" + patchOut.getAbsolutePath() + "'...");
|
||||
try {
|
||||
FileUtils.deleteDirectory(patchTmpOut);
|
||||
FileUtils.moveDirectory(patchOut, patchTmpOut);
|
||||
}catch(Throwable t) {
|
||||
tmpMerged.delete();
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Extracting '" + tmpMergedDiffs + "' to 'patches/resources'...");
|
||||
int cnt = SetupWorkspace.extractJarTo(tmpMergedDiffs, patchOut);
|
||||
|
||||
if(!tmpMergedDiffs.delete()) {
|
||||
System.err.println("ERROR: could not delete '" + tmpMergedDiffs.getName() + "'!");
|
||||
}
|
||||
|
||||
System.out.println("Wrote " + cnt + " files.");
|
||||
|
||||
System.out.println("Copying '" + tmpMerged.getName() + "' to '" + tmpOriginal.getName() + "'...");
|
||||
|
||||
if((tmpOriginal.exists() && !tmpOriginal.delete()) || !tmpMerged.renameTo(tmpOriginal)) {
|
||||
System.err.println("ERROR: could not copy '" + tmpMerged.getName() + "' to '" + tmpOriginal.getName() + "'!");
|
||||
System.err.println("Run the 'init' task again before proceeding");
|
||||
tmpOriginal.delete();
|
||||
}
|
||||
|
||||
if(tmpMerged.exists()) {
|
||||
tmpMerged.delete();
|
||||
}
|
||||
|
||||
System.out.println("Deleting backup folder...");
|
||||
try {
|
||||
FileUtils.deleteDirectory(patchTmpOut);
|
||||
}catch(Throwable t) {
|
||||
System.err.println("ERROR: could not delete 'patches.bak/resources'!");
|
||||
System.err.println(t.getMessage());
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
}
|
||||
|
||||
(new File("./patches.bak")).delete();
|
||||
|
||||
System.out.println("Successfully merged pullrequest directory!");
|
||||
|
||||
try {
|
||||
SimpleDateFormat fmt1 = new SimpleDateFormat("MM-dd-yy");
|
||||
SimpleDateFormat fmt2 = new SimpleDateFormat("kk:mm:ss");
|
||||
Date dt = new Date();
|
||||
FileUtils.writeStringToFile(new File(pullRequestDir, "merged.txt"), "This pullrequest was merged on " +
|
||||
fmt1.format(new Date()) + " at " + fmt2.format(dt) + ".", "UTF-8");
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: could not write 'merged.txt' in pullrequest directory!");
|
||||
System.err.println("Creating a file called 'merged.txt' is important to tell buildtools that the");
|
||||
System.err.println("existing pullrequest has already been merged! Do not try to merge it again!");
|
||||
}
|
||||
|
||||
System.out.println("Backing up to 'pullrequest_merged_backup'...");
|
||||
|
||||
String pth = pullRequestDir.getAbsolutePath();
|
||||
if(pth.endsWith("/") || pth.endsWith("\\")) {
|
||||
pth = pth.substring(0, pth.length() - 1);
|
||||
}
|
||||
|
||||
File m0 = new File(pth + "_merged_backup");
|
||||
|
||||
if(m0.exists() && !FileUtils.deleteQuietly(m0)) {
|
||||
System.err.println("Could not delete old backup!");
|
||||
m0 = new File(pth + "_merged_backup1");
|
||||
if(m0.exists() && !FileUtils.deleteQuietly(m0)) {
|
||||
System.err.println("Could not delete 2nd old backup!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
FileUtils.moveDirectory(pullRequestDir, m0);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not create backup!");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void createMergeDiffs(File tmpMerged, File tmpOriginalUnpatched, File tmpMergedDiffs) throws Throwable {
|
||||
System.out.println("Creating patches from '" + tmpMerged.getName() + "'...");
|
||||
|
||||
System.out.println("Loading files from '" + tmpOriginalUnpatched.getName() + "'...");
|
||||
Map<String, byte[]> memoryCacheUnpatched;
|
||||
try(InputStream is = new FileInputStream(tmpOriginalUnpatched)) {
|
||||
memoryCacheUnpatched = JARMemoryCache.loadJAR(is);
|
||||
}
|
||||
|
||||
if(memoryCacheUnpatched == null) {
|
||||
throw new IOException("Failed to load JAR into memory: '" + tmpOriginalUnpatched.getName());
|
||||
}
|
||||
|
||||
System.out.println("Loading files from '" + tmpMerged.getName() + "'...");
|
||||
Map<String, byte[]> memoryCacheMerged;
|
||||
try(InputStream is = new FileInputStream(tmpMerged)) {
|
||||
memoryCacheMerged = JARMemoryCache.loadJAR(is);
|
||||
}
|
||||
|
||||
if(memoryCacheMerged == null) {
|
||||
throw new IOException("Failed to load JAR into memory: '" + tmpMerged.getName());
|
||||
}
|
||||
|
||||
Set<String> deleteList = new HashSet();
|
||||
deleteList.addAll(memoryCacheUnpatched.keySet());
|
||||
|
||||
System.out.println("Generating patch files..");
|
||||
System.out.println("(Writing to: " + tmpMergedDiffs.getName() + ")");
|
||||
System.out.println("(this may take a while)");
|
||||
System.out.print(" ");
|
||||
int cnt = 0;
|
||||
try(ZipOutputStream mgd = new ZipOutputStream(new FileOutputStream(tmpMergedDiffs))) {
|
||||
mgd.setLevel(5);
|
||||
for(Entry<String,byte[]> met : memoryCacheMerged.entrySet()) {
|
||||
String n = met.getKey();
|
||||
byte[] orig = memoryCacheUnpatched.get(n);
|
||||
if(orig == null) {
|
||||
System.err.println("Error: tried to patch file '" + n + "' that doesn't exist in the minecraft source");
|
||||
continue;
|
||||
}
|
||||
deleteList.remove(n);
|
||||
if(writeDiff(orig, met.getValue(), n, mgd)) {
|
||||
++cnt;
|
||||
if(cnt % 75 == 74) {
|
||||
System.out.print(".");
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
System.out.println("Wrote " + cnt + " patch files.");
|
||||
|
||||
mgd.putNextEntry(new ZipEntry("delete.txt"));
|
||||
PrintWriter delWriter = new PrintWriter(mgd);
|
||||
delWriter.println("# " + deleteList.size() + " files to delete:");
|
||||
for(String s : deleteList) {
|
||||
delWriter.println(s);
|
||||
}
|
||||
delWriter.flush();
|
||||
|
||||
System.out.println("Wrote " + deleteList.size() + " deletes.");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static boolean writeDiff(byte[] old, byte[] _new, String outName, ZipOutputStream output) throws IOException {
|
||||
if(Arrays.equals(old, _new)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String oldStr = toStringIfValid(old);
|
||||
String newStr = oldStr == null ? null : toStringIfValid(_new);
|
||||
|
||||
if(oldStr == null || newStr == null) {
|
||||
output.putNextEntry(new ZipEntry(makeName(outName, "replace")));
|
||||
IOUtils.write(_new, output);
|
||||
return true;
|
||||
}else {
|
||||
List<String> oldLines = Lines.linesList(oldStr);
|
||||
List<String> newLines = Lines.linesList(newStr);
|
||||
Patch<String> deltas = DiffUtils.diff(oldLines, newLines);
|
||||
|
||||
// List<String> diffFile = UnifiedDiffUtils.generateUnifiedDiff(outName, outName, oldLines, deltas, ApplyPatchesToZip.patchContextLength);
|
||||
//
|
||||
// if(diffFile.size() == 0) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// output.putNextEntry(new ZipEntry(makeName(outName, "edit")));
|
||||
// PrintWriter foutStream = new PrintWriter(output);
|
||||
// for(int i = 0, l = diffFile.size(); i < l; ++i) {
|
||||
// foutStream.println(diffFile.get(i));
|
||||
// }
|
||||
// foutStream.flush();
|
||||
|
||||
output.putNextEntry(new ZipEntry(makeName(outName, "edit")));
|
||||
PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, "UTF-8"));
|
||||
EaglerContextRedacted.writeContextRedacted(deltas, writer);
|
||||
writer.flush();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static String makeName(String input, String type) {
|
||||
int lastSlash = input.lastIndexOf('/');
|
||||
int lastDot = input.lastIndexOf('.');
|
||||
if(lastDot > lastSlash + 1) {
|
||||
return input.substring(0, lastDot) + "." + type + input.substring(lastDot);
|
||||
}else {
|
||||
return input + "." + type;
|
||||
}
|
||||
}
|
||||
|
||||
private static final CharsetDecoder utf8Decoder = StandardCharsets.UTF_8.newDecoder();
|
||||
|
||||
private static String toStringIfValid(byte[] in) {
|
||||
ByteBuffer inn = ByteBuffer.wrap(in);
|
||||
CharBuffer cb;
|
||||
try {
|
||||
cb = utf8Decoder.decode(inn);
|
||||
}catch(Throwable t) {
|
||||
return null;
|
||||
}
|
||||
return cb.toString();
|
||||
}
|
||||
|
||||
public static boolean mergeDirect() {
|
||||
try {
|
||||
return mergeDirect0();
|
||||
}catch(Throwable t) {
|
||||
System.err.println();
|
||||
System.err.println("Exception encountered while running task 'merge_direct'!");
|
||||
t.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean mergeDirect0() throws Throwable {
|
||||
|
||||
if(!PullRequestTask.pullRequest()) {
|
||||
System.err.println();
|
||||
System.err.println("Error: could not create merge_direct pull request!");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
if(!mergeTask0()) {
|
||||
System.err.println();
|
||||
System.err.println("Exception encountered while running task 'merge_direct'!");
|
||||
return false;
|
||||
}
|
||||
}catch(Throwable t) {
|
||||
System.err.println();
|
||||
System.err.println("Exception encountered while running task 'merge_direct'!");
|
||||
t.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,426 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.diff;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import com.github.difflib.DiffUtils;
|
||||
import com.github.difflib.UnifiedDiffUtils;
|
||||
import com.github.difflib.patch.Patch;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildTools;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildToolsConfig;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.formatter.EclipseFormatter;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.InsertJavaDoc;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.util.FileWriterUTF;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class PullRequestTask {
|
||||
|
||||
public static boolean pullRequest() {
|
||||
try {
|
||||
return pullRequest0();
|
||||
}catch(Throwable t) {
|
||||
System.err.println();
|
||||
System.err.println("Exception encountered while running task 'pullrequest'!");
|
||||
t.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean pullRequest0() throws Throwable {
|
||||
File originalUnpatchedSourceMainJar = new File(EaglerBuildToolsConfig.getTemporaryDirectory(), "MinecraftSrc/minecraft_src.jar");
|
||||
File originalSourceMainJar = new File(EaglerBuildToolsConfig.getTemporaryDirectory(), "MinecraftSrc/minecraft_src_patch.jar");
|
||||
File minecraftJavadocTmp = new File(EaglerBuildToolsConfig.getTemporaryDirectory(), "MinecraftSrc/minecraft_src_javadoc.jar");
|
||||
File originalSourceMain = new File(EaglerBuildTools.repositoryRoot, "sources/main/java");
|
||||
File originalSourceTeaVM = new File(EaglerBuildTools.repositoryRoot, "sources/teavm/java");
|
||||
File originalSourceLWJGL = new File(EaglerBuildTools.repositoryRoot, "sources/lwjgl/java");
|
||||
File originalUnpatchedSourceResourcesJar = new File(EaglerBuildToolsConfig.getTemporaryDirectory(), "MinecraftSrc/minecraft_res.jar");
|
||||
File originalSourceResourcesJar = new File(EaglerBuildToolsConfig.getTemporaryDirectory(), "MinecraftSrc/minecraft_res_patch.jar");
|
||||
File originalSourceResources = new File(EaglerBuildTools.repositoryRoot, "sources/resources");
|
||||
File diffFromMain = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/main/java");
|
||||
File diffFromTeaVM = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/teavm/java");
|
||||
File diffFromLWJGL = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/lwjgl/java");
|
||||
File diffFromResources = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "desktopRuntime/resources");
|
||||
File pullRequestTo = new File(EaglerBuildTools.repositoryRoot, "pullrequest");
|
||||
|
||||
boolean prExist = pullRequestTo.exists();
|
||||
if(prExist && !(pullRequestTo.isDirectory() && pullRequestTo.list().length == 0)) {
|
||||
System.out.println();
|
||||
System.out.print("Warning: The 'pullrequest' folder already exists in your repository. Overwrite? [Y/n]: ");
|
||||
String ret = "n";
|
||||
try {
|
||||
ret = (new BufferedReader(new InputStreamReader(System.in))).readLine();
|
||||
}catch(IOException ex) {
|
||||
// ?
|
||||
}
|
||||
ret = ret.toLowerCase();
|
||||
if(!ret.startsWith("y")) {
|
||||
System.out.println();
|
||||
System.out.println("The pull request was cancelled.");
|
||||
return true;
|
||||
}else {
|
||||
try {
|
||||
FileUtils.deleteDirectory(pullRequestTo);
|
||||
prExist = false;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: Could not delete \"" + pullRequestTo.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!prExist && !pullRequestTo.mkdirs()) {
|
||||
System.err.println("ERROR: Could not create folder \"" + pullRequestTo.getAbsolutePath() + "\"!");
|
||||
}
|
||||
|
||||
File pullRequestToMain = new File(pullRequestTo, "source");
|
||||
File pullRequestToResources = new File(pullRequestTo, "resources");
|
||||
|
||||
boolean flag = false;
|
||||
int i = copyAllModified(diffFromTeaVM, originalSourceTeaVM);
|
||||
if(i > 0) {
|
||||
flag = true;
|
||||
}
|
||||
System.out.println("Found " + i + " changed files in /src/teavm/java/");
|
||||
|
||||
i = copyAllModified(diffFromLWJGL, originalSourceLWJGL);
|
||||
if(i > 0) {
|
||||
flag = true;
|
||||
}
|
||||
System.out.println("Found " + i + " changed files in /src/lwjgl/java/");
|
||||
|
||||
i = createDiffFiles(originalSourceMain, minecraftJavadocTmp, originalUnpatchedSourceMainJar,
|
||||
originalSourceMainJar, diffFromMain, pullRequestToMain, true);
|
||||
if(i > 0) {
|
||||
flag = true;
|
||||
}
|
||||
System.out.println("Found " + i + " changed files in /src/main/java/");
|
||||
|
||||
i = createDiffFiles(originalSourceResources, originalSourceResourcesJar, originalUnpatchedSourceResourcesJar,
|
||||
null, diffFromResources, pullRequestToResources, false);
|
||||
if(i > 0) {
|
||||
flag = true;
|
||||
}
|
||||
System.out.println("Found " + i + " changed files in /desktopRuntime/resources/");
|
||||
|
||||
if(!flag) {
|
||||
System.out.println("ERROR: No modified files were found!");
|
||||
if(pullRequestTo.exists()) {
|
||||
pullRequestTo.delete();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static int createDiffFiles(File folderOriginal, File jarOriginal, File jarOriginalUnpatched, File originalJarNoJavadoc,
|
||||
File folderEdited, File folderOut, boolean isJava) throws Throwable {
|
||||
if(!folderEdited.isDirectory()) {
|
||||
return 0;
|
||||
}
|
||||
boolean createdFolderOut = folderOut.isDirectory();
|
||||
int cnt = 0;
|
||||
Collection<File> workspaceFiles = FileUtils.listFiles(folderEdited, null, true);
|
||||
Map<String,byte[]> jarEntriesUnpatched;
|
||||
if(jarOriginalUnpatched != null) {
|
||||
System.out.println("Loading files from '" + jarOriginalUnpatched.getName() + "'...");
|
||||
try(FileInputStream is = new FileInputStream(jarOriginalUnpatched)) {
|
||||
jarEntriesUnpatched = JARMemoryCache.loadJAR(is);
|
||||
}
|
||||
}else {
|
||||
jarEntriesUnpatched = new WeakHashMap();
|
||||
}
|
||||
Map<String,byte[]> jarEntriesPatched;
|
||||
if(jarOriginal != null) {
|
||||
System.out.println("Loading files from '" + jarOriginal.getName() + "'...");
|
||||
try(FileInputStream is = new FileInputStream(jarOriginal)) {
|
||||
jarEntriesPatched = JARMemoryCache.loadJAR(is);
|
||||
}
|
||||
}else {
|
||||
jarEntriesPatched = new WeakHashMap();
|
||||
}
|
||||
Map<String,byte[]> jarEntries = new HashMap();
|
||||
jarEntries.putAll(jarEntriesUnpatched);
|
||||
jarEntries.putAll(jarEntriesPatched);
|
||||
Map<String,byte[]> jarEntriesNoJavadoc;
|
||||
if(originalJarNoJavadoc != null) {
|
||||
System.out.println("Loading files from '" + originalJarNoJavadoc.getName() + "'...");
|
||||
try(FileInputStream is = new FileInputStream(originalJarNoJavadoc)) {
|
||||
jarEntriesNoJavadoc = JARMemoryCache.loadJAR(is);
|
||||
}
|
||||
}else {
|
||||
jarEntriesNoJavadoc = new WeakHashMap();
|
||||
}
|
||||
System.out.println("Comparing...");
|
||||
System.out.println("(this may take a while)");
|
||||
String editedPrefix = folderEdited.getAbsolutePath();
|
||||
Set<String> filesReplaced = new HashSet();
|
||||
for(File wf : workspaceFiles) {
|
||||
String newPath = wf.getAbsolutePath().replace(editedPrefix, "");
|
||||
if(newPath.indexOf('\\') != -1) {
|
||||
newPath = newPath.replace('\\', '/');
|
||||
}
|
||||
if(newPath.startsWith("/")) {
|
||||
newPath = newPath.substring(1);
|
||||
}
|
||||
File orig = new File(folderOriginal, newPath);
|
||||
byte[] jarData = null;
|
||||
boolean replacedFileExists = orig.exists();
|
||||
if(replacedFileExists) {
|
||||
filesReplaced.add(newPath);
|
||||
if(copyFileIfChanged(wf, orig)) {
|
||||
++cnt;
|
||||
}
|
||||
}else if((jarData = jarEntries.get(newPath)) != null) {
|
||||
filesReplaced.add(newPath);
|
||||
byte [] o = jarData;
|
||||
byte [] n = FileUtils.readFileToByteArray(wf);
|
||||
boolean changed = false;
|
||||
if(o.length != n.length) {
|
||||
if(!createdFolderOut) {
|
||||
if(!folderOut.mkdirs()) {
|
||||
throw new IOException("Could not create folder: \"" + folderOut.getAbsolutePath() + "\"!");
|
||||
}
|
||||
createdFolderOut = true;
|
||||
}
|
||||
String noJavaDocString = null;
|
||||
byte[] noJavaDoc = jarEntriesNoJavadoc.get(newPath);
|
||||
if(noJavaDoc != null) {
|
||||
noJavaDocString = new String(noJavaDoc, StandardCharsets.UTF_8);
|
||||
}
|
||||
if(writeDiff(o, n, folderOut, newPath, isJava, noJavaDocString)) {
|
||||
changed = true;
|
||||
++cnt;
|
||||
}
|
||||
}else {
|
||||
for(int i = 0; i < o.length; ++i) {
|
||||
if(o[i] != n[i]) {
|
||||
if(!createdFolderOut) {
|
||||
if(!folderOut.mkdirs()) {
|
||||
throw new IOException("Could not create folder: \"" + folderOut.getAbsolutePath() + "\"!");
|
||||
}
|
||||
createdFolderOut = true;
|
||||
}
|
||||
String noJavaDocString = null;
|
||||
byte[] noJavaDoc = jarEntriesNoJavadoc.get(newPath);
|
||||
if(noJavaDoc != null) {
|
||||
noJavaDocString = new String(noJavaDoc, StandardCharsets.UTF_8);
|
||||
}
|
||||
if(writeDiff(o, n, folderOut, newPath, isJava, noJavaDocString)) {
|
||||
changed = true;
|
||||
++cnt;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!changed && !jarEntriesPatched.containsKey(newPath)) {
|
||||
FileUtils.writeByteArrayToFile(new File(folderOut, makeName(newPath, "recreate")), jarData);
|
||||
++cnt;
|
||||
}
|
||||
}else {
|
||||
filesReplaced.add(newPath);
|
||||
FileUtils.copyFile(wf, orig);
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
|
||||
if(jarEntriesPatched.size() > 0) {
|
||||
for(Entry<String,byte[]> etr : jarEntriesPatched.entrySet()) {
|
||||
if(filesReplaced.contains(etr.getKey())) {
|
||||
continue;
|
||||
}
|
||||
if(!(new File(folderEdited, etr.getKey())).exists()) {
|
||||
if(!createdFolderOut) {
|
||||
if(!folderOut.mkdirs()) {
|
||||
throw new IOException("Could not create folder: \"" + folderOut.getAbsolutePath() + "\"!");
|
||||
}
|
||||
createdFolderOut = true;
|
||||
}
|
||||
FileUtils.writeStringToFile(new File(folderOut, makeName(etr.getKey(), "delete")),
|
||||
"#hash: " + getCRC32(etr.getValue()), "UTF-8");
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
private static boolean writeDiff(byte[] old, byte[] _new, File outDir, String outName, boolean isJava, String javaNotJavadoc) throws IOException {
|
||||
String oldStr = toStringIfValid(old);
|
||||
String newStr = oldStr == null ? null : toStringIfValid(_new);
|
||||
if(oldStr == null || newStr == null) {
|
||||
FileUtils.writeByteArrayToFile(new File(outDir, makeName(outName, "replace")), _new);
|
||||
}else {
|
||||
if(javaNotJavadoc != null) {
|
||||
oldStr = javaNotJavadoc;
|
||||
}
|
||||
//oldStr = stripJavadocAndFormat(oldStr);
|
||||
newStr = stripJavadocAndFormat(newStr);
|
||||
List<String> oldLines = Lines.linesList(oldStr);
|
||||
List<String> newLines = Lines.linesList(newStr);
|
||||
Patch<String> deltas = DiffUtils.diff(oldLines, newLines);
|
||||
|
||||
List<String> diffFile = UnifiedDiffUtils.generateUnifiedDiff(outName, outName, oldLines, deltas, ApplyPatchesToZip.patchContextLength);
|
||||
|
||||
if(diffFile.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
File fout = new File(outDir, makeName(outName, "edit"));
|
||||
File p = fout.getParentFile();
|
||||
if(!p.isDirectory()) {
|
||||
if(!p.mkdirs()) {
|
||||
throw new IOException("Failed to create directory \"" + p.getAbsolutePath() + "\"!");
|
||||
}
|
||||
}
|
||||
try(PrintWriter foutStream = new PrintWriter(new FileWriterUTF(fout))) {
|
||||
for(int i = 0, l = diffFile.size(); i < l; ++i) {
|
||||
foutStream.println(diffFile.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static String stripJavadocAndFormat(String input) {
|
||||
input = InsertJavaDoc.stripDocForDiff(input);
|
||||
input = EclipseFormatter.processSource(input, System.lineSeparator());
|
||||
return input;
|
||||
}
|
||||
|
||||
private static int copyAllModified(File inDir, File outDir) throws IOException {
|
||||
if(!inDir.isDirectory()) {
|
||||
return 0;
|
||||
}
|
||||
int cnt = 0;
|
||||
Collection<File> workspaceFiles = FileUtils.listFiles(inDir, null, true);
|
||||
String editedPrefix = inDir.getAbsolutePath();
|
||||
for(File wf : workspaceFiles) {
|
||||
String newPath = wf.getAbsolutePath().replace(editedPrefix, "");
|
||||
if(newPath.indexOf('\\') != -1) {
|
||||
newPath = newPath.replace('\\', '/');
|
||||
}
|
||||
if(newPath.startsWith("/")) {
|
||||
newPath = newPath.substring(1);
|
||||
}
|
||||
File orig = new File(outDir, newPath);
|
||||
if(copyFileIfChanged(wf, orig)) {
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
private static String makeName(String input, String type) {
|
||||
int lastSlash = input.lastIndexOf('/');
|
||||
int lastDot = input.lastIndexOf('.');
|
||||
if(lastDot > lastSlash + 1) {
|
||||
return input.substring(0, lastDot) + "." + type + input.substring(lastDot);
|
||||
}else {
|
||||
return input + "." + type;
|
||||
}
|
||||
}
|
||||
|
||||
private static final CharsetDecoder utf8Decoder = StandardCharsets.UTF_8.newDecoder();
|
||||
|
||||
private static String toStringIfValid(byte[] in) {
|
||||
ByteBuffer inn = ByteBuffer.wrap(in);
|
||||
CharBuffer cb;
|
||||
try {
|
||||
cb = utf8Decoder.decode(inn);
|
||||
}catch(Throwable t) {
|
||||
return null;
|
||||
}
|
||||
return cb.toString();
|
||||
}
|
||||
|
||||
private static final String hex = "0123456789ABCDEF";
|
||||
|
||||
private static String hex32(long in) {
|
||||
char[] ret = new char[8];
|
||||
for(int i = 7; i >= 0; --i) {
|
||||
ret[i] = hex.charAt((int)((in >> (i << 2)) & 0xF));
|
||||
}
|
||||
return new String(ret);
|
||||
}
|
||||
|
||||
private static String getCRC32(File in) throws IOException {
|
||||
CRC32 crc = new CRC32();
|
||||
crc.update(FileUtils.readFileToByteArray(in));
|
||||
return hex32(crc.getValue());
|
||||
}
|
||||
|
||||
private static String getCRC32(byte[] in) {
|
||||
CRC32 crc = new CRC32();
|
||||
crc.update(in);
|
||||
return hex32(crc.getValue());
|
||||
}
|
||||
|
||||
private static boolean checkCRC32(File in1, File in2) throws IOException {
|
||||
CRC32 crc = new CRC32();
|
||||
crc.update(FileUtils.readFileToByteArray(in1));
|
||||
long v1 = crc.getValue();
|
||||
crc.reset();
|
||||
crc.update(FileUtils.readFileToByteArray(in2));
|
||||
return v1 != crc.getValue();
|
||||
}
|
||||
|
||||
private static boolean copyFileIfChanged(File in1, File in2) throws IOException {
|
||||
if(!in2.exists()) {
|
||||
FileUtils.copyFile(in1, in2);
|
||||
return true;
|
||||
}
|
||||
if(in1.lastModified() == in2.lastModified()) {
|
||||
return false;
|
||||
}
|
||||
CRC32 crc = new CRC32();
|
||||
byte[] f1 = FileUtils.readFileToByteArray(in1);
|
||||
crc.update(f1);
|
||||
long v1 = crc.getValue();
|
||||
crc.reset();
|
||||
byte[] f2 = FileUtils.readFileToByteArray(in2);
|
||||
crc.update(f2);
|
||||
if(v1 != crc.getValue()) {
|
||||
//System.out.println("changed: " + in1.getAbsolutePath());
|
||||
FileUtils.writeByteArrayToFile(in2, f1);
|
||||
return true;
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.formatter;
|
||||
|
||||
import org.eclipse.jdt.core.formatter.CodeFormatter;
|
||||
import org.eclipse.jdt.internal.formatter.DefaultCodeFormatter;
|
||||
import org.eclipse.jdt.internal.formatter.DefaultCodeFormatterOptions;
|
||||
import org.eclipse.jface.text.Document;
|
||||
import org.eclipse.jface.text.IDocument;
|
||||
import org.eclipse.text.edits.TextEdit;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class EclipseFormatter {
|
||||
|
||||
private static final DefaultCodeFormatter formatter = new DefaultCodeFormatter(DefaultCodeFormatterOptions.getEclipseDefaultSettings());
|
||||
|
||||
public static String processSource(String input, String lineSeparator) {
|
||||
try {
|
||||
IDocument doc = new Document();
|
||||
doc.set(input);
|
||||
TextEdit edit = formatter.format(CodeFormatter.K_COMPILATION_UNIT |
|
||||
CodeFormatter.F_INCLUDE_COMMENTS, input, 0, input.length(), 0, lineSeparator);
|
||||
edit.apply(doc);
|
||||
return doc.get();
|
||||
}catch(Throwable t) {
|
||||
System.err.println("Code formatting failed!");
|
||||
t.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.commons.csv.CSVParser;
|
||||
import org.apache.commons.csv.CSVRecord;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class CSVMappings {
|
||||
|
||||
public final Map<String, Symbol> csvFieldsMappings = new HashMap();
|
||||
public final Map<String, Symbol> csvMethodsMappings = new HashMap();
|
||||
public final Map<String, Param> csvParamsMappings = new HashMap();
|
||||
public final Map<String, Param[]> csvParamsForFunction = new HashMap();
|
||||
|
||||
public static class Symbol {
|
||||
|
||||
public final String name;
|
||||
public final int mod;
|
||||
public final String comment;
|
||||
|
||||
public Symbol(String name, int mod, String comment) {
|
||||
this.name = name;
|
||||
this.mod = mod;
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Param {
|
||||
|
||||
public final String name;
|
||||
public final int mod;
|
||||
|
||||
public Param(String name, int mod) {
|
||||
this.name = name;
|
||||
this.mod = mod;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void loadMethodsFile(Reader reader) throws IOException {
|
||||
loadSymbols(reader, csvMethodsMappings, "methods.csv");
|
||||
}
|
||||
|
||||
public void loadFieldsFile(Reader reader) throws IOException {
|
||||
loadSymbols(reader, csvFieldsMappings, "fields.csv");
|
||||
}
|
||||
|
||||
private void loadSymbols(Reader reader, Map<String, Symbol> map, String debugFileName) throws IOException {
|
||||
try {
|
||||
CSVParser ps = CSVFormat.DEFAULT.withFirstRecordAsHeader().parse(reader);
|
||||
Iterator<CSVRecord> rows = ps.iterator();
|
||||
while(rows.hasNext()) {
|
||||
CSVRecord rec = rows.next();
|
||||
String srgName = rec.get("searge");
|
||||
String deobfName = rec.get("name");
|
||||
int mod = Integer.parseInt(rec.get("side"));
|
||||
String comment = rec.get("desc");
|
||||
map.put(srgName, new Symbol(deobfName, mod, comment));
|
||||
}
|
||||
System.out.println(" Loaded " + map.size() + " symbols from " + debugFileName);
|
||||
}catch(Throwable t) {
|
||||
t.printStackTrace();
|
||||
throw new IOException("Invalid " + debugFileName + " file!");
|
||||
}
|
||||
}
|
||||
|
||||
public void loadParamsFile(Reader reader) throws IOException {
|
||||
try {
|
||||
CSVParser ps = CSVFormat.DEFAULT.withFirstRecordAsHeader().parse(reader);
|
||||
Iterator<CSVRecord> rows = ps.iterator();
|
||||
while(rows.hasNext()) {
|
||||
CSVRecord rec = rows.next();
|
||||
String srgName = rec.get("param");
|
||||
String deobfName = rec.get("name");
|
||||
int mod = Integer.parseInt(rec.get("side"));
|
||||
csvParamsMappings.put(srgName, new Param(deobfName, mod));
|
||||
String fName = srgName.substring(srgName.indexOf('_') + 1);
|
||||
if(!fName.startsWith("i")) {
|
||||
int i2 = fName.indexOf('_');
|
||||
if(i2 != -1) {
|
||||
int ordinal = -1;
|
||||
String ordStr = fName.substring(i2 + 1);
|
||||
if(ordStr.length() >= 2) {
|
||||
try {
|
||||
ordinal = Integer.parseInt(ordStr.substring(0, ordStr.length() - 1));
|
||||
}catch(NumberFormatException ex) {
|
||||
}
|
||||
}
|
||||
if(ordinal >= 0) {
|
||||
fName = "func_" + fName.substring(0, i2);
|
||||
Param[] prm = csvParamsForFunction.get(fName);
|
||||
if(prm == null || prm.length <= ordinal) {
|
||||
Param[] prm2 = new Param[ordinal + 1];
|
||||
if(prm != null) {
|
||||
System.arraycopy(prm, 0, prm2, 0, prm.length);
|
||||
}
|
||||
prm = prm2;
|
||||
}
|
||||
prm[ordinal] = new Param(deobfName, mod);
|
||||
csvParamsForFunction.put(fName, prm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println(" Loaded " + csvParamsMappings.size() + " symbols from params.csv");
|
||||
}catch(Throwable t) {
|
||||
throw new IOException("Invalid params.csv file!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildToolsConfig;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class CreateUnpatched {
|
||||
|
||||
public static boolean createUnpatched() {
|
||||
try {
|
||||
return createUnpatched0();
|
||||
}catch(Throwable t) {
|
||||
System.err.println();
|
||||
System.err.println("Exception encountered while running task 'unpatched'!");
|
||||
t.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static boolean createUnpatched0() throws Throwable {
|
||||
File tmpDirectory = EaglerBuildToolsConfig.getTemporaryDirectory();
|
||||
File mcpDir = new File(tmpDirectory, "ModCoderPack");
|
||||
File minecraftSrc = new File(tmpDirectory, "MinecraftSrc/minecraft_src.jar");
|
||||
File minecraftRes = new File(tmpDirectory, "MinecraftSrc/minecraft_res.jar");
|
||||
File outputFile = new File("./MinecraftSrc.zip");
|
||||
|
||||
if(outputFile.exists()) {
|
||||
System.err.println("ERROR: The file 'MinecraftSrc.zip' already exists in this directory!");
|
||||
System.err.println("Delete it and re-run 'unpatched' to try again");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!mcpDir.isDirectory()) {
|
||||
System.err.println("The '" + mcpDir.getName() + "' directory was not found in the temporary directory!");
|
||||
System.err.println("Please run the 'init' command to create it");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!minecraftSrc.isFile()) {
|
||||
System.err.println("The '" + minecraftSrc.getName() + "' file was not found in the temporary directory!");
|
||||
System.err.println("Please run the 'init' command to create it");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!minecraftRes.isFile()) {
|
||||
System.err.println("The '" + minecraftRes.getName() + "' file was not found in the temporary directory!");
|
||||
System.err.println("Please run the 'init' command to create it");
|
||||
return false;
|
||||
}
|
||||
|
||||
File tmpJavadocOut = new File(tmpDirectory, "MinecraftSrc/minecraft_unpatched_javadoc.jar");
|
||||
System.out.println();
|
||||
System.out.println("Preparing source in '" + minecraftSrc.getName() + "'...");
|
||||
System.out.println();
|
||||
CSVMappings mp = new CSVMappings();
|
||||
InsertJavaDoc.processSource(minecraftSrc, tmpJavadocOut, mcpDir, mp, false);
|
||||
|
||||
try(ZipOutputStream zot = new ZipOutputStream(new FileOutputStream(outputFile))) {
|
||||
zot.setLevel(0);
|
||||
int tl;
|
||||
System.out.println("Extracting '" + tmpJavadocOut.getName() + "' into '" + outputFile.getName() + "'...");
|
||||
try(FileInputStream fin = new FileInputStream(tmpJavadocOut)) {
|
||||
tl = extractZipTo(new ZipInputStream(fin), zot, "src");
|
||||
}
|
||||
System.out.println("Extracted " + tl + " files.");
|
||||
System.out.println();
|
||||
System.out.println("Extracting '" + minecraftRes.getName() + "' into '" + outputFile.getName() + "'...");
|
||||
try(FileInputStream fin = new FileInputStream(minecraftRes)) {
|
||||
tl = extractZipTo(new ZipInputStream(fin), zot, "res");
|
||||
}
|
||||
System.out.println("Extracted " + tl + " files.");
|
||||
}
|
||||
|
||||
if(!tmpJavadocOut.delete()) {
|
||||
System.err.println();
|
||||
System.err.println("ERROR: failed to delete '" + tmpJavadocOut.getName() + "' from temporary directory!");
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private static int extractZipTo(ZipInputStream zin, ZipOutputStream zout, String pfx) throws IOException {
|
||||
int cnt = 0;
|
||||
ZipEntry in;
|
||||
while((in = zin.getNextEntry()) != null) {
|
||||
if(in.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
String n = in.getName();
|
||||
if(n.startsWith("/")) {
|
||||
n = n.substring(1);
|
||||
}
|
||||
if(n.startsWith("META-INF")) {
|
||||
continue;
|
||||
}
|
||||
ZipEntry out = new ZipEntry(pfx + "/" + n);
|
||||
zout.putNextEntry(out);
|
||||
IOUtils.copy(zin, zout, 8192);
|
||||
++cnt;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,241 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildTools;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.diff.ApplyPatchesToZip;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.formatter.EclipseFormatter;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.util.JARSubprocess;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class DecompileMinecraft {
|
||||
|
||||
public static boolean decompileMinecraft(File mcpDataTMP, File minecraftJar, File minecraftSrc, File assetsJson, boolean writeJavaDoc) throws Throwable {
|
||||
|
||||
File filterOut = new File(minecraftSrc, "minecraft_classes.jar");
|
||||
System.out.println();
|
||||
System.out.println("Extracting '" + minecraftJar.getAbsolutePath() + "\" to \"" + filterOut.getAbsolutePath() + "\"...");
|
||||
|
||||
int xt = 0;
|
||||
try(ZipInputStream jarIn = new ZipInputStream(new FileInputStream(minecraftJar));
|
||||
ZipOutputStream jarOut = new ZipOutputStream(new FileOutputStream(filterOut))) {
|
||||
jarOut.setLevel(0);
|
||||
jarOut.putNextEntry(new ZipEntry("META-INF/MANIFEST.MF"));
|
||||
jarOut.write("Manifest-Version: 1.0\nCreated-By: Eaglercraft BuildTools\n".getBytes(StandardCharsets.UTF_8));
|
||||
ZipEntry et;
|
||||
String nm;
|
||||
while((et = jarIn.getNextEntry()) != null) {
|
||||
if(!et.isDirectory() && (nm = et.getName()).endsWith(".class")) {
|
||||
ZipEntry z2 = new ZipEntry(nm);
|
||||
jarOut.putNextEntry(z2);
|
||||
IOUtils.copy(jarIn, jarOut);
|
||||
++xt;
|
||||
}
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: failed to extract \"" + minecraftJar.getAbsolutePath() + "\" to \"" + filterOut.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
if(filterOut.exists()) {
|
||||
filterOut.delete();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
System.out.println("Extracted " + xt + " class files.");
|
||||
|
||||
File deobfOut = new File(minecraftSrc, "minecraft_specialsource.jar");
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Running SpecialSource...");
|
||||
int ex = JARSubprocess.runJava(mcpDataTMP, new String[] {
|
||||
"-cp", filterOut.getAbsolutePath() + JARSubprocess.classPathSeperator + "runtime.jar",
|
||||
"net.md_5.specialsource.SpecialSource", "-i", filterOut.getAbsolutePath(), "-o",
|
||||
deobfOut.getAbsolutePath(), "-m", "minecraft.srg", "--kill-source"
|
||||
}, " [SpecialSource]");
|
||||
|
||||
filterOut.delete();
|
||||
|
||||
if(ex == 0) {
|
||||
System.out.println("SpecialSource completed successfully.");
|
||||
}else {
|
||||
System.err.println("ERROR: MCP SpecialSource execution failed!");
|
||||
return false;
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
File deobfOut2 = new File(minecraftSrc, "minecraft_mcinjector.jar");
|
||||
|
||||
System.out.println("Running MCInjector...");
|
||||
ex = JARSubprocess.runJava(mcpDataTMP, new String[] {
|
||||
"-cp", filterOut.getAbsolutePath() + JARSubprocess.classPathSeperator + "runtime.jar",
|
||||
"de.oceanlabs.mcp.mcinjector.MCInjector", "--jarIn", deobfOut.getAbsolutePath(), "--jarOut",
|
||||
deobfOut2.getAbsolutePath(), "--mapIn", "minecraft.exc", "--jsonIn", "exceptor.json",
|
||||
"--lvt", "STRIP"
|
||||
}, " [MCInjector]");
|
||||
|
||||
deobfOut.delete();
|
||||
|
||||
if(ex == 0) {
|
||||
System.out.println("MCInjector completed successfully.");
|
||||
}else {
|
||||
System.err.println("ERROR: MCP MCInjector execution failed!");
|
||||
return false;
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
File ffOut = new File(minecraftSrc, "fernflower.tmp");
|
||||
|
||||
if(ffOut.isFile()) {
|
||||
ffOut.delete();
|
||||
}else if(ffOut.isDirectory()) {
|
||||
FileUtils.deleteDirectory(ffOut);
|
||||
}
|
||||
|
||||
if(!ffOut.mkdir()) {
|
||||
System.err.println("ERROR: Could not create Fernflower output directory!");
|
||||
return false;
|
||||
}
|
||||
|
||||
System.out.println("Decompiling with Fernflower...");
|
||||
System.out.println("This will take a while, go get a drink or something lol.");
|
||||
System.out.println();
|
||||
|
||||
System.out.println("Staying hydrated is important when u work on a fucked up project that");
|
||||
System.out.println("will make you angry enough put your fists through your bedroom wall");
|
||||
System.out.println();
|
||||
|
||||
ex = JARSubprocess.runJava(mcpDataTMP, new String[] {
|
||||
"-jar", "fernflower.jar", "-din=1", "-rbr=1", "-dgs=1", "-asc=1", "-rsy=1", "-iec=1",
|
||||
"-ren=0", "-jvn=1", "-udv=1", "-ump=1", "-log=WARN", deobfOut2.getAbsolutePath(),
|
||||
ffOut.getAbsolutePath()
|
||||
}, " [Fernflower]");
|
||||
|
||||
deobfOut2.delete();
|
||||
|
||||
if(ex == 0) {
|
||||
System.out.println("Decompiler completed successfully.");
|
||||
}else {
|
||||
System.err.println("ERROR: Fernflower decompiler failed!");
|
||||
return false;
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
File[] ff = ffOut.listFiles();
|
||||
File decomp = null;
|
||||
for(int i = 0; i < ff.length; ++i) {
|
||||
if(ff[i].getName().endsWith(".jar")) {
|
||||
if(ff[i].getName().equalsIgnoreCase("minecraft_mcinjector.jar")) {
|
||||
decomp = ff[i];
|
||||
}else {
|
||||
if(decomp == null) {
|
||||
decomp = ff[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(decomp == null) {
|
||||
System.err.println("Could not find Fernflower output jar! (in " + ffOut.getAbsolutePath() + ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
File formatOut = new File(minecraftSrc, "minecraft_src.jar");
|
||||
|
||||
System.out.println("Formatting source for patches...");
|
||||
System.out.println(" (Using default Eclipse format)");
|
||||
System.out.print(" ");
|
||||
xt = 0;
|
||||
try(ZipInputStream jarIn = new ZipInputStream(new FileInputStream(decomp));
|
||||
ZipOutputStream jarOut = new ZipOutputStream(new FileOutputStream(formatOut))) {
|
||||
jarOut.setLevel(5);
|
||||
jarOut.putNextEntry(new ZipEntry("META-INF/MANIFEST.MF"));
|
||||
jarOut.write("Manifest-Version: 1.0\nCreated-By: Eaglercraft BuildTools\n".getBytes(StandardCharsets.UTF_8));
|
||||
ZipEntry et;
|
||||
String nm;
|
||||
while((et = jarIn.getNextEntry()) != null) {
|
||||
if((nm = et.getName()).endsWith(".java")) {
|
||||
String txt = IOUtils.toString(jarIn, "UTF-8");
|
||||
txt = EclipseFormatter.processSource(txt, "\n");
|
||||
ZipEntry z2 = new ZipEntry(nm);
|
||||
jarOut.putNextEntry(z2);
|
||||
IOUtils.write(txt, jarOut, "UTF-8");
|
||||
++xt;
|
||||
if(xt % 75 == 74) {
|
||||
System.out.print(".");
|
||||
}
|
||||
}else {
|
||||
if(!nm.startsWith("META-INF")) {
|
||||
ZipEntry z2 = new ZipEntry(nm);
|
||||
jarOut.putNextEntry(z2);
|
||||
IOUtils.copy(jarIn, jarOut, 4096);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Formatted " + xt + " classes.");
|
||||
System.out.println();
|
||||
|
||||
try {
|
||||
FileUtils.deleteDirectory(ffOut);
|
||||
}catch(IOException exx) {
|
||||
}
|
||||
|
||||
File patchOut = new File(minecraftSrc, "minecraft_src_patch.jar");
|
||||
|
||||
try {
|
||||
ApplyPatchesToZip.applyPatches(formatOut, null, new File(EaglerBuildTools.repositoryRoot, "patches/minecraft"), patchOut, true, true);
|
||||
}catch(Throwable t) {
|
||||
System.err.println("ERROR: Could not apply 'patches' directory to: " + patchOut.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
File javadocOut = new File(minecraftSrc, "minecraft_src_javadoc.jar");
|
||||
CSVMappings comments = writeJavaDoc ? new CSVMappings() : null;
|
||||
if(!InsertJavaDoc.processSource(patchOut, javadocOut, mcpDataTMP, comments)) {
|
||||
System.err.println("ERROR: Could not create javadoc!");
|
||||
return false;
|
||||
}
|
||||
|
||||
File resourcesOut = new File(minecraftSrc, "minecraft_res.jar");
|
||||
if(!LoadResources.loadResources(minecraftJar, assetsJson, resourcesOut, mcpDataTMP, new File(minecraftSrc, "minecraft_languages.zip"))) {
|
||||
System.err.println("ERROR: Could not copy resources!");
|
||||
return false;
|
||||
}
|
||||
|
||||
File patchResourcesOut = new File(minecraftSrc, "minecraft_res_patch.jar");
|
||||
|
||||
try {
|
||||
ApplyPatchesToZip.applyPatches(resourcesOut, null, new File(EaglerBuildTools.repositoryRoot, "patches/resources"), patchResourcesOut, true, true);
|
||||
}catch(Throwable t) {
|
||||
System.err.println("ERROR: Could not apply 'patches' directory to: " + patchResourcesOut.getName());
|
||||
t.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,175 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.ProcessBuilder.Redirect;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class FFMPEG {
|
||||
|
||||
public static final boolean windows = System.getProperty("os.name").toLowerCase().contains("windows");
|
||||
|
||||
public static String foundFFMPEG = null;
|
||||
|
||||
public static void confirmFFMPEG() {
|
||||
if(checkFFMPEGOnPath()) {
|
||||
foundFFMPEG = "ffmpeg";
|
||||
return;
|
||||
}
|
||||
if(windows) {
|
||||
File f = new File("mcp918/ffmpeg.exe");
|
||||
if(!f.isFile()) {
|
||||
System.out.println();
|
||||
System.out.println("ERROR: 'ffmpeg.exe' wasn't found in the 'mcp918' folder!");
|
||||
System.out.println();
|
||||
System.out.println("Please visit one of the following URLs to download it:");
|
||||
System.out.println(" - https://www.gyan.dev/ffmpeg/builds/");
|
||||
System.out.println(" - https://github.com/BtbN/FFmpeg-Builds/releases");
|
||||
System.out.println();
|
||||
System.out.println("Locate 'bin/ffmpeg.exe' in the .zip file you download and");
|
||||
System.out.println("place it in the 'mcp918' folder and press enter to continue");
|
||||
System.out.println();
|
||||
try {
|
||||
while(System.in.read() != '\n') {
|
||||
try {
|
||||
Thread.sleep(20l);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
}
|
||||
confirmFFMPEG();
|
||||
}else {
|
||||
foundFFMPEG = f.getAbsolutePath();
|
||||
}
|
||||
}else {
|
||||
do {
|
||||
File f = new File("mcp918/ffmpeg");
|
||||
if(f.isFile() && f.canExecute()) {
|
||||
foundFFMPEG = f.getAbsolutePath();
|
||||
return;
|
||||
}
|
||||
System.out.println();
|
||||
System.out.println("ERROR: ffmpeg is not installed on this system!");
|
||||
System.out.println();
|
||||
System.out.println("Please install it to continue, you can use the package");
|
||||
System.out.println("manager on most distros to do this automatically:");
|
||||
System.out.println(" - Debian: apt install ffmpeg");
|
||||
System.out.println(" - Ubuntu: apt install ffmpeg");
|
||||
System.out.println(" - Fedora: dnf install ffmpeg");
|
||||
System.out.println(" - Arch: pacman -S ffmpeg");
|
||||
System.out.println();
|
||||
System.out.println("Alternatively, place the 'ffmpeg' executable in the");
|
||||
System.out.println("'mcp918' folder of this repository");
|
||||
System.out.println();
|
||||
System.out.println("Make sure it has chmod +x");
|
||||
System.out.println();
|
||||
System.out.println("Press enter to continue once it has installed");
|
||||
System.out.println();
|
||||
try {
|
||||
while(System.in.read() != '\n') {
|
||||
try {
|
||||
Thread.sleep(20l);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
}
|
||||
}while(!checkFFMPEGOnPath());
|
||||
foundFFMPEG = "ffmpeg";
|
||||
}
|
||||
}
|
||||
|
||||
public static int run(File rundir, String... args) {
|
||||
String[] e = new String[args.length + 1];
|
||||
System.arraycopy(args, 0, e, 1, args.length);
|
||||
|
||||
if(foundFFMPEG == null) {
|
||||
confirmFFMPEG();
|
||||
}
|
||||
|
||||
e[0] = foundFFMPEG;
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(e);
|
||||
pb.directory(rundir);
|
||||
pb.redirectOutput(Redirect.INHERIT);
|
||||
pb.redirectError(Redirect.INHERIT);
|
||||
|
||||
try {
|
||||
Process p = pb.start();
|
||||
while(true) {
|
||||
try {
|
||||
return p.waitFor();
|
||||
} catch (InterruptedException ee) {
|
||||
}
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not start ffmpeg process!");
|
||||
ex.printStackTrace();
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static byte[] encodeOgg(File temporaryDir, byte[] bytesInput, int samples, int bitrate, boolean stereo) throws IOException {
|
||||
File src = new File(temporaryDir, "temp.src.ogg");
|
||||
FileUtils.writeByteArrayToFile(src, bytesInput);
|
||||
|
||||
File dst = new File(temporaryDir, "temp.dst.ogg");
|
||||
|
||||
int i;
|
||||
if (stereo) {
|
||||
i = run(temporaryDir, "-y", "-v", "error", "-i", "temp.src.ogg", "-c:a", "libvorbis", "-ac", "2",
|
||||
"-apply_phase_inv", "1", "-b:a", "" + bitrate + "k", "-ar", "" + samples, "temp.dst.ogg");
|
||||
} else {
|
||||
i = run(temporaryDir, "-y", "-v", "error", "-i", "temp.src.ogg", "-c:a", "libvorbis", "-ac", "1",
|
||||
"-apply_phase_inv", "0", "-b:a", "" + bitrate + "k", "-ar", "" + samples, "temp.dst.ogg");
|
||||
}
|
||||
|
||||
src.delete();
|
||||
|
||||
if(i != 0) {
|
||||
throw new IOException("FFMPEG returned error code: " + i);
|
||||
}
|
||||
|
||||
byte[] read = FileUtils.readFileToByteArray(dst);
|
||||
|
||||
dst.delete();
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
public static boolean checkFFMPEGOnPath() {
|
||||
ProcessBuilder pb = new ProcessBuilder("ffmpeg", "-version");
|
||||
Process proc;
|
||||
try {
|
||||
proc = pb.start();
|
||||
}catch(IOException ex) {
|
||||
return false;
|
||||
}
|
||||
int exitCode;
|
||||
while(true) {
|
||||
try {
|
||||
exitCode = proc.waitFor();
|
||||
break;
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
return exitCode == 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,231 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.decompiler.ParameterSplitter;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.CSVMappings.Param;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.CSVMappings.Symbol;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.util.FileReaderUTF;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.util.FileWriterUTF;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class GenerateEXCs {
|
||||
|
||||
public static boolean generateEXCs(File mcpDataTMP, File excOut, CSVMappings params) {
|
||||
System.out.println();
|
||||
System.out.println("Generating \"" + excOut.getName() + "\" from \"" + mcpDataTMP.getName() + "\"...");
|
||||
|
||||
File paramsCSV = new File(mcpDataTMP, "params.csv");
|
||||
try(FileReaderUTF fr = new FileReaderUTF(paramsCSV)) {
|
||||
params.loadParamsFile(fr);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: failed to read \"" + paramsCSV.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
Map<Integer,String> paramsTmp = new HashMap();
|
||||
Set<String> definedFunctions = new HashSet();
|
||||
|
||||
int pcount = 0;
|
||||
int mcount = 0;
|
||||
int pgcount = 0;
|
||||
try(BufferedReader is = new BufferedReader(new FileReaderUTF(new File(mcpDataTMP, "joined.exc")));
|
||||
PrintWriter os = new PrintWriter(new FileWriterUTF(excOut));) {
|
||||
String s;
|
||||
while((s = is.readLine()) != null) {
|
||||
int idx = s.lastIndexOf('|');
|
||||
if(idx != -1) {
|
||||
String pfx = s.substring(0, idx);
|
||||
String func = null;
|
||||
int p1 = pfx.indexOf('(');
|
||||
if(p1 != -1) {
|
||||
func = pfx.substring(0, p1);
|
||||
func = pfx.substring(func.lastIndexOf('.') + 1);
|
||||
}
|
||||
if(func != null) {
|
||||
definedFunctions.add(func);
|
||||
}
|
||||
if(idx != s.length() - 1) {
|
||||
paramsTmp.clear();
|
||||
String[] prms = s.substring(idx + 1).split(",");
|
||||
String[] nprms = new String[prms.length];
|
||||
int lpc = 0;
|
||||
for(int i = 0; i < prms.length; ++i) {
|
||||
Param p = params.csvParamsMappings.get(prms[i]);
|
||||
if(p != null) {
|
||||
nprms[i] = p.name;
|
||||
++pcount;
|
||||
++lpc;
|
||||
}
|
||||
}
|
||||
if(lpc != prms.length) {
|
||||
if(p1 != -1) {
|
||||
String sig = pfx.substring(p1);
|
||||
sig = sig.substring(0, sig.indexOf('='));
|
||||
pgcount += ParameterSplitter.getParameterArray(sig, nprms);
|
||||
}
|
||||
for(int i = 0; i < nprms.length; ++i) {
|
||||
if(nprms[i] == null) {
|
||||
nprms[i] = "param0" + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
s = pfx + "|" + String.join(",", nprms);
|
||||
}else if(func != null) {
|
||||
int idxx = func.indexOf('_');
|
||||
int idxx2 = func.lastIndexOf('_');
|
||||
if(idxx2 > idxx) {
|
||||
func = func.substring(0, idxx2 - 1);
|
||||
}
|
||||
Param[] pars = params.csvParamsForFunction.get(func);
|
||||
String sig = null;
|
||||
if(p1 != -1) {
|
||||
sig = pfx.substring(p1);
|
||||
sig = sig.substring(0, sig.indexOf('='));
|
||||
}
|
||||
if(pars == null) {
|
||||
if(sig != null) {
|
||||
String[] sg = ParameterSplitter.getParameterSigArray(sig, "par");
|
||||
if(sg != null) {
|
||||
s = pfx + "|" + String.join(",", sg);
|
||||
}
|
||||
pgcount += sg.length;
|
||||
}
|
||||
}else {
|
||||
int notNullLen = 0;
|
||||
for(int i = 0; i < pars.length; ++i) {
|
||||
if(pars[i] != null) {
|
||||
++notNullLen;
|
||||
}
|
||||
}
|
||||
String[] sg = new String[notNullLen];
|
||||
notNullLen = 0;
|
||||
for(int i = 0; i < pars.length; ++i) {
|
||||
if(pars[i] != null) {
|
||||
sg[notNullLen++] = pars[i].name;
|
||||
++pcount;
|
||||
}
|
||||
}
|
||||
s = pfx + "|" + String.join(",", sg);
|
||||
}
|
||||
}
|
||||
}
|
||||
int idx3 = s.indexOf('(');
|
||||
if(idx3 != -1) {
|
||||
int idx4 = s.lastIndexOf('.', idx3);
|
||||
if(idx4 != -1) {
|
||||
String func = s.substring(idx4 + 1, idx3);
|
||||
Symbol rp = params.csvMethodsMappings.get(func);
|
||||
if(rp != null) {
|
||||
String pfx = s.substring(0, idx4);
|
||||
String pofx = s.substring(idx3);
|
||||
s = pfx + "." + rp.name + pofx;
|
||||
++mcount;
|
||||
}
|
||||
}
|
||||
}
|
||||
os.println(s);
|
||||
}
|
||||
os.println();
|
||||
os.println("# auto generated entries start here:");
|
||||
try(BufferedReader iss = new BufferedReader(new FileReaderUTF(new File(mcpDataTMP, "joined.srg")))) {
|
||||
while((s = iss.readLine()) != null) {
|
||||
if(s.startsWith("MD:")) {
|
||||
int idx = s.lastIndexOf(' ');
|
||||
if(idx > 0) {
|
||||
int idx2 = s.lastIndexOf(' ', idx - 1);
|
||||
String fname = s.substring(idx2 + 1, idx);
|
||||
String fnameShort = fname;
|
||||
String fsig = s.substring(idx + 1);
|
||||
fnameShort = fname.substring(fname.lastIndexOf('/') + 1);
|
||||
int idx3 = fnameShort.lastIndexOf('_');
|
||||
if(idx3 != -1 && fnameShort.lastIndexOf('_', idx3 - 1) > 0) {
|
||||
fnameShort = fnameShort.substring(0, idx3);
|
||||
}
|
||||
if(definedFunctions.add(fnameShort)) {
|
||||
String[] sg = ParameterSplitter.getParameterSigArray(fsig, "par");
|
||||
Param[] pars = params.csvParamsForFunction.get(fnameShort);
|
||||
if(pars != null) {
|
||||
int notNullLen = 0;
|
||||
for(int i = 0; i < pars.length; ++i) {
|
||||
if(pars[i] != null) {
|
||||
++notNullLen;
|
||||
}
|
||||
}
|
||||
if(notNullLen > 0) {
|
||||
notNullLen = 0;
|
||||
for(int i = 0; i < pars.length; ++i) {
|
||||
if(pars[i] != null) {
|
||||
int ii = notNullLen++;
|
||||
if(ii < sg.length) {
|
||||
sg[ii] = pars[i].name;
|
||||
++pcount;
|
||||
}
|
||||
}
|
||||
}
|
||||
int idx4 = fname.lastIndexOf('/');
|
||||
String ppfx = fname.substring(0, idx4);
|
||||
String ppfunc = fname.substring(idx4 + 1);
|
||||
Symbol rp = params.csvMethodsMappings.get(ppfunc);
|
||||
if(rp != null) {
|
||||
ppfunc = rp.name;
|
||||
++mcount;
|
||||
}
|
||||
fname = ppfx + "." + ppfunc;
|
||||
os.println(fname + fsig + "=|" + String.join(",", sg));
|
||||
}
|
||||
}else {
|
||||
if(sg != null) {
|
||||
if(sg.length > 0) {
|
||||
pgcount += sg.length;
|
||||
int idx4 = fname.lastIndexOf('/');
|
||||
String ppfx = fname.substring(0, idx4);
|
||||
String ppfunc = fname.substring(idx4 + 1);
|
||||
Symbol rp = params.csvMethodsMappings.get(ppfunc);
|
||||
if(rp != null) {
|
||||
ppfunc = rp.name;
|
||||
++mcount;
|
||||
}
|
||||
fname = ppfx + "." + ppfunc;
|
||||
os.println(fname + fsig + "=|" + String.join(",", sg));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: failed to write \"" + excOut.getName() + "\" from \"joined.exc\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
System.out.println(" - Deobf " + pcount + " params to \"" + excOut.getName() + "\"");
|
||||
System.out.println(" - Generate " + pgcount + " params to \"" + excOut.getName() + "\"");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.CSVMappings.Symbol;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.util.FileReaderUTF;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.util.FileWriterUTF;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class GenerateSRGs {
|
||||
|
||||
public static boolean generate(File mcpDataTMP, File srgOut, CSVMappings csv) throws Throwable {
|
||||
System.out.println();
|
||||
System.out.println("Generating \"" + srgOut.getName() + "\" from \"" + mcpDataTMP.getName() + "\"...");
|
||||
|
||||
File methodsCSV = new File(mcpDataTMP, "methods.csv");
|
||||
try(FileReaderUTF fr = new FileReaderUTF(methodsCSV)) {
|
||||
csv.loadMethodsFile(fr);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: failed to read \"" + methodsCSV.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
File fieldsCSV = new File(mcpDataTMP, "fields.csv");
|
||||
try(FileReaderUTF fr = new FileReaderUTF(fieldsCSV)) {
|
||||
csv.loadFieldsFile(fr);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: failed to read \"" + fieldsCSV.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
int ccount = 0;
|
||||
int mcount = 0;
|
||||
int fcount = 0;
|
||||
|
||||
try(BufferedReader is = new BufferedReader(new FileReaderUTF(new File(mcpDataTMP, "joined.srg")));
|
||||
PrintWriter os = new PrintWriter(new FileWriterUTF(srgOut));) {
|
||||
String s;
|
||||
while((s = is.readLine()) != null) {
|
||||
if(s.startsWith("MD:")) {
|
||||
int lastSpace = s.lastIndexOf(' ');
|
||||
String sig = s.substring(lastSpace + 1);
|
||||
s = s.substring(0, lastSpace);
|
||||
int lastSlash = s.lastIndexOf('/');
|
||||
String fd = s.substring(lastSlash + 1);
|
||||
s = s.substring(0, lastSlash);
|
||||
Symbol sm = csv.csvMethodsMappings.get(fd);
|
||||
if(sm != null) {
|
||||
++mcount;
|
||||
fd = sm.name;
|
||||
}
|
||||
os.println(s + "/" + fd + " " + sig);
|
||||
}else if(s.startsWith("FD:")) {
|
||||
int lastSlash = s.lastIndexOf('/');
|
||||
String fd = s.substring(lastSlash + 1);
|
||||
s = s.substring(0, lastSlash);
|
||||
Symbol sm = csv.csvFieldsMappings.get(fd);
|
||||
if(sm != null) {
|
||||
++fcount;
|
||||
fd = sm.name;
|
||||
}
|
||||
os.println(s + "/" + fd);
|
||||
}else if(s.startsWith("CL:")) {
|
||||
++ccount;
|
||||
os.println(s);
|
||||
}else {
|
||||
os.println(s);
|
||||
}
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: failed to write \"" + srgOut.getName() + "\" from \"joined.srg\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
System.out.println(" - Deobf " + ccount + " classes to \"" + srgOut.getName() + "\"");
|
||||
System.out.println(" - Deobf " + mcount + " methods to \"" + srgOut.getName() + "\"");
|
||||
System.out.println(" - Deobf " + fcount + " fields to \"" + srgOut.getName() + "\"");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class InitMCP {
|
||||
|
||||
public static boolean initTask(File f, File mcpDataTMP) throws Throwable {
|
||||
File mcpUnifiedJar = new File(mcpDataTMP, "runtime.jar");
|
||||
String[] jarsToUnify = new String[] { "mcinjector.jar", "specialsource.jar" }; //, "retroguard.jar" };
|
||||
boolean[] jarsFound = new boolean[jarsToUnify.length];
|
||||
String[] configToCopy = new String[] { "exceptor.json", "fields.csv", "joined.exc",
|
||||
"joined.srg", "methods.csv", "params.csv", "fernflower.jar" };
|
||||
boolean[] configFound = new boolean[configToCopy.length];
|
||||
Set<String> copiedFiles = new HashSet();
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Extracting \"" + f.getAbsolutePath() + "\" to \"" + mcpDataTMP.getAbsolutePath() + "\"...");
|
||||
|
||||
try(ZipInputStream is = new ZipInputStream(new FileInputStream(f));
|
||||
ZipOutputStream os = new ZipOutputStream(new FileOutputStream(mcpUnifiedJar))) {
|
||||
|
||||
os.setLevel(0);
|
||||
os.putNextEntry(new ZipEntry("META-INF/MANIFEST.MF"));
|
||||
os.write("Manifest-Version: 1.0\nCreated-By: Eaglercraft BuildTools\n".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
ZipEntry e;
|
||||
entry_read: while((e = is.getNextEntry()) != null) {
|
||||
String zn = e.getName();
|
||||
if(zn.startsWith("/")) {
|
||||
zn = zn.substring(1);
|
||||
}
|
||||
for(int ii = 0; ii < jarsToUnify.length; ++ii) {
|
||||
if(zn.endsWith(jarsToUnify[ii])) {
|
||||
System.out.println(" " + jarsToUnify[ii] + " -> " + mcpUnifiedJar.getName());
|
||||
ZipInputStream iis = new ZipInputStream(is);
|
||||
ZipEntry e2;
|
||||
while((e2 = iis.getNextEntry()) != null) {
|
||||
if(e2.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
String n = e2.getName();
|
||||
int i = n.indexOf("META-INF");
|
||||
if(i == 0 || i == 1) {
|
||||
continue;
|
||||
}
|
||||
if(copiedFiles.add(n)) {
|
||||
ZipEntry e3 = new ZipEntry(e2.getName());
|
||||
os.putNextEntry(e3);
|
||||
IOUtils.copy(iis, os, 4096);
|
||||
}
|
||||
}
|
||||
jarsFound[ii] = true;
|
||||
continue entry_read;
|
||||
}
|
||||
}
|
||||
|
||||
for(int ii = 0; ii < configToCopy.length; ++ii) {
|
||||
if(zn.endsWith(configToCopy[ii])) {
|
||||
System.out.println(" " + configToCopy[ii] + " -> " + configToCopy[ii]);
|
||||
try(OutputStream oss = new FileOutputStream(new File(mcpDataTMP, configToCopy[ii]))) {
|
||||
IOUtils.copy(is, oss, 32768);
|
||||
}
|
||||
configFound[ii] = true;
|
||||
continue entry_read;
|
||||
}
|
||||
}
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: failed to extract \"" + f.getAbsolutePath() + "\" to \"" + mcpDataTMP.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean err = false;
|
||||
for(int ii = 0; ii < jarsToUnify.length; ++ii) {
|
||||
if(!jarsFound[ii]) {
|
||||
err = true;
|
||||
System.err.println("JAR not found: \"" + jarsToUnify[ii] + "\"!");
|
||||
}
|
||||
}
|
||||
for(int ii = 0; ii < configToCopy.length; ++ii) {
|
||||
if(!configFound[ii]) {
|
||||
err = true;
|
||||
System.err.println("Config not found: \"" + configToCopy[ii] + "\"!");
|
||||
}
|
||||
}
|
||||
|
||||
if(err) {
|
||||
System.err.println("ERROR: Could not extract all required MCP files from \"" + f.getName() + "\"!");
|
||||
return false;
|
||||
}
|
||||
|
||||
CSVMappings mappings = new CSVMappings();
|
||||
|
||||
File srgsOut = new File(mcpDataTMP, "minecraft.srg");
|
||||
if(!GenerateSRGs.generate(mcpDataTMP, srgsOut, mappings)) {
|
||||
System.err.println("ERROR: could not generate joined \"minecraft.srg\" file from conf in \"" + mcpDataTMP.getAbsolutePath() + "\"!");
|
||||
return false;
|
||||
}
|
||||
|
||||
File excsOut = new File(mcpDataTMP, "minecraft.exc");
|
||||
if(!GenerateEXCs.generateEXCs(mcpDataTMP, excsOut, mappings)) {
|
||||
System.err.println("ERROR: could not generate joined \"minecraft.exc\" file from conf in \"" + mcpDataTMP.getAbsolutePath() + "\"!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildTools;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildToolsConfig;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class InitTask {
|
||||
|
||||
private static File locatedMCPZip = null;
|
||||
private static File locatedMinecraftJar = null;
|
||||
private static File locatedAssetsJson = null;
|
||||
|
||||
public static boolean initTask() {
|
||||
try {
|
||||
return initTask0();
|
||||
}catch(Throwable t) {
|
||||
System.err.println();
|
||||
System.err.println("Exception encountered while running task 'init'!");
|
||||
t.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean initTask0() throws Throwable {
|
||||
System.out.println("Scanning 'mcp918' folder...");
|
||||
File mcp918dir = new File(EaglerBuildTools.repositoryRoot, "mcp918");
|
||||
|
||||
if(!mcp918dir.isDirectory()) {
|
||||
System.err.println("ERROR: \"" + mcp918dir.getAbsolutePath() + "\" is not a directory!");
|
||||
return false;
|
||||
}
|
||||
|
||||
for(File f : mcp918dir.listFiles()) {
|
||||
if(f.getName().equalsIgnoreCase("mcp918.zip")) {
|
||||
locatedMCPZip = f;
|
||||
}
|
||||
if(locatedMCPZip == null && f.getName().endsWith(".zip")) {
|
||||
locatedMCPZip = f;
|
||||
}
|
||||
if(f.getName().equalsIgnoreCase("1.8.8.jar")) {
|
||||
locatedMinecraftJar = f;
|
||||
}
|
||||
if(locatedMinecraftJar == null && f.getName().endsWith(".jar")) {
|
||||
locatedMinecraftJar = f;
|
||||
}
|
||||
if(f.getName().equalsIgnoreCase("1.8.json")) {
|
||||
locatedAssetsJson = f;
|
||||
}
|
||||
if(locatedAssetsJson == null && f.getName().endsWith(".json")) {
|
||||
locatedAssetsJson = f;
|
||||
}
|
||||
}
|
||||
|
||||
if(locatedMCPZip == null) {
|
||||
System.err.println("ERROR: could not find ./mcp918/mcp918.zip! Please locate it and copy it into the 'mcp918' folder.");
|
||||
return false;
|
||||
}
|
||||
if(locatedMinecraftJar == null) {
|
||||
locatedMinecraftJar = MinecraftLocator.locateMinecraftVersionJar("1.8.8");
|
||||
if(locatedMinecraftJar == null) {
|
||||
System.err.println("ERROR: could not find ./mcp918/1.8.8.jar! Please locate it and copy it into the 'mcp918' folder.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(locatedAssetsJson == null) {
|
||||
locatedAssetsJson = MinecraftLocator.locateMinecraftVersionAssets("1.8");
|
||||
if(locatedAssetsJson == null) {
|
||||
System.err.println("ERROR: could not find ./mcp918/1.8.json! Please locate it and copy it into the 'mcp918' folder.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
FFMPEG.confirmFFMPEG();
|
||||
|
||||
File buildToolsTmp = EaglerBuildToolsConfig.getTemporaryDirectory();
|
||||
boolean btExist = buildToolsTmp.exists();
|
||||
if(btExist && !(buildToolsTmp.isDirectory() && buildToolsTmp.list().length == 0)) {
|
||||
System.out.println();
|
||||
System.out.println("Notice: BuildTools is already initialized.");
|
||||
System.out.println();
|
||||
System.out.println("you must revert all changes in the 'patches' directory of");
|
||||
System.out.println("this repo back to the main repository's current commits,");
|
||||
System.out.println("otherwise the 'pullrequest' command wll not work properly");
|
||||
System.out.println();
|
||||
System.out.print("Do you want to re-initialize? [Y/n]: ");
|
||||
|
||||
String ret = "n";
|
||||
try {
|
||||
ret = (new BufferedReader(new InputStreamReader(System.in))).readLine();
|
||||
}catch(IOException ex) {
|
||||
// ?
|
||||
}
|
||||
ret = ret.toLowerCase();
|
||||
if(!ret.startsWith("y")) {
|
||||
System.out.println();
|
||||
System.out.println("Ok nice, the re-init will be cancelled. (thank god)");
|
||||
return true;
|
||||
}else {
|
||||
try {
|
||||
FileUtils.deleteDirectory(buildToolsTmp);
|
||||
btExist = false;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: Could not delete \"" + buildToolsTmp.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File mcpDataTMP = new File(buildToolsTmp, "ModCoderPack");
|
||||
if(!mcpDataTMP.isDirectory() && !mcpDataTMP.mkdirs()) {
|
||||
System.err.println("ERROR: failed to create \"" + mcpDataTMP.getAbsolutePath() + "\"!");
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean skipMCP = false;
|
||||
|
||||
if(!skipMCP && !InitMCP.initTask(locatedMCPZip, mcpDataTMP)) {
|
||||
System.err.println("ERROR: could not initialize MCP from \"" + locatedMCPZip.getAbsolutePath() + "\"!");
|
||||
return false;
|
||||
}
|
||||
|
||||
File minecraftSrcTmp = new File(buildToolsTmp, "MinecraftSrc");
|
||||
if(!minecraftSrcTmp.isDirectory() && !minecraftSrcTmp.mkdirs()) {
|
||||
System.err.println("ERROR: failed to create \"" + minecraftSrcTmp.getAbsolutePath() + "\"!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!DecompileMinecraft.decompileMinecraft(mcpDataTMP, locatedMinecraftJar, minecraftSrcTmp, locatedAssetsJson, true)) {
|
||||
System.err.println("ERROR: could not decompile and patch 1.8.8.jar from \"" + locatedMinecraftJar.getAbsolutePath() + "\"!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,389 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildTools;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.diff.Lines;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.CSVMappings.Symbol;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.util.FileReaderUTF;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class InsertJavaDoc {
|
||||
|
||||
public static final String enumImport = "import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;";
|
||||
|
||||
private static final String[] typeModifiersFields = new String[] {
|
||||
"public", "private", "protected", "static",
|
||||
"final", "volatile", "transient"
|
||||
};
|
||||
|
||||
private static boolean isTypeModifierField(String tk) {
|
||||
for(int i = 0; i < typeModifiersFields.length; ++i) {
|
||||
if(typeModifiersFields[i].equals(tk)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static final String[] typeModifiersMethods = new String[] {
|
||||
"public", "private", "protected", "static",
|
||||
"final", "synchronized", "abstract", "default"
|
||||
};
|
||||
|
||||
private static final Pattern illegalCharactersNotATypeName = Pattern.compile("[^a-zA-Z0-9_\\-\\$\\[\\]<>\\.]");
|
||||
|
||||
private static boolean isTypeModifierMethod(String tk) {
|
||||
for(int i = 0; i < typeModifiersMethods.length; ++i) {
|
||||
if(typeModifiersMethods[i].equals(tk)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean processSource(File fileIn, File fileOut, File mcpDataTMP, CSVMappings csv) throws Throwable {
|
||||
return processSource(fileIn, fileOut, mcpDataTMP, csv, true);
|
||||
}
|
||||
|
||||
public static boolean processSource(File fileIn, File fileOut, File mcpDataTMP, CSVMappings csv, boolean compress) throws Throwable {
|
||||
System.out.println("Adding javadoc...");
|
||||
|
||||
if(csv == null) {
|
||||
System.out.println("(writing enums only, skipping field/method annotations)");
|
||||
}
|
||||
|
||||
//RealOpenGLEnums.initEnums();
|
||||
//System.out.println("Loaded " + RealOpenGLEnums.enumNames.size() + " OpenGL enums");
|
||||
|
||||
List<String> copyrightComment = null;
|
||||
try(BufferedReader is = new BufferedReader(new FileReaderUTF(new File(EaglerBuildTools.repositoryRoot, "patches/minecraft/output_license.txt")))) {
|
||||
copyrightComment = new ArrayList();
|
||||
copyrightComment.add("/**+");
|
||||
String ln;
|
||||
while((ln = is.readLine()) != null) {
|
||||
copyrightComment.add(" * " + ln);
|
||||
}
|
||||
copyrightComment.add(" * ");
|
||||
copyrightComment.add(" */");
|
||||
}
|
||||
|
||||
Map<String, List<Symbol>> methodsInClasses = new HashMap();
|
||||
Map<String, List<Symbol>> fieldsInClasses = new HashMap();
|
||||
|
||||
if(csv != null) {
|
||||
File methodsCSV = new File(mcpDataTMP, "methods.csv");
|
||||
try(FileReaderUTF fr = new FileReaderUTF(methodsCSV)) {
|
||||
csv.loadMethodsFile(fr);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: failed to read \"" + methodsCSV.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
File fieldsCSV = new File(mcpDataTMP, "fields.csv");
|
||||
try(FileReaderUTF fr = new FileReaderUTF(fieldsCSV)) {
|
||||
csv.loadFieldsFile(fr);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: failed to read \"" + fieldsCSV.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
try(BufferedReader is = new BufferedReader(new FileReaderUTF(new File(mcpDataTMP, "joined.srg")))) {
|
||||
String s;
|
||||
while((s = is.readLine()) != null) {
|
||||
if(s.startsWith("MD:")) {
|
||||
s = s.trim();
|
||||
int idxx = s.lastIndexOf(' ');
|
||||
int idxx2 = s.lastIndexOf(' ', idxx - 1);
|
||||
s = s.substring(idxx2 + 1, idxx);
|
||||
idxx = s.lastIndexOf('/');
|
||||
String s1 = s.substring(0, idxx);
|
||||
String s2 = s.substring(idxx + 1);
|
||||
Symbol sm = csv.csvMethodsMappings.get(s2);
|
||||
if(sm != null && sm.comment != null && sm.comment.length() > 0) {
|
||||
List<Symbol> sbls = methodsInClasses.get(s1);
|
||||
if(sbls == null) {
|
||||
methodsInClasses.put(s1, sbls = new ArrayList());
|
||||
}
|
||||
sbls.add(sm);
|
||||
}
|
||||
}else if(s.startsWith("FD:")) {
|
||||
s = s.trim();
|
||||
int idxx = s.lastIndexOf(' ');
|
||||
s = s.substring(idxx + 1);
|
||||
idxx = s.lastIndexOf('/');
|
||||
String s1 = s.substring(0, idxx);
|
||||
String s2 = s.substring(idxx + 1);
|
||||
Symbol sm = csv.csvFieldsMappings.get(s2);
|
||||
if(sm != null && sm.comment != null && sm.comment.length() > 0) {
|
||||
List<Symbol> sbls = fieldsInClasses.get(s1);
|
||||
if(sbls == null) {
|
||||
fieldsInClasses.put(s1, sbls = new ArrayList());
|
||||
}
|
||||
sbls.add(sm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OpenGLEnumManager.loadEnumMap();
|
||||
|
||||
System.out.print(" ");
|
||||
int xt = 0;
|
||||
int modm = 0;
|
||||
int modf = 0;
|
||||
final int[] enums = new int[1];
|
||||
|
||||
Consumer<Integer> enumCounter = new Consumer<Integer>() {
|
||||
@Override
|
||||
public void accept(Integer t) {
|
||||
enums[0] += t.intValue();
|
||||
}
|
||||
};
|
||||
|
||||
try(ZipInputStream jarIn = new ZipInputStream(new FileInputStream(fileIn));
|
||||
ZipOutputStream jarOut = new ZipOutputStream(new FileOutputStream(fileOut))) {
|
||||
jarOut.setLevel(compress ? 5 : 0);
|
||||
jarOut.putNextEntry(new ZipEntry("META-INF/MANIFEST.MF"));
|
||||
jarOut.write("Manifest-Version: 1.0\nCreated-By: Eaglercraft BuildTools\n".getBytes(StandardCharsets.UTF_8));
|
||||
ZipEntry et;
|
||||
String nm;
|
||||
while((et = jarIn.getNextEntry()) != null) {
|
||||
if(et.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
nm = et.getName();
|
||||
if(nm.endsWith(".java")) {
|
||||
String fs = IOUtils.toString(jarIn, "UTF-8");
|
||||
List<String> linesLst = new ArrayList();
|
||||
linesLst.addAll(Lines.linesList(fs));
|
||||
if(copyrightComment != null) {
|
||||
for(int i = 0; i < linesLst.size(); ++i) {
|
||||
String ln = linesLst.get(i);
|
||||
if(!ln.startsWith("import")) {
|
||||
if(ln.startsWith("public")) {
|
||||
ln = ln.substring(6).trim();
|
||||
}
|
||||
if(ln.startsWith("class") || ln.startsWith("enum") || ln.startsWith("interface") || ln.startsWith("@interface")) {
|
||||
linesLst.addAll(i, copyrightComment);
|
||||
i += copyrightComment.size();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String cnm = nm.substring(0, nm.length() - 5);
|
||||
List<Symbol> meths = csv == null ? null : methodsInClasses.get(cnm);
|
||||
List<Symbol> fields = csv == null ? null : fieldsInClasses.get(cnm);
|
||||
if(meths != null || fields != null) {
|
||||
for(int i = 0; i < linesLst.size(); ++i) {
|
||||
String ln2 = linesLst.get(i);
|
||||
boolean notMethod = ln2.endsWith(";");
|
||||
String ln = ln2;
|
||||
String indent = "";
|
||||
while(ln.length() > 0 && Character.isWhitespace(ln.charAt(0))) {
|
||||
indent += ln.charAt(0);
|
||||
ln = ln.substring(1);
|
||||
}
|
||||
String[] tokens = ln.split("\\s+");
|
||||
boolean hasTypeDecl = false;
|
||||
boolean hasMethodDecl = false;
|
||||
boolean hasType = false;
|
||||
for(int j = 0; j < tokens.length; ++j) {
|
||||
if(tokens[j].length() > 0) {
|
||||
boolean b1 = false;
|
||||
boolean b2 = false;
|
||||
if(isTypeModifierField(tokens[j])) {
|
||||
b1 = true;
|
||||
hasTypeDecl = true;
|
||||
}
|
||||
if(!notMethod && isTypeModifierMethod(tokens[j])) {
|
||||
b2 = true;
|
||||
hasMethodDecl = true;
|
||||
}
|
||||
if(b1 || b2) {
|
||||
continue;
|
||||
}else if(!hasType) {
|
||||
if(illegalCharactersNotATypeName.matcher(tokens[j]).find()) {
|
||||
break;
|
||||
}else {
|
||||
hasType = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
int idx = 0;
|
||||
if(hasTypeDecl && j < tokens.length - 1 && tokens[j + 1].equals("=")) {
|
||||
if(fields != null) {
|
||||
for(int k = 0, l = fields.size(); k < l; ++k) {
|
||||
Symbol ss = fields.get(k);
|
||||
if(ss.name.equals(tokens[j])) {
|
||||
List<String> lines = wordWrapComment(ss.comment, indent);
|
||||
linesLst.addAll(i, lines);
|
||||
i += lines.size();
|
||||
++modf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}else if(((idx = tokens[j].indexOf('(')) != -1 && j > 0) || hasMethodDecl) {
|
||||
if(meths != null) {
|
||||
if(idx > 0) {
|
||||
String sss = tokens[j].substring(0, idx);
|
||||
for(int k = 0, l = meths.size(); k < l; ++k) {
|
||||
Symbol ss = meths.get(k);
|
||||
if(ss.name.equals(sss)) {
|
||||
List<String> lines = wordWrapComment(ss.comment, indent);
|
||||
linesLst.addAll(i, lines);
|
||||
i += lines.size();
|
||||
++modm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int cnt0 = enums[0];
|
||||
for(int i = 0, l = linesLst.size(); i < l; ++i) {
|
||||
linesLst.set(i, OpenGLEnumManager.insertIntoLine(linesLst.get(i), enumCounter));
|
||||
}
|
||||
|
||||
if(cnt0 != enums[0]) {
|
||||
for(int i = 0, l = linesLst.size(); i < l; ++i) {
|
||||
String line = linesLst.get(i);
|
||||
if(line.startsWith("package")) {
|
||||
linesLst.addAll(i + 1, Arrays.asList("", enumImport));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ZipEntry z2 = new ZipEntry(nm);
|
||||
jarOut.putNextEntry(z2);
|
||||
IOUtils.write(String.join(System.lineSeparator(), linesLst), jarOut, "UTF-8");
|
||||
++xt;
|
||||
if(xt % 75 == 74) {
|
||||
System.out.print(".");
|
||||
}
|
||||
}else {
|
||||
if(!nm.startsWith("META-INF")) {
|
||||
ZipEntry z2 = new ZipEntry(nm);
|
||||
jarOut.putNextEntry(z2);
|
||||
IOUtils.copy(jarIn, jarOut, 4096);
|
||||
}
|
||||
}
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Failed to process jar '" + fileIn.getName() + "' and write it to '" + fileOut.getName() + "!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Added " + enums[0] + " OpenGL enums");
|
||||
if(csv != null) {
|
||||
System.out.println("Added " + modm + " comments to methods");
|
||||
System.out.println("Added " + modf + " comments to fields");
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static List<String> wordWrapComment(String strIn, String indent) {
|
||||
String[] wds = strIn.split("\\s+");
|
||||
List<String> ret = new ArrayList();
|
||||
ret.add(indent + "/**+");
|
||||
String ln = "";
|
||||
for(int i = 0; i < wds.length; ++i) {
|
||||
if(ln.length() > 0 && wds[i].length() + ln.length() > 60) {
|
||||
ret.add(indent + " * " + ln);
|
||||
ln = "";
|
||||
}
|
||||
ln += ln.length() > 0 ? " " + wds[i] : wds[i];
|
||||
}
|
||||
if(ln.length() > 0) {
|
||||
ret.add(indent + " * " + ln);
|
||||
}
|
||||
ret.add(indent + " */");
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static String stripDocForDiff(String fileIn) {
|
||||
List<String> linesIn = Lines.linesList(fileIn);
|
||||
OpenGLEnumManager.loadEnumMap();
|
||||
List<String> linesOut = new ArrayList();
|
||||
boolean addOpenGLImport = false;
|
||||
for(int i = 0, l = linesIn.size(); i < l; ++i) {
|
||||
String line = linesIn.get(i);
|
||||
if(line.trim().startsWith("/**+")) {
|
||||
for(; i < l; ++i) {
|
||||
if(linesIn.get(i).endsWith("*/")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else {
|
||||
String line2 = OpenGLEnumManager.stripFromLine(line);
|
||||
if(line2 != null) {
|
||||
linesOut.add(line2);
|
||||
addOpenGLImport = true;
|
||||
}else {
|
||||
linesOut.add(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(addOpenGLImport) {
|
||||
int idx = linesOut.indexOf(enumImport);
|
||||
if(idx != -1) {
|
||||
if(idx - 1 >= 0 && linesOut.get(idx - 1).trim().length() == 0 && linesOut.size() > 1) {
|
||||
idx -= 1;
|
||||
linesOut.remove(idx);
|
||||
linesOut.remove(idx);
|
||||
}else {
|
||||
linesOut.remove(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return String.join(System.lineSeparator(), linesOut);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Iterator;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildTools;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class LoadResources {
|
||||
|
||||
public static boolean loadResources(File minecraftJarIn, File assetsIndexIn, File assetsJarOut, File tmpDir, File languagesZipOut) {
|
||||
System.out.println("Copying resources from '" + minecraftJarIn.getName() + "' into '" + assetsJarOut.getName() + "'");
|
||||
try(ZipOutputStream os = new ZipOutputStream(new FileOutputStream(assetsJarOut))) {
|
||||
os.setLevel(5);
|
||||
os.putNextEntry(new ZipEntry("META-INF/MANIFEST.MF"));
|
||||
os.write("Manifest-Version: 1.0\nCreated-By: Eaglercraft BuildTools\n".getBytes(StandardCharsets.UTF_8));
|
||||
try(ZipInputStream is = new ZipInputStream(new FileInputStream(minecraftJarIn))) {
|
||||
ZipEntry e;
|
||||
while((e = is.getNextEntry()) != null) {
|
||||
if(e.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
String zn = e.getName();
|
||||
if(zn.startsWith("/")) {
|
||||
zn = zn.substring(1);
|
||||
}
|
||||
if(zn.startsWith("META-INF") || zn.endsWith(".class")) {
|
||||
continue;
|
||||
}
|
||||
os.putNextEntry(e);
|
||||
IOUtils.copy(is, os, 4096);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Reading 'assetsIndexTransformer.json'...");
|
||||
|
||||
ResourceRulesList rules;
|
||||
|
||||
try {
|
||||
rules = ResourceRulesList.loadResourceRules(new File(EaglerBuildTools.repositoryRoot, "mcp918/assetsIndexTransformer.json"));
|
||||
}catch(IOException ex) {
|
||||
System.err.println();
|
||||
System.err.println("ERROR: failed to read 'mcp918/assetsIndexTransformer.json'!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Reading asset index '" + assetsIndexIn.getAbsolutePath() + "'...");
|
||||
|
||||
try(ZipOutputStream os2 = new ZipOutputStream(new FileOutputStream(languagesZipOut))) {
|
||||
os2.setLevel(5);
|
||||
|
||||
try {
|
||||
JSONObject json = (new JSONObject(FileUtils.readFileToString(assetsIndexIn, StandardCharsets.UTF_8))).getJSONObject("objects");
|
||||
Iterator<String> itr = json.keys();
|
||||
|
||||
System.out.println("Downloading assets from 'https://resources.download.minecraft.net/'...");
|
||||
|
||||
while(itr.hasNext()) {
|
||||
String name = itr.next();
|
||||
JSONObject obj = json.getJSONObject(name);
|
||||
|
||||
|
||||
ResourceRulesList.ResourceRule r = rules.get(name);
|
||||
if(r.action == ResourceRulesList.Action.EXCLUDE) {
|
||||
System.out.println("Skipping file '" + name + "'");
|
||||
continue;
|
||||
}
|
||||
|
||||
String hash = obj.getString("hash");
|
||||
int len = obj.getInt("size");
|
||||
|
||||
System.out.println("Downloading '" + name + "' (" + formatByteLength(len) + ") ...");
|
||||
|
||||
URL url;
|
||||
try {
|
||||
url = new URL("https://resources.download.minecraft.net/" + hash.substring(0, 2) + "/" + hash);
|
||||
}catch(MalformedURLException ex) {
|
||||
System.err.println("Resource file '" + name + "' had an invalid URL!");
|
||||
ex.printStackTrace();
|
||||
continue;
|
||||
}
|
||||
|
||||
byte[] downloadedFile = new byte[len];
|
||||
|
||||
try(InputStream is = url.openStream()) {
|
||||
int dl = 0;
|
||||
int i = 0;
|
||||
while(dl != len && (i = is.read(downloadedFile, dl, len - dl)) > 0) {
|
||||
dl += i;
|
||||
}
|
||||
int a = is.available();
|
||||
if(dl != len || a > 0) {
|
||||
throw new IOException("File '" + url.toString() + "' was the wrong length! " + (a > 0 ? "" + a + " bytes remaining" : "" + (len - dl) + " bytes missing"));
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Resource file '" + url.toString() + "' could not be downloaded!");
|
||||
ex.printStackTrace();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(r.action == ResourceRulesList.Action.ENCODE) {
|
||||
try {
|
||||
System.out.println(" - encoding ogg: " + (r.ffmpegSamples / 1000) + "kHz, " + r.ffmpegBitrate + "kbps, " + (r.ffmpegStereo ? "stereo" : "mono"));
|
||||
downloadedFile = FFMPEG.encodeOgg(tmpDir, downloadedFile, r.ffmpegSamples, r.ffmpegBitrate, r.ffmpegStereo);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Resource file '" + name + "' could not be encoded!");
|
||||
ex.printStackTrace();
|
||||
continue;
|
||||
}
|
||||
}else if(r.action == ResourceRulesList.Action.LANGUAGES_ZIP) {
|
||||
int j = name.lastIndexOf('/');
|
||||
if(j != -1) {
|
||||
name = name.substring(j + 1);
|
||||
}
|
||||
System.out.println(" - writing language '" + name + "' to '" + languagesZipOut.getName() + "'");
|
||||
os2.putNextEntry(new ZipEntry(name));
|
||||
os2.write(downloadedFile);
|
||||
continue;
|
||||
}
|
||||
|
||||
os.putNextEntry(new ZipEntry("assets/" + name));
|
||||
os.write(downloadedFile);
|
||||
}
|
||||
}catch(IOException | JSONException ex) {
|
||||
System.err.println("ERROR: failed to download additional assets from '" + assetsIndexIn.getName() + "'!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: failed to copy from '" + minecraftJarIn.getName() + "' -> '" +assetsJarOut.getName() + "'!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static String formatByteLength(int len) {
|
||||
if(len < 4096) {
|
||||
return "" + len;
|
||||
}else if(len < 1024 * 4096) {
|
||||
return "" + (len / 1024) + "k";
|
||||
}else {
|
||||
return "" + (len / 1024 / 1024) + "M";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class MinecraftLocator {
|
||||
|
||||
private static boolean hasTriedToFind = false;
|
||||
private static File directory = null;
|
||||
|
||||
private static File locateOrCopyFile(String name, String copyPath) {
|
||||
File f = new File("./mcp918/" + name);
|
||||
if(f.isFile()) {
|
||||
return f;
|
||||
}
|
||||
if(!hasTriedToFind) {
|
||||
hasTriedToFind = true;
|
||||
String var0 = System.getProperty("os.name").toLowerCase();
|
||||
if(var0.contains("win")) {
|
||||
String ad = System.getenv("APPDATA");
|
||||
if(ad != null) {
|
||||
directory = new File(ad, ".minecraft");
|
||||
}else {
|
||||
directory = new File(System.getProperty("user.home"), ".minecraft");
|
||||
}
|
||||
}else if(var0.contains("mac")) {
|
||||
directory = new File(System.getProperty("user.home"), "Library/Application Support/minecraft");
|
||||
}else {
|
||||
directory = new File(System.getProperty("user.home"), ".minecraft");
|
||||
}
|
||||
if(!directory.isDirectory()) {
|
||||
directory = new File(System.getProperty("user.home"), "minecraft");
|
||||
if(!directory.isDirectory()) {
|
||||
directory = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(directory == null) {
|
||||
return null;
|
||||
}else {
|
||||
File f2 = new File(directory, copyPath);
|
||||
if(f2.isFile()) {
|
||||
try {
|
||||
System.out.println("Copying '" + copyPath + "' from your .minecraft directory into './mcp918'...");
|
||||
FileUtils.copyFile(f2, f, true);
|
||||
return f;
|
||||
} catch (IOException e) {
|
||||
System.err.println("ERROR: failed to copy '" + copyPath + "' from your .minecraft directory into './mcp918'!");
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static File locateMinecraftVersionJar(String name) {
|
||||
return locateOrCopyFile(name + ".jar", "versions/" + name + "/" + name + ".jar");
|
||||
}
|
||||
|
||||
public static File locateMinecraftVersionAssets(String name) {
|
||||
return locateOrCopyFile(name + ".json", "assets/indexes/" + name + ".json");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,228 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class OpenGLEnumManager {
|
||||
|
||||
private static boolean hasLoaded = false;
|
||||
public static final Set<String> classNames = new HashSet();
|
||||
public static final Map<String,String> enumsForGLStateManager = new HashMap();
|
||||
public static final Map<String,Map<Integer,String>> enumsForFunctionKV = new HashMap();
|
||||
public static final Map<String,Map<String,Integer>> enumsForFunctionVK = new HashMap();
|
||||
|
||||
public static boolean loadEnumMap() {
|
||||
if(hasLoaded) {
|
||||
return true;
|
||||
}
|
||||
hasLoaded = true;
|
||||
try {
|
||||
|
||||
String enumsPath = "/lang/enums.json";
|
||||
System.out.println("Loading OpenGL enums: " + enumsPath);
|
||||
|
||||
int fcnt = 0;
|
||||
int ecnt = 0;
|
||||
|
||||
String jsonData;
|
||||
try(InputStream is = OpenGLEnumManager.class.getResourceAsStream(enumsPath)) {
|
||||
if(is == null) {
|
||||
throw new FileNotFoundException("classpath:/" + enumsPath);
|
||||
}
|
||||
jsonData = IOUtils.toString(is, "UTF-8");
|
||||
}
|
||||
|
||||
JSONArray enumJSON = (new JSONObject(jsonData)).getJSONArray("enums");
|
||||
for(Object o : enumJSON.toList()) {
|
||||
List<Object> enumData = (List<Object>) o;
|
||||
|
||||
List<String> functionsToAdd = new ArrayList();
|
||||
Map<Integer,String> enumsToAddKV = new HashMap();
|
||||
Map<String,Integer> enumsToAddVK = new HashMap();
|
||||
|
||||
Map<String,Object> functionSet = (Map<String,Object>)enumData.get(0);
|
||||
|
||||
for(Entry<String,Object> etr : functionSet.entrySet()) {
|
||||
classNames.add(etr.getKey());
|
||||
List<Object> functionArr = (List<Object>)etr.getValue();
|
||||
for(Object func : functionArr) {
|
||||
functionsToAdd.add(etr.getKey() + "." + (String)func);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String,Object> enumSet = (Map<String,Object>)enumData.get(1);
|
||||
|
||||
for(Entry<String,Object> etr : enumSet.entrySet()) {
|
||||
Map<String,Object> enumEnums = (Map<String,Object>)etr.getValue();
|
||||
for(Entry<String,Object> etr2 : enumEnums.entrySet()) {
|
||||
Integer intg = Integer.parseInt(etr2.getKey());
|
||||
enumsToAddKV.put(intg, (String)etr2.getValue());
|
||||
enumsToAddVK.put((String)etr2.getValue(), intg);
|
||||
++ecnt;
|
||||
}
|
||||
}
|
||||
|
||||
for(String fn : functionsToAdd) {
|
||||
if(!enumsForFunctionKV.containsKey(fn)) {
|
||||
++fcnt;
|
||||
enumsForFunctionKV.put(fn, enumsToAddKV);
|
||||
enumsForFunctionVK.put(fn, enumsToAddVK);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
String glStateEnumsPath = "/lang/statemgr.json";
|
||||
System.out.println("Loading OpenGL enums: " + glStateEnumsPath);
|
||||
|
||||
try(InputStream is = OpenGLEnumManager.class.getResourceAsStream(glStateEnumsPath)) {
|
||||
if(is == null) {
|
||||
throw new FileNotFoundException("classpath:/" + glStateEnumsPath);
|
||||
}
|
||||
jsonData = IOUtils.toString(is, "UTF-8");
|
||||
}
|
||||
|
||||
JSONObject enumStateJSON = (new JSONObject(jsonData)).getJSONObject("statemgr_mappings");
|
||||
for(Entry<String,Object> etr : enumStateJSON.toMap().entrySet()) {
|
||||
String f = etr.getKey();
|
||||
String m = (String)etr.getValue();
|
||||
enumsForGLStateManager.put(f, m);
|
||||
if(!enumsForFunctionKV.containsKey(f) && enumsForFunctionKV.containsKey(m)) {
|
||||
enumsForFunctionKV.put(f, enumsForFunctionKV.get(m));
|
||||
enumsForFunctionVK.put(f, enumsForFunctionVK.get(m));
|
||||
++fcnt;
|
||||
}
|
||||
}
|
||||
|
||||
for(String str : enumsForGLStateManager.keySet()) {
|
||||
int idx = str.indexOf('.');
|
||||
if(idx != -1) {
|
||||
classNames.add(str.substring(0, idx));
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Loaded " + ecnt + " enums for " + fcnt + " functions");
|
||||
|
||||
return true;
|
||||
}catch(Throwable ex) {
|
||||
System.err.println("ERROR: could not load opengl enum map!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static String insertIntoLine(String input, Consumer<Integer> progressCallback) {
|
||||
int idx1 = input.indexOf('.');
|
||||
if(idx1 != -1) {
|
||||
String pfx = input.substring(0, idx1);
|
||||
String p2 = pfx.trim();
|
||||
if(classNames.contains(p2)) {
|
||||
String fn = input.substring(idx1 + 1);
|
||||
int idx2 = fn.indexOf('(');
|
||||
if(idx2 != -1) {
|
||||
String argz = fn.substring(idx2 + 1);
|
||||
fn = fn.substring(0, idx2);
|
||||
int idx3 = argz.lastIndexOf(')');
|
||||
String pofx = "";
|
||||
if(idx3 == -1) {
|
||||
idx3 = argz.length();
|
||||
}else {
|
||||
pofx = argz.substring(idx3);
|
||||
}
|
||||
Map<Integer,String> repValues = enumsForFunctionKV.get(p2 + "." + fn);
|
||||
if(repValues != null) {
|
||||
argz = argz.substring(0, idx3);
|
||||
String[] args = argz.split(", ");
|
||||
int cnt = 0;
|
||||
for(int i = 0; i < args.length; ++i) {
|
||||
Integer j;
|
||||
try {
|
||||
j = Integer.valueOf(args[i]);
|
||||
}catch(NumberFormatException ex) {
|
||||
continue;
|
||||
}
|
||||
String estr = repValues.get(j);
|
||||
if(estr != null) {
|
||||
args[i] = estr;
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
if(cnt > 0) {
|
||||
input = pfx + "." + fn + "(" + String.join(", ", args) + pofx;
|
||||
if(progressCallback != null) {
|
||||
progressCallback.accept(cnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
public static String stripFromLine(String input) {
|
||||
int idx1 = input.indexOf('.');
|
||||
if(idx1 != -1) {
|
||||
String pfx = input.substring(0, idx1);
|
||||
String p2 = pfx.trim();
|
||||
if(classNames.contains(p2)) {
|
||||
String fn = input.substring(idx1 + 1);
|
||||
int idx2 = fn.indexOf('(');
|
||||
if(idx2 != -1) {
|
||||
String argz = fn.substring(idx2 + 1);
|
||||
fn = fn.substring(0, idx2);
|
||||
int idx3 = argz.lastIndexOf(')');
|
||||
String pofx = "";
|
||||
if(idx3 == -1) {
|
||||
idx3 = argz.length();
|
||||
}else {
|
||||
pofx = argz.substring(idx3);
|
||||
}
|
||||
Map<String,Integer> repValues = enumsForFunctionVK.get(p2 + "." + fn);
|
||||
if(repValues != null) {
|
||||
argz = argz.substring(0, idx3);
|
||||
String[] args = argz.split(", ");
|
||||
int cnt = 0;
|
||||
for(int i = 0; i < args.length; ++i) {
|
||||
Integer estr = repValues.get(args[i]);
|
||||
if(estr != null) {
|
||||
args[i] = estr.toString();
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
if(cnt > 0) {
|
||||
return pfx + "." + fn + "(" + String.join(", ", args) + pofx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class ResourceRulesList {
|
||||
|
||||
public static ResourceRulesList loadResourceRules(File conf) throws IOException {
|
||||
List<ResourceRule> list = new ArrayList();
|
||||
|
||||
try {
|
||||
JSONArray rulesArray = new JSONObject(FileUtils.readFileToString(conf, StandardCharsets.UTF_8)).getJSONArray("rules");
|
||||
for(int i = 0, l = rulesArray.length(); i < l; ++i) {
|
||||
JSONObject obj = rulesArray.getJSONObject(i);
|
||||
|
||||
Iterator<String> itr = obj.keys();
|
||||
while(itr.hasNext()) {
|
||||
String name = itr.next();
|
||||
JSONObject a = obj.getJSONObject(name);
|
||||
boolean wildcard = name.endsWith("*");
|
||||
|
||||
if(wildcard) {
|
||||
name = name.substring(0, name.length() - 1);
|
||||
}
|
||||
|
||||
Action action = Action.valueOf(a.getString("action").toUpperCase());
|
||||
|
||||
int ffmpegSamples = 16000;
|
||||
int ffmpegBitrate = 48;
|
||||
boolean ffmpegStereo = false;
|
||||
|
||||
if(action == Action.ENCODE) {
|
||||
JSONObject ffmpegObj = a.optJSONObject("ffmpeg", null);
|
||||
if(ffmpegObj != null) {
|
||||
ffmpegSamples = ffmpegObj.optInt("samples", ffmpegSamples);
|
||||
ffmpegBitrate = ffmpegObj.optInt("bitrate", ffmpegBitrate);
|
||||
ffmpegStereo = ffmpegObj.optBoolean("stereo", ffmpegStereo);
|
||||
}
|
||||
}
|
||||
|
||||
list.add(new ResourceRule(name, wildcard, action, ffmpegSamples, ffmpegBitrate, ffmpegStereo));
|
||||
}
|
||||
}
|
||||
}catch(JSONException ex) {
|
||||
throw new IOException("Invalid JSON file: " + conf.getAbsolutePath(), ex);
|
||||
}
|
||||
|
||||
return new ResourceRulesList(list);
|
||||
}
|
||||
|
||||
private final List<ResourceRule> list;
|
||||
|
||||
private ResourceRulesList(List<ResourceRule> list) {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
public ResourceRule get(String str) {
|
||||
|
||||
for(int i = 0, l = list.size(); i < l; ++i) {
|
||||
ResourceRule r = list.get(i);
|
||||
if(r.wildcard) {
|
||||
if(str.startsWith(r.path)) {
|
||||
return r;
|
||||
}
|
||||
}else {
|
||||
if(str.equals(r.path)) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return defaultRule;
|
||||
}
|
||||
|
||||
private static final ResourceRule defaultRule = new ResourceRule("", true, Action.EXCLUDE, 16000, 48, false);
|
||||
|
||||
public static class ResourceRule {
|
||||
|
||||
private final String path;
|
||||
private final boolean wildcard;
|
||||
public final Action action;
|
||||
|
||||
public final int ffmpegSamples;
|
||||
public final int ffmpegBitrate;
|
||||
public final boolean ffmpegStereo;
|
||||
|
||||
protected ResourceRule(String path, boolean wildcard, Action action, int ffmpegSamples, int ffmpegBitrate,
|
||||
boolean ffmpegStereo) {
|
||||
this.path = path;
|
||||
this.wildcard = wildcard;
|
||||
this.action = action;
|
||||
this.ffmpegSamples = ffmpegSamples;
|
||||
this.ffmpegBitrate = ffmpegBitrate;
|
||||
this.ffmpegStereo = ffmpegStereo;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static enum Action {
|
||||
INCLUDE, EXCLUDE, ENCODE, LANGUAGES_ZIP
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,396 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildToolsConfig;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.diff.ApplyPatchesToZip;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class SetupWorkspace {
|
||||
|
||||
public static boolean setupWorkspace() {
|
||||
return setupWorkspace0(false);
|
||||
}
|
||||
|
||||
public static boolean pullRequestTest() {
|
||||
return setupWorkspace0(true);
|
||||
}
|
||||
|
||||
private static boolean setupWorkspace0(boolean applyPullRequest) {
|
||||
File tmp = EaglerBuildToolsConfig.getTemporaryDirectory();
|
||||
File dst = EaglerBuildToolsConfig.getWorkspaceDirectory();
|
||||
try {
|
||||
return setupWorkspace1(tmp, dst, applyPullRequest);
|
||||
}catch(Throwable t) {
|
||||
System.err.println();
|
||||
if(applyPullRequest) {
|
||||
System.err.println("Exception encountered while running task 'pullrequest_test'!");
|
||||
}else {
|
||||
System.err.println("Exception encountered while running task 'workspace'!");
|
||||
}
|
||||
t.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean setupWorkspace1(File btTmpDirectory, File workspaceDirectory, boolean applyPullRequest) throws Throwable {
|
||||
|
||||
boolean wsExist = workspaceDirectory.exists();
|
||||
if(wsExist && !(workspaceDirectory.isDirectory() && workspaceDirectory.list().length == 0)) {
|
||||
System.err.println();
|
||||
System.err.println("WARNING: A workspace already exists in \"" + workspaceDirectory.getAbsolutePath() + "\"!");
|
||||
System.err.println();
|
||||
System.err.println("Any changes you've made to the code will be lost!");
|
||||
System.err.println();
|
||||
System.out.print("Do you want to reset the workspace? [Y/n]: ");
|
||||
|
||||
String ret = "n";
|
||||
try {
|
||||
ret = (new BufferedReader(new InputStreamReader(System.in))).readLine();
|
||||
}catch(IOException ex) {
|
||||
// ?
|
||||
}
|
||||
ret = ret.toLowerCase();
|
||||
if(!ret.startsWith("y")) {
|
||||
System.out.println();
|
||||
System.out.println("Ok nice, the workspace folder will not be reset. (thank god)");
|
||||
System.out.println();
|
||||
System.out.println("Edit 'buildtools_config.json' to set up a different workspace folder");
|
||||
return true;
|
||||
}else {
|
||||
try {
|
||||
FileUtils.deleteDirectory(workspaceDirectory);
|
||||
wsExist = false;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: Could not delete \"" + workspaceDirectory.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File mcTmpDirectory = new File(btTmpDirectory, "MinecraftSrc");
|
||||
File minecraftResJar = new File(mcTmpDirectory, "minecraft_res_patch.jar");
|
||||
File minecraftJavadocTmp = new File(mcTmpDirectory, "minecraft_src_javadoc.jar");
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Setting up dev workspace in \"" + workspaceDirectory.getAbsolutePath() + "\"...");
|
||||
System.out.println();
|
||||
|
||||
if(!workspaceDirectory.isDirectory() && !workspaceDirectory.mkdirs()) {
|
||||
System.err.println("ERROR: could not create \"" + workspaceDirectory.getAbsolutePath() + "\"!");
|
||||
throw new IOException("Could not create \"" + workspaceDirectory.getAbsolutePath() + "\"!");
|
||||
}
|
||||
|
||||
if(!minecraftJavadocTmp.isFile()) {
|
||||
System.err.println("ERROR: could not find 'minecraft_src_javadoc.jar' in your current temporary directory!");
|
||||
System.err.println("Run the 'init' command again to generate it");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!minecraftResJar.isFile()) {
|
||||
System.err.println("ERROR: could not find 'minecraft_res_patch.jar' in your current temporary directory!");
|
||||
System.err.println("Run the 'init' command again to generate it");
|
||||
return false;
|
||||
}
|
||||
|
||||
File repoSources = new File("./sources");
|
||||
File repoSourcesSetup = new File(repoSources, "setup/workspace_template");
|
||||
File repoSourcesGame = new File(repoSources, "main/java");
|
||||
File repoSourcesTeaVM = new File(repoSources, "teavm/java");
|
||||
File repoSourcesLWJGL = new File(repoSources, "lwjgl/java");
|
||||
File repoSourcesResources = new File(repoSources, "resources");
|
||||
File srcMainJava = new File(workspaceDirectory, "src/main/java");
|
||||
File srcLWJGLJava = new File(workspaceDirectory, "src/lwjgl/java");
|
||||
File srcTeaVMJava = new File(workspaceDirectory, "src/teavm/java");
|
||||
File resourcesExtractTo = new File(workspaceDirectory, "desktopRuntime/resources");
|
||||
File mcLanguagesZip = new File(mcTmpDirectory, "minecraft_languages.zip");
|
||||
File mcLanguagesExtractTo = new File(workspaceDirectory, "javascript/lang");
|
||||
|
||||
System.out.println("Copying files from \"/setup/workspace_template/\" to \"" + workspaceDirectory.getName() + "\"...");
|
||||
|
||||
try {
|
||||
FileUtils.copyDirectory(repoSourcesSetup, workspaceDirectory);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: could not copy \"/setup/workspace_template/\" to \"" + workspaceDirectory.getAbsolutePath() + "\"!");
|
||||
throw ex;
|
||||
}
|
||||
|
||||
String os = System.getProperty("os.name").toLowerCase();
|
||||
if(os.contains("linux") || os.contains("macos") || os.contains("osx")) {
|
||||
File gradleW = new File(workspaceDirectory, "gradlew");
|
||||
if(!gradleW.setExecutable(true)) {
|
||||
System.err.println("ERROR: could not set executable bit on 'gradlew'!");
|
||||
System.err.println("Enter the root directory of the repository and run 'chmod +x gradlew' if you need access to the gradlew command");
|
||||
}
|
||||
}
|
||||
|
||||
File existingGi = new File(workspaceDirectory, ".gitignore");
|
||||
if((existingGi.exists() && !existingGi.delete()) || !(new File(workspaceDirectory, ".gitignore.default").renameTo(existingGi))) {
|
||||
System.err.println("ERROR: Could not rename \".gitignore.default\" to \".gitignore\" in the workspace directory!");
|
||||
}
|
||||
|
||||
if(repoSourcesTeaVM.isDirectory()) {
|
||||
System.out.println("Copying files from \"/sources/teavm/java/\" to workspace...");
|
||||
|
||||
try {
|
||||
if(!srcTeaVMJava.isDirectory() && !srcTeaVMJava.mkdirs()) {
|
||||
System.err.println("ERROR: Could not create destination directory!");
|
||||
return false;
|
||||
}
|
||||
FileUtils.copyDirectory(repoSourcesTeaVM, srcTeaVMJava);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: could not copy \"/sources/teavm/java/\" to \"" + srcTeaVMJava.getAbsolutePath() + "\"!");
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Copying files from \"/sources/main/java/\" to workspace...");
|
||||
|
||||
try {
|
||||
FileUtils.copyDirectory(repoSourcesGame, srcMainJava);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: could not copy \"/sources/main/java/\" to \"" + srcMainJava.getAbsolutePath() + "\"!");
|
||||
throw ex;
|
||||
}
|
||||
|
||||
if(repoSourcesLWJGL.isDirectory()) {
|
||||
System.out.println("Copying files from \"/sources/lwjgl/java/\" to workspace...");
|
||||
|
||||
try {
|
||||
if(!srcLWJGLJava.isDirectory() && !srcLWJGLJava.mkdirs()) {
|
||||
System.err.println("ERROR: Could not create destination directory!");
|
||||
return false;
|
||||
}
|
||||
FileUtils.copyDirectory(repoSourcesLWJGL, srcLWJGLJava);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: could not copy \"/sources/lwjgl/java/\" to \"" + srcLWJGLJava.getAbsolutePath() + "\"!");
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Copying files from \"/sources/resources/\" to workspace...");
|
||||
|
||||
try {
|
||||
if(!resourcesExtractTo.isDirectory() && !resourcesExtractTo.mkdirs()) {
|
||||
System.err.println("ERROR: Could not create destination directory!");
|
||||
return false;
|
||||
}
|
||||
FileUtils.copyDirectory(repoSourcesResources, resourcesExtractTo);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: could not copy \"/sources/resources/\" to \"" + resourcesExtractTo.getAbsolutePath() + "\"!");
|
||||
throw ex;
|
||||
}
|
||||
|
||||
if(applyPullRequest) {
|
||||
System.out.println();
|
||||
System.out.println("Applying \"pullrequest\" directory to \"minecraft_src_patch.jar\"...");
|
||||
|
||||
File unpatchOut = new File(mcTmpDirectory, "minecraft_src.jar");
|
||||
File patchOut = new File(mcTmpDirectory, "minecraft_src_patch.jar");
|
||||
File unpatchResOut = new File(mcTmpDirectory, "minecraft_res.jar");
|
||||
File patchResOut = new File(mcTmpDirectory, "minecraft_res_patch.jar");
|
||||
File tmpPatchedPatchOut = new File(mcTmpDirectory, "minecraft_src_pullrequest_patch.jar");
|
||||
File tmpPatchedPatchJavadocOut = new File(mcTmpDirectory, "minecraft_src_pullrequest_javadoc.jar");
|
||||
File tmpPatchedPatchResOut = new File(mcTmpDirectory, "minecraft_res_pullrequest_patch.jar");
|
||||
|
||||
try {
|
||||
ApplyPatchesToZip.applyPatches(patchOut, unpatchOut, new File("./pullrequest/source"), tmpPatchedPatchOut, false, false);
|
||||
}catch(Throwable t) {
|
||||
System.err.println();
|
||||
System.err.println("ERROR: Could not apply pullrequest directory patches to: " + patchOut.getName());
|
||||
System.err.println(t.toString());
|
||||
tmpPatchedPatchOut.delete();
|
||||
return false;
|
||||
}
|
||||
|
||||
CSVMappings comments = new CSVMappings();
|
||||
if(!InsertJavaDoc.processSource(tmpPatchedPatchOut, tmpPatchedPatchJavadocOut,
|
||||
new File(btTmpDirectory, "ModCoderPack"), comments)) {
|
||||
System.err.println();
|
||||
System.err.println("ERROR: Could not create pullrequest javadoc!");
|
||||
return false;
|
||||
}
|
||||
|
||||
tmpPatchedPatchOut.delete();
|
||||
|
||||
try {
|
||||
ApplyPatchesToZip.applyPatches(patchResOut, unpatchResOut, new File("./pullrequest/resources"), tmpPatchedPatchResOut, false, false);
|
||||
}catch(Throwable t) {
|
||||
System.err.println();
|
||||
System.err.println("ERROR: Could not apply pullrequest directory patches to: " + patchResOut.getName());
|
||||
System.err.println(t.toString());
|
||||
tmpPatchedPatchOut.delete();
|
||||
tmpPatchedPatchResOut.delete();
|
||||
return false;
|
||||
}
|
||||
|
||||
minecraftJavadocTmp = tmpPatchedPatchJavadocOut;
|
||||
minecraftResJar = tmpPatchedPatchResOut;
|
||||
|
||||
}else {
|
||||
System.out.println("Extracting files from \"minecraft_src_javadoc.jar\" to \"/src/main/java/\"...");
|
||||
}
|
||||
|
||||
try {
|
||||
if(!srcMainJava.isDirectory() && !srcMainJava.mkdirs()) {
|
||||
System.err.println("ERROR: Could not create destination directory!");
|
||||
return false;
|
||||
}
|
||||
extractJarTo(minecraftJavadocTmp, srcMainJava);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: could not extract \"" + minecraftJavadocTmp.getName() + ".jar\" to \"" +
|
||||
srcMainJava.getAbsolutePath() + "\"!");
|
||||
throw ex;
|
||||
}
|
||||
|
||||
System.out.println("Extracting files from \"minecraft_res_patch.jar\" to \"/desktopRuntime/resources/\"...");
|
||||
|
||||
try {
|
||||
extractJarTo(minecraftResJar, resourcesExtractTo);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: could not extract \"" + minecraftResJar.getName() + "\" to \"" +
|
||||
resourcesExtractTo.getAbsolutePath() + "\"!");
|
||||
throw ex;
|
||||
}
|
||||
|
||||
if(applyPullRequest) {
|
||||
minecraftJavadocTmp.delete();
|
||||
minecraftResJar.delete();
|
||||
}
|
||||
|
||||
System.out.println("Extracting files from \"minecraft_languages.zip\" to \"/javascript/lang/\"...");
|
||||
|
||||
try {
|
||||
extractJarTo(mcLanguagesZip, mcLanguagesExtractTo);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: could not extract \"" + mcLanguagesZip.getName() + "\" to \"" +
|
||||
mcLanguagesExtractTo.getAbsolutePath() + "\"!");
|
||||
throw ex;
|
||||
}
|
||||
|
||||
System.out.println("Creating eclipse project for desktop runtime...");
|
||||
if(!createDesktopRuntimeProject(new File(repoSources, "setup/eclipseProjectFiles"), workspaceDirectory)) {
|
||||
System.err.println("ERROR: could not create eclipse project for desktop runtime!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static int extractJarTo(File in, File out) throws IOException {
|
||||
int cnt = 0;
|
||||
try(ZipInputStream jarIn = new ZipInputStream(new FileInputStream(in))) {
|
||||
ZipEntry e;
|
||||
while((e = jarIn.getNextEntry()) != null) {
|
||||
if(e.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
String n = e.getName();
|
||||
if(n.startsWith("/")) {
|
||||
n = n.substring(1);
|
||||
}
|
||||
if(!n.startsWith("META-INF")) {
|
||||
File o = new File(out, n);
|
||||
if(!o.exists()) {
|
||||
File p = o.getParentFile();
|
||||
if(!p.isDirectory() && !p.mkdirs()) {
|
||||
throw new IOException("Could not create directory: " + p.getAbsolutePath());
|
||||
}
|
||||
try(FileOutputStream os = new FileOutputStream(o)) {
|
||||
IOUtils.copy(jarIn, os, 4096);
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
private static boolean createDesktopRuntimeProject(File templateFolderIn, File workspaceDirectory) throws Throwable {
|
||||
File desktopRuntimeDirectory = new File(workspaceDirectory, "desktopRuntime");
|
||||
File desktopRuntimeProjectDir = new File(desktopRuntimeDirectory, "eclipseProject");
|
||||
if(!desktopRuntimeProjectDir.isDirectory() && !desktopRuntimeProjectDir.mkdirs()) {
|
||||
System.err.println("ERROR: failed to create directory: \"" + desktopRuntimeProjectDir.getAbsolutePath() + "\"!");
|
||||
return false;
|
||||
}
|
||||
File binFolder = new File(desktopRuntimeProjectDir, "bin");
|
||||
if(!binFolder.isDirectory() && !binFolder.mkdir()) {
|
||||
System.err.println("ERROR: failed to create directory: \"" + binFolder.getAbsolutePath() + "\"!");
|
||||
return false;
|
||||
}
|
||||
String dotClasspathFile = FileUtils.readFileToString(new File(templateFolderIn, ".classpath"), "UTF-8");
|
||||
String dotClasspathEntryFile = FileUtils.readFileToString(new File(templateFolderIn, "classpath_entry.txt"), "UTF-8");
|
||||
String dotProjectFile = FileUtils.readFileToString(new File(templateFolderIn, ".project"), "UTF-8");
|
||||
String debugRuntimeLaunchConfig = FileUtils.readFileToString(new File(templateFolderIn, "eaglercraftDebugRuntime.launch"), "UTF-8");
|
||||
String mainClassConfFile = FileUtils.readFileToString(new File(templateFolderIn, "main_class.txt"), "UTF-8");
|
||||
|
||||
List<String> classpathEntries = new ArrayList();
|
||||
File[] flist = desktopRuntimeDirectory.listFiles();
|
||||
for(int i = 0; i < flist.length; ++i) {
|
||||
File f = flist[i];
|
||||
if(f.getName().endsWith(".jar")) {
|
||||
classpathEntries.add(dotClasspathEntryFile.replace("${JAR_PATH}", bsToS(f.getAbsolutePath())));
|
||||
}
|
||||
}
|
||||
|
||||
dotClasspathFile = dotClasspathFile.replace("${LIBRARY_CLASSPATH}", String.join(System.lineSeparator(), classpathEntries));
|
||||
FileUtils.writeStringToFile(new File(desktopRuntimeProjectDir, ".classpath"), dotClasspathFile, "UTF-8");
|
||||
|
||||
dotProjectFile = dotProjectFile.replace("${LWJGL_SRC_FOLDER}", bsToS((new File(workspaceDirectory, "src/lwjgl/java")).getAbsolutePath()));
|
||||
dotProjectFile = dotProjectFile.replace("${MAIN_SRC_FOLDER}", bsToS((new File(workspaceDirectory, "src/main/java")).getAbsolutePath()));
|
||||
FileUtils.writeStringToFile(new File(desktopRuntimeProjectDir, ".project"), dotProjectFile, "UTF-8");
|
||||
|
||||
debugRuntimeLaunchConfig = debugRuntimeLaunchConfig.replace("${MAIN_CLASS_FILE}", mainClassConfFile);
|
||||
|
||||
String mainClassSubstr = mainClassConfFile.substring(mainClassConfFile.indexOf('/') + 1);
|
||||
if(mainClassSubstr.endsWith(".java")) {
|
||||
mainClassSubstr = mainClassSubstr.substring(0, mainClassSubstr.length() - 5);
|
||||
}
|
||||
mainClassSubstr = mainClassSubstr.replace('/', '.');
|
||||
debugRuntimeLaunchConfig = debugRuntimeLaunchConfig.replace("${MAIN_CLASS_NAME}", mainClassSubstr);
|
||||
debugRuntimeLaunchConfig = debugRuntimeLaunchConfig.replace("${WORKING_DIRECTORY}", bsToS(desktopRuntimeDirectory.getAbsolutePath()));
|
||||
FileUtils.writeStringToFile(new File(desktopRuntimeProjectDir, "eaglercraftDebugRuntime.launch"), debugRuntimeLaunchConfig, "UTF-8");
|
||||
|
||||
File dotSettingsPrefFile = new File(templateFolderIn, "org.eclipse.jdt.core.prefs");
|
||||
File destDotSettingsFolder = new File(desktopRuntimeProjectDir, ".settings");
|
||||
if(!destDotSettingsFolder.isDirectory() && !destDotSettingsFolder.mkdir()) {
|
||||
System.err.println("ERROR: failed to create directory: \"" + destDotSettingsFolder.getAbsolutePath() + "\"!");
|
||||
return false;
|
||||
}
|
||||
|
||||
FileUtils.copyFile(dotSettingsPrefFile, new File(destDotSettingsFolder, "org.eclipse.jdt.core.prefs"));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static String bsToS(String in) {
|
||||
return in.replace('\\', '/');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildToolsConfig;
|
||||
|
||||
public class TaskClean {
|
||||
|
||||
public static boolean taskClean() {
|
||||
try {
|
||||
return taskClean0();
|
||||
}catch(Throwable t) {
|
||||
System.err.println();
|
||||
System.err.println("Exception encountered while running task 'clean'!");
|
||||
t.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static boolean taskClean0() throws Throwable {
|
||||
File buildToolsTmp = EaglerBuildToolsConfig.getTemporaryDirectory();
|
||||
File pullRequestTo = new File("pullrequest");
|
||||
boolean btExist = buildToolsTmp.exists();
|
||||
boolean prExist = pullRequestTo.exists();
|
||||
if((btExist && !(buildToolsTmp.isDirectory() && buildToolsTmp.list().length == 0)) ||
|
||||
(prExist && !(pullRequestTo.isDirectory() && pullRequestTo.list().length == 0))) {
|
||||
System.out.println();
|
||||
System.out.println("Notice: Clean will delete the init directory and also");
|
||||
System.out.println("all of the files in the current pull request");
|
||||
System.out.println();
|
||||
System.out.println("you must revert all changes in the 'patches' directory of");
|
||||
System.out.println("this repo back to the main repository's current commits,");
|
||||
System.out.println("otherwise the 'pullrequest' command wll not work properly");
|
||||
System.out.println();
|
||||
System.out.print("Do you want to clean? [Y/n]: ");
|
||||
|
||||
String ret = "n";
|
||||
try {
|
||||
ret = (new BufferedReader(new InputStreamReader(System.in))).readLine();
|
||||
}catch(IOException ex) {
|
||||
// ?
|
||||
}
|
||||
ret = ret.toLowerCase();
|
||||
if(!ret.startsWith("y")) {
|
||||
System.out.println();
|
||||
System.out.println("Ok nice, the clean will be cancelled. (thank god)");
|
||||
return true;
|
||||
}else {
|
||||
try {
|
||||
if(prExist) {
|
||||
System.out.println();
|
||||
System.out.println("Deleting pull request...");
|
||||
FileUtils.deleteDirectory(pullRequestTo);
|
||||
prExist = false;
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: Could not delete \"" + pullRequestTo.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
if(btExist) {
|
||||
System.out.println();
|
||||
System.out.println("Deleting init directory...");
|
||||
FileUtils.deleteDirectory(buildToolsTmp);
|
||||
btExist = false;
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: Could not delete \"" + buildToolsTmp.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.teavm;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Map;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.gui.TeaVMBinaries;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class TeaVMBridge {
|
||||
|
||||
private static URLClassLoader classLoader = null;
|
||||
|
||||
/**
|
||||
* <h3>List of required options:</h3>
|
||||
* <table>
|
||||
* <tr><td><b>classPathEntries</b></td><td>-> BuildStrategy.setClassPathEntries(List<String>)</td></tr>
|
||||
* <tr><td><b>entryPointName</b></td><td>-> BuildStrategy.setEntryPointName(String)</td></tr>
|
||||
* <tr><td><b>mainClass</b></td><td>-> BuildStrategy.setMainClass(String)</td></tr>
|
||||
* <tr><td><b>minifying</b></td><td>-> BuildStrategy.setMinifying(boolean)</td></tr>
|
||||
* <tr><td><b>optimizationLevel</b></td><td>-> BuildStrategy.setOptimizationLevel(TeaVMOptimizationLevel)</td></tr>
|
||||
* <tr><td><b>generateSourceMaps</b></td><td>-> BuildStrategy.setSourceMapsFileGenerated(boolean)</td></tr>
|
||||
* <tr><td><b>targetDirectory</b></td><td>-> BuildStrategy.setTargetDirectory(String)</td></tr>
|
||||
* <tr><td><b>targetFileName</b></td><td>-> BuildStrategy.setTargetFileName(String)</td></tr>
|
||||
* </table>
|
||||
* <br>
|
||||
*/
|
||||
public static boolean compileTeaVM(Map<String, Object> options) throws TeaVMClassLoadException, TeaVMRuntimeException {
|
||||
File[] cp = TeaVMBinaries.getTeaVMCompilerClasspath();
|
||||
URL[] urls = new URL[cp.length];
|
||||
|
||||
for(int i = 0; i < cp.length; ++i) {
|
||||
try {
|
||||
urls[i] = cp[i].toURI().toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
throw new TeaVMClassLoadException("Could not resolve URL for: " + cp[i].getAbsolutePath(), e);
|
||||
}
|
||||
}
|
||||
|
||||
Method found = null;
|
||||
|
||||
try {
|
||||
if(classLoader == null) {
|
||||
classLoader = new URLClassLoader(urls, ClassLoader.getSystemClassLoader());
|
||||
}
|
||||
Class c = classLoader.loadClass("net.lax1dude.eaglercraft.v1_8.buildtools.task.teavm.TeaVMBridgeImpl");
|
||||
Method[] methods = c.getDeclaredMethods();
|
||||
for(int i = 0; i < methods.length; ++i) {
|
||||
Method m = methods[i];
|
||||
if(m.getName().equals("compileTeaVM")) {
|
||||
found = m;
|
||||
}
|
||||
}
|
||||
if(found == null) {
|
||||
throw new NoSuchMethodException("compileTeaVM");
|
||||
}
|
||||
}catch(TeaVMClassLoadException | NoSuchMethodException | ClassNotFoundException t) {
|
||||
throw new TeaVMClassLoadException("Could not link TeaVM compiler!", t);
|
||||
}catch(RuntimeException t) {
|
||||
String msg = t.getMessage();
|
||||
if(msg.startsWith("[TeaVMBridge]")) {
|
||||
throw new TeaVMRuntimeException(msg.substring(13).trim(), t.getCause());
|
||||
}else {
|
||||
throw new TeaVMRuntimeException("Uncaught exception was thrown!", t);
|
||||
}
|
||||
}catch(Throwable t) {
|
||||
throw new TeaVMRuntimeException("Uncaught exception was thrown!", t);
|
||||
}
|
||||
|
||||
try {
|
||||
Object ret = found.invoke(null, options);
|
||||
return ret != null && (ret instanceof Boolean) && ((Boolean)ret).booleanValue();
|
||||
}catch(InvocationTargetException ex) {
|
||||
throw new TeaVMRuntimeException("Uncaught exception was thrown!", ex.getCause());
|
||||
} catch (Throwable t) {
|
||||
throw new TeaVMRuntimeException("Failed to invoke 'compileTeaVM'!", t);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class TeaVMClassLoadException extends RuntimeException {
|
||||
public TeaVMClassLoadException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
public TeaVMClassLoadException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TeaVMRuntimeException extends RuntimeException {
|
||||
public TeaVMRuntimeException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
public TeaVMRuntimeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void free() {
|
||||
if(classLoader != null) {
|
||||
try {
|
||||
classLoader.close();
|
||||
classLoader = null;
|
||||
} catch (IOException e) {
|
||||
System.err.println("Memory leak, failed to release TeaVM JAR ClassLoader!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class FileReaderUTF extends InputStreamReader {
|
||||
|
||||
public FileReaderUTF(File file) throws FileNotFoundException {
|
||||
super(new FileInputStream(file), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class FileWriterUTF extends OutputStreamWriter {
|
||||
|
||||
public FileWriterUTF(File file) throws IOException {
|
||||
super(new FileOutputStream(file), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class JARSubprocess {
|
||||
|
||||
public static final char classPathSeperator;
|
||||
|
||||
static {
|
||||
classPathSeperator = System.getProperty("os.name").toLowerCase().contains("windows") ? ';' : ':';
|
||||
}
|
||||
|
||||
public static int runJava(File directory, String[] javaExeArguments, String logPrefix) throws IOException {
|
||||
if(logPrefix.length() > 0 && !logPrefix.endsWith(" ")) {
|
||||
logPrefix = logPrefix + " ";
|
||||
}
|
||||
String javaHome = System.getProperty("java.home");
|
||||
if(classPathSeperator == ';') {
|
||||
File javaExe = new File(javaHome, "bin/java.exe");
|
||||
if(!javaExe.isFile()) {
|
||||
javaExe = new File(javaHome, "java.exe");
|
||||
if(!javaExe.isFile()) {
|
||||
throw new IOException("Could not find /bin/java.exe equivelant on java.home! (java.home=" + javaHome + ")");
|
||||
}
|
||||
}
|
||||
javaHome = javaExe.getAbsolutePath();
|
||||
}else {
|
||||
File javaExe = new File(javaHome, "bin/java");
|
||||
if(!javaExe.isFile()) {
|
||||
javaExe = new File(javaHome, "java");
|
||||
if(!javaExe.isFile()) {
|
||||
throw new IOException("Could not find /bin/java equivelant on java.home! (java.home=" + javaHome + ")");
|
||||
}
|
||||
}
|
||||
javaHome = javaExe.getAbsolutePath();
|
||||
}
|
||||
|
||||
String[] fullArgs = new String[javaExeArguments.length + 1];
|
||||
fullArgs[0] = javaHome;
|
||||
System.arraycopy(javaExeArguments, 0, fullArgs, 1, javaExeArguments.length);
|
||||
|
||||
ProcessBuilder exec = new ProcessBuilder(fullArgs);
|
||||
exec.directory(directory);
|
||||
|
||||
Process ps = exec.start();
|
||||
InputStream is = ps.getInputStream();
|
||||
InputStream ise = ps.getErrorStream();
|
||||
BufferedReader isb = new BufferedReader(new InputStreamReader(is));
|
||||
BufferedReader iseb = new BufferedReader(new InputStreamReader(ise));
|
||||
|
||||
String isbl = "";
|
||||
String isebl = "";
|
||||
int maxReadPerLoop = 128;
|
||||
int c = 0;
|
||||
do {
|
||||
boolean tick = false;
|
||||
c = 0;
|
||||
while(isb.ready() && (!iseb.ready() || ++c < maxReadPerLoop)) {
|
||||
char cc = (char)isb.read();
|
||||
if(cc != '\r') {
|
||||
if(cc == '\n') {
|
||||
System.out.println(logPrefix + isbl);
|
||||
isbl = "";
|
||||
}else {
|
||||
isbl += cc;
|
||||
}
|
||||
}
|
||||
tick = true;
|
||||
}
|
||||
c = 0;
|
||||
while(iseb.ready() && (!isb.ready() || ++c < maxReadPerLoop)) {
|
||||
char cc = (char)iseb.read();
|
||||
if(cc != '\r') {
|
||||
if(cc == '\n') {
|
||||
System.err.println(logPrefix + isebl);
|
||||
isebl = "";
|
||||
}else {
|
||||
isebl += cc;
|
||||
}
|
||||
}
|
||||
tick = true;
|
||||
}
|
||||
if(!tick) {
|
||||
try {
|
||||
Thread.sleep(10l);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
} while(ps.isAlive());
|
||||
|
||||
while(true) {
|
||||
try {
|
||||
return ps.waitFor();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
BIN
buildtools/src/main/resources/icon/eagler.png
Normal file
BIN
buildtools/src/main/resources/icon/eagler.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 402 B |
BIN
buildtools/src/main/resources/icon/icon32.png
Normal file
BIN
buildtools/src/main/resources/icon/icon32.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
18
buildtools/src/main/resources/lang/LICENSE.txt
Normal file
18
buildtools/src/main/resources/lang/LICENSE.txt
Normal file
|
@ -0,0 +1,18 @@
|
|||
|
||||
Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
|
||||
WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
|
||||
NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
|
||||
Prohibited sharing, distribution, and repurposing these files includes but is not limited to: Publicly sharing or distributing any significant portion, modified or unmodified, of any source code files produced by the buildtools commands without minification or obfuscation, with the exception of patch files. Publicly repurposing, without permission, the source code for any file which is a part of the Eaglercraft runtime, as in any additional source files required for output of buildtools commands to run on a specific platform. Publicly repurposing, without permission, any resource file found in the project's default resource pack that does not exist in vanilla Minecraft resource packs. And, additionally, publicly repurposing, without permission, any data produced by the act of compiling or converting the files described in these previous three cases, besides the compiled or minified application (the 'game') itself.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Prohibited commercial use includes selling access to any files or data (including the game itself) contained or produced by this repository, requiring the direct forced viewing of advertisement presented when a user attempts to load a compiled version of this project (or follow a hyperlink to the project's source or files derived from it, examples include using adfoc.us or adf.ly on your site), and selling content in any form that can only be accessed through the use of this project or files produced by or derived from it. Making a pay-to-win multiplayer server, for example, would be prohibited under these terms.
|
||||
|
||||
Malicious use includes creating and/or distributing modified versions of the game's 1.8 client (often referred to as "hacked clients") which give you an unfair advantage on multiplayer servers, creating and/or distributing modified clients which allow you to exploit bugs in EaglercraftXBungee or Eagler-compatible server software, creating and/or distributing modified clients which allow you to exploit bugs in Minecraft servers or Minecraft-compatible server software, or creating and/or distributing modified clients which allow you to exploit bugs in portions of any other software used in companion with EaglerXBungee or on an Eagler-compatible server (e.g. VIAaaS, NGINX, Caddy)
|
||||
|
||||
Distribution of any file or a product of compilation or conversion covered by this document must retain all existing copyright notices found within the file and folders before any modifications were made.
|
||||
|
||||
BY VIOLATING THESE TERMS YOU AGREE TO A BLOCK/BAN FROM ALL SOURCES OF DOCUMENTATION AND SUPPORT FOR THIS PROJECT, PERMISSION TO USE THESE FILES WAS GIVEN TO YOU IN GOOD FAITH THAT THE WORK WILL NOT BE ABUSED, AND VIOLATING THIS AGREEMENT IS A DEMONSTRATION OF A LACK OF RESPECT AND GOOD INTENTIONS ON BEHALF OF YOUR EFFORTS TO LEARN HOW TO USE THESE TOOLS CORRECTLY AND IS JUSTIFICATION FOR YOUR EXCLUSION FROM ANY AND ALL SOURCES OF DOCUMENTATION OR SUPPORT THAT WILL ASSIST YOU TO CONTINUE TO VIOLATE THESE TERMS
|
|
@ -0,0 +1,86 @@
|
|||
Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
|
||||
WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT,
|
||||
AND ALL FILES NORMALLY FOUND IN AN UNMODIFIED MINECRAFT
|
||||
RESOURCE PACK, YOU ARE NOT ALLOWED TO SHARE, DISTRIBUTE,
|
||||
OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE SOFTWARE
|
||||
IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE
|
||||
PROJECT AUTHOR.
|
||||
|
||||
NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
<press enter>
|
||||
Prohibited sharing, distribution, and repurposing these
|
||||
files includes but is not limited to: Publicly sharing or
|
||||
distributing any significant portion, modified or
|
||||
unmodified, of any source code files produced by the
|
||||
buildtools commands without minification or obfuscation,
|
||||
with the exception of patch files. Publicly repurposing,
|
||||
without permission, the source code for any file which is
|
||||
a part of the Eaglercraft runtime, as in any additional
|
||||
source files required for output of buildtools commands to
|
||||
run on a specific platform. Publicly repurposing, without
|
||||
permission, any resource file found in the project's
|
||||
default resource pack that does not exist in vanilla
|
||||
Minecraft resource packs. And, additionally, publicly
|
||||
repurposing, without permission, any data produced by the
|
||||
act of compiling or converting the files described in
|
||||
these previous three cases, besides the compiled or
|
||||
minified application (the 'game') itself.
|
||||
<press enter>
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
<press enter>
|
||||
Prohibited commercial use includes selling access to any
|
||||
files or data (including the game itself) contained or
|
||||
produced by this repository, requiring the direct forced
|
||||
viewing of advertisement presented when a user attempts to
|
||||
load a compiled version of this project (or follow a
|
||||
hyperlink to the project's source or files derived from it,
|
||||
examples include using adfoc.us or adf.ly on your site),
|
||||
and selling content in any form that can only be accessed
|
||||
through the use of this project or files produced by or
|
||||
derived from it. Making a pay-to-win multiplayer server,
|
||||
for example, would be prohibited under these terms.
|
||||
<press enter>
|
||||
Malicious use includes creating and/or distributing
|
||||
modified versions of the game's 1.8 client (often referred
|
||||
to as "hacked clients") which give you an unfair advantage
|
||||
on multiplayer servers, creating and/or distributing
|
||||
modified clients which allow you to exploit bugs in
|
||||
EaglercraftXBungee or Eagler-compatible server software,
|
||||
creating and/or distributing modified clients which allow
|
||||
you to exploit bugs in Minecraft servers or
|
||||
Minecraft-compatible server software, or creating and/or
|
||||
distributing modified clients which allow you to exploit
|
||||
bugs in portions of any other software used in companion
|
||||
with EaglerXBungee or on an Eagler-compatible server (e.g.
|
||||
VIAaaS, NGINX, Caddy)
|
||||
<press enter>
|
||||
Distribution of any file or a product of compilation or
|
||||
conversion covered by this document must retain all
|
||||
existing copyright notices found within the file and
|
||||
folders before any modifications were made.
|
||||
<press enter>
|
||||
BY VIOLATING THESE TERMS YOU AGREE TO A BLOCK/BAN FROM
|
||||
ALL SOURCES OF DOCUMENTATION AND SUPPORT FOR THIS PROJECT,
|
||||
PERMISSION TO USE THESE FILES WAS GIVEN TO YOU IN GOOD
|
||||
FAITH THAT THE WORK WILL NOT BE ABUSED, AND VIOLATING
|
||||
THIS AGREEMENT IS A DEMONSTRATION OF A LACK OF RESPECT
|
||||
AND GOOD INTENTIONS ON BEHALF OF YOUR EFFORTS TO LEARN
|
||||
HOW TO USE THESE TOOLS CORRECTLY AND IS JUSTIFICATION FOR
|
||||
YOUR EXCLUSION FROM ANY AND ALL SOURCES OF DOCUMENTATION
|
||||
OR SUPPORT THAT WILL ASSIST YOU TO CONTINUE TO VIOLATE
|
||||
THESE TERMS
|
||||
<press enter>
|
1
buildtools/src/main/resources/lang/enums.json
Normal file
1
buildtools/src/main/resources/lang/enums.json
Normal file
File diff suppressed because one or more lines are too long
20
buildtools/src/main/resources/lang/statemgr.json
Normal file
20
buildtools/src/main/resources/lang/statemgr.json
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"statemgr_mappings": {
|
||||
"GlStateManager.alphaFunc": "GL11.glAlphaFunc",
|
||||
"GlStateManager.colorMaterial": "GL11.glColorMaterial",
|
||||
"GlStateManager.depthFunc": "GL11.glDepthFunc",
|
||||
"GlStateManager.blendFunc": "GL11.glBlendFunc",
|
||||
"GlStateManager.tryBlendFuncSeparate": "GL14.glBlendFuncSeparate",
|
||||
"GlStateManager.setFog": "GL11.glFogi",
|
||||
"GlStateManager.cullFace": "GL11.glCullFace",
|
||||
"GlStateManager.doPolygonOffset": "GL11.glPolygonOffset",
|
||||
"GlStateManager.colorLogicOp": "GL11.glLogicOp",
|
||||
"GlStateManager.texGen": "GL11.glTexGeni",
|
||||
"GlStateManager.func_179105_a": "GL11.glTexGen",
|
||||
"GlStateManager.setActiveTexture": "GL13.glActiveTexture",
|
||||
"GlStateManager.shadeModel": "GL11.glShadeModel",
|
||||
"GlStateManager.clear": "GL11.glClear",
|
||||
"GlStateManager.matrixMode": "GL11.glMatrixMode",
|
||||
"GlStateManager.getFloat": "GL11.glGetFloat"
|
||||
}
|
||||
}
|
12
buildtools/teavm-bridge/.classpath
Normal file
12
buildtools/teavm-bridge/.classpath
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="bin/main" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="gradle_scope" value="main"/>
|
||||
<attribute name="gradle_used_by_scope" value="main,test"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
|
||||
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
|
||||
<classpathentry kind="output" path="bin/default"/>
|
||||
</classpath>
|
4
buildtools/teavm-bridge/.gitignore
vendored
Normal file
4
buildtools/teavm-bridge/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
.gradle
|
||||
.settings
|
||||
build
|
||||
bin
|
34
buildtools/teavm-bridge/.project
Normal file
34
buildtools/teavm-bridge/.project
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>eaglercraft-teavm-bridge</name>
|
||||
<comment>Project teavm-bridge created by Buildship.</comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
|
||||
</natures>
|
||||
<filteredResources>
|
||||
<filter>
|
||||
<id>1672150683920</id>
|
||||
<name></name>
|
||||
<type>30</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.core.resources.regexFilterMatcher</id>
|
||||
<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
</filteredResources>
|
||||
</projectDescription>
|
24
buildtools/teavm-bridge/build.gradle
Normal file
24
buildtools/teavm-bridge/build.gradle
Normal file
|
@ -0,0 +1,24 @@
|
|||
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'eclipse'
|
||||
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
srcDir 'src/main/java'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
/** we use 0.6.1 due to performance issues on 7.0.0 */
|
||||
implementation 'org.teavm:teavm-cli:0.6.1'
|
||||
implementation 'org.teavm:teavm-tooling:0.6.1'
|
||||
}
|
BIN
buildtools/teavm-bridge/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
buildtools/teavm-bridge/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
buildtools/teavm-bridge/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
buildtools/teavm-bridge/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
183
buildtools/teavm-bridge/gradlew
vendored
Normal file
183
buildtools/teavm-bridge/gradlew
vendored
Normal file
|
@ -0,0 +1,183 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=`save "$@"`
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
exec "$JAVACMD" "$@"
|
100
buildtools/teavm-bridge/gradlew.bat
vendored
Normal file
100
buildtools/teavm-bridge/gradlew.bat
vendored
Normal file
|
@ -0,0 +1,100 @@
|
|||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
10
buildtools/teavm-bridge/settings.gradle
Normal file
10
buildtools/teavm-bridge/settings.gradle
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* This file was generated by the Gradle 'init' task.
|
||||
*
|
||||
* The settings file is used to specify which projects to include in your build.
|
||||
*
|
||||
* Detailed information about configuring a multi-project build in Gradle can be found
|
||||
* in the user manual at https://docs.gradle.org/6.0/userguide/multi_project_builds.html
|
||||
*/
|
||||
|
||||
rootProject.name = 'eaglercraft-teavm-bridge'
|
|
@ -0,0 +1,181 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.teavm;
|
||||
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.teavm.diagnostics.Problem;
|
||||
import org.teavm.diagnostics.ProblemProvider;
|
||||
import org.teavm.tooling.TeaVMTargetType;
|
||||
import org.teavm.tooling.builder.BuildException;
|
||||
import org.teavm.tooling.builder.BuildResult;
|
||||
import org.teavm.tooling.builder.BuildStrategy;
|
||||
import org.teavm.tooling.builder.ClassLoaderFactory;
|
||||
import org.teavm.tooling.builder.InProcessBuildStrategy;
|
||||
import org.teavm.vm.TeaVMOptimizationLevel;
|
||||
import org.teavm.vm.TeaVMPhase;
|
||||
import org.teavm.vm.TeaVMProgressFeedback;
|
||||
import org.teavm.vm.TeaVMProgressListener;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class TeaVMBridgeImpl {
|
||||
|
||||
static {
|
||||
System.out.println("[TeaVMBridge] Class was loaded");
|
||||
}
|
||||
|
||||
/**
|
||||
* <h3>List of required options:</h3>
|
||||
* <table>
|
||||
* <tr><td><b>classPathEntries</b></td><td>-> BuildStrategy.setClassPathEntries(List<String>)</td></tr>
|
||||
* <tr><td><b>entryPointName</b></td><td>-> BuildStrategy.setEntryPointName(String)</td></tr>
|
||||
* <tr><td><b>mainClass</b></td><td>-> BuildStrategy.setMainClass(String)</td></tr>
|
||||
* <tr><td><b>minifying</b></td><td>-> BuildStrategy.setMinifying(boolean)</td></tr>
|
||||
* <tr><td><b>optimizationLevel</b></td><td>-> BuildStrategy.setOptimizationLevel(TeaVMOptimizationLevel)</td></tr>
|
||||
* <tr><td><b>generateSourceMaps</b></td><td>-> BuildStrategy.setSourceMapsFileGenerated(boolean)</td></tr>
|
||||
* <tr><td><b>targetDirectory</b></td><td>-> BuildStrategy.setTargetDirectory(String)</td></tr>
|
||||
* <tr><td><b>targetFileName</b></td><td>-> BuildStrategy.setTargetFileName(String)</td></tr>
|
||||
* </table>
|
||||
* <br>
|
||||
*/
|
||||
public static boolean compileTeaVM(Map<String, Object> options) throws RuntimeException {
|
||||
|
||||
System.out.println();
|
||||
System.out.println("[TeaVMBridge] Configuring InProcessBuildStrategy:");
|
||||
|
||||
for(Entry<String, Object> etr : options.entrySet()) {
|
||||
System.out.println("[TeaVMBridge] " + etr.getKey() + " = " + etr.getValue());
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
final List<URLClassLoader> openedClassLoaders = new ArrayList();
|
||||
|
||||
BuildStrategy buildStrategy = new InProcessBuildStrategy(new ClassLoaderFactory() {
|
||||
@Override
|
||||
public ClassLoader create(URL[] var1, ClassLoader var2) {
|
||||
URLClassLoader classLoader = new URLClassLoader(var1, var2);
|
||||
synchronized(openedClassLoaders) {
|
||||
openedClassLoaders.add(classLoader);
|
||||
}
|
||||
return classLoader;
|
||||
}
|
||||
});
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
BuildResult result = null;
|
||||
|
||||
try {
|
||||
buildStrategy.setClassPathEntries((List<String>)options.get("classPathEntries"));
|
||||
buildStrategy.setDebugInformationGenerated(false);
|
||||
buildStrategy.setEntryPointName((String)options.get("entryPointName"));
|
||||
buildStrategy.setMainClass((String)options.get("mainClass"));
|
||||
buildStrategy.setMaxTopLevelNames(10000); // TODO: what does this do? sounds important
|
||||
buildStrategy.setMinifying(((Boolean)options.get("minifying")).booleanValue());
|
||||
buildStrategy.setOptimizationLevel(TeaVMOptimizationLevel.valueOf((String)options.get("optimizationLevel")));
|
||||
buildStrategy.setSourceFilesCopied(false);
|
||||
buildStrategy.setSourceMapsFileGenerated(((Boolean)options.get("generateSourceMaps")).booleanValue());
|
||||
buildStrategy.setTargetDirectory((String)options.get("targetDirectory"));
|
||||
buildStrategy.setTargetFileName((String)options.get("targetFileName"));
|
||||
buildStrategy.setTargetType(TeaVMTargetType.JAVASCRIPT);
|
||||
|
||||
buildStrategy.setProgressListener(new TeaVMProgressListener() {
|
||||
|
||||
@Override
|
||||
public TeaVMProgressFeedback progressReached(int var1) {
|
||||
return TeaVMProgressFeedback.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TeaVMProgressFeedback phaseStarted(TeaVMPhase var1, int var2) {
|
||||
if(var1 == TeaVMPhase.DEPENDENCY_ANALYSIS) {
|
||||
System.out.println("[TeaVMBridge] Analyzing dependencies...");
|
||||
}else if(var1 == TeaVMPhase.COMPILING) {
|
||||
System.out.println("[TeaVMBridge] Running compiler...");
|
||||
}
|
||||
return TeaVMProgressFeedback.CONTINUE;
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
result = buildStrategy.build();
|
||||
}catch(BuildException ex) {
|
||||
throw new RuntimeException("[TeaVMBridge] BuildException thrown while building!", ex.getCause());
|
||||
}catch(Throwable t) {
|
||||
throw new RuntimeException("[TeaVMBridge] Unhandled exception thrown while building!", t);
|
||||
}
|
||||
}finally {
|
||||
for(int i = 0, l = openedClassLoaders.size(); i < l; ++i) {
|
||||
URLClassLoader cl = openedClassLoaders.get(i);
|
||||
try {
|
||||
cl.close();
|
||||
}catch(Throwable t) {
|
||||
System.out.println("[TeaVMBridge] ERROR: could not free classloader " + cl + ": " + t.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("[TeaVMBridge] Build complete! Took " + ((System.currentTimeMillis() - start) / 1000l) + " seconds");
|
||||
|
||||
boolean returnError = false;
|
||||
ProblemProvider prov = result.getProblems();
|
||||
if(prov != null) {
|
||||
List<Problem> problems = prov.getProblems();
|
||||
if(problems != null && problems.size() > 0) {
|
||||
returnError = true;
|
||||
System.err.println("[TeaVMBridge] Encountered " + problems.size() + " problems while building:");
|
||||
for(int i = 0, l = problems.size(); i < l; ++i) {
|
||||
Problem p = problems.get(i);
|
||||
System.err.println("[TeaVMBridge] - " + p.getSeverity() + ": " + p.getClass() + " : " + p.getLocation() + " - " + p.getText() + " - params: " + collectionToString(p.getParams()));
|
||||
}
|
||||
System.err.println();
|
||||
}
|
||||
|
||||
List<Problem> severeProblems = prov.getSevereProblems();
|
||||
if(severeProblems != null && severeProblems.size() > 0) {
|
||||
returnError = true;
|
||||
System.err.println("[TeaVMBridge] Encountered " + severeProblems.size() + " high-severity problems while building:");
|
||||
for(int i = 0, l = severeProblems.size(); i < l; ++i) {
|
||||
Problem p = severeProblems.get(i);
|
||||
System.err.println("[TeaVMBridge] - " + p.getSeverity() + ": " + p.getClass() + " : " + p.getLocation() + " - " + p.getText() + " - params: " + collectionToString(p.getParams()));
|
||||
}
|
||||
System.err.println();
|
||||
}
|
||||
}
|
||||
|
||||
return !returnError;
|
||||
}
|
||||
|
||||
private static String collectionToString(Object[] params) {
|
||||
if(params.length == 0) {
|
||||
return "[ ]";
|
||||
}
|
||||
StringBuilder ret = new StringBuilder();
|
||||
ret.append("[ ");
|
||||
for(int i = 0; i < params.length; ++i) {
|
||||
if(i > 0) {
|
||||
ret.append(" , ");
|
||||
}
|
||||
ret.append(params[i]);
|
||||
}
|
||||
ret.append(" ]");
|
||||
return ret.toString();
|
||||
}
|
||||
|
||||
}
|
1
client_version
Normal file
1
client_version
Normal file
|
@ -0,0 +1 @@
|
|||
u5
|
4
gateway/EaglercraftXBungee/.gitignore
vendored
Normal file
4
gateway/EaglercraftXBungee/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
lib/*
|
||||
.idea/*
|
||||
*.iml
|
||||
out/*
|
BIN
gateway/EaglercraftXBungee/EaglerXBungee-Latest.jar
Normal file
BIN
gateway/EaglercraftXBungee/EaglerXBungee-Latest.jar
Normal file
Binary file not shown.
9
gateway/EaglercraftXBungee/readme.txt
Normal file
9
gateway/EaglercraftXBungee/readme.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
Plugin for eaglercraft on bungeecord
|
||||
|
||||
Not using gradle to give more direct access to bungeecord's internals, as gradle only provides a dummy jar containing the api.
|
||||
|
||||
EaglercraftXBungee requires netty's websocket client/server, which is already in the production bungeecord jar so it's ideal to compile directly against the real jar
|
||||
|
||||
Simply link "src/main/java" and "src/main/resources" as source folders, and then add the latest version of bungeecord jar for minecraft 1.8 to the build path.
|
||||
|
||||
To build, export the source folders as a JAR and export the JAR to contain all the classes found in the JARs in "deps" within it, but not including the classes from the actual bungeecord jar
|
|
@ -0,0 +1,278 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.auth.DefaultAuthSystem;
|
||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.command.CommandConfirmCode;
|
||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.command.CommandEaglerPurge;
|
||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.command.CommandEaglerRegister;
|
||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.command.CommandRatelimit;
|
||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerAuthConfig;
|
||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerBungeeConfig;
|
||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerListenerConfig;
|
||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.handlers.EaglerPacketEventListener;
|
||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.handlers.EaglerPluginEventListener;
|
||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerPipeline;
|
||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.web.HttpWebServer;
|
||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.BinaryHttpClient;
|
||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.ISkinService;
|
||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.SkinService;
|
||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.SkinServiceOffline;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import net.md_5.bungee.api.plugin.PluginManager;
|
||||
import net.md_5.bungee.netty.PipelineUtils;
|
||||
import net.md_5.bungee.BungeeCord;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class EaglerXBungee extends Plugin {
|
||||
|
||||
private static EaglerXBungee instance = null;
|
||||
private EaglerBungeeConfig conf = null;
|
||||
private EventLoopGroup eventLoopGroup;
|
||||
private Collection<Channel> openChannels;
|
||||
private final Timer closeInactiveConnections;
|
||||
private Timer skinServiceTasks = null;
|
||||
private Timer authServiceTasks = null;
|
||||
private final ChannelFutureListener newChannelListener;
|
||||
private ISkinService skinService;
|
||||
private DefaultAuthSystem defaultAuthSystem;
|
||||
|
||||
public EaglerXBungee() {
|
||||
instance = this;
|
||||
openChannels = new LinkedList();
|
||||
closeInactiveConnections = new Timer("EaglerXBungee: Close Inactive");
|
||||
newChannelListener = new ChannelFutureListener() {
|
||||
@Override
|
||||
public void operationComplete(ChannelFuture ch) throws Exception {
|
||||
synchronized(openChannels) { // synchronize whole block to preserve logging order
|
||||
if(ch.isSuccess()) {
|
||||
EaglerXBungee.logger().info("Eaglercraft is listening on: " + ch.channel().attr(EaglerPipeline.LOCAL_ADDRESS).get().toString());
|
||||
openChannels.add(ch.channel());
|
||||
}else {
|
||||
EaglerXBungee.logger().severe("Eaglercraft could not bind port: " + ch.channel().attr(EaglerPipeline.LOCAL_ADDRESS).get().toString());
|
||||
EaglerXBungee.logger().severe("Reason: " + ch.cause().toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
try {
|
||||
eventLoopGroup = ((BungeeCord) getProxy()).eventLoops;
|
||||
} catch (NoSuchFieldError e) {
|
||||
try {
|
||||
eventLoopGroup = (EventLoopGroup) BungeeCord.class.getField("workerEventLoopGroup").get(getProxy());
|
||||
} catch (IllegalAccessException | NoSuchFieldException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
reloadConfig();
|
||||
closeInactiveConnections.scheduleAtFixedRate(EaglerPipeline.closeInactive, 0l, 250l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
PluginManager mgr = getProxy().getPluginManager();
|
||||
mgr.registerListener(this, new EaglerPluginEventListener(this));
|
||||
mgr.registerListener(this, new EaglerPacketEventListener(this));
|
||||
mgr.registerCommand(this, new CommandRatelimit());
|
||||
mgr.registerCommand(this, new CommandConfirmCode());
|
||||
EaglerAuthConfig authConf = conf.getAuthConfig();
|
||||
if(authConf.isEnableAuthentication() && authConf.isUseBuiltInAuthentication()) {
|
||||
if(!BungeeCord.getInstance().getConfig().isOnlineMode()) {
|
||||
getLogger().severe("Online mode is set to false! Authentication system has been disabled");
|
||||
authConf.triggerOnlineModeDisabled();
|
||||
}else {
|
||||
mgr.registerCommand(this, new CommandEaglerRegister(authConf.getEaglerCommandName()));
|
||||
mgr.registerCommand(this, new CommandEaglerPurge(authConf.getEaglerCommandName()));
|
||||
}
|
||||
}
|
||||
getProxy().registerChannel(SkinService.CHANNEL);
|
||||
startListeners();
|
||||
if(skinServiceTasks != null) {
|
||||
skinServiceTasks.cancel();
|
||||
skinServiceTasks = null;
|
||||
}
|
||||
boolean downloadSkins = conf.getDownloadVanillaSkins();
|
||||
if(downloadSkins) {
|
||||
if(skinService == null) {
|
||||
skinService = new SkinService();
|
||||
}else if(skinService instanceof SkinServiceOffline) {
|
||||
skinService.shutdown();
|
||||
skinService = new SkinService();
|
||||
}
|
||||
} else {
|
||||
if(skinService == null) {
|
||||
skinService = new SkinServiceOffline();
|
||||
}else if(skinService instanceof SkinService) {
|
||||
skinService.shutdown();
|
||||
skinService = new SkinServiceOffline();
|
||||
}
|
||||
}
|
||||
skinService.init(conf.getSkinCacheURI(), conf.getSQLiteDriverClass(), conf.getSQLiteDriverPath(),
|
||||
conf.getKeepObjectsDays(), conf.getKeepProfilesDays(), conf.getMaxObjects(), conf.getMaxProfiles());
|
||||
if(skinService instanceof SkinService) {
|
||||
skinServiceTasks = new Timer("EaglerXBungee: Skin Service Tasks");
|
||||
skinServiceTasks.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
skinService.flush();
|
||||
}catch(Throwable t) {
|
||||
logger().log(Level.SEVERE, "Error flushing skin cache!", t);
|
||||
}
|
||||
}
|
||||
}, 1000l, 1000l);
|
||||
}
|
||||
if(authConf.isEnableAuthentication() && authConf.isUseBuiltInAuthentication()) {
|
||||
try {
|
||||
defaultAuthSystem = DefaultAuthSystem.initializeAuthSystem(authConf);
|
||||
}catch(DefaultAuthSystem.AuthSystemException ex) {
|
||||
logger().log(Level.SEVERE, "Could not load authentication system!", ex);
|
||||
}
|
||||
if(defaultAuthSystem != null) {
|
||||
authServiceTasks = new Timer("EaglerXBungee: Auth Service Tasks");
|
||||
authServiceTasks.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
defaultAuthSystem.flush();
|
||||
}catch(Throwable t) {
|
||||
logger().log(Level.SEVERE, "Error flushing auth cache!", t);
|
||||
}
|
||||
}
|
||||
}, 60000l, 60000l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
PluginManager mgr = getProxy().getPluginManager();
|
||||
mgr.unregisterListeners(this);
|
||||
mgr.unregisterCommands(this);
|
||||
getProxy().unregisterChannel(SkinService.CHANNEL);
|
||||
stopListeners();
|
||||
if(skinServiceTasks != null) {
|
||||
skinServiceTasks.cancel();
|
||||
skinServiceTasks = null;
|
||||
}
|
||||
skinService.shutdown();
|
||||
if(defaultAuthSystem != null) {
|
||||
defaultAuthSystem.destroy();
|
||||
defaultAuthSystem = null;
|
||||
if(authServiceTasks != null) {
|
||||
authServiceTasks.cancel();
|
||||
authServiceTasks = null;
|
||||
}
|
||||
}
|
||||
BinaryHttpClient.killEventLoop();
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
stopListeners();
|
||||
reloadConfig();
|
||||
startListeners();
|
||||
}
|
||||
|
||||
private void reloadConfig() {
|
||||
try {
|
||||
conf = EaglerBungeeConfig.loadConfig(getDataFolder());
|
||||
if(conf == null) {
|
||||
throw new IOException("Config failed to parse!");
|
||||
}
|
||||
HttpWebServer.regenerate404Pages();
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void startListeners() {
|
||||
for(EaglerListenerConfig conf : conf.getServerListeners()) {
|
||||
if(conf.getAddress() != null) {
|
||||
makeListener(conf, conf.getAddress());
|
||||
}
|
||||
if(conf.getAddressV6() != null) {
|
||||
makeListener(conf, conf.getAddressV6());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void makeListener(EaglerListenerConfig confData, InetSocketAddress addr) {
|
||||
ServerBootstrap bootstrap = new ServerBootstrap();
|
||||
bootstrap.option(ChannelOption.SO_REUSEADDR, true)
|
||||
.childOption(ChannelOption.TCP_NODELAY, true)
|
||||
.channel(PipelineUtils.getServerChannel(addr))
|
||||
.group(eventLoopGroup)
|
||||
.childAttr(EaglerPipeline.LISTENER, confData)
|
||||
.attr(EaglerPipeline.LOCAL_ADDRESS, addr)
|
||||
.localAddress(addr)
|
||||
.childHandler(EaglerPipeline.SERVER_CHILD)
|
||||
.bind().addListener(newChannelListener);
|
||||
}
|
||||
|
||||
public void stopListeners() {
|
||||
synchronized(openChannels) {
|
||||
for(Channel c : openChannels) {
|
||||
c.close().syncUninterruptibly();
|
||||
EaglerXBungee.logger().info("Eaglercraft listener closed: " + c.attr(EaglerPipeline.LOCAL_ADDRESS).get().toString());
|
||||
}
|
||||
openChannels.clear();
|
||||
}
|
||||
synchronized(EaglerPipeline.openChannels) {
|
||||
EaglerPipeline.openChannels.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public EaglerBungeeConfig getConfig() {
|
||||
return conf;
|
||||
}
|
||||
|
||||
public EventLoopGroup getEventLoopGroup() {
|
||||
return eventLoopGroup;
|
||||
}
|
||||
|
||||
public ISkinService getSkinService() {
|
||||
return skinService;
|
||||
}
|
||||
|
||||
public DefaultAuthSystem getAuthService() {
|
||||
return defaultAuthSystem;
|
||||
}
|
||||
|
||||
public static EaglerXBungee getEagler() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static Logger logger() {
|
||||
return instance.getLogger();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,194 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerListenerConfig;
|
||||
import net.md_5.bungee.api.plugin.Event;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class EaglercraftHandleAuthPasswordEvent extends Event {
|
||||
|
||||
public static enum AuthResponse {
|
||||
ALLOW, DENY
|
||||
}
|
||||
|
||||
private final EaglerListenerConfig listener;
|
||||
private final InetAddress authRemoteAddress;
|
||||
private final String authOrigin;
|
||||
private final byte[] authUsername;
|
||||
private final byte[] authSaltingData;
|
||||
private final byte[] authPasswordData;
|
||||
private final EaglercraftIsAuthRequiredEvent.AuthMethod eventAuthMethod;
|
||||
private final String eventAuthMessage;
|
||||
private final Object authAttachment;
|
||||
|
||||
private AuthResponse eventResponse;
|
||||
private CharSequence authProfileUsername;
|
||||
private UUID authProfileUUID;
|
||||
private String authRequestedServerRespose;
|
||||
private String authDeniedMessage = "Password Incorrect!";
|
||||
private String applyTexturesPropValue;
|
||||
private String applyTexturesPropSignature;
|
||||
private boolean overrideEaglerToVanillaSkins;
|
||||
private Consumer<EaglercraftHandleAuthPasswordEvent> continueThread;
|
||||
private Runnable continueRunnable;
|
||||
private volatile boolean hasContinue = false;
|
||||
|
||||
public EaglercraftHandleAuthPasswordEvent(EaglerListenerConfig listener, InetAddress authRemoteAddress,
|
||||
String authOrigin, byte[] authUsername, byte[] authSaltingData, CharSequence authProfileUsername,
|
||||
UUID authProfileUUID, byte[] authPasswordData, EaglercraftIsAuthRequiredEvent.AuthMethod eventAuthMethod,
|
||||
String eventAuthMessage, Object authAttachment, String authRequestedServerRespose,
|
||||
Consumer<EaglercraftHandleAuthPasswordEvent> continueThread) {
|
||||
this.listener = listener;
|
||||
this.authRemoteAddress = authRemoteAddress;
|
||||
this.authOrigin = authOrigin;
|
||||
this.authUsername = authUsername;
|
||||
this.authSaltingData = authSaltingData;
|
||||
this.authProfileUsername = authProfileUsername;
|
||||
this.authProfileUUID = authProfileUUID;
|
||||
this.authPasswordData = authPasswordData;
|
||||
this.eventAuthMethod = eventAuthMethod;
|
||||
this.eventAuthMessage = eventAuthMessage;
|
||||
this.authAttachment = authAttachment;
|
||||
this.authRequestedServerRespose = authRequestedServerRespose;
|
||||
this.continueThread = continueThread;
|
||||
}
|
||||
|
||||
public EaglerListenerConfig getListener() {
|
||||
return listener;
|
||||
}
|
||||
|
||||
public InetAddress getRemoteAddress() {
|
||||
return authRemoteAddress;
|
||||
}
|
||||
|
||||
public String getOriginHeader() {
|
||||
return authOrigin;
|
||||
}
|
||||
|
||||
public byte[] getAuthUsername() {
|
||||
return authUsername;
|
||||
}
|
||||
|
||||
public byte[] getAuthSaltingData() {
|
||||
return authSaltingData;
|
||||
}
|
||||
|
||||
public CharSequence getProfileUsername() {
|
||||
return authProfileUsername;
|
||||
}
|
||||
|
||||
public void setProfileUsername(CharSequence username) {
|
||||
this.authProfileUsername = username;
|
||||
}
|
||||
|
||||
public UUID getProfileUUID() {
|
||||
return authProfileUUID;
|
||||
}
|
||||
|
||||
public void setProfileUUID(UUID uuid) {
|
||||
this.authProfileUUID = uuid;
|
||||
}
|
||||
|
||||
public byte[] getAuthPasswordDataResponse() {
|
||||
return authPasswordData;
|
||||
}
|
||||
|
||||
public EaglercraftIsAuthRequiredEvent.AuthMethod getAuthType() {
|
||||
return eventAuthMethod;
|
||||
}
|
||||
|
||||
public String getAuthMessage() {
|
||||
return eventAuthMessage;
|
||||
}
|
||||
|
||||
public <T> T getAuthAttachment() {
|
||||
return (T)authAttachment;
|
||||
}
|
||||
|
||||
public String getAuthRequestedServer() {
|
||||
return authRequestedServerRespose;
|
||||
}
|
||||
|
||||
public void setAuthRequestedServer(String server) {
|
||||
this.authRequestedServerRespose = server;
|
||||
}
|
||||
|
||||
public void setLoginAllowed() {
|
||||
this.eventResponse = AuthResponse.ALLOW;
|
||||
this.authDeniedMessage = null;
|
||||
}
|
||||
|
||||
public void setLoginDenied(String message) {
|
||||
this.eventResponse = AuthResponse.DENY;
|
||||
this.authDeniedMessage = message;
|
||||
}
|
||||
|
||||
public AuthResponse getLoginAllowed() {
|
||||
return eventResponse;
|
||||
}
|
||||
|
||||
public String getLoginDeniedMessage() {
|
||||
return authDeniedMessage;
|
||||
}
|
||||
|
||||
public Runnable makeAsyncContinue() {
|
||||
if(continueRunnable == null) {
|
||||
continueRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(!hasContinue) {
|
||||
hasContinue = true;
|
||||
continueThread.accept(EaglercraftHandleAuthPasswordEvent.this);
|
||||
}else {
|
||||
throw new IllegalStateException("Thread was already continued from a different function! Auth plugin conflict?");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
return continueRunnable;
|
||||
}
|
||||
|
||||
public boolean isAsyncContinue() {
|
||||
return continueRunnable != null;
|
||||
}
|
||||
|
||||
public void doDirectContinue() {
|
||||
continueThread.accept(this);
|
||||
}
|
||||
|
||||
public void applyTexturesProperty(String value, String signature) {
|
||||
applyTexturesPropValue = value;
|
||||
applyTexturesPropSignature = signature;
|
||||
}
|
||||
|
||||
public String getApplyTexturesPropertyValue() {
|
||||
return applyTexturesPropValue;
|
||||
}
|
||||
|
||||
public String getApplyTexturesPropertySignature() {
|
||||
return applyTexturesPropSignature;
|
||||
}
|
||||
|
||||
public void setOverrideEaglerToVanillaSkins(boolean overrideEaglerToVanillaSkins) {
|
||||
this.overrideEaglerToVanillaSkins = overrideEaglerToVanillaSkins;
|
||||
}
|
||||
|
||||
public boolean isOverrideEaglerToVanillaSkins() {
|
||||
return overrideEaglerToVanillaSkins;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerListenerConfig;
|
||||
import net.md_5.bungee.api.plugin.Event;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class EaglercraftIsAuthRequiredEvent extends Event {
|
||||
|
||||
public static enum AuthResponse {
|
||||
SKIP, REQUIRE, DENY
|
||||
}
|
||||
|
||||
public static enum AuthMethod {
|
||||
PLAINTEXT, EAGLER_SHA256, AUTHME_SHA256
|
||||
}
|
||||
|
||||
public EaglercraftIsAuthRequiredEvent(EaglerListenerConfig listener, InetAddress authRemoteAddress,
|
||||
String authOrigin, boolean wantsAuth, byte[] authUsername,
|
||||
Consumer<EaglercraftIsAuthRequiredEvent> continueThread) {
|
||||
this.listener = listener;
|
||||
this.authRemoteAddress = authRemoteAddress;
|
||||
this.authOrigin = authOrigin;
|
||||
this.wantsAuth = wantsAuth;
|
||||
this.authUsername = authUsername;
|
||||
this.continueThread = continueThread;
|
||||
}
|
||||
|
||||
private final EaglerListenerConfig listener;
|
||||
private AuthResponse authResponse;
|
||||
private final InetAddress authRemoteAddress;
|
||||
private final String authOrigin;
|
||||
private final boolean wantsAuth;
|
||||
private final byte[] authUsername;
|
||||
private byte[] authSaltingData;
|
||||
private AuthMethod eventAuthMethod = null;
|
||||
private String eventAuthMessage = "enter the code:";
|
||||
private String kickUserMessage = "Login Denied";
|
||||
private Object authAttachment;
|
||||
private Consumer<EaglercraftIsAuthRequiredEvent> continueThread;
|
||||
private Runnable continueRunnable;
|
||||
private volatile boolean hasContinue = false;
|
||||
|
||||
public EaglerListenerConfig getListener() {
|
||||
return listener;
|
||||
}
|
||||
|
||||
public InetAddress getRemoteAddress() {
|
||||
return authRemoteAddress;
|
||||
}
|
||||
|
||||
public String getOriginHeader() {
|
||||
return authOrigin;
|
||||
}
|
||||
|
||||
public boolean isClientSolicitingPasscode() {
|
||||
return wantsAuth;
|
||||
}
|
||||
|
||||
public byte[] getAuthUsername() {
|
||||
return authUsername;
|
||||
}
|
||||
|
||||
public byte[] getSaltingData() {
|
||||
return authSaltingData;
|
||||
}
|
||||
|
||||
public void setSaltingData(byte[] saltingData) {
|
||||
authSaltingData = saltingData;
|
||||
}
|
||||
|
||||
public AuthMethod getUseAuthType() {
|
||||
return eventAuthMethod;
|
||||
}
|
||||
|
||||
public void setUseAuthMethod(AuthMethod authMethod) {
|
||||
this.eventAuthMethod = authMethod;
|
||||
}
|
||||
|
||||
public AuthResponse getAuthRequired() {
|
||||
return authResponse;
|
||||
}
|
||||
|
||||
public void setAuthRequired(AuthResponse required) {
|
||||
this.authResponse = required;
|
||||
}
|
||||
|
||||
public String getAuthMessage() {
|
||||
return eventAuthMessage;
|
||||
}
|
||||
|
||||
public void setAuthMessage(String eventAuthMessage) {
|
||||
this.eventAuthMessage = eventAuthMessage;
|
||||
}
|
||||
|
||||
public <T> T getAuthAttachment() {
|
||||
return (T)authAttachment;
|
||||
}
|
||||
|
||||
public void setAuthAttachment(Object authAttachment) {
|
||||
this.authAttachment = authAttachment;
|
||||
}
|
||||
|
||||
public boolean shouldKickUser() {
|
||||
return authResponse == null || authResponse == AuthResponse.DENY;
|
||||
}
|
||||
|
||||
public String getKickMessage() {
|
||||
return kickUserMessage;
|
||||
}
|
||||
|
||||
public void kickUser(String message) {
|
||||
authResponse = AuthResponse.DENY;
|
||||
kickUserMessage = message;
|
||||
}
|
||||
|
||||
public Runnable makeAsyncContinue() {
|
||||
if(continueRunnable == null) {
|
||||
continueRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(!hasContinue) {
|
||||
hasContinue = true;
|
||||
continueThread.accept(EaglercraftIsAuthRequiredEvent.this);
|
||||
}else {
|
||||
throw new IllegalStateException("Thread was already continued from a different function! Auth plugin conflict?");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
return continueRunnable;
|
||||
}
|
||||
|
||||
public boolean isAsyncContinue() {
|
||||
return continueRunnable != null;
|
||||
}
|
||||
|
||||
public void doDirectContinue() {
|
||||
continueThread.accept(this);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event;
|
||||
|
||||
import java.net.InetAddress;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.query.MOTDConnection;
|
||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerListenerConfig;
|
||||
import net.md_5.bungee.api.plugin.Event;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class EaglercraftMOTDEvent extends Event {
|
||||
|
||||
protected final MOTDConnection connection;
|
||||
|
||||
public EaglercraftMOTDEvent(MOTDConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
public InetAddress getRemoteAddress() {
|
||||
return connection.getAddress();
|
||||
}
|
||||
|
||||
public EaglerListenerConfig getListener() {
|
||||
return connection.getListener();
|
||||
}
|
||||
|
||||
public String getAccept() {
|
||||
return connection.getAccept();
|
||||
}
|
||||
|
||||
public MOTDConnection getConnection() {
|
||||
return connection;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import net.md_5.bungee.api.plugin.Event;
|
||||
import net.md_5.bungee.protocol.Property;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class EaglercraftRegisterSkinEvent extends Event {
|
||||
|
||||
private final String username;
|
||||
private final UUID uuid;
|
||||
private Property useMojangProfileProperty = null;
|
||||
private boolean useLoginResultTextures = false;
|
||||
private int presetId = -1;
|
||||
private byte[] customTex = null;
|
||||
private String customURL = null;
|
||||
|
||||
public EaglercraftRegisterSkinEvent(String username, UUID uuid) {
|
||||
this.username = username;
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public void setForceUseMojangProfileProperty(Property prop) {
|
||||
useMojangProfileProperty = prop;
|
||||
useLoginResultTextures = false;
|
||||
presetId = -1;
|
||||
customTex = null;
|
||||
customURL = null;
|
||||
}
|
||||
|
||||
public void setForceUseLoginResultObjectTextures(boolean b) {
|
||||
useMojangProfileProperty = null;
|
||||
useLoginResultTextures = b;
|
||||
presetId = -1;
|
||||
customTex = null;
|
||||
customURL = null;
|
||||
}
|
||||
|
||||
public void setForceUsePreset(int p) {
|
||||
useMojangProfileProperty = null;
|
||||
useLoginResultTextures = false;
|
||||
presetId = p;
|
||||
customTex = new byte[5];
|
||||
customTex[0] = (byte)1;
|
||||
customTex[1] = (byte)(p >> 24);
|
||||
customTex[2] = (byte)(p >> 16);
|
||||
customTex[3] = (byte)(p >> 8);
|
||||
customTex[4] = (byte)(p & 0xFF);
|
||||
customURL = null;
|
||||
}
|
||||
|
||||
public void setForceUseCustom(int model, byte[] tex) {
|
||||
useMojangProfileProperty = null;
|
||||
useLoginResultTextures = false;
|
||||
presetId = -1;
|
||||
customTex = new byte[2 + tex.length];
|
||||
customTex[0] = (byte)2;
|
||||
customTex[1] = (byte)model;
|
||||
System.arraycopy(tex, 0, customTex, 2, tex.length);
|
||||
customURL = null;
|
||||
}
|
||||
|
||||
public void setForceUseCustomByPacket(byte[] packet) {
|
||||
useMojangProfileProperty = null;
|
||||
useLoginResultTextures = false;
|
||||
presetId = -1;
|
||||
customTex = packet;
|
||||
customURL = null;
|
||||
}
|
||||
|
||||
public void setForceUseURL(String url) {
|
||||
useMojangProfileProperty = null;
|
||||
useLoginResultTextures = false;
|
||||
presetId = -1;
|
||||
customTex = null;
|
||||
customURL = url;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public Property getForceUseMojangProfileProperty() {
|
||||
return useMojangProfileProperty;
|
||||
}
|
||||
|
||||
public boolean getForceUseLoginResultObjectTextures() {
|
||||
return useLoginResultTextures;
|
||||
}
|
||||
|
||||
public byte[] getForceSetUseCustomPacket() {
|
||||
return customTex;
|
||||
}
|
||||
|
||||
public String getForceSetUseURL() {
|
||||
return customURL;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.query;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.HttpServerQueryHandler;
|
||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.query.QueryManager;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public abstract class EaglerQueryHandler extends HttpServerQueryHandler {
|
||||
|
||||
public static void registerQueryType(String name, Class<? extends EaglerQueryHandler> clazz) {
|
||||
QueryManager.registerQueryType(name, clazz);
|
||||
}
|
||||
|
||||
public static void unregisterQueryType(String name) {
|
||||
QueryManager.unregisterQueryType(name);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.query;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public abstract class EaglerQuerySimpleHandler extends EaglerQueryHandler {
|
||||
|
||||
@Override
|
||||
protected void processString(String str) {
|
||||
throw new UnexpectedDataException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processJson(JsonObject obj) {
|
||||
throw new UnexpectedDataException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processBytes(byte[] bytes) {
|
||||
throw new UnexpectedDataException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void acceptText() {
|
||||
throw new UnsupportedOperationException("EaglerQuerySimpleHandler does not support duplex");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void acceptText(boolean bool) {
|
||||
throw new UnsupportedOperationException("EaglerQuerySimpleHandler does not support duplex");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void acceptBinary() {
|
||||
throw new UnsupportedOperationException("EaglerQuerySimpleHandler does not support duplex");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void acceptBinary(boolean bool) {
|
||||
throw new UnsupportedOperationException("EaglerQuerySimpleHandler does not support duplex");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void closed() {
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.query;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.List;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerListenerConfig;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public interface MOTDConnection {
|
||||
|
||||
boolean isClosed();
|
||||
void close();
|
||||
|
||||
String getAccept();
|
||||
InetAddress getAddress();
|
||||
EaglerListenerConfig getListener();
|
||||
long getConnectionTimestamp();
|
||||
|
||||
public default long getConnectionAge() {
|
||||
return System.currentTimeMillis() - getConnectionTimestamp();
|
||||
}
|
||||
|
||||
void sendToUser();
|
||||
|
||||
String getLine1();
|
||||
String getLine2();
|
||||
List<String> getPlayerList();
|
||||
int[] getBitmap();
|
||||
int getOnlinePlayers();
|
||||
int getMaxPlayers();
|
||||
String getSubType();
|
||||
|
||||
void setLine1(String p);
|
||||
void setLine2(String p);
|
||||
void setPlayerList(List<String> p);
|
||||
void setPlayerList(String... p);
|
||||
void setBitmap(int[] p);
|
||||
void setOnlinePlayers(int i);
|
||||
void setMaxPlayers(int i);
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user