添加更新模块 修复少量bug

This commit is contained in:
LingASDJ 2023-04-27 00:57:28 +08:00
parent 645b53bab7
commit 46d7648b49
21 changed files with 777 additions and 368 deletions

View File

@ -12,6 +12,9 @@ android {
manifestPlaceholders = [appName:appName]
applicationId appPackageName
//Dex,65535
multiDexEnabled true
versionCode appVersionCode
versionName appVersionName
@ -28,8 +31,8 @@ android {
applicationIdSuffix ".indev"
versionNameSuffix '-INDEV'
dependencies {
debugImplementation project(':services:updates:debugUpdates')
debugImplementation project(':services:news:debugNews')
releaseImplementation project(':services:updates:githubUpdates')
releaseImplementation project(':services:news:shatteredNews')
}
}
release {
@ -62,9 +65,7 @@ dependencies {
implementation project(':core')
// Import the Firebase BoM
implementation platform('com.google.firebase:firebase-bom:30.3.1')
implementation platform('com.google.firebase:firebase-bom:31.4.0')
// Declare the dependencies for the Crashlytics and Analytics libraries
// When using the BoM, you don't specify versions in Firebase library dependencies
@ -83,9 +84,14 @@ dependencies {
// https://firebase.google.com/docs/android/setup#available-libraries
//DEX
implementation 'com.android.support:multidex:1.0.3'
//noinspection GradleDependency
implementation "com.badlogicgames.gdx:gdx-backend-android:$gdxVersion"
implementation project(path: ':services:updates:githubUpdates')
implementation project(path: ':services:news:shatteredNews')
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi-v7a"
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86"
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-arm64-v8a"

View File

@ -36,10 +36,10 @@ import com.badlogic.gdx.backends.android.AsynchronousAndroidAudio;
import com.google.firebase.analytics.FirebaseAnalytics;
import com.shatteredpixel.shatteredpixeldungeon.SPDSettings;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.services.news.GameNesImpl;
import com.shatteredpixel.shatteredpixeldungeon.services.news.News;
import com.shatteredpixel.shatteredpixeldungeon.services.news.NewsImpl;
import com.shatteredpixel.shatteredpixeldungeon.services.updates.UpdateImpl;
import com.shatteredpixel.shatteredpixeldungeon.services.updates.Updates;
import com.shatteredpixel.shatteredpixeldungeon.services.news.UpdateNews;
import com.shatteredpixel.shatteredpixeldungeon.ui.Button;
import com.watabou.noosa.Game;
import com.watabou.utils.FileUtils;
@ -70,10 +70,8 @@ public class AndroidGame extends AndroidApplication {
Game.versionCode = 0;
}
if (UpdateImpl.supportsUpdates()) {
Updates.service = UpdateImpl.getUpdateService();
}
if (NewsImpl.supportsNews()) {
UpdateNews.service = GameNesImpl.getNewsService();
News.service = NewsImpl.getNewsService();
}

View File

@ -186,6 +186,14 @@ scenes.newsscene$newsinfo.no_internet=无法查看新闻,请确认您已连接
scenes.newsscene$newsinfo.news_disabled=您已禁用新闻功能,所以这里什么也不会显示。
scenes.newsscene$newsinfo.enable_news=启用新闻
scenes.gamenewsscene.title=游戏更新
scenes.gamenewsscene$newsinfo.no_internet=正在检查新版本,长时间无响应可能是检查失败,若长时间未成功。请继续游玩,等待下次启动检查游戏。
scenes.gamenewsscene.read_more=继续游玩
scenes.gamenewsscene$articlebutton.btndownload_more=立即下载最新版本
scenes.gamenewsscene$articlebutton.btnfixeddownload=建议安装最新正版
scenes.rankingsscene.title=最高纪录
scenes.rankingsscene.total=游戏次数:
scenes.rankingsscene.no_games=目前为止还没有已经结束的游戏。

View File

@ -168,8 +168,6 @@ public class DiamondKnight extends Boss {
Dungeon.level.seal();
}
super.damage(dmg, src);
LockedFloor lock = hero.buff(LockedFloor.class);
if (lock != null) lock.addTime(dmg*2);
@ -196,6 +194,7 @@ public class DiamondKnight extends Boss {
GameScene.flash(0x808080);
((ColdChestBossLevel)Dungeon.level).progress();
spriteClass=DimandKingSprite.PrismaticSprite.class;
//强制刷新屏幕
ShatteredPixelDungeon.resetScene();
GameScene.flash(0x888888);
phase++;
@ -204,6 +203,7 @@ public class DiamondKnight extends Boss {
GLog.n(Messages.get(DiamondKnight.class,"ok_go"));
GameScene.flash(0x808080);
spriteClass=DimandKingSprite.class;
//强制刷新屏幕
ShatteredPixelDungeon.resetScene();
GameScene.flash(0x888888);
((ColdChestBossLevel)Dungeon.level).progress();
@ -211,7 +211,6 @@ public class DiamondKnight extends Boss {
}
}
@Override
public void die( Object cause ) {

View File

@ -214,7 +214,12 @@ public class BloodthirstyThorn extends MeleeWeapon {
*/
bloodthirstyThorn.identify();
bloodthirstyThorn.level=chaliceOfBlood.level();
if(chaliceOfBlood!=null){
bloodthirstyThorn.level=chaliceOfBlood.level();
} else {
bloodthirstyThorn.level=0;
}
return bloodthirstyThorn;
}
}

View File

@ -14,6 +14,7 @@ import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.bosses.DiamondKnight;
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfPurity;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTeleportation;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.watabou.utils.Bundle;
@ -287,6 +288,7 @@ public class ColdChestBossLevel extends Level {
ScrollOfTeleportation.appear(boss,647);
//玩家移动到初始位
ScrollOfTeleportation.appear(hero, 962);
drop( new PotionOfPurity(),648 );
boss.HP = 300;
pro = VSBOSS_START;
}

View File

@ -0,0 +1,311 @@
package com.shatteredpixel.shatteredpixeldungeon.scenes;
import com.shatteredpixel.shatteredpixeldungeon.Chrome;
import com.shatteredpixel.shatteredpixeldungeon.SPDSettings;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.messages.Languages;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.services.news.GameUpdateNewsArticles;
import com.shatteredpixel.shatteredpixeldungeon.services.news.UpdateNews;
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.ui.Archs;
import com.shatteredpixel.shatteredpixeldungeon.ui.Icons;
import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock;
import com.shatteredpixel.shatteredpixeldungeon.ui.StyledButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
import com.shatteredpixel.shatteredpixeldungeon.windows.IconTitle;
import com.watabou.noosa.BitmapText;
import com.watabou.noosa.Camera;
import com.watabou.noosa.Game;
import com.watabou.noosa.NinePatch;
import com.watabou.noosa.ui.Component;
import java.util.ArrayList;
import java.util.Calendar;
public class GameNewsScene extends PixelScene {
boolean displayingNoArticles = false;
private static final int BTN_HEIGHT = 22;
private static final int BTN_WIDTH = 100;
@Override
public void create() {
super.create();
uiCamera.visible = false;
int w = Camera.main.width;
int h = Camera.main.height;
int fullWidth = PixelScene.landscape() ? 202 : 100;
int left = (w - fullWidth)/2;
Archs archs = new Archs();
archs.setSize(w, h);
add(archs);
RenderedTextBlock title = PixelScene.renderTextBlock(Messages.get(this, "title"), 9);
title.hardlight(Window.TITLE_COLOR);
title.setPos(
(w - title.width()) / 2f,
(20 - title.height()) / 2f
);
align(title);
add(title);
float top = 18;
displayingNoArticles = !UpdateNews.articlesAvailable();
if (displayingNoArticles || Messages.lang() != Languages.CHINESE) {
Component newsInfo = new GameNewsScene.NewsInfo();
newsInfo.setRect(left, 20, fullWidth, 0);
add(newsInfo);
top = newsInfo.bottom();
}
if (!displayingNoArticles) {
ArrayList<GameUpdateNewsArticles> articles = UpdateNews.articles();
float articleSpace = h - top - 2;
int rows = articles.size();
if (PixelScene.landscape()){
rows /= 2;
}
rows++;
while ((articleSpace) / (BTN_HEIGHT+0.5f) < rows) {
articles.remove(articles.size() - 1);
if (PixelScene.landscape()) {
articles.remove(articles.size() - 1);
}
rows--;
}
float gap = ((articleSpace) - (BTN_HEIGHT * rows)) / (float)rows;
boolean rightCol = false;
for (GameUpdateNewsArticles article : articles) {
StyledButton b = new GameNewsScene.ArticleButton(article);
b.multiline = true;
if (!rightCol) {
top += gap;
b.setRect( left, top, BTN_WIDTH, BTN_HEIGHT);
} else {
b.setRect( left + fullWidth - BTN_WIDTH, top, BTN_WIDTH, BTN_HEIGHT);
}
align(b);
add(b);
if (!PixelScene.landscape()) {
top += BTN_HEIGHT;
} else {
if (rightCol){
top += BTN_HEIGHT;
}
rightCol = !rightCol;
}
}
top += gap;
} else {
top += 18;
}
StyledButton btnSite = new StyledButton(Chrome.Type.GREY_BUTTON_TR, Messages.get(this, "read_more")){
@Override
protected void onClick() {
super.onClick();
ShatteredPixelDungeon.switchNoFade( TitleScene.class );
}
};
btnSite.icon(Icons.get(Icons.NEWS));
btnSite.textColor(Window.TITLE_COLOR);
btnSite.setRect(left, 190, fullWidth, BTN_HEIGHT);
add(btnSite);
}
@Override
public void update() {
if (displayingNoArticles && UpdateNews.articlesAvailable()){
ShatteredPixelDungeon.seamlessResetScene();
}
super.update();
}
private static class NewsInfo extends Component {
NinePatch bg;
RenderedTextBlock text;
RedButton button;
@Override
protected void createChildren() {
bg = Chrome.get(Chrome.Type.GREY_BUTTON_TR);
add(bg);
String message = "";
if (Messages.lang() != Languages.CHINESE){
message += Messages.get(this, "english_warn");
}
SPDSettings.WiFi(false);
UpdateNews.checkForNews();
if (!UpdateNews.articlesAvailable()){
if (SPDSettings.news()) {
if (SPDSettings.WiFi() && !Game.platform.connectedToUnmeteredNetwork()) {
message += "\n\n" + Messages.get(this, "metered_network");
button = new RedButton(Messages.get(this, "enable_data")) {
@Override
protected void onClick() {
super.onClick();
SPDSettings.WiFi(false);
UpdateNews.checkForNews();
ShatteredPixelDungeon.seamlessResetScene();
}
};
add(button);
} else {
message += "\n\n" + Messages.get(this, "no_internet");
}
} else {
message += "\n\n" + Messages.get(this, "news_disabled");
button = new RedButton(Messages.get(this, "enable_news")) {
@Override
protected void onClick() {
super.onClick();
SPDSettings.news(true);
UpdateNews.checkForNews();
ShatteredPixelDungeon.seamlessResetScene();
}
};
add(button);
}
}
if (message.startsWith("\n\n")) message = message.replaceFirst("\n\n", "");
text = PixelScene.renderTextBlock(message, 6);
text.hardlight(CharSprite.WARNING);
add(text);
}
@Override
protected void layout() {
bg.x = x;
bg.y = y;
text.maxWidth((int)width - bg.marginHor());
text.setPos(x + bg.marginLeft(), y + bg.marginTop()+1);
height = (text.bottom()) - y;
if (button != null){
height += 4;
button.multiline = true;
button.setSize(width - bg.marginHor(), 16);
button.setSize(width - bg.marginHor(), Math.max(button.reqHeight(), 16));
button.setPos(x + (width - button.width())/2, y + height);
height = button.bottom() - y;
}
height += bg.marginBottom() + 1;
bg.size(width, height);
}
}
private static class ArticleButton extends StyledButton {
GameUpdateNewsArticles article;
BitmapText date;
public ArticleButton(GameUpdateNewsArticles article) {
super(Chrome.Type.GREY_BUTTON_TR, article.title, 6);
this.article = article;
icon(UpdateNews.parseArticleIcon(article));
Calendar cal = Calendar.getInstance();
cal.setTime(article.date);
date = new BitmapText( UpdateNews.parseArticleDate(article), pixelFont);
date.scale.set(PixelScene.align(0.5f));
date.hardlight( 0x888888 );
date.measure();
//add(date);
IconTitle title = new IconTitle(new ItemSprite( ItemSpriteSheet.MAGICGIRLBOOKS ),article.title);
title.setRect( 30, 20, 100, 0 );
title.setPos( title.centerX(), title.bottom() + 4 );
add(title);
int w = Camera.main.width;
String message = article.summary;
message += "\n\n你现在的游戏版本代码"+ Game.versionCode;
message += "\n\n网络上的游戏版本代码"+ article.ling;
message += "\n\n"+(
article.ling > Game.versionCode ? "✦你的版本是旧版本,请及时更新✦":
article.ling == Game.versionCode ? "Δ版本一致,你已是最新版本。Δ": "Γ版本号大于服务器数据,可能是修改版,请谨慎游玩。Γ");
int fullWidth = PixelScene.landscape() ? 202 : 100;
int left = (w - fullWidth)/2;
if(article.ling > Game.versionCode || article.ling < Game.versionCode){
StyledButton btnDownload = new StyledButton(Chrome.Type.SCROLL,
//这里读取的是外面的数据,Condition 'article.ling < Game.versionCode' is always 'true'
//AS不会判定这种外网数据它实际可以运行请勿通过AS优化此代码
article.ling > Game.versionCode ? Messages.get(this, "btnDownload_more") :
article.ling < Game.versionCode ? Messages.get(this, "btnFixedDownload") : ""){
@Override
protected void onClick() {
super.onClick();
ShatteredPixelDungeon.platform.openURI(article.URL);
}
};
btnDownload.icon(Icons.get(article.ling > Game.versionCode?Icons.STATS :
article.ling < Game.versionCode ? Icons.WARNING: Icons.STATS));
btnDownload.textColor(Window.TITLE_COLOR);
btnDownload.setRect(left, 160, fullWidth, BTN_HEIGHT);
add(btnDownload);
}
RenderedTextBlock text = PixelScene.renderTextBlock( 6 );
text.text( message, 100 );
text.setPos( title.left(), title.bottom() + 4 );
add( text );
}
@Override
protected void layout() {
super.layout();
bg.active=false;
bg.visible=false;
icon.x = x + bg.marginLeft() + (16-icon.width())/2f;
icon.visible=false;
PixelScene.align(icon);
text.setPos(x + bg.marginLeft() + 18, text.top());
text.visible=false;
if (date != null) {
date.x = x + width - bg.marginRight() - date.width() + 1;
date.y = y + height - bg.marginBottom() - date.height() + 2.5f;
align(date);
}
}
@Override
protected void onClick() {
super.onClick();
//
}
}
}

View File

@ -0,0 +1,110 @@
package com.shatteredpixel.shatteredpixeldungeon.services.news;
import com.badlogic.gdx.Application;
import com.badlogic.gdx.Gdx;
import com.shatteredpixel.shatteredpixeldungeon.SPDSettings;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.ui.Icons;
import com.watabou.noosa.Image;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
public class UpdateNews {
public static GameUpdateNewsService service;
public static boolean supportsNews() {
return service != null;
}
private static Date lastCheck = null;
private static final long CHECK_DELAY = 1000 * 60 * 60; //1 hour
public static void checkForNews() {
if (!supportsNews()) return;
if (lastCheck != null && (new Date().getTime() - lastCheck.getTime()) < CHECK_DELAY) return;
boolean useHTTPS = true;
if (Gdx.app.getType() == Application.ApplicationType.Android && Gdx.app.getVersion() < 20) {
useHTTPS = false; //android versions below 5.0 don't support TLSv1.2 by default
}
service.checkForArticles(!SPDSettings.WiFi(), useHTTPS, new GameUpdateNewsService.NewsResultCallback() {
@Override
public void onArticlesFound(ArrayList<GameUpdateNewsArticles> articles) {
lastCheck = new Date();
UpdateNews.articles = articles;
}
@Override
public void onConnectionFailed() {
lastCheck = null;
UpdateNews.articles = null;
}
});
}
private static ArrayList<GameUpdateNewsArticles> articles;
public static synchronized boolean articlesAvailable() {
return articles != null && !articles.isEmpty();
}
public static synchronized ArrayList<GameUpdateNewsArticles> articles() {
return new ArrayList<>(articles);
}
public static synchronized int unreadArticles(Date lastRead) {
int unread = 0;
if (articles != null) {
for (GameUpdateNewsArticles article : articles) {
if (article.date.after(lastRead)) unread++;
}
}
return unread;
}
public static synchronized void clearArticles() {
articles = null;
lastCheck = null;
}
public static Image parseArticleIcon(GameUpdateNewsArticles article) {
try {
//recognized formats are:
//"ICON: <name of enum constant in Icons.java>"
if (article.icon.startsWith("ICON: ")) {
return Icons.get(Icons.valueOf(article.icon.replace("ICON: ", "")));
//"ITEM: <integer constant corresponding to values in ItemSpriteSheet.java>"
} else if (article.icon.startsWith("ITEM: ")) {
return new ItemSprite(Integer.parseInt(article.icon.replace("ITEM: ", "")));
//"<asset filename>, <tx left>, <tx top>, <width>, <height>"
} else {
String[] split = article.icon.split(", ");
return new Image(split[0],
Integer.parseInt(split[1]),
Integer.parseInt(split[2]),
Integer.parseInt(split[3]),
Integer.parseInt(split[4]));
}
//if we run into any formatting errors (or icon is null), default to the news icon
} catch (Exception e) {
if (article.icon != null) ShatteredPixelDungeon.reportException(e);
return Icons.get(Icons.NEWS);
}
}
public static String parseArticleDate(GameUpdateNewsArticles article) {
Calendar cal = Calendar.getInstance();
cal.setTime(article.date);
return cal.get(Calendar.YEAR)
+ "-" + String.format("%02d", cal.get(Calendar.MONTH) + 1)
+ "-" + String.format("%02d", cal.get(Calendar.DAY_OF_MONTH));
}
}

View File

@ -14,6 +14,7 @@ import com.watabou.utils.Callback;
public class DimandKingSprite extends MobSprite {
private Emitter teleParticles;
public DimandKingSprite() {
super();
@ -117,7 +118,7 @@ public class DimandKingSprite extends MobSprite {
super();
texture( Dungeon.hero.heroClass.spritesheet() );
updateArmor( 0 );
updateArmor( 6 );
idle();
}
@ -128,7 +129,7 @@ public class DimandKingSprite extends MobSprite {
}
public void updateArmor( int tier ) {
TextureFilm film = new TextureFilm( HeroSprite.tiers(), tier, FRAME_WIDTH, FRAME_HEIGHT );
TextureFilm film = new TextureFilm( HeroSprite.tiers(), 6, FRAME_WIDTH, FRAME_HEIGHT );
idle = new Animation( 1, true );
idle.frames( film, 0, 0, 0, 1, 0, 0, 1, 1 );

View File

@ -2,7 +2,7 @@ package com.shatteredpixel.shatteredpixeldungeon.ui;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.FeedBackScene;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameNewsScene;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndKeyBindings;
import com.watabou.input.GameAction;
@ -18,7 +18,7 @@ public class EndButton extends IconButton {
@Override
protected void onClick() {
super.onClick();
ShatteredPixelDungeon.switchNoFade(FeedBackScene.class);
ShatteredPixelDungeon.switchNoFade(GameNewsScene.class);
}
@Override

View File

@ -30,8 +30,10 @@ import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.SharedLibraryLoader;
import com.shatteredpixel.shatteredpixeldungeon.SPDSettings;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.services.news.GameNesImpl;
import com.shatteredpixel.shatteredpixeldungeon.services.news.News;
import com.shatteredpixel.shatteredpixeldungeon.services.news.NewsImpl;
import com.shatteredpixel.shatteredpixeldungeon.services.news.UpdateNews;
import com.watabou.noosa.Game;
import com.watabou.utils.FileUtils;
import com.watabou.utils.Point;
@ -110,7 +112,10 @@ public class DesktopLauncher {
Game.versionCode = Integer.parseInt(System.getProperty("Implementation-Version"));
}
if (NewsImpl.supportsNews()){
UpdateNews.service = GameNesImpl.getNewsService();
News.service = NewsImpl.getNewsService();
}

View File

@ -1,30 +0,0 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2021 Evan Debenham
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
apply plugin: 'java-library'
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
sourceCompatibility = targetCompatibility = appJavaCompatibility
dependencies {
implementation project(':SPD-classes')
api project(':services')
}

View File

@ -1,113 +0,0 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2022 Evan Debenham
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.services.news;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Net;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.XmlReader;
import com.watabou.noosa.Game;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DebugNews extends NewsService {
@Override
public void checkForArticles(boolean useMetered, boolean preferHTTPS, NewsResultCallback callback) {
if (!useMetered && !Game.platform.connectedToUnmeteredNetwork()){
callback.onConnectionFailed();
return;
}
Net.HttpRequest httpGet = new Net.HttpRequest(Net.HttpMethods.GET);
if (preferHTTPS) {
httpGet.setUrl("https://jdsalingzx.top/assets/xml/news.xml");
} else {
httpGet.setUrl("https://jdsalingzx.top/assets/xml/news.xml");
}
Gdx.net.sendHttpRequest(httpGet, new Net.HttpResponseListener() {
@Override
public void handleHttpResponse(Net.HttpResponse httpResponse) {
ArrayList<NewsArticle> articles = new ArrayList<>();
XmlReader reader = new XmlReader();
XmlReader.Element xmlDoc = reader.parse(httpResponse.getResultAsStream());
SimpleDateFormat dateParser = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
for (XmlReader.Element xmlArticle : xmlDoc.getChildrenByName("entry")){
NewsArticle article = new NewsArticle();
article.title = xmlArticle.get("title");
try {
article.date = dateParser.parse(xmlArticle.get("published"));
} catch (ParseException e) {
Game.reportException(e);
}
article.summary = xmlArticle.get("summary");
article.URL = xmlArticle.getChildByName("link").getAttribute("href");
if (!preferHTTPS) {
article.URL = article.URL.replace("https://", "http://");
}
Pattern versionCodeMatcher = Pattern.compile("v[0-9]+");
try {
Array<XmlReader.Element> properties = xmlArticle.getChildrenByName("category");
for (XmlReader.Element prop : properties){
String propVal = prop.getAttribute("term");
if (propVal.startsWith("SHPD_ICON")){
Matcher m = versionCodeMatcher.matcher(propVal);
if (m.find()) {
int iconGameVer = Integer.parseInt(m.group().substring(1));
if (iconGameVer <= Game.versionCode) {
article.icon = propVal.substring(propVal.indexOf(": ") + 2);
}
}
}
}
} catch (Exception e){
article.icon = null;
}
articles.add(article);
}
callback.onArticlesFound(articles);
}
@Override
public void failed(Throwable t) {
callback.onConnectionFailed();
}
@Override
public void cancelled() {
callback.onConnectionFailed();
}
});
}
}

View File

@ -1,36 +0,0 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2022 Evan Debenham
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.services.news;
public class NewsImpl {
private static NewsService newsChecker = new DebugNews();
public static NewsService getNewsService(){
return newsChecker;
}
public static boolean supportsNews(){
return true;
}
}

View File

@ -0,0 +1,15 @@
package com.shatteredpixel.shatteredpixeldungeon.services.news;
public class GameNesImpl{
private static GameUpdateNewsService newsChecker = new GameUpdateNews();
public static GameUpdateNewsService getNewsService(){
return newsChecker;
}
public static boolean supportsNews(){
return true;
}
}

View File

@ -0,0 +1,94 @@
package com.shatteredpixel.shatteredpixeldungeon.services.news;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Net;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.XmlReader;
import com.watabou.noosa.Game;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class GameUpdateNews extends GameUpdateNewsService {
@Override
public void checkForArticles(boolean useMetered, boolean preferHTTPS, NewsResultCallback callback) {
if (!useMetered && !Game.platform.connectedToUnmeteredNetwork()){
callback.onConnectionFailed();
return;
}
Net.HttpRequest httpGet = new Net.HttpRequest(Net.HttpMethods.GET);
if (preferHTTPS) {
httpGet.setUrl("https://jdsalingzx.top/assets/xml/gamenews.xml");
} else {
httpGet.setUrl("https://jdsalingzx.top/assets/xml/gamenews.xml");
}
Gdx.net.sendHttpRequest(httpGet, new Net.HttpResponseListener() {
@Override
public void handleHttpResponse(Net.HttpResponse httpResponse) {
ArrayList<GameUpdateNewsArticles> articles = new ArrayList<>();
XmlReader reader = new XmlReader();
XmlReader.Element xmlDoc = reader.parse(httpResponse.getResultAsStream());
SimpleDateFormat dateParser = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
for (XmlReader.Element xmlArticle : xmlDoc.getChildrenByName("entry")){
GameUpdateNewsArticles article = new GameUpdateNewsArticles();
article.title = xmlArticle.get("title");
try {
article.date = dateParser.parse(xmlArticle.get("published"));
} catch (ParseException e) {
Game.reportException(e);
}
article.summary = xmlArticle.get("summary");
article.ling = xmlArticle.getInt("ling");
article.URL = xmlArticle.getChildByName("link").getAttribute("href");
if (!preferHTTPS) {
article.URL= article.URL.replace("https://", "http://");
}
Pattern versionCodeMatcher = Pattern.compile("v[0-9]+");
try {
Array<XmlReader.Element> properties = xmlArticle.getChildrenByName("category");
for (XmlReader.Element prop : properties){
String propVal = prop.getAttribute("term");
if (propVal.startsWith("SHPD_ICON")){
Matcher m = versionCodeMatcher.matcher(propVal);
if (m.find()) {
int iconGameVer = Integer.parseInt(m.group().substring(1));
if (iconGameVer <= Game.versionCode) {
article.icon = propVal.substring(propVal.indexOf(": ") + 2);
}
}
}
}
} catch (Exception e){
article.icon = null;
}
articles.add(article);
}
callback.onArticlesFound(articles);
}
@Override
public void failed(Throwable t) {
callback.onConnectionFailed();
}
@Override
public void cancelled() {
callback.onConnectionFailed();
}
});
}
}

View File

@ -0,0 +1,17 @@
package com.shatteredpixel.shatteredpixeldungeon.services.news;
import java.util.Date;
public class GameUpdateNewsArticles {
public String title;
public Date date;
public String summary;
public int ling;
public String URL;
//the icon is stored as a string here so it can be decoded to an image later
//See News.java for supported formats
public String icon;
}

View File

@ -0,0 +1,12 @@
package com.shatteredpixel.shatteredpixeldungeon.services.news;
import java.util.ArrayList;
public abstract class GameUpdateNewsService {
public static abstract class NewsResultCallback {
public abstract void onArticlesFound(ArrayList<GameUpdateNewsArticles> articles);
public abstract void onConnectionFailed();
}
public abstract void checkForArticles(boolean useMetered, boolean forceHTTPS, GameUpdateNewsService.NewsResultCallback callback);
}

View File

@ -1,134 +1,140 @@
package com.shatteredpixel.shatteredpixeldungeon.services.updates;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Net;
import com.watabou.noosa.Game;
import com.watabou.utils.Bundle;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.net.ssl.SSLProtocolException;
public class GitHubUpdates extends UpdateService {
private static Pattern descPattern = Pattern.compile("(.*?)(\r\n|\n|\r)(\r\n|\n|\r)---", Pattern.DOTALL + Pattern.MULTILINE);
private static Pattern versionCodePattern = Pattern.compile("internal version number: ([0-9]*)", Pattern.CASE_INSENSITIVE);
@Override
public boolean isUpdateable() {
return true;
}
@Override
public boolean supportsBetaChannel() {
return true;
}
@Override
public void checkForUpdate(boolean useMetered, boolean includeBetas, UpdateResultCallback callback) {
if (!useMetered && !Game.platform.connectedToUnmeteredNetwork()){
callback.onConnectionFailed();
return;
}
Net.HttpRequest httpGet = new Net.HttpRequest(Net.HttpMethods.GET);
httpGet.setUrl("https://api.github.com/repos/00-Evan/shattered-pixel-dungeon/releases");
httpGet.setHeader("Accept", "application/vnd.github.v3+json");
Gdx.net.sendHttpRequest(httpGet, new Net.HttpResponseListener() {
@Override
public void handleHttpResponse(Net.HttpResponse httpResponse) {
try {
Bundle latestRelease = null;
int latestVersionCode = Game.versionCode;
for (Bundle b : Bundle.read( httpResponse.getResultAsStream() ).getBundleArray()){
Matcher m = versionCodePattern.matcher(b.getString("body"));
if (m.find()){
int releaseVersion = Integer.parseInt(m.group(1));
if (releaseVersion > latestVersionCode
&& (includeBetas || !b.getBoolean("prerelease"))){
latestRelease = b;
latestVersionCode = releaseVersion;
}
}
}
if (latestRelease == null){
callback.onNoUpdateFound();
} else {
AvailableUpdateData update = new AvailableUpdateData();
update.versionName = latestRelease.getString("name");
update.versionCode = latestVersionCode;
Matcher m = descPattern.matcher(latestRelease.getString("body"));
m.find();
update.desc = m.group(1);
update.URL = latestRelease.getString("html_url");
callback.onUpdateAvailable(update);
}
} catch (Exception e) {
Game.reportException( e );
callback.onConnectionFailed();
}
}
@Override
public void failed(Throwable t) {
//Failure in SSL handshake, possibly because GitHub requires TLS 1.2+.
// Often happens for old OS versions with outdated security protocols.
// Future update attempts won't work anyway, so just pretend nothing was found.
if (t instanceof SSLProtocolException){
callback.onNoUpdateFound();
} else {
Game.reportException(t);
callback.onConnectionFailed();
}
}
@Override
public void cancelled() {
callback.onConnectionFailed();
}
});
}
@Override
public void initializeUpdate(AvailableUpdateData update) {
Game.platform.openURI( update.URL );
}
@Override
public boolean isInstallable() {
return false;
}
@Override
public void initializeInstall() {
//does nothing, always installed
}
@Override
public boolean supportsReviews() {
return false;
}
@Override
public void initializeReview(ReviewResultCallback callback) {
//does nothing, no review functionality here
callback.onComplete();
}
@Override
public void openReviewURI() {
//does nothing
}
}
//package com.shatteredpixel.shatteredpixeldungeon.services.updates;
//
//
//import com.badlogic.gdx.Gdx;
//import com.badlogic.gdx.Net;
//import com.shatteredpixel.shatteredpixeldungeon.services.news.NewsService;
//import com.watabou.noosa.Game;
//import com.watabou.utils.Bundle;
//
//import java.util.regex.Matcher;
//import java.util.regex.Pattern;
//
//import javax.net.ssl.SSLProtocolException;
//
//public class GitHubUpdates extends UpdateService {
//
// private static Pattern descPattern = Pattern.compile("(.*?)(\r\n|\n|\r)(\r\n|\n|\r)---", Pattern.DOTALL + Pattern.MULTILINE);
// private static Pattern versionCodePattern = Pattern.compile("internal version number: ([0-9]*)", Pattern.CASE_INSENSITIVE);
//
// @Override
// public boolean isUpdateable() {
// return true;
// }
//
// @Override
// public boolean supportsBetaChannel() {
// return true;
// }
//
// @Override
// public void checkForUpdate(boolean useMetered, boolean includeBetas, UpdateResultCallback callback) {
//
// if (!useMetered && !Game.platform.connectedToUnmeteredNetwork()){
// callback.onConnectionFailed();
// return;
// }
//
// Net.HttpRequest httpGet = new Net.HttpRequest(Net.HttpMethods.GET);
// httpGet.setUrl("https://api.github.com/repos/00-Evan/shattered-pixel-dungeon/releases");
// httpGet.setHeader("Accept", "application/vnd.github.v3+json");
//
// Gdx.net.sendHttpRequest(httpGet, new Net.HttpResponseListener() {
// @Override
// public void handleHttpResponse(Net.HttpResponse httpResponse) {
// try {
// Bundle latestRelease = null;
// int latestVersionCode = Game.versionCode;
//
// for (Bundle b : Bundle.read( httpResponse.getResultAsStream() ).getBundleArray()){
// Matcher m = versionCodePattern.matcher(b.getString("body"));
//
// if (m.find()){
// int releaseVersion = Integer.parseInt(m.group(1));
// if (releaseVersion > latestVersionCode
// && (includeBetas || !b.getBoolean("prerelease"))){
// latestRelease = b;
// latestVersionCode = releaseVersion;
// }
// }
//
// }
//
// if (latestRelease == null){
// callback.onNoUpdateFound();
// } else {
//
// AvailableUpdateData update = new AvailableUpdateData();
//
// update.versionName = latestRelease.getString("name");
// update.versionCode = latestVersionCode;
// Matcher m = descPattern.matcher(latestRelease.getString("body"));
// m.find();
// update.desc = m.group(1);
// update.URL = latestRelease.getString("html_url");
//
// callback.onUpdateAvailable(update);
// }
// } catch (Exception e) {
// Game.reportException( e );
// callback.onConnectionFailed();
// }
// }
//
// @Override
// public void failed(Throwable t) {
// //Failure in SSL handshake, possibly because GitHub requires TLS 1.2+.
// // Often happens for old OS versions with outdated security protocols.
// // Future update attempts won't work anyway, so just pretend nothing was found.
// if (t instanceof SSLProtocolException){
// callback.onNoUpdateFound();
// } else {
// Game.reportException(t);
// callback.onConnectionFailed();
// }
// }
//
// @Override
// public void cancelled() {
// callback.onConnectionFailed();
// }
// });
//
// }
//
// @Override
// public void initializeUpdate(AvailableUpdateData update) {
// Game.platform.openURI( update.URL );
// }
//
// @Override
// public boolean isInstallable() {
// return false;
// }
//
// @Override
// public void initializeInstall() {
// //does nothing, always installed
// }
//
// @Override
// public boolean supportsReviews() {
// return false;
// }
//
// @Override
// public void initializeReview(ReviewResultCallback callback) {
// //does nothing, no review functionality here
// callback.onComplete();
// }
//
// @Override
// public void openReviewURI() {
// //does nothing
// }
//
// @Override
// public void checkForArticles(boolean useMetered, boolean forceHTTPS, NewsService.NewsResultCallback callback) {
//
// }
//}

View File

@ -1,35 +1,35 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2022 Evan Debenham
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.services.updates;
import com.watabou.noosa.Game;
public class UpdateImpl {
private static UpdateService updateChecker = new GitHubUpdates();
public static UpdateService getUpdateService(){
return updateChecker;
}
}
///*
// * Pixel Dungeon
// * Copyright (C) 2012-2015 Oleg Dolya
// *
// * Shattered Pixel Dungeon
// * Copyright (C) 2014-2022 Evan Debenham
// *
// * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 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 General Public License for more details.
// *
// * You should have received a copy of the GNU General Public License
// * along with this program. If not, see <http://www.gnu.org/licenses/>
// */
//
//package com.shatteredpixel.shatteredpixeldungeon.services.updates;
//
//import com.watabou.noosa.Game;
//
//public class UpdateImpl {
//
// private static UpdateService updateChecker = new GitHubUpdates();
//
// public static UpdateService getUpdateService(){
// return updateChecker;
// }
//
//
//}

View File

@ -9,8 +9,7 @@ include ':desktop'
//service modules
include ':services'
//updates
include ':services:updates:debugUpdates'
include ':services:updates:githubUpdates'
include ':services:updates:githubUpdates'
//news
include ':services:news:debugNews'
include ':services:news:shatteredNews'